# 本代码已不再维护，请使用evaluator.py
import json
import re

__all__ = [
    "eval"
]

def eval(json_data, y_preds, task: str):
    """
    integrated evaluation entry

    json_data: json-like object
    y_pred: list of strings
    task: {'NER', 'RE', 'Event', 'MRC', 'SM'}
    """
    func_dict = {
        'NER': eval_NER,
        'RE': eval_RE,
        'Event': eval_Event,
        'MRC': eval_MRC,
        'SM': eval_SM
    }
    metric_dict = {
        'NER': 'f1',
        'RE': 'f1',
        'Event': 'f1',
        'MRC': 'acc',
        'SM': 'acc'
    }
    assert task in func_dict, 'Invalid task name %s.'%(task)

    metric = metric_dict[task]

    if metric == 'acc':
        scores = []
        for json_datus, y_pred in zip(json_data, y_preds):
            score = func_dict[task](json_datus, y_pred)
            scores.append(score)
        return sum(scores) / len(scores)
    elif metric == 'f1':
        # f1 score 应该在数据集集合尺度上计算 precision、recall，而不是对单个样本计算，之后求平均
        sum_TP = sum_FN = sum_FP = 0
        for json_datus, y_pred in zip(json_data, y_preds):
            TP, FN, FP = func_dict[task](json_datus, y_pred)
            sum_TP += TP
            sum_FN += FN
            sum_FP += FP
        return _calc_f1_score(sum_TP, sum_FN, sum_FP)

def _remove_redundant_space(s):
    # '   a  b  \t  c  \n' --> 'a b c'
    return ' '.join(s.split())

def _TFPN(truth: set, pred: set):
    # TP: 在truth中存在，且在pred中存在
    # FN: 在truth中存在，但在pred中不存在
    # FP: 在truth中不存在，但在pred中存在
    TP = len(truth & pred)
    FN = len(truth - pred)
    FP = len(pred - truth)
    return TP, FN, FP

def _calc_f1_score(TP, FN, FP):
    # TP + FN 可能为0
    # TP + FP 可能为0
    if TP + FN == 0:
        recall = 0
    else:
        recall = TP / (TP + FN)
    if TP + FP == 0:
        precision = 0
    else:
        precision = TP / (TP + FP)
    if recall + precision == 0:
        f1 = 0
    else:
        f1 = 2 * recall * precision / (recall + precision)
    return f1

def eval_NER(json_data, y_pred: str):
    """
    json_data: json-like object
    y_pred: single string outputed by model
    return: TP, FN, FP
    """
    entity_truth = set()
    tmp = json.loads(json_data['instance']['entities'].replace("'",'"'))

    for ent in tmp:
        ent = ent['type']+':'+ent['name']
        ent = _remove_redundant_space(ent)
        entity_truth.add(ent)

    entity_pred = set()
    for ent in y_pred.split(','):
        ent = ent.split(':')
        if len(ent) == 2:
            # 预测中不符合格式的实体会被抛弃
            ent = ent[0].strip()+':'+ent[1].strip()
            ent = _remove_redundant_space(ent)
            entity_pred.add(ent)

    return _TFPN(entity_truth, entity_pred)

def eval_RE(json_data, y_pred: str):
    """
    json_data: json-like object
    y_pred: single string outputed by model
    return: TP, FN, FP
    """
    truth = set()
    for rel in json.loads(json_data['Instance']['entities']):
        head = rel['head']['name']
        rel_type = rel['type']
        tail = rel['tail']['name']
        if rel_type not in ['no_relation', 'NA', 'N/A']:
            # 数据集中type为'no_relation'或'NA'的关系会被全部忽略掉
            rel = '(%s,%s,%s)'%(head, rel_type, tail)
            rel = _remove_redundant_space(rel)
            truth.add(rel)

    # y_pred中理应只包含模型自己输出的内容，而不包含prompt
    y_pred = y_pred.split('Answer:')[-1]

    pred = set()
    if y_pred.strip() != 'no relation':
        # 如果模型输出'no relation'，则认为其预测的关系集合为空集
        for rel in re.findall(r'\(.+?\)', y_pred):
            rel = rel[1:-1]
            elements = tuple([i.strip() for i in rel.split(',')])
            if len(elements) == 3:
                # 预测中不符合格式的关系会被舍弃
                rel_type = elements[1]
                if rel_type not in ['no_relation', 'NA', 'N/A']:
                    rel = '(%s,%s,%s)'%elements
                    rel = _remove_redundant_space(rel)
                    pred.add(rel)
    return _TFPN(truth, pred)

def eval_MRC(json_data, y_pred: str):
    """
    json_data: json-like object
    y_pred: single string outputed by model
    return: right or not
    """
    y = _remove_redundant_space(json_data['answer_text'])
    y_pred = _remove_redundant_space(y_pred)
    if y == y_pred:
        return 1
    else:
        return 0

def eval_SM(json_data, y_pred: str):
    """
    data: json-like object
    y_pred: single string outputed by model
    return: right or not
    """
    y = _remove_redundant_space(json_data['label'])
    y_pred = _remove_redundant_space(y_pred)
    trans_dict = {
        '是': 'Yes',
        '否': 'No',
        'yes': 'Yes',
        'no': 'No'
    }
    if y in trans_dict:
        y = trans_dict[y]
    if y_pred in trans_dict:
        y_pred = trans_dict[y_pred]

    if y_pred == y:
        return 1
    else:
        return 0

def eval_Event(json_data, y_pred: str):
    """
    json_data: json-like object
    y_pred: single string outputed by model
    return: TP, FN, FP
    """
    truth = set()
    for event in json_data['events']:
        event_elements = []

        event_type = event['type']
        event_elements.append('event type:%s'%event_type.strip())

        trigger = event['trigger']
        event_elements.append('trigger:%s'%trigger.strip())

        for arg in event['arguments']:
            name = arg['name']
            role = arg['role']
            event_elements.append('%s:%s'%(role.strip(), name.strip()))

        event_string = ','.join(sorted(event_elements)) # 'a:b,c:d'
        event_string = _remove_redundant_space(event_string)
        truth.add(event_string)

    pred = set()
    for event in re.findall(r'\(.+?\)', y_pred):
        event = event[1:-1]
        valid_event = True
        pair_strings = []
        for pair in event.split(','):
            pair = pair.split(':')
            if len(pair) != 2:
                valid_event = False
                break
            pair_strings.append('%s:%s'%(pair[0].strip(), pair[1].strip()))
        if valid_event:
            event_string = ','.join(sorted(pair_strings))
            event_string = _remove_redundant_space(event_string)
            pred.add(event_string)
    return _TFPN(truth, pred)

if __name__ == '__main__':
    print(
        eval(
            json.loads("""
            [{
                "sentence": "我在复旦大学上学，想去墨脱喝奶茶。",
                "entities": [
                    {
                        "name": "复旦大学",
                        "type": "organization",
                        "pos": [
                            2,
                            6
                        ]
                    },
                    {
                        "name": "墨脱",
                        "type": "location",
                        "pos": [
                            11,
                            13
                        ]
                    }
                ]
            }]
            """),
            ["organization: 复旦大学, location: 墨脱"],
            task = 'NER'
        ),
        'Expected Result: 1.0',
        eval(
            json.loads("""
            [{
                "sentence": "我在复旦大学上学，想去墨脱喝奶茶。",
                "relations": [
                    {
                        "head":
                                {"name": "复旦大学",
                                    "type": "organization",
                                    "pos": [
                                        2,
                                        6
                                    ]
                                },
                        "type":
                                "no_relation",
                        "tail":
                                {"name": "墨脱",
                                "type": "location",
                                "pos": [
                                    11,
                                    13
                                    ]
                                }
                    }
                ]
            },
            {
                "sentence": "小明在上海的复旦大学上学。",
                "relations": [
                    {
                        "head":
                                {"name": "复旦大学",
                                    "type": "organization",
                                    "pos": [
                                        6,
                                        10
                                    ]
                                },
                        "type":
                                "locate in",
                        "tail":
                                {"name": "上海",
                                "type": "location",
                                "pos": [
                                    3,
                                    5
                                    ]
                                }
                    },
                    {
                        "head":
                                {"name": "小明",
                                    "type": "person",
                                    "pos": [
                                        0,
                                        2
                                    ]
                                },
                        "type":
                                "belong to",
                        "tail":
                                {"name": "复旦大学",
                                "type": "organization",
                                "pos": [
                                    6,
                                    10
                                    ]
                                }
                    }
                ]
            }
            ]
            """),
            ['no relation', '(复旦大学, locate  in, 上海), (李田所,belong to, 复旦大学)'],
            task = 'RE'
        ),
        'Expected Result: 0.5',
        eval(
            json.loads("""
            [{
                "sentence": "雀巢裁员4000人：时代抛弃你时，连招呼都不会打！",
                "events": [
                    {
                        "trigger": "裁员",
                        "type": "组织关系-裁员",
                        "pos":[
                            2,
                            3
                        ],
                        "arguments": [
                            {
                                "name": "雀巢",
                                "role": "裁员方",
                                "pos":[
                                    0,
                                    2
                                ]
                            },
                            {
                                "name": "4000人",
                                "role": "裁员人数",
                                "pos":[
                                    4,
                                    9
                                ]
                            }
                        ]
                    }
                ]
            }]
            """),
            ["(event type : 组织关系-裁员, trigger: 裁员, 裁员方: 雀巢, 裁员人数: 4000人), (event type : 组织关系-裁员, trigger: 裁员, 裁员方: 雀巢, 裁员人数: 3000人)"],
            task = 'Event'
        ),
        'Expected Result: 2/3',
        eval(
            json.loads("""
            [{
                "paragraph": "Another approach to brain function is to examine the consequences of damage to specific brain areas. Even though it is protected by the skull and meninges, surrounded by cerebrospinal fluid, and isolated from the bloodstream by the blood\u2013brain barrier, the delicate nature of the brain makes it vulnerable to numerous diseases and several types of damage. In humans, the effects of strokes and other types of brain damage have been a key source of information about brain function. Because there is no ability to experimentally control the nature of the damage, however, this information is often difficult to interpret. In animal studies, most commonly involving rats, it is possible to use electrodes or locally injected chemicals to produce precise patterns of damage and then examine the consequences for behavior.",
                "question": "What sare the benifts of the blood brain barrir?",
                "answer_start": 195,
                "answer_text": "isolated from the bloodstream"
            }]
            """),
            ["isolated from the bloodstream"],
            task = 'MRC'
        ),
        'Expected Result: 1.0',
        eval(
            json.loads("""
            [{
                "sen1": "A man with a hard hat is dancing.",
                "sen2": "A man wearing a hard hat is dancing.",
                "label": "Yes"
            },
            {
                "sen1": "蚂蚁借呗等额还款可以换成先息后本吗",
                "sen2": "借呗有先息到期还本吗",
                "label": "否"
            }
            ]
            """),
            ["是", "no"],
            task = 'SM'
        ),
        'Expected Result: 1.0',
        sep='\n'
    )


from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.interval import IntervalTrigger
from src.service import DataService

scheduler = BlockingScheduler()
@scheduler.scheduled_job(IntervalTrigger(hours=1))
def main():
    servicio = DataService()
    servicio.dataextraction()
    servicio.dataprocess()
    servicio.datawriter()

scheduler.start()


from collections import deque
branch_list = [0x1c6, 0x21f, 0x309, 0x21f, 0x309, 0x1c6, 0x309, 0x1c6, 0x21f]
true_take = [1, 0, 0, 0, 0, 1, 0, 1, 1]

BHT = [0 for _ in range(8)]

history_queue = deque(true_take[-3:])

for i in range(100):
    accuracy = 0
    prediction = []
    for j in range(len(true_take)):
        BHT_index = int("".join(map(str, list(history_queue))), 2)
        prediction.append(BHT[BHT_index] // 2)

        if BHT[BHT_index] // 2 == true_take[j]:
            accuracy += 1

        if true_take[j] == 1:
            if BHT[BHT_index] != 3:
                BHT[BHT_index] += 1
        if true_take[j] == 0:
            if BHT[BHT_index] != 0:
                BHT[BHT_index] -= 1

        history_queue.pop()
        history_queue.appendleft(true_take[j])

    print("Round " + str(i) + ":")
    print("BHT:")
    print(BHT)
    print("True take:")
    print(true_take)
    print("Prediction:")
    print(prediction)
    print("__________________")

    accuracy = accuracy / float(len(true_take))
    print(accuracy)


import argparse

import uvicorn

from market.config import settings

parser = argparse.ArgumentParser()
parser.add_argument('--app-host', default=settings.app_host)
parser.add_argument('--app-port', default=settings.app_port, type=int)

def main():
    args = parser.parse_args()
    uvicorn.run(
        'market.app:get_app',
        factory=True,
        host=args.app_host,
        port=args.app_port,
        reload=settings.is_debug
    )

if __name__ == '__main__':
    main()


import matplotlib.pyplot as plt
import numpy as np

def som(X_all, y_all, a, b, max_ep):
    cls, train_idx = np.unique(y_all, True)
    W = X_all[train_idx].astype(np.float64)
    X = np.array([x for i, x in enumerate(X_all) if i not in train_idx])
    y = np.array([y for i, y in enumerate(y_all) if i not in train_idx])
    hues = 'bo', 'go', 'ko', 'mo'
    dir = 'D:/LVQ'

    for i, c in enumerate(cls):
        x = X_all[y_all == c]
        plt.plot(x[:, 0], x[:, 1], hues[i])

    ep = 0

    plt.title('Data')
    plt.savefig('%s/0-0.png' % dir)

    plt.title('Bobot Awal')
    plt.plot(W[:, 0], W[:, 1], 'rX')
    plt.savefig('%s/0-1.png' % dir)
    plt.clf()

    while ep < max_ep:
        for i, x in enumerate(X):
            for i_, c in enumerate(cls):
                x_all = X_all[y_all == c]
                plt.plot(x_all[:, 0], x_all[:, 1], hues[i_])

            plt.title('Epoch: %d, data: %d' % (ep + 1, i + 1))
            plt.plot(W[:, 0], W[:, 1], 'rX')
            plt.plot(x[0], x[1], 'yD')
            plt.savefig('%s/%d-%da.png' % (dir, ep + 1, i + 1))
            plt.clf()

            d = [sum((w - x) ** 2) for w in W]
            min = np.argmin(d)
            s = 1 if y[i] == cls[min] else -1
            W[min] += s * a * (x - W[min])

            for i_, c in enumerate(cls):
                x_all = X_all[y_all == c]
                plt.plot(x_all[:, 0], x_all[:, 1], hues[i_])

            plt.title('Epoch: %d, data: %d' % (ep + 1, i + 1))
            plt.plot(W[:, 0], W[:, 1], 'rX')
            plt.savefig('%s/%d-%db.png' % (dir, ep + 1, i + 1))
            plt.clf()

        a *= b
        ep += 1

    return W

if __name__ == '__main__':
    x2 = np.array([[1.25, 1.25],
                   [1, 1],
                   [2, 1],
                   [1, 2],
                   [2, 2],
                   [3.25, 3.25],
                   [3, 3],
                   [4, 3],
                   [3, 4],
                   [4, 4]])

    x4 = np.array([[1.25, 3.25],
                   [1, 3],
                   [2, 3],
                   [1, 4],
                   [2, 4],
                   [3.25, 3.25],
                   [3, 3],
                   [4, 3],
                   [3, 4],
                   [4, 4],
                   [1.25, 1.25],
                   [1, 1],
                   [2, 1],
                   [1, 2],
                   [2, 2],
                   [3.25, 1.25],
                   [3, 1],
                   [4, 1],
                   [3, 2],
                   [4, 2]])

    y2 = np.array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2])
    y4 = np.array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4])

    R = 0
    a = .6
    b = .5
    w = som(x4, y4, a, b, 3)

    print(w)


import torch
from torch.utils.data import DataLoader
from torchvision.datasets import ImageFolder, CIFAR10
from torchvision import transforms
from torchvision.datasets.folder import *

class FilterableImageFolder(ImageFolder):
    def __init__(
            self,
            root: str,
            transform: Optional[Callable] = None,
            target_transform: Optional[Callable] = None,
            loader: Callable[[str], Any] = default_loader,
            is_valid_file: Optional[Callable[[str], bool]] = None,
            valid_classes: List = None
    ):
        self.valid_classes = valid_classes
        super(FilterableImageFolder, self).__init__(root, transform, target_transform, loader, is_valid_file)

    def find_classes(self, directory: str) -> Tuple[List[str], Dict[str, int]]:
        classes = sorted(entry.name for entry in os.scandir(directory) if entry.is_dir())
        #增加了这下面这句
        if self.valid_classes is not None:
            classes = [valid_class for valid_class in classes if valid_class in self.valid_classes]
        if not classes:
            raise FileNotFoundError(f"Couldn't find any class folder in {directory}.")

        class_to_idx = {cls_name: i for i, cls_name in enumerate(classes)}
        return classes, class_to_idx

def get_loader(
        data_dir,
        batch_size,
        image_size,
        random_flip=True,
        is_gray=False
):
    """
        For a dataset, create a generator over (images, kwargs) pairs.
        :param data_dir: a dataset directory.
        :param batch_size: the batch size of each returned pair.
        :param image_size: the size to which images are resized.
        :param random_flip: if True, randomly flip the images for augmentation.
        :param is_gray: if True, convert images to grayscale
        """
    tf = [transforms.Resize(image_size), transforms.ToTensor()]
    if random_flip:
        tf = [transforms.RandomHorizontalFlip()] + tf
    if is_gray:
        tf = [transforms.Grayscale(1)] + tf
    tf = transforms.Compose(tf)
    dataset = FilterableImageFolder(
        root=data_dir, transform=tf)

    dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
    return dataloader

if __name__ == "__main__":
    loader = get_loader("./dataset/images", 1, 256, is_gray=True)
    # tf = [transforms.ToTensor()]
    # tf = transforms.Compose(tf)
    # train_set = CIFAR10("./CIFAR10", train=True, download=False, transform=tf)
    # loader = DataLoader(
    #     train_set,
    #     batch_size=1,
    #     num_workers=0,
    # )
    for x, c in loader:
        print(c.cpu().numpy())
        # from torchvision.utils import save_image
        # save_image(x, "./a.png")
        break


import os
import argparse
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import backend as K
from ...lib.training import utils as trainutils

def main(
    patches_df_path,
    images_dir,
    min_threshold,
    base_model_name,
    x_col,
    y_col,
    epochs,
    batch_size,
    history_save_dir,
    model_save_dir,
    random_seed,
    rotation_range,
    width_shift_range,
    height_shift_range,
    zoom_range,
    horizontal_flip,
    vertical_flip,
    balanced_weights,
    previous_checkpoint,
    df_patches_val=""):

    aug_args = {
        "rotation_range": rotation_range,
        "width_shift_range": width_shift_range,
        "height_shift_range": height_shift_range,
        "zoom_range": zoom_range,
        "horizontal_flip": horizontal_flip,
        "vertical_flip": vertical_flip,
    }

    np.random.seed(random_seed)
    tf.set_random_seed(random_seed)

    model_path = os.path.join(
        model_save_dir,
        f"{base_model_name}_finetuned.h5",
    )
    folder, _ = os.path.split(model_path)
    os.makedirs(folder, exist_ok=True)

    patches_df = pd.read_csv(patches_df_path)
    patches_df = patches_df[~patches_df[y_col].isna()]
    patches_useful = patches_df[patches_df["Tissue"] > min_threshold]
    patches_useful = patches_df[patches_df["Artifact"] < 0.2]

    classes = sorted(patches_df[y_col].unique())
    print("Training with classes:", ", ".join(classes))

    train_df = patches_useful
    test_df = pd.read_csv(df_patches_val)

    model, history = trainutils.finetune_model(
        base_model_name,
        images_dir,
        train_df,
        test_df,
        classes,
        x_col,
        y_col,
        batch_size,
        epochs,
        balanced_weights,
        aug_args,
        random_seed,
        model_path,
        previous_checkpoint
    )

    history_path = os.path.join(
        history_save_dir,
        f"{base_model_name}_finetuned.csv",
    )

    model_path = os.path.join(
        model_save_dir,
        f"{base_model_name}_finetuned_end.h5",
    )

    trainutils.save_history(history, history_path)
    trainutils.save_model(model, model_path)
    K.clear_session()

if __name__ == "__main__":
    PARSER = argparse.ArgumentParser()
    PARSER.add_argument(
        "--patches_df_path",
        type=str,
        help="""\
        Ruta al archivo csv con los datos de los parches, indicando la cantidad
        de tejido, fondo y artefacto calculada para cada imagen.""",
        required=True,
    )
    PARSER.add_argument(
        "--images_dir",
        type=str,
        help="""\
        Directorio base donde se encuentran las imágenes.\
        """,
        required=True,
    )
    PARSER.add_argument(
        "--min_threshold",
        type=float,
        help="""\
        Umbral mínimo para el filtro de calidad.\
        """,
        required=True,
    )
    PARSER.add_argument(
        "--base_model_name",
        type=str,
        help="""\
        Nombre del modelo a usar en el entrenamiento. \
        """,
        choices=["inception-v3", "xception", "vgg16"],
        required=True,
    )
    PARSER.add_argument(
        "--x_col",
        type=str,
        help="""\
        Nombre de la columna del dataframe usada como input.\
        """,
        default="Filepath",
    )
    PARSER.add_argument(
        "--y_col",
        type=str,
        help="""\
        Nombre de la columna del dataframe usada como output.\
        """,
        default="Label",
    )
    PARSER.add_argument(
        "--epochs",
        type=int,
        help="""\
        Número de épocas de entrenamiento.\
        """,
        required=True,
    )
    PARSER.add_argument(
        "--batch_size",
        type=int,
        help="""\
        Tamaño de cada batch de entrenamiento.\
        """,
        default=32,
    )
    PARSER.add_argument(
        "--history_save_dir",
        type=str,
        help="""\
        Directorio donde se guardarán los historiales de entrenamiento.
        """,
        required=True,
    )
    PARSER.add_argument(
        "--model_save_dir",
        type=str,
        help="""\
        Directorio donde se guardarán los modelos ya entrenados.
        """,
        required=True,
    )
    PARSER.add_argument(
        "--random_seed",
        type=int,
        help="""\
        Semilla para obtener números aleatorios reproducibles.\
        """,
        default=0,
    )
    PARSER.add_argument(
        "--rotation_range",
        type=int,
        help="""\
        Rango de ángulo de rotación para data augmentation.\
        """,
        default=10,
    )
    PARSER.add_argument(
        "--width_shift_range",
        type=float,
        help="""\
        Rango de desplazamiento horizontal, entre 0 y 1, para data augmentation.\
        """,
        default=0.1,
    )
    PARSER.add_argument(
        "--height_shift_range",
        type=float,
        help="""\
        Rango de desplazamiento vertical, entre 0 y 1, para data augmentation.\
        """,
        default=0.1,
    )
    PARSER.add_argument(
        "--zoom_range",
        type=float,
        help="""\
        Rango de zoom para data augmentation.\
        """,
        default=0.1,
    )
    PARSER.add_argument(
        "--horizontal_flip",
        type=bool,
        help="""\
        True para voltear imágenes horizontalmente (data augmentation).\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--vertical_flip",
        type=bool,
        help="""\
        True para voltear imágenes verticalmente (data augmentation).\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--balanced_weights",
        type=bool,
        help="""\
        True para que se asigne pesos a las clases de tal forma de balancear el
        entrenamiento.\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--previous_checkpoint",
        type=str,
        help="""\
        Path con pesos del modelo a ajustar.\
        """,
        default=True,
    )
    PARSER.add_argument(
        "--df_patches_val",
        type=str,
        help="""\
        DataFrame con los patches a utilizar como validación para cada modelo.\
        """,
        default=True,
    )
    FLAGS = PARSER.parse_args()

    main(
        FLAGS.patches_df_path,
        FLAGS.images_dir,
        FLAGS.min_threshold,
        FLAGS.base_model_name,
        FLAGS.x_col,
        FLAGS.y_col,
        FLAGS.epochs,
        FLAGS.batch_size,
        FLAGS.history_save_dir,
        FLAGS.model_save_dir,
        FLAGS.random_seed,
        FLAGS.rotation_range,
        FLAGS.width_shift_range,
        FLAGS.height_shift_range,
        FLAGS.zoom_range,
        FLAGS.horizontal_flip,
        FLAGS.vertical_flip,
        FLAGS.balanced_weights,
        FLAGS.previous_checkpoint,
        FLAGS.df_patches_val
    )


from fastapi import Depends, APIRouter, HTTPException, BackgroundTasks, status
from sqlalchemy.orm import joinedload, selectinload
from sqlalchemy.ext.asyncio import AsyncSession

from backgrounds import task_clear_db_cache
from dependencies import ValidGetByIdDependency, valid_empty_schema
from routers.consts import RouteSlug
from models.database import get_session
from core.utils.decorators import cached
from core.utils.time_seconds import TimeSeconds
from entities.offer.models_offer import OfferModel, OfferInSchema
from entities.offer.choices_offer import OfferFilter
from entities.offer.schemas_offer import (
    OfferOptionalSchema,
    OfferFullResponseSchema,
)
from entities.offer.services_offer import OfferService
from entities.category.models_category import CategoryModel
from entities.service_name.models_service_name import ServiceNameModel

router_offer = APIRouter()
R_OFFER = '/offer/'

@router_offer.get(R_OFFER + RouteSlug.ifilter + RouteSlug.pk, response_model=list[OfferModel])
@cached(expire=TimeSeconds.M5, extra_keys=('pk', 'ifilter'))
async def view_filter_offer(ifilter: OfferFilter, pk: int, session: AsyncSession = Depends(get_session)):
    offers = await OfferService(db_session=session).filter(params=ifilter.get_filters(pk=pk))
    if not offers:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'item with id {pk} not found')
    return offers

@router_offer.get(R_OFFER + RouteSlug.full + RouteSlug.ifilter + RouteSlug.pk, response_model=OfferFullResponseSchema)
@cached(expire=TimeSeconds.M5, extra_keys=('pk', 'ifilter'))
async def view_filter_offer_full(ifilter: OfferFilter, pk: int, session: AsyncSession = Depends(get_session)):
    options = [
        joinedload(OfferModel.employee),
        selectinload(OfferModel.service_name).joinedload(ServiceNameModel.category),
    ]
    offer_service = OfferService(db_session=session)
    params = [
        *offer_service.parse_params(ifilter.get_filters(pk=pk)),
        CategoryModel.is_active == True,
    ]
    offers = await offer_service.filter(params=params, options=options, joins=[ServiceNameModel, CategoryModel])
    if not offers:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'item with id {pk} not found')
    return OfferFullResponseSchema.build(offers=offers)

@router_offer.post(R_OFFER, response_model=OfferModel)
async def view_add_offer(
    schema: OfferInSchema, background_tasks: BackgroundTasks, session: AsyncSession = Depends(get_session)
):
    result = await OfferService(db_session=session).add(schema=schema)
    background_tasks.add_task(task_clear_db_cache)
    return result

@router_offer.patch(R_OFFER + RouteSlug.pk, response_model=OfferModel)
async def view_patch_offer(
    background_tasks: BackgroundTasks,
    schema: OfferOptionalSchema = Depends(valid_empty_schema(class_schema=OfferOptionalSchema)),
    obj_db: OfferModel = Depends(ValidGetByIdDependency(class_service=OfferService)),
    session: AsyncSession = Depends(get_session),
):
    await OfferService(db_session=session).update(obj_db=obj_db, schema=schema)
    background_tasks.add_task(task_clear_db_cache)
    return obj_db

@router_offer.delete(R_OFFER + RouteSlug.pk, response_model=OfferModel)
async def view_delete_offer(
    background_tasks: BackgroundTasks,
    obj_db: OfferModel = Depends(ValidGetByIdDependency(class_service=OfferService)),
    session: AsyncSession = Depends(get_session),
):
    schema = OfferOptionalSchema(is_active=False)
    await OfferService(db_session=session).update(obj_db=obj_db, schema=schema)
    background_tasks.add_task(task_clear_db_cache)
    return obj_db


import sys
from collections import deque

N, M = map(int, input().split())
graph = [list(map(int, sys.stdin.readline().rstrip())) for _ in range(N)]
# visited[x][y][0] 는 벽 파괴 가능, visited[0][0][1]은 벽 파괴 불가능
visited = [[[0,0] for _ in range(M)] for _ in range(N)]
dx = [-1, 1, 0, 0]
dy = [0, 0, 1, -1]

def bfs():
    q = deque()
    q.append([0,0,0])
    visited[0][0][0] = 1

    while q:
        x, y, c = q.popleft()
        if x == N-1 and y == M-1 :
            return visited[x][y][c]
        for i in range(4):
            nx, ny = x + dx[i], y + dy[i]
            if 0 <= nx < N and 0 <= ny < M:
                if graph[nx][ny] == 0 and visited[nx][ny][c] == 0:
                    visited[nx][ny][c] = visited[x][y][c]+1
                    q.append([nx,ny,c])
                elif graph[nx][ny] == 1 and c == 0:
                    visited[nx][ny][1] = visited[x][y][c]+1
                    q.append([nx,ny,1])
    return -1
print(bfs())

백준/Gold/2206. 벽 부수고 이동하기/벽 부수고 이동하기.py

벽 부수고 이동하기.py


import json
import os
import sys

import falcon
import yaml
from django.core.wsgi import get_wsgi_application

from auth_service.utils.helper import validate_token
from clients.logger_client import LoggerClient
from clients.utils import convert_utc_into_ist

sys.path.append(os.pardir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'cricbett_db.settings'
get_wsgi_application()

from db.models import Match
from db.models import Player

class MatchService(object):
    """
    A Falcon service class that handles GET requests and filters a list of matches based on query parameters "match_type" and "match_status".
    GET /matches?&match_type=cricket&match_status=upcoming
    [
        {
            "match_name": "2nd ODI, IND v NZ",
            "match_status": "COMPLETED",
            "match_start_datetime": "2023-02-11T04:00:00Z",
            "match_end_datetime": null,
            "match_venue": "Raipur",
            "match_type": "CRICKET",
            "first_team": "INDIA",
            "second_team": "NEW ZEALAND",
            "match_id": 1
        }
    ]
    """

    def __init__(self, logger):
        """
        Initialize the MatchService class.

        :param logger: Logger client used for logging.
        """
        self.logger = logger

    @validate_token
    def on_get(self, req, resp, **kwargs):
        """
        Handles GET requests to the endpoint and filters the matches based on query parameters "match_type" and "match_status".
        If no query parameters are provided, it returns all the matches.

        :param req: Falcon request object.
        :param resp: Falcon response object.
        """
        try:
            match_type = req.params.get("match_type", "").upper()
            match_status = req.params.get("match_status", "").upper()

            matches = Match.objects.filter(
                match_type__contains=match_type, match_status__contains=match_status
            )
            response = []
            for match in matches:
                response.append(self.get_match_response(match))

            resp.status = falcon.HTTP_202
            resp.text = json.dumps(response)
            self.logger.info(
                f"MatchService: Successfully retrieved matches with match_type={match_type} and match_status={match_status}")
        except Exception as e:
            resp.status = falcon.HTTP_400
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"MatchService: Failed to retrieve matches: {e}")

    @staticmethod
    def get_match_response(match):
        match_start_datetime = convert_utc_into_ist(str(match.match_start_datetime))
        return {
            "match_id": str(match.match_id),
            "match_name": str(match.match_name),
            "match_status": str(match.match_status),
            "match_start_datetime": str(match_start_datetime),
            "match_venue": str(match.match_venue),
            "match_type": str(match.match_type),
            "first_team": str(match.first_team),
            "second_team": str(match.second_team)
        }

class MyGameService(object):
    """
    This class is responsible for handling the requests for getting the bookings related to a player.
    GET /my_games?game_status=live&match_type=football
    """

    def __init__(self, logger):
        """
        Initializes the service with a logger.

        :param logger: Logger client used for logging.
        """
        self.logger = logger

    @validate_token
    def on_get(self, req, resp, **kwargs):
        """
        Handles the GET request for getting the bookings related to a player.
        """
        token = kwargs.get("token")
        match_type = req.params.get("match_type", "").upper()
        game_status = req.params.get("game_status", "").upper()

        player = Player.objects.filter(token__token_id=token).first()
        if not player:
            self.logger.error(f"MyGameService: Player with token {token} not found")
            resp.status = falcon.HTTP_400
            resp.text = json.dumps({"error": "Invalid token"})
            return

        player_booking_set = player.booking_set.filter(
            game__game_status__contains=game_status,
            game__match__match_type__contains=match_type
        )

        my_bookings = {
            "player_id": player.player_id,
            "player_phone": player.phone,
            "player_games": [
                self.get_response_template(player_booking) for player_booking in player_booking_set
            ]
        }

        resp.status = falcon.HTTP_202
        resp.text = json.dumps(my_bookings)

    @staticmethod
    def get_response_template(player_booking):
        """
        Creates the response template for the contest details.
        """
        if player_booking.game.game_type == "WIN_PREDICT":
            game_start_time = convert_utc_into_ist(str(player_booking.game.match.match_start_datetime))
        else:
            game_start_time = convert_utc_into_ist(str(player_booking.game.match.match_start_datetime), 30)
        return {
            "game_id": player_booking.game.game_id,
            "match_name": player_booking.game.match.match_name,
            "match_type": player_booking.game.match.match_type,
            "game_start_time": str(game_start_time),
            "game_type": player_booking.game.game_type,
            "game_status": player_booking.game.game_status,
            "team_won": player_booking.game.team_won,
            "player_bid_price": str(player_booking.player_bid_price),
            "player_bid_team": player_booking.player_bid_team,
            "player_bid_multiplier": str(player_booking.player_bid_multiplier),
            "player_won_price": str(player_booking.player_won_price),
            "is_player_won": player_booking.is_player_won
        }

class RetrieveGamesByMatchService(object):
    """
    This class handles GET requests to the endpoint and returns the details of the games in a match
    GET /retrieve_game_by_match/{match_id}
    {
    "playerDetails": {
        "name": null,
        "email": "",
        "phone": "8709996580"
    },
    "games": [
        {
            "game_type": "WIN_PREDICT",
            "game_status": "COMPLETED",
            "first_team_bid_multiplier": "1.50",
            "second_team_bid_multiplier": "2.00",
            "match": 1,
            "game_id": 1
        },
        {
            "game_type": "TOSS_PREDICT",
            "game_status": "COMPLETED",
            "first_team_bid_multiplier": "1.80",
            "second_team_bid_multiplier": "1.70",
            "match": 1,
            "game_id": 2
        }
    ]
}
    """

    def __init__(self, logger):
        """
        Initializes the service with a logger.

        :param logger: Logger client used for logging.
        """
        self.logger = logger

    @validate_token
    def on_get(self, req, resp, **kwargs):
        """
        This method handles GET requests to the endpoint and returns the details of the games in a match
        """
        try:
            # Get the match_id from the request path
            match_id = kwargs.get("match_id")
            if match_id is None:
                # Raise an error if match_id is not provided
                raise ValueError("Missing match_id in request path")

            # Check if match with the provided id exists
            if Match.objects.filter(match_id=match_id).exists():
                match = Match.objects.get(match_id=match_id)
            else:
                # Raise an error if match with the provided id does not exist
                raise Match.DoesNotExist("Match with id {} does not exist".format(match_id))

            # All games in the match
            games_in_match = match.game_set.all()

            # Retrieve user details using token
            token = kwargs.get("token")
            player = Player.objects.filter(token__token_id=token).first()
            if not player:
                self.logger.error(f"MyGameService: Player with token {token} not found")
                resp.status = falcon.HTTP_400
                resp.text = json.dumps({"error": "Invalid token"})
                return

            # Prepare the response
            response = {"playerDetails": {"name": player.name, "email": player.email, "phone": player.phone},
                        "games": []}
            for game in games_in_match:
                response["games"].append(self.get_upcoming_resp(game))

            # Return a successful response
            resp.status = falcon.HTTP_202
            resp.text = json.dumps(response)
            self.logger.info(f"GET request to RetrieveGamesByMatchService endpoint successfully processed")
        except ValueError as e:
            # Handle missing match_id error
            resp.status = falcon.HTTP_400
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"Error in GET request to RetrieveGamesByMatchService endpoint: {str(e)}")
        except Match.DoesNotExist as e:
            # Handle non-existent match error
            resp.status = falcon.HTTP_404
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"Error in GET request to RetrieveGamesByMatchService endpoint: {str(e)}")
        except Exception as e:
            # Handle any other unexpected error
            resp.status = falcon.HTTP_500
            resp.text = json.dumps({"error": str(e)})
            self.logger.error(f"Error in GET request to RetrieveGamesByMatchService endpoint: {str(e)}")

    @staticmethod
    def get_upcoming_resp(game):
        if game.game_type == "WIN_PREDICT":
            game_start_time = convert_utc_into_ist(str(game.match.match_start_datetime))
        else:
            game_start_time = convert_utc_into_ist(str(game.match.match_start_datetime), 30)
        return {
            "game_id": game.game_id,
            "game_type": str(game.game_type),
            "game_status": str(game.game_status),
            "game_start_time": str(game_start_time),
            "first_team_bid_multiplier": str(game.first_team_bid_multiplier),
            "second_team_bid_multiplier": str(game.second_team_bid_multiplier),
            "match_name": str(game.match.match_name)
        }

class HealthCheck(object):
    """
    HealthCheck class, it is a Falcon web framework's resource class.
    """

    def on_get(self, req, resp):
        """
        Handles GET requests to the endpoint
        """
        resp.status = falcon.HTTP_200
        resp.text = json.dumps("OK")

def initialize_and_start_service(cfg, logger):
    app = falcon.App()

    matchService = MatchService(logger=logger)
    app.add_route('/matches', matchService)

    myGameService = MyGameService(logger=logger)
    app.add_route('/my_games', myGameService)

    # GET /retrieve_game_by_match/{match_id}
    retrieveGamesByMatch = RetrieveGamesByMatchService(logger=logger)
    app.add_route('/retrieve_games_by_match/{match_id}', retrieveGamesByMatch)

    healthCheck = HealthCheck()
    app.add_route('/healthcheck', healthCheck)

    logger.info("Cricbett-Feeds API is live now!")

    return app

# Load the configuration file
config_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "config/feeds_config.yaml")

# Open and read the configuration file into the config variable
with open(config_file, 'r') as cf:
    config = yaml.safe_load(cf)

# Setup LoggingClient by passing the config
logger_client = LoggerClient("cricbett-feeds", config)

# Initialize and start the service using the config
api = initialize_and_start_service(config, logger_client)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: ai ts=4 sts=4 et sw=4 nu

# Note that while the regex tester test Python 2.7 regex idioms,
# the code base itself has been made to be run on host with Python 2.6

import re
import sys
import os
import webbrowser
import json

from pprint import pformat
from operator import or_

ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
RUN_REGEX_SCRIPT = os.path.join(ROOT_DIR, 'run_regex.py')

try:
    import bottle
    import regex_tester
    ROOT_DIR = os.path.dirname(os.path.abspath(regex_tester.__file__))
    bottle.TEMPLATE_PATH.insert(0, os.path.join(ROOT_DIR, 'views'))
except ImportError:
    sys.path.insert(0, os.path.join(ROOT_DIR, 'libs'))
    import bottle

STATIC_FILES_ROOT = os.path.join(ROOT_DIR, 'static')

from clize import clize
from bottle import request, run, view, static_file, Bottle

from parallel import worker

DEBUG = False
TIMEOUT = 5
STATIC_FILES_ROOT = os.path.join(ROOT_DIR, 'static')
ENCODING = sys.stdout.encoding or 'utf-8'

CODES = {
    'search': """re.search(%(is_unicode)s%(is_raw)s'''%(regex)s''', %(is_unicode)s'''%(text)s'''%(flags_param)s)""",
    'split': """re.split(%(is_unicode)s%(is_raw)s'''%(regex)s''', %(is_unicode)s'''%(text)s'''%(flags_param)s)""",
    'findall': """re.findall(%(is_unicode)s%(is_raw)s'''%(regex)s''', %(is_unicode)s'''%(text)s'''%(flags_param)s)""",
    'match': """re.match(%(is_unicode)s%(is_raw)s'''%(regex)s''', %(is_unicode)s'''%(text)s'''%(flags_param)s)""",
    'sub': """re.sub(%(is_unicode)s%(is_raw)s'''%(regex)s''', %(is_unicode)s%(is_raw)s'''%(replace)s''', %(is_unicode)s'''%(text)s'''%(flags_param)s)""",
    'subn': """re.subn(%(is_unicode)s%(is_raw)s'''%(regex)s''', %(is_unicode)s%(is_raw)s'''%(replace)s''', %(is_unicode)s'''%(text)s'''%(flags_param)s)""",
}

FLAGS = dict((flag, getattr(re, flag)) for flag in (
    'IGNORECASE',
    'LOCALE',
    'MULTILINE',
    'DOTALL',
    'UNICODE',
    'VERBOSE'
))

DEFAULT = {
        'regex': '',
        'text': '',
        'replace': '',
        'is_unicode': '',
        'error': '',
        'code': '',
        'match': None,
        'function': 'search',
        'is_unicode': 'u',
        'is_raw': 'r',
        'markers': '[]',
        'flags_param': '',
        'group': (),
        'groupdict': {}
    }

@worker(timeout=TIMEOUT)
def run_regex(message):
    """
        Apply regex on text and return the results as a dictionary
    """

    regex = message['regex']
    function = message.get('function', 'search')
    replace = message.get('replace', '')
    isunicode = message.get('isunicode', False)
    flags = int(message.get('flags', 0))
    text = message.get('text', None)

    if isunicode:
        text = text.decode(ENCODING)
        regex = regex.decode(ENCODING)
        replace = regex.decode(ENCODING)

    pattern = re.compile(regex, flags=flags)

    try:
        if 'sub' in function:
            result = getattr(re, function)(pattern, replace, text)
        else:
            result = getattr(re, function)(pattern, text)
    except re.error as e:
        if text:
            raise e
        sys.exit(u'Error in your regular expression: %s' % e)

    out = {'match': bool(result)}

    if result:
        if hasattr(result, 'group'):
            out['group'] = pformat(result.group())
            out['groupdict'] = pformat(result.groupdict())
            markers = result.span()
        else:
            markers = (m.span() for m in re.finditer(regex, text, flags=flags))
            markers = (x for boundaries in markers for x in boundaries)

        out['markers'] = json.dumps(tuple(markers))

    return out

# todo: allow arguments functions surch as maxsplit for split

app = Bottle()

@app.get('/')
@view('index')
def index():
    ctx = dict(DEFAULT)
    ctx.update(dict((flag, False) for flag in FLAGS))
    return ctx

@app.post('/')
@view('index')
def index():

    forms = request.forms
    ctx = dict(DEFAULT)
    regex = forms.get('regex', '').decode('utf-8')
    text = forms.get('text', '').decode('utf-8')
    replace = forms.get('replace', '')
    is_unicode =  'u' * bool(forms.get('is_unicode', False))
    is_raw = 'r' * bool(forms.get('is_raw', False))
    function = forms.get('function', 'search')

    set_flags = dict((flag, bool(forms.get(flag))) for flag in FLAGS)
    ctx.update(set_flags)
    set_flags = set_flags.items()
    flags = reduce(or_, (FLAGS[flag] for flag, on in set_flags if on), 0)

    if function not in CODES:
        error = u'This function is not supported'

    ctx.update(locals())

    if regex.strip() and text.strip():

        if "'''" in regex:
            ctx['error'] = u"""
                        Regex containing ''' (triple single quotes) are
                        not supported
                            """
            return ctx

        if not is_raw:
            regex = regex.decode('unicode_escape')

        elif regex.endswith('\\'):
            ctx['error'] = u"""
                        Raw string litterals ending with '\\' are not supported
                        in Python
                           """
            return ctx

        app.regex_process.put(ctx)

        try:
            res = app.regex_process.get(True)
        except run_regex.TimeoutError:
            ctx['error'] = u"""
                                This regex took too much time to process. If
                                you want to experiment with heavy regexes,
                                download the stand alone version of the regex
                                tester, set the timeout to None and run it
                                on your machine.
                            """
        except Exception as e:
            ctx['error'] = unicode(e)
        else:
            if isinstance(res, Exception):
                ctx['error'] = unicode(res)
            else:
                ctx.update(res)

        if flags != 0:
            ctx['flags_param'] = ", flags=" + '|'.join('re.' + flag for flag, on in set_flags if on)
        ctx['code'] = CODES[function] % ctx

    return ctx

@app.route('/static/<filename>')
def server_static(filename):
    return static_file(filename, root=STATIC_FILES_ROOT)

@app.route('/download/<filename:path>')
def download(filename):
    return static_file(filename, root=STATIC_FILES_ROOT, download=filename)

@clize
def main(host='localhost', port=9999, debug=DEBUG, timeout=TIMEOUT):
    try:
        app.regex_process = run_regex.start()
        if debug:
            bottle.debug(True)
            run(app, host=host, port=port, reloader=True)
        else:
            webbrowser.open('http://%s:%s/' % (host, port))
            run(app, host=host, port=port)
    finally:
        app.regex_process.stop()

if __name__ == "__main__":
    main(*sys.argv)