import os
import cv2
import tqdm
from datetime import datetime
import argparse

from datasets.prepare_custom import get_custom_dataset, get_target_labels
from detectron2.engine import DefaultTrainer, DefaultPredictor
from detectron2.config import get_cfg
from detectron2.data import MetadataCatalog, DatasetCatalog
from detectron2 import model_zoo
from detectron2.utils.logger import setup_logger
from detectron2.evaluation import COCOEvaluator, inference_on_dataset
from detectron2.data import build_detection_test_loader
from detectron2.utils.video_visualizer import VideoVisualizer
from detectron2.utils.visualizer import ColorMode, Visualizer
from detectron2.checkpoint import DetectionCheckpointer

logger = setup_logger()

parser = argparse.ArgumentParser()
parser.add_argument('--mode', type=str, default='', help='ex) train')
parser.add_argument('--model', type=str, default='', help='ex) output_20200624_1655')

target = 'multi'

def set_dataset():
    for d in ["train", "test"]:
        DatasetCatalog.register("custom/" + d, lambda d=d: get_custom_dataset(target, "custom/" + d))
        MetadataCatalog.get("custom/" + d).set(thing_classes=get_target_labels()[target])

def set_config_custom(output_folder, mode, now_date):
    logger.debug(f" Set configs")
    config_custom = {
        'DATASET': '20200625_103328_8posture',
        'AUG_IN_DATASET': 'X',
        'CLASS_LIST': str(get_target_labels()[target]),
        'NUM_WORKERS': 2,
        # 2
        # Number of data loading threads

        'IMS_PER_BATCH': 2,
        # 2
        # Number of images per batch across all machines.
        # If we have 16 GPUs and IMS_PER_BATCH = 32,
        # each GPU will see 2 images per batch.

        'BASE_LR': 0.00025,
        # 0.00025

        'MAX_ITER': 30000,
        # 40000

        'BATCH_SIZE_PER_IMAGE': 512,
        # 256
        # RoI minibatch size *per image* (number of regions of interest [ROIs])
        # Total number of RoIs per training minibatch =
        #   ROI_HEADS.BATCH_SIZE_PER_IMAGE * SOLVER.IMS_PER_BATCH
        # E.g., a common configuration is: 512 * 16 = 8192
        'MODEL_WEIGHTS': 'COCO-InstanceSegmentation/mask_rcnn_X_101_32x8d_FPN_3x.yaml',
        'TEST_EVAL_PERIOD': 100
    }
    os.makedirs(os.path.join(output_folder, f'{now_date}_{mode}'), exist_ok=True)
    seq_path = os.path.join(output_folder, f'{now_date}_{mode}', f'config_custom.txt')
    wf = open(seq_path, 'w', newline='', encoding='utf-8')
    for k, v in config_custom.items():
        wf.write(f'{str(k)}: {str(v)}\n')
    wf.write(f'\n')
    wf.write(f'TARGET_OBJECT: {str(target)}\n')
    wf.write(f'START_TIME: {str(datetime.now())}\n')
    wf.close()

    return config_custom

def set_config_all(cfg, config_custom, output_folder, mode, now_date):
    ## 1. https://rosenfelder.ai/Instance_Image_Segmentation_for_Window_and_Building_Detection_with_detectron2/
    cfg.merge_from_file(f'./configs/{config_custom["MODEL_WEIGHTS"]}')
    cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(config_custom["MODEL_WEIGHTS"])

    ## 2. https://towardsdatascience.com/detectron2-the-basic-end-to-end-tutorial-5ac90e2f90e3
    # cfg.merge_from_file(model_zoo.get_config_file("COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml"))
    # cfg.MODEL.WEIGHTS = "detectron2://COCO-Detection/faster_rcnn_R_50_FPN_3x/137849458/model_final_280758.pkl"

    cfg.DATASETS.TRAIN = ("custom/train",)
    cfg.DATASETS.TEST = ()
    # cfg.DATASETS.TEST = ()  # no metrics implemented for this dataset
    cfg.DATALOADER.NUM_WORKERS = config_custom['NUM_WORKERS']
    cfg.SOLVER.IMS_PER_BATCH = (
        config_custom['IMS_PER_BATCH']
    )
    cfg.SOLVER.BASE_LR = (
        config_custom['BASE_LR']
    )
    # cfg.SOLVER.WARMUP_ITERS = 1000 # the learning rate starts from 0 and goes to the preset one for this number of iterations
    cfg.SOLVER.MAX_ITER = (
        config_custom['MAX_ITER']
    )
    # cfg.SOLVER.STEPS = (1000, 1500) # the checkpoints (number of iterations) at which the learning rate will be reduced by GAMMA
    # cfg.SOLVER.GAMMA = 0.05
    cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = (
        config_custom['BATCH_SIZE_PER_IMAGE']
    )
    cfg.MODEL.ROI_HEADS.NUM_CLASSES = len(get_target_labels()[target])  # 4 action class (none,eating,peeing,pooping)
    # cfg.MODEL.DEVICE = "cuda:0,1"
    cfg.TEST.EVAL_PERIOD = config_custom['TEST_EVAL_PERIOD']

    cfg.OUTPUT_DIR=output_folder
    ## write config list
    seq_path = os.path.join(output_folder, f'{now_date}_{mode}', f'config_all.txt')
    wf = open(seq_path, 'w', newline='', encoding='utf-8')
    wf.write(f'{str(cfg)}')
    wf.close()

    return cfg

def train_model(cfg, output_folder, mode, now_date):
    logger.debug(f" Start train model")
    trainer = DefaultTrainer(cfg)
    trainer.resume_or_load(resume=False)
    trainer.train()

    # trainer.register_hooks(
    #     [hooks.EvalHook(0, lambda: test_with_TTA(cfg, trainer.model))]
    # )
    # 실시간 로스율 계산하기 참고: https://medium.com/@apofeniaco/training-on-detectron2-with-a-validation-set-and-plot-loss-on-it-to-avoid-overfitting-6449418fbf4e

    seq_path = os.path.join(output_folder, f"{now_date}_{mode}", f'config_custom.txt')
    wf = open(seq_path, 'a', newline='', encoding='utf-8')
    wf.write(f'END_TIME_TRAIN: {str(datetime.now())}\n')
    logger.debug(f" End to train:{str(datetime.now())}")
    wf.close()

    return True

def make_prediction_image(cfg, output_folder, mode, now_date):
    logger.debug(f" Start evaluating image")
    os.makedirs(os.path.join(output_folder, f"{now_date}_{mode}", f"prediction_{target}"), exist_ok=True)

    cfg.MODEL.WEIGHTS = os.path.join(output_folder, "model_final.pth")
    cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7  # set the testing threshold for this model
    cfg.DATASETS.TEST = ("custom/test",)

    # Evaluate test datasets
    model = DefaultTrainer(cfg).build_model(cfg)
    DetectionCheckpointer(model, save_dir=output_folder).resume_or_load(cfg.MODEL.WEIGHTS, resume=False)

    evaluator = COCOEvaluator("custom/test", cfg, False,
                              output_dir=os.path.join(output_folder, f"{now_date}_{mode}", 'COCO_eval'))
    val_loader = build_detection_test_loader(cfg, "custom/test")
    order_dicts = inference_on_dataset(DefaultTrainer(cfg).model, val_loader, evaluator)

    seq_path = os.path.join(output_folder, f"{now_date}_{mode}", f'eval_result.txt')
    wf = open(seq_path, 'w', newline='', encoding='utf-8')
    wf.write(f'{str(order_dicts)}:\n')
    wf.close()

    # Predict test dataset
    predictor = DefaultPredictor(cfg)
    dataset_dicts = get_custom_dataset(target, "custom/test")
    for i, d in enumerate(dataset_dicts):
        logger.debug(f"predicting...{d['file_name']}")
        im = cv2.imread(d["file_name"])
        file_name = os.path.basename(d["file_name"])
        outputs = predictor(im)

        ## 1 https://rosenfelder.ai/Instance_Image_Segmentation_for_Window_and_Building_Detection_with_detectron2/
        v = Visualizer(
            im[:, :, ::-1],
            metadata=MetadataCatalog.get("custom/test"),
            scale=1,
            instance_mode=ColorMode.IMAGE_BW,  # remove the colors of unsegmented pixels
        )

        v = v.draw_instance_predictions(outputs["instances"].to("cpu"))
        cv2.imwrite(os.path.join(output_folder, f"{now_date}_{mode}", f"prediction_{target}", file_name),
                    v.get_image())

    logger.debug(f" End evaluating image")

    seq_path = os.path.join(output_folder, f"{now_date}_{mode}", f'config_custom.txt')
    wf = open(seq_path, 'a', newline='', encoding='utf-8')
    wf.write(f'END_TIME_EVAL_IMAGE: {str(datetime.now())}\n')
    logger.debug(f" End to train:{str(datetime.now())}")
    wf.close()

    return True

# https://stackoverflow.com/questions/60663073/how-can-i-properly-run-detectron2-on-videos
def make_prediction_video(cfg, output_folder, mode, now_date):
    logger.debug(f" Start evaluating video")

    # Extract video properties
    video = cv2.VideoCapture('./test_video.mp4')
    width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
    frames_per_second = video.get(cv2.CAP_PROP_FPS)
    num_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))

    # Initialize video writer
    video_writer = cv2.VideoWriter(os.path.join(output_folder, f"{now_date}_{mode}", f'test_result.mp4'),
                                   fourcc=cv2.VideoWriter_fourcc(*"mp4v"), fps=float(frames_per_second),
                                   frameSize=(width, height), isColor=True)

    # Initialize predictor
    cfg.MODEL.WEIGHTS = os.path.join(output_folder, "model_final.pth")
    cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7  # set the testing threshold for this model
    cfg.DATASETS.TEST = ("custom/test",)
    predictor = DefaultPredictor(cfg)

    # Initialize visualizer
    v = VideoVisualizer(MetadataCatalog.get("custom/test"), ColorMode.IMAGE)

    # Create a cut-off for debugging
    # num_frames = 5000

    # Enumerate the frames of the video
    for visualization in tqdm.tqdm(run_on_video(video, v, num_frames, predictor), total=num_frames):
        # Write test image
        # cv2.imwrite(os.path.join(output_folder, 'test_result.png'), visualization)

        # Write to video file
        video_writer.write(visualization)

    # Release resources
    video.release()
    video_writer.release()
    # cv2.destroyAllWindows()
    logger.debug(f" End evaluating video")

    seq_path = os.path.join(output_folder, f"{now_date}_{mode}", f'config_custom.txt')
    wf = open(seq_path, 'a', newline='', encoding='utf-8')
    wf.write(f'END_TIME_EVAL_VIDEO: {str(datetime.now())}\n')
    logger.debug(f" End to train:{str(datetime.now())}")
    wf.close()

    return True

def run_on_video(video, v, maxFrames, predictor):
    """ Runs the predictor on every frame in the video (unless maxFrames is given),
    and returns the frame with the predictions drawn.
    """
    readFrames = 0
    while True:
        hasFrame, frame = video.read()

        if not hasFrame:
            break

        # Get prediction results for this frame
        outputs = predictor(frame)
        # Make sure the frame is colored
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
        # Draw a visualization of the predictions using the video visualizer
        visualization = v.draw_instance_predictions(frame, outputs["instances"].to("cpu"))
        # Convert Matplotlib RGB format to OpenCV BGR format
        visualization = cv2.cvtColor(visualization.get_image(), cv2.COLOR_RGB2BGR)
        yield visualization
        readFrames += 1
        if readFrames > maxFrames:
            break

def init(mode, model=None):
    cfg_origin = get_cfg()
    today_date = datetime.now().strftime("%Y%m%d_%H%M")
    if model is not None and model != '':
        output_folder = os.path.splitext(cfg_origin.OUTPUT_DIR)[0].replace('output', model)
    else:
        output_folder = os.path.join(f'{cfg_origin.OUTPUT_DIR}_{today_date}_{target}')
        os.makedirs(output_folder, exist_ok=True)

    config_custom = set_config_custom(output_folder, mode, now_date)
    cfg = set_config_all(cfg_origin, config_custom, output_folder, mode, now_date)

    return cfg, output_folder

if __name__ == "__main__":
    # os.environ["CUDA_VISIBLE_DEVICES"] = "0,1"
    args = parser.parse_args()
    mode = args.mode
    model = args.model
    now_date = datetime.now().strftime("%Y%m%d_%H%M")
    cfg, output_folder = init(mode, model)

    set_dataset()
    if mode == 'train':
        train_model(cfg, output_folder, mode, now_date)
        make_prediction_image(cfg, output_folder, mode, now_date)
        make_prediction_video(cfg, output_folder, mode, now_date)
    elif mode == 'predict_image':
        make_prediction_image(cfg, output_folder, mode, now_date)
    elif mode == 'predict_video':
        make_prediction_video(cfg, output_folder, mode, now_date)


from pattern_loadings import one_order_pattern, two_order_pattern, squared_pattern
from layer_mirroring import mirroring_layer
from labels import labeling
from centering import centering
from stretching import stretching

# GENERATING THE OUTPUT BOX LISTS IN 2 DIMENSIONS FOR THE 3 ALGORITHMS, BOTH FOR THE FIRST AND SECOND LAYER,
# BASED ON THE INFORMATION GETTING FROM THE PATTERN LOADING FUNCTIONS

# GENERATING THE OUTPUT BOX LIST FOR THE ONE-ORDER PATTERN:
def generate_boxes_oop(pallet_x, pallet_y, box_x, box_y, middle=False, stretch=False,
                       label_side="None", label_place="None", gap=0):
    output_box_list = []
    output_box_list_rotated = []

    box_x = box_x + gap / 2
    box_y = box_y + gap / 2

    # Getting the information from the pattern loading functions about how many boxes we can put on the pallet
    # for both orders
    result_oop_0 = one_order_pattern(pallet_x, pallet_y, box_x, box_y, 0)
    result_oop_1 = one_order_pattern(pallet_x, pallet_y, box_x, box_y, 1)

    # Checking which order performed better
    if result_oop_0[0] >= result_oop_1[0]:
        orientation = 0
        rotated = 1
        box_0 = box_x
        box_1 = box_y
    else:
        orientation = 1
        rotated = 0
        box_0 = box_y
        box_1 = box_x

    # ---------LAYER 1--------- #
    # Using the orientation with the MORE boxes and calculating how many boxes we can put along the X and Y dimensions
    # of the pallet
    result_oop = one_order_pattern(pallet_x, pallet_y, box_x, box_y, orientation)
    num_x = result_oop[2]
    num_y = result_oop[3]

    # Generating the output box list for the one order pattern FIRST LAYER based on the calculated values
    for i in range(num_x):
        box_coordinate = [0, 0, 0, orientation]
        box_coordinate[0] = box_0 * i + box_0 / 2
        for j in range(num_y):
            box_coordinate = [box_coordinate[0], 0, 0, orientation]
            box_coordinate[1] = box_1 * j + box_1 / 2
            output_box_list.append(box_coordinate)

    # Making a rotated second layer, which has all of the boxes in the other order

    # ---------LAYER 2--------- #
    # Using the orientation with the LESS boxes and calculating how many boxes we can put along the X and Y dimensions
    # of the pallet
    result_oop_rotated = one_order_pattern(pallet_x, pallet_y, box_x, box_y, rotated)
    num_x_rotated = result_oop_rotated[2]
    num_y_rotated = result_oop_rotated[3]

    # Generating the output box list for the one order pattern SECOND LAYER (rotated) based on the calculated values
    for i in range(num_x_rotated):
        box_coordinate_rotated = [0, 0, 0, rotated]
        box_coordinate_rotated[0] = box_1 * i + box_1 / 2
        for j in range(num_y_rotated):
            box_coordinate_rotated = [box_coordinate_rotated[0], 0, 0, rotated]
            box_coordinate_rotated[1] = box_0 * j + box_0 / 2
            output_box_list_rotated.append(box_coordinate_rotated)

    # --------- CENTERING --------- #
    # Aligning the pattern to the middle of the pallet
    # Centering the first and second layer
    if middle and len(output_box_list) > 0:
        output_box_list = centering(output_box_list, pallet_x, pallet_y, box_x, box_y)
        output_box_list_rotated = centering(output_box_list_rotated, pallet_x, pallet_y, box_x, box_y)

    # --------- LABELING --------- #
    # Labeling the first and second layer as well
    if label_side != "None" and label_place != "None":
        output_box_list = labeling(output_box_list, label_side, label_place, box_x, box_y)
        output_box_list_rotated = labeling(output_box_list_rotated, label_side, label_place, box_x, box_y)

    for box in output_box_list:
        box[0] = round(box[0], 4)
        box[1] = round(box[1], 4)
    for box in output_box_list_rotated:
        box[0] = round(box[0], 4)
        box[1] = round(box[1], 4)

    return [output_box_list, output_box_list_rotated]

# GENERATING THE OUTPUT BOX LIST FOR THE TWO-ORDER PATTERN:
def generate_boxes_top(pallet_x, pallet_y, box_x, box_y, middle=False,
                       label_side="None", label_place="None", x=True, y=True, gap=0):
    output_box_list = []

    box_x = box_x + gap / 2
    box_y = box_y + gap / 2

    # Getting the two-order pattern results for both starting orientations
    result_top_1 = two_order_pattern(pallet_x, pallet_y, box_x, box_y, 0)
    result_top_2 = two_order_pattern(pallet_x, pallet_y, box_x, box_y, 1)

    # Selecting the best two-order patterns for the two orientations
    # If more patterns give the same number of boxes then choose the one with the most mixed orientation combination
    # for more stable second layer if we want to mirror it
    pattern_index_o1 = 0
    pattern_index_o2 = 0
    for i in range(len(result_top_1)):
        if result_top_1[pattern_index_o1][4] <= result_top_1[i][4]:
            pattern_index_o1 = i
    for i in range(len(result_top_2)):
        if result_top_2[pattern_index_o2][4] <= result_top_2[i][4]:
            pattern_index_o2 = i

    # Selecting the better from the 2 two-order pattern solution
    if result_top_1[pattern_index_o1][4] >= result_top_2[pattern_index_o2][4]:
        orientation_1 = 0
        orientation_2 = 1
        box_0 = box_x
        box_1 = box_y
        pattern_index = pattern_index_o1
    else:
        orientation_1 = 1
        orientation_2 = 0
        box_0 = box_y
        box_1 = box_x
        pattern_index = pattern_index_o2

    # Finalizing the selected two-order pattern and having the information about how much boxes we can put along
    # the X and Y dimensions of the pallet in both orders
    result_top = two_order_pattern(pallet_x, pallet_y, box_x, box_y, orientation_1)
    num_x_o1 = result_top[pattern_index][0]
    num_y_o1 = result_top[pattern_index][1]
    num_x_o2 = result_top[pattern_index][2]
    num_y_o2 = result_top[pattern_index][3]

    x_start = num_x_o1 * box_0  # Starting x coordinate for the 2. order (offsetting with the width of the 1. order)

    # --------- ALIGNING THE TWO ORDERS --------- #
    # checking if there is remaining space at the end of the columns or not and splitting them if there is
    rem_space_y = num_y_o1 * box_1 - num_y_o2 * box_0  # Calculating the remaining space along the pallet Y dimension

    # Checking if the first or second order hangs beyond the Y dimension relative to the other and calculating the
    # spacing for it
    o1_spacing = 0
    o2_spacing = 0
    if rem_space_y < 0:
        if num_y_o1 - 1 != 0:
            o1_spacing = abs(rem_space_y / (num_y_o1 - 1))
    elif rem_space_y > 0:
        if num_y_o2 - 1 != 0:
            o2_spacing = rem_space_y / (num_y_o2 - 1)

    # --------- FIRST LAYER --------- #

    # Making the output box list for the first layer for the first order (including the aligning)
    for i in range(num_x_o1):
        box_coordinate = [0, 0, 0, orientation_1]
        box_coordinate[0] = box_0 * i + box_0 / 2
        for j in range(num_y_o1):
            box_coordinate = [box_coordinate[0], 0, 0, orientation_1]
            box_coordinate[1] = o1_spacing * j + box_1 * j + box_1 / 2
            output_box_list.append(box_coordinate)

    # Extending the output box list for the first layer with the second order (including the aligning)
    for i in range(num_x_o2):
        box_coordinate = [0, 0, 0, orientation_2]
        box_coordinate[0] = x_start + box_1 * i + box_1 / 2
        for j in range(num_y_o2):
            box_coordinate = [box_coordinate[0], 0, 0, orientation_2]
            box_coordinate[1] = o2_spacing * j + box_0 * j + box_0 / 2
            output_box_list.append(box_coordinate)

    # --------- CENTERING --------- #

    if middle and len(output_box_list) > 0:
        output_box_list = centering(output_box_list, pallet_x, pallet_y, box_x, box_y)

    # --------- SECOND LAYER --------- #
    # Making a second layer from the first layer by mirroring it
    output_box_list_mirrored = mirroring_layer(output_box_list, x, y, pallet_x, pallet_y, box_x, box_y, middle)

    # --------- LABELING --------- #
    # Rotating the boxes in the first and second layer to put the labels in the desired directions
    if label_side != "None" and label_place != "None":
        output_box_list = labeling(output_box_list, label_side, label_place, box_x, box_y)
        output_box_list_mirrored = labeling(output_box_list_mirrored, label_side, label_place, box_x, box_y)

    for box in output_box_list:
        box[0] = round(box[0], 4)
        box[1] = round(box[1], 4)
    for box in output_box_list_mirrored:
        box[0] = round(box[0], 4)
        box[1] = round(box[1], 4)

    return [output_box_list, output_box_list_mirrored]

# GENERATING THE OUTPUT BOX LIST FOR THE SQUARED PATTERN:
def generate_boxes_sp(pallet_x, pallet_y, box_x, box_y, middle=False, stretch=False,
                      label_side="None", label_place="None", x=True, y=True, gap=0):
    output_box_list = []

    box_x = box_x + gap / 2
    box_y = box_y + gap / 2

    # Getting the squared pattern results
    result_sp = squared_pattern(pallet_x, pallet_y, box_x, box_y)

    # Getting how many squares we can put in a row (pallet X dim) and in a col (pallet Y dim)
    num_squares_row = result_sp[2]
    num_squares_col = result_sp[3]

    # Checking the remaining space besides the squares with boxes
    rem_space_x_1 = result_sp[4]
    rem_space_y_1 = result_sp[5]
    rem_space_x_2 = result_sp[6]
    rem_space_y_2 = result_sp[7]

    splitting = result_sp[8]  # The split remaining space is bigger along the x dim or the y dim

    # Filling the remaining spaces with the oop function
    filling_1 = generate_boxes_oop(rem_space_x_1, rem_space_y_1, box_x, box_y)[0]
    filling_2 = generate_boxes_oop(rem_space_x_2, rem_space_y_2, box_x, box_y)[0]

    num_box_x_filling1 = 0
    num_box_y_filling1 = 0
    num_box_x_filling2 = 0
    num_box_y_filling2 = 0

    # Checking the orientation of the boxes in filling 1
    if len(filling_1) != 0:
        if filling_1[0][0] == box_x / 2:
            orientation_filling1 = 0
            box_side_split_1 = box_x
        else:
            orientation_filling1 = 1
            box_side_split_1 = box_y
        filling1_oop = one_order_pattern(rem_space_x_1, rem_space_y_1, box_x, box_y, orientation_filling1)
        num_box_x_filling1 = filling1_oop[2]
        num_box_y_filling1 = filling1_oop[3]

    # Checking the orientation of the boxes in filling 2
    if len(filling_2) != 0:
        if filling_2[0][0] == box_x / 2:
            orientation_filling2 = 0
            not_box_side_split_2 = box_y
        else:
            orientation_filling2 = 1
            not_box_side_split_2 = box_x

    # Offsetting the fillings with the width and height of the square block
    for box in filling_1:
        box[1] += num_squares_col * (box_x + box_y)

    for box in filling_2:
        box[0] += num_squares_row * (box_x + box_y)

    # checking if there is remaining space at the end of the rows and columns or not and splitting them
    # (comparing the square block to the oop fillings)

    # Calculating the number of boxes in a row in the two fillings
    num_box_in_row_filling1 = 0
    num_box_in_row_filling2 = 0
    for box in filling_1:
        if box[1] == filling_1[0][1]:
            num_box_in_row_filling1 += 1
    for box in filling_2:
        if box[1] == filling_2[0][1]:
            num_box_in_row_filling2 += 1

    # Calculating the number of boxes in a column in the two fillings
    num_box_in_col_filling_1 = 0
    num_box_in_col_filling_2 = 0
    for box in filling_1:
        if box[0] == filling_1[0][0]:
            num_box_in_col_filling_1 += 1
    for box in filling_2:
        if box[0] == filling_2[0][0]:
            num_box_in_col_filling_2 += 1

    # Calculating the number of rows in the filling 1
    num_rows = 0
    for box in filling_1:
        if box[0] - box_side_split_1 / 2 == 0:
            num_rows += 1
    # Calculating the number of columns in the filling 2
    num_cols = 0
    for box in filling_2:
        if box[1] - not_box_side_split_2 / 2 == 0:
            num_cols += 1

    # Defining the box dimensions in filling 1 along the pallet X and Y dimensions
    if len(filling_1) != 0:
        if filling_1[0][3] == 0:
            box_f1_x = box_x
            box_f1_y = box_y
        elif filling_1[0][3] == 1:
            box_f1_x = box_y
            box_f1_y = box_x
    else:
        box_f1_x = 0
        box_f1_y = 0

    # Defining the box dimensions in filling 2 along the pallet X and Y dimensions
    if len(filling_2) != 0:
        if filling_2[0][3] == 0:
            box_f2_x = box_x
            box_f2_y = box_y
        elif filling_2[0][3] == 1:
            box_f2_x = box_y
            box_f2_y = box_x
    else:
        box_f2_x = 0
        box_f2_y = 0

    # Calculating the remaining space along the X and Y dimensions of the pallet based on which splitting part
    # is bigger, the one along the X dimension (splitting 1) or the other along the Y dimension (splitting 2)
    if splitting == "x":
        remaining_space_x = num_squares_row * (box_x + box_y) + num_cols * box_f2_x - num_box_in_row_filling1 * box_f1_x
        remaining_space_y = num_squares_col * (box_x + box_y) - num_box_in_col_filling_2 * box_f2_y
    elif splitting == "y":
        remaining_space_x = num_squares_row * (box_x + box_y) - num_box_in_row_filling1 * box_f1_x
        remaining_space_y = num_squares_col * (
                box_x + box_y) + num_rows * box_f1_y - num_box_in_col_filling_2 * box_f2_y

    # --------- SPACING --------- #
    # Calculating the spacings along X dimension of the pallet
    square_and_row_spacing_x = 0  # The spacing for the squares and rows (splitting 1) along the X dimension
    row_spacing_f1_x = 0  # The spacing
    col_spacing_f2_x = 0
    if remaining_space_x < 0:
        if num_squares_row + num_cols - 1 != 0: # When the filling 1 is wider than the squares and cols together
            square_and_row_spacing_x = abs(remaining_space_x) / (num_squares_row + num_cols - 1)
            col_spacing_f2_x = abs(remaining_space_x) / (num_squares_row + num_cols - 1)
    elif remaining_space_x > 0:  # When the squares and cols together is wider than the filling 1
        if num_box_in_row_filling1 - 1 != 0:
            row_spacing_f1_x = remaining_space_x / (num_box_in_row_filling1 - 1)

    # Calculating the spacing along the Y dimension of the pallet
    square_spacing_y = 0
    col_spacing_f2_y = 0
    row_spacing_f1_y = 0
    if remaining_space_y < 0:
        if num_squares_col + num_rows - 1 != 0:
            square_spacing_y = abs(remaining_space_y / (num_squares_col + num_rows - 1))
            row_spacing_f1_y = abs(remaining_space_y / (num_squares_col + num_rows - 1))
    elif remaining_space_y > 0:
        if num_box_in_col_filling_2 - 1 != 0:
            col_spacing_f2_y = remaining_space_y / (num_box_in_col_filling_2 - 1)

    # --------- SQUARES --------- #
    # Making the box coordinates for the first of four elements of the box squares
    for i in range(num_squares_row):
        box_coordinate = [0, 0, 0, 0]
        box_coordinate[0] = box_x * i + box_y * i + square_and_row_spacing_x * i + box_x / 2
        for j in range(num_squares_col):
            box_coordinate = [box_coordinate[0], 0, 0, 0]
            box_coordinate[1] = box_x * j + box_y * j + square_spacing_y * j + box_y / 2
            output_box_list.append(box_coordinate)

    # Making the box coordinates for the second of four elements of the box squares
    for i in range(num_squares_row):
        box_coordinate = [box_x, 0, 0, 1]
        box_coordinate[0] = box_x + box_x * i + box_y * i + square_and_row_spacing_x * i + box_y / 2
        for j in range(num_squares_col):
            box_coordinate = [box_coordinate[0], box_y, 0, 1]
            box_coordinate[1] = box_x * j + box_y * j + square_spacing_y * j + box_x / 2
            output_box_list.append(box_coordinate)

    # Making the box coordinates for the third of four elements of the box squares
    for i in range(num_squares_row):
        box_coordinate = [0, box_y, 0, 1]
        box_coordinate[0] = box_x * i + box_y * i + square_and_row_spacing_x * i + box_y / 2
        for j in range(num_squares_col):
            box_coordinate = [box_coordinate[0], box_y, 0, 1]
            box_coordinate[1] = box_y + box_x * j + box_y * j + square_spacing_y * j + box_x / 2
            output_box_list.append(box_coordinate)

    # Making the box coordinates for the first element of the box squares
    for i in range(num_squares_row):
        box_coordinate = [box_y, box_x, 0, 0]
        box_coordinate[0] = box_y + box_x * i + box_y * i + square_and_row_spacing_x * i + box_x / 2
        for j in range(num_squares_col):
            box_coordinate = [box_coordinate[0], box_x, 0, 0]
            box_coordinate[1] = box_x + box_x * j + box_y * j + square_spacing_y * j + box_y / 2
            output_box_list.append(box_coordinate)

    # --------- FILLINGS --------- #
    # Making the box coordinates for the filling1
    i = 0
    k = 0
    for x_i in range(num_box_in_row_filling1):
        for y_i in range(num_box_in_col_filling_1):
            filling_1[i][1] += row_spacing_f1_y * (y_i + num_squares_col - 1 + 1)
            filling_1[i][0] += row_spacing_f1_x * k
            i += 1
        k += 1

    # Making the box coordinates for the filling2
    j = 0
    for x_j in range(num_box_in_row_filling2):
        m = 0
        for y_j in range(num_box_in_col_filling_2):
            filling_2[j][0] += col_spacing_f2_x * (x_j + num_squares_row - 1 + 1)
            filling_2[j][1] += col_spacing_f2_y * m
            j += 1
            m += 1

    # Adding filling1 and filling2 boxes to the output box list
    output_box_list.extend(filling_1)
    output_box_list.extend(filling_2)

    # --------- CENTERING --------- #
    if middle and len(output_box_list) > 0:
        output_box_list = centering(output_box_list, pallet_x, pallet_y, box_x, box_y)

    # --------- SECOND LAYER --------- #
    # Making a second layer from the first layer by mirroring it
    output_box_list_mirrored = mirroring_layer(output_box_list, x, y, pallet_x, pallet_y, box_x, box_y, middle)

    # --------- LABELING --------- #
    # Rotating the boxes in the first and second layer to put the labels in the desired directions
    if label_side != "None" and label_place != "None":
        output_box_list = labeling(output_box_list, label_side, label_place, box_x, box_y)
        output_box_list_mirrored = labeling(output_box_list_mirrored, label_side, label_place, box_x, box_y)

    for box in output_box_list:
        box[0] = round(box[0], 4)
        box[1] = round(box[1], 4)
    for box in output_box_list_mirrored:
        box[0] = round(box[0], 4)
        box[1] = round(box[1], 4)

    return [output_box_list, output_box_list_mirrored]


import lump
import line
import vertex
import sqlite3
import contextlib

def create_line_schema(conn):
    conn.execute("DROP TABLE IF EXISTS Line")
    conn.execute("""
    CREATE TABLE IF NOT EXISTS Line(
      line_id INTEGER PRIMARY KEY,
      v1 INTEGER,
      v2 INTEGER,
      FOREIGN KEY(v1) REFERENCES Vertex (vertex_id),
      FOREIGN KEY(v2) REFERENCES Vertex (vertex_id)
    )""")

def create_vertex_schema(conn):
    conn.execute("DROP TABLE IF EXISTS Vertex")
    conn.execute("""
    CREATE TABLE IF NOT EXISTS Vertex(
       vertex_id INTEGER PRIMARY KEY,
       x, y INTEGER
    )""")

def _build_vertex_table(conn):
    conn.executemany("""
    INSERT INTO Vertex (vertex_id, x, y)
    VALUES (:vertex_id, :x, :y)
    """,vertex.do_read())

def _build_line_table(conn):
    fix_line = lambda line_entry: dict(line_id=line_entry.line_id,
                                       v1=line_entry.v1,
                                       v2=line_entry.v2)
    conn.executemany("""
    INSERT INTO Line (line_id, v1, v2)
    VALUES (:line_id, :v1, :v2)
    """, map(fix_line, line.do_read()))

@contextlib.contextmanager
def awesome_manager(filename, foreign_keys=True):
    with sqlite3.connect(filename) as conn:
        if foreign_keys:
            conn.execute("PRAGMA foreign_keys=ON")
        yield conn

def build_level_data():
    lump.build_lump_database()

    with awesome_manager("leveldata.db", foreign_keys=False) as conn:
        create_vertex_schema(conn)
        create_line_schema(conn)

    with awesome_manager("leveldata.db") as conn:
        _build_vertex_table(conn)
        _build_line_table(conn)

def main():
    build_level_data()

if __name__ == "__main__":
    main()


#!/usr/bin/python3
# -*- coding: utf-8 -*-

import numpy as np

def is_orthonormal(matrix):

    m, n = matrix.shape

    # Verifica se as colunas são vetores unitários
    for j in range(n):
        col = matrix[:, j]
        norm = np.linalg.norm(col)
        if abs(norm - 1) > 1e-10:
            return False

    # Verifica se as colunas são ortogonais entre si
    for j1 in range(n):
        for j2 in range(j1+1, n):
            dot_product = np.dot(matrix[:, j1], matrix[:, j2])
            if abs(dot_product) > 1e-10:
                return False

    # Se chegou até aqui, a matriz é ortonormal
    return True


_base_ = [
    '../_base_/schedules/schedule_1x.py', '../_base_/default_runtime.py'
]

img_scale = (960, 960)  # height, width

model = dict(
    type='YOLOF',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(3, ),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=False),
        norm_eval=True),
        # style='caffe',
        # init_cfg=dict(
        #     type='Pretrained',
        #     checkpoint='open-mmlab://detectron/resnet50_caffe')),
    neck=dict(
        type='DilatedEncoder',
        in_channels=2048,
        out_channels=512,
        block_mid_channels=128,
        num_residual_blocks=4,
        block_dilations=[2, 4, 6, 8]),
    bbox_head=dict(
        type='YOLOFHead',
        num_classes=6,
        in_channels=512,
        reg_decoded_bbox=True,
        anchor_generator=dict(
            type='AnchorGenerator',
            ratios=[1.0],
            scales=[1, 2, 4, 8, 16],
            strides=[32]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[.0, .0, .0, .0],
            target_stds=[1., 1., 1., 1.],
            add_ctr_clamp=True,
            ctr_clamp=32),
        loss_cls=dict(
            type='FocalLoss',
            use_sigmoid=True,
            gamma=2.0,
            alpha=0.25,
            loss_weight=1.0),
        loss_bbox=dict(type='GIoULoss', loss_weight=1.0)),
    # training and testing settings
    train_cfg=dict(
        assigner=dict(
            type='UniformAssigner', pos_ignore_thr=0.15, neg_ignore_thr=0.7),
        allowed_border=-1,
        pos_weight=-1,
        debug=False),
    test_cfg=dict(
        nms_pre=1000,
        min_bbox_size=0,
        score_thr=0.01,
        nms=dict(type='nms', iou_threshold=0.65),
        max_per_img=100))

# use caffe img_norm
img_norm_cfg = dict(
    mean=[103.530, 116.280, 123.675], std=[1.0, 1.0, 1.0], to_rgb=False)
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', with_bbox=True),
    dict(type='Resize', img_scale=img_scale, keep_ratio=True),
    dict(type='RandomFlip', flip_ratio=0.5),
    dict(type='RandomShift', shift_ratio=0.5, max_shift_px=32),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='Pad', size_divisor=32),
    dict(type='DefaultFormatBundle'),
    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
]
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipAug',
        img_scale=img_scale,
        flip=False,
        transforms=[
            dict(type='Resize', keep_ratio=True),
            dict(type='RandomFlip'),
            dict(type='Normalize', **img_norm_cfg),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img']),
        ])
]
# data = dict(
#     samples_per_gpu=2,
#     workers_per_gpu=2,
#     train=dict(pipeline=train_pipeline),
#     val=dict(pipeline=test_pipeline),
#     test=dict(pipeline=test_pipeline))
dataset_type = 'VOCDataset'
data_root = 'data/SeaShips/'
data = dict(
    samples_per_gpu=4,
    workers_per_gpu=4,
    train=dict(
        type=dataset_type,
        ann_file=data_root + 'VOC2007/ImageSets/Main/trainval.txt',
        img_prefix=data_root + 'VOC2007/',
        pipeline=train_pipeline),
    val=dict(
        type=dataset_type,
        ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt',
        img_prefix=data_root + 'VOC2007/',
        pipeline=test_pipeline),
    test=dict(
        type=dataset_type,
        ann_file=data_root + 'VOC2007/ImageSets/Main/test.txt',
        img_prefix=data_root + 'VOC2007/',
        pipeline=test_pipeline))

# optimizer

# optimizer
# optimizer = dict(
#     type='SGD',
#     lr=0.12,
#     momentum=0.9,
#     weight_decay=0.0001,
#     paramwise_cfg=dict(
#         norm_decay_mult=0., custom_keys={'backbone': dict(lr_mult=1. / 3)}))
# lr_config = dict(warmup_iters=1500, warmup_ratio=0.00066667)
optimizer = dict(
    type='SGD',
    lr=0.01,
    momentum=0.9,
    weight_decay=5e-4,
    nesterov=True,
    paramwise_cfg=dict(norm_decay_mult=0., bias_decay_mult=0.))
optimizer_config = dict(grad_clip=None)

max_epochs = 50
num_last_epochs = 5
resume_from = None
interval = 10

# learning policy
lr_config = dict(
    policy='step',
    warmup='linear',
    warmup_iters=5,
    warmup_ratio=1,
    step=[8, 11])
runner = dict(type='EpochBasedRunner', max_epochs=50)

log_config = dict(interval=100)

evaluation = dict(
    save_best='auto',
    # The evaluation interval is 'interval' when running epoch is
    # less than ‘max_epochs - num_last_epochs’.
    # The evaluation interval is 1 when running epoch is greater than
    # or equal to ‘max_epochs - num_last_epochs’.
    interval=1,
    dynamic_intervals=[(max_epochs - num_last_epochs, 1)],
    metric='mAP')

checkpoint_config = dict(interval=interval)

# resume_from = 'work_dirs/my_yolov5/latest.pth'
custom_hooks = [
    dict(
        type='SyncNormHook',
        num_last_epochs=num_last_epochs,
        interval=interval,
        priority=48),
    dict(
        type='ExpMomentumEMAHook',
        resume_from=None,
        momentum=0.0001,
        priority=49)
]

# NOTE: `auto_scale_lr` is for automatically scaling LR,
# USER SHOULD NOT CHANGE ITS VALUES.
# base_batch_size = (8 GPUs) x (8 samples per GPU)
auto_scale_lr = dict(base_batch_size=64)
# optimizer = dict(
#     type='SGD',
#     lr=0.01,
#     momentum=0.9,
#     weight_decay=5e-4,
#     nesterov=True,
#     paramwise_cfg=dict(norm_decay_mult=0., bias_decay_mult=0.))
# optimizer_config = dict(grad_clip=None)
#
# max_epochs = 50
# num_last_epochs = 5
# resume_from = None
# interval = 10
#
# # learning policy
# lr_config = dict(
#     _delete_=True,
#     policy='YOLOX',
#     warmup='exp',
#     by_epoch=False,
#     warmup_by_epoch=True,
#     warmup_ratio=1,
#     warmup_iters=5,  # 5 epoch
#     num_last_epochs=num_last_epochs,
#     min_lr_ratio=0.05)
#
# runner = dict(type='EpochBasedRunner', max_epochs=max_epochs)
#
# custom_hooks = [
#     dict(
#         type='YOLOXModeSwitchHook',
#         num_last_epochs=num_last_epochs,
#         priority=48),
#     dict(
#         type='SyncNormHook',
#         num_last_epochs=num_last_epochs,
#         interval=interval,
#         priority=48),
#     dict(
#         type='ExpMomentumEMAHook',
#         resume_from=resume_from,
#         momentum=0.0001,
#         priority=49)
# ]
# checkpoint_config = dict(interval=interval)
# evaluation = dict(
#     save_best='auto',
#     # The evaluation interval is 'interval' when running epoch is
#     # less than ‘max_epochs - num_last_epochs’.
#     # The evaluation interval is 1 when running epoch is greater than
#     # or equal to ‘max_epochs - num_last_epochs’.
#     interval=interval,
#     dynamic_intervals=[(max_epochs - num_last_epochs, 1)],
#     metric='mAP')
# log_config = dict(interval=100)
#
# # NOTE: `auto_scale_lr` is for automatically scaling LR,
# # USER SHOULD NOT CHANGE ITS VALUES.
# # base_batch_size = (8 GPUs) x (8 samples per GPU)
# auto_scale_lr = dict(base_batch_size=64)


#Tags - string, letters, indexing, reverse
#https://leetcode.com/problems/reverse-prefix-of-word/
#beats 84%
class Solution:
    def reversePrefix(self, word: str, ch: str) -> str:
        pos = -1
        for i in range(len(word)):
            if word[i] == ch:
                pos = i
                break

        if pos == -1:
            return word
        return word[0:pos+1][::-1] + word[pos+1:]


e,s,m = map(int,input().split())
answer = s
if e == 15 :
    e = 0
if s == 28 :
    s = 0
if m == 19 :
    m = 0
while True:
    if answer%15 == e and answer%19 == m :
        break
    else:
        answer += 28
print(answer)


class Menu:
    @staticmethod
    def choose_class():
        print("Choisissez votre classe :")
        print("1. Guerrier")
        print("2. Assassin")
        print("3. Chasseur")

        choice = int(input("Entrez le numéro de votre classe : "))
        if choice == 1:
            return "Guerrier"
        elif choice == 2:
            return "Assassin"
        elif choice == 3:
            return "Chasseur"
        else:
            return "Guerrier"  # Default to Guerrier if an invalid choice is entered

    @staticmethod
    def choose_action():
        print("Choisissez une action :")
        print("1. Taper")
        print("2. Soigner")

        choice = int(input("Entrez le numéro de votre action : "))
        if choice == 1:
            return "Taper"
        elif choice == 2:
            return "Soigner"
        else:
            return "Taper"  # Default to Taper if an invalid choice is entered

    @staticmethod
    def choose_direction():
        print("Choisissez une direction :")
        print("1. Nord")
        print("2. Sud")
        print("3. Est")
        print("4. Ouest")

        choice = int(input("Entrez le numéro de votre direction : "))
        if choice == 1:
            return "Nord"
        elif choice == 2:
            return "Sud"
        elif choice == 3:
            return "Est"
        elif choice == 4:
            return "Ouest"
        else:
            return "Nord"


import sys
import math
import random
import numpy as np
from tabulate import tabulate
from data_augmentation import jittering, smote_based_wDBA, window_slicing
from enum import Enum
from utility.conversion_methods import join_dataset_dictionaries, fix_rotation_matrices, list_to_matrix

PERFORMANCE_MEASURES = ["Binary crossentropy loss", "Binary accuracy", "AUC", "f1-score", "Precision", "Recall"]
DATA_AUGMENTATION_TECHNIQUES = ["smote_based_wdba", "jittering"]

class ProficiencyLabel(Enum):
    """
        Scanned region
    """
    Novice = 0
    Expert = 1

# Represents the data for a single surgery. Stores time series data captured from the surgery, as well as related info
# May store multiple time series if multiple sequence types are considered (assumption is they all share the same timestamps)

class SurgeryData:

    def __init__(self, skill_level, surgery_type, timestamps=[]):
        self.sequences = dict()
        self.skill_level = skill_level
        self.surgery_type = surgery_type
        self.timestamps = timestamps

    def add_sequence(self, sequence_type, time_series):
        self.sequences[sequence_type] = time_series

# Instances stores all surgeries data recorded for some participant
class ParticipantData:

    def __init__(self, name):
        self.name = name
        self.surgeries = []
        self.surgeries_stats = dict(
            novices_IP=0,
            novices_OOP=0,
            experts_IP=0,
            experts_OOP=0
        )

    # To add a surgery, must pass in a Surgery object
    def add_surgery(self, surgery):

        self.surgeries.append(surgery)
        self.update_surgery_stats(surgery)

    def update_surgery_stats(self, surgery):

        skill_level = surgery.skill_level
        surgery_type = surgery.surgery_type
        for stat in self.surgeries_stats:
            if (skill_level.lower() in stat.lower()) and (surgery_type.lower() in stat.lower()):
                self.surgeries_stats[stat] += 1
                break

# Contains a dictionary that stores participant names as keys, and the corresponding ParticipantsStorage objects as keys
# Altogether, it contains all time series data
class ParticipantsStorage:

    def __init__(self):
        self.participants = dict()
        self.surgeries_stats = dict(
            surgeries=0,
            novices=0,
            experts=0,
            novices_IP=0,
            novices_OOP=0,
            experts_IP=0,
            experts_OOP=0
        )

    # Adds a surgery to the storage, within the corresponding participant's storage. If the participant does not exist,
    # then they are created
    def add_surgery(self, participant_name, surgery):

        if participant_name not in self.participants:
            self.participants[participant_name] = ParticipantData(participant_name)
        self.participants[participant_name].add_surgery(surgery)
        self.update_surgeries_stats(surgery)

    def add_participant(self, participant):

        if (not isinstance(participant, ParticipantData)) or participant.name in self.participants:
            return False
        self.participants[participant.name] = participant
        for surgery in participant.surgeries:
            self.update_surgeries_stats(surgery)
        return True

    def pop_participant(self, participant_name=None):

        if len(self.participants) == 0:
            return None
        participant = None
        names = list(self.participants.keys())
        if participant_name is None:
            # Pops random participant
            participant = self.participants.pop(names[random.randint(0, len(self.participants)-1)])
        elif participant_name in names:
            participant = self.participants.pop(participant_name)
        else:
            return None

        for surgery in participant.surgeries:
            self.update_surgeries_stats(surgery, False)

        return participant

    def update_surgeries_stats(self, surgery, add=True):

        # Values we add below depend on whether a surgery is being added or removed
        term = 1 if add else -1
        skill_level = surgery.skill_level
        surgery_type = surgery.surgery_type
        self.surgeries_stats["surgeries"] += term
        self.surgeries_stats[(skill_level + "s").lower()] += term  # Updates number of novices / experts
        for stat in self.surgeries_stats:
            if (skill_level.lower() in stat.lower()) and (surgery_type.lower() in stat.lower()):
                self.surgeries_stats[stat] += term
                break

    # Note: In all ratios, we return math.inf if denominator is 0
    def novices_to_experts_ratio(self):

        return self.surgeries_stats["novices"] / self.surgeries_stats["experts"] if  \
            self.surgeries_stats["experts"] else math.inf

    def novices_IP_to_OOP_ratio(self):

        return self.surgeries_stats["novices_IP"] / self.surgeries_stats["novices_OOP"] if \
            self.surgeries_stats["novices_OOP"] else math.inf

    def experts_IP_to_OOP_ratio(self):

        return self.surgeries_stats["experts_IP"] / self.surgeries_stats["experts_OOP"] if \
            self.surgeries_stats["experts_OOP"] else 0

class Jittering:

    def __init__(self, rotation_magnitude=1, translation_magnitude=1):

        self.rotation_magnitude = rotation_magnitude
        self.translation_magnitude = translation_magnitude

    def execute(self, dataset, synthetic_amount):
        return jittering.jittering_specified_amount(
            dataset, synthetic_amount, self.rotation_magnitude, self.translation_magnitude)

class SmoteBasedWDBA:

    def __init__(self, k=None):
        self.k = k

    def execute(self, dataset, synthetic_amount):
        return smote_based_wDBA.smote_based_weighted_dba_specified_amount(
            dataset, synthetic_amount, self.k)

class WindowSlicing:

    def __init__(self, window_slice_prop=0.9):
        self.window_slice_prop = window_slice_prop

    def execute(self, dataset, synthetic_amount):
        return window_slicing.window_slicing_specified_amount(dataset, synthetic_amount, self.window_slice_prop)

class DataAugmentationInstruction:

    # Technique refers to the data augmentation technique to use
    def __init__(self, technique, augment_synthetic=False):
        self.technique = technique
        self.augment_synthetic = augment_synthetic

class BalanceDataset(DataAugmentationInstruction):

    def __init__(self, technique, augment_synthetic=False):

        super().__init__(technique, augment_synthetic)

    # Here is the code for balancing a dataset. First balance novices IP, OOP and experts IP, OOP.
    # Afterwards, balance novices and experts . We always up-sample, via the specified technique.
    # Returns synthetic samples
    def execute(self, original_dataset, synthetic_dataset):

        enhanced_set = join_dataset_dictionaries(original_dataset, synthetic_dataset)
        # print("Num of novices IP:", len(enhanced_set["Novices"]["IP"]))
        # print("Num of novices OOP:", len(enhanced_set["Novices"]["OOP"]))
        # print("Num of experts OP:", len(enhanced_set["Experts"]["IP"]))
        # print("Num of experts OOP:", len(enhanced_set["Experts"]["OOP"]))

        # If enhanced_set assigned, then new samples may be creating using the synthetic ones passed in.
        set_used_for_augmentation = enhanced_set if self.augment_synthetic else original_dataset

        # Balance novices IP and OOP, and then experts IP, OOP (in enhanced set)
        for skill_level in ["Novices", "Experts"]:
            desired_size = max(len(enhanced_set[skill_level]["IP"]), len(enhanced_set[skill_level]["OOP"]))
            for surgery_type in ["IP", "OOP"]:
                synthetic_amount = desired_size - len(enhanced_set[skill_level][surgery_type])
                synthetic_dataset[skill_level][surgery_type] += \
                    self.technique.execute(set_used_for_augmentation[skill_level][surgery_type], synthetic_amount)

        # Balance novices and experts. At this point, 1:1 IP to OOP ratio for both skill levels
        num_novices_IP = len(original_dataset["Novices"]["IP"]) + len(synthetic_dataset["Novices"]["IP"])
        num_experts_IP = len(original_dataset["Experts"]["IP"]) + len(synthetic_dataset["Experts"]["IP"])
        desired_size = max(num_novices_IP, num_experts_IP)

        # print("num_novices_IP:", num_novices_IP)
        # print("num_experts_IP", num_experts_IP)

        for skill_level in ["Novices", "Experts"]:
            for surgery_type in ["IP", "OOP"]:
                # Want to get to the desired size. Need to account both original and synthetic samples
                synthetic_amount = desired_size - (len(original_dataset[skill_level][surgery_type]) +
                                                   len(synthetic_dataset[skill_level][surgery_type]))
                synthetic_dataset[skill_level][surgery_type] += \
                    self.technique.execute(set_used_for_augmentation[skill_level][surgery_type], synthetic_amount)

        return synthetic_dataset

# Novices IP, Novices OOP, Experts IP, Experts OOP, which make up the dataset, are all increased by the given factor
# independently.
# NOTE: ** Increase is relative to the size of the enhanced set, not the original dataset
class IncreaseDatasetProportionally(DataAugmentationInstruction):

    def __init__(self, technique, increase_factor, augment_synthetic=False):

        super().__init__(technique, augment_synthetic)
        self.increase_factor = increase_factor

    def execute(self, original_dataset, synthetic_dataset):

        enhanced_set = join_dataset_dictionaries(original_dataset, synthetic_dataset)
        set_used_for_augmentation = enhanced_set if self.augment_synthetic else original_dataset

        if self.increase_factor <= 1:
            return synthetic_dataset

        # Increase each division separately
        for skill_level in ["Novices", "Experts"]:
            for surgery_type in ["IP", "OOP"]:
                desired_size = round(self.increase_factor * len(enhanced_set[skill_level][surgery_type]))
                synthetic_amount = desired_size - len(enhanced_set[skill_level][surgery_type])
                synthetic_dataset[skill_level][surgery_type] += \
                    self.technique.execute(set_used_for_augmentation[skill_level][surgery_type], synthetic_amount)

        return synthetic_dataset

# Novices IP, Novices OOP, Experts IP, Experts OOP, which make up the dataset, are all increased by aprx. the same number
# of synthetic samples such that the dataset reaches the required size, which is len(original_dataset) * increase_factor.
# -This means increase is relative to size of the original dataset
# NOTE: the resulting enhanced set may be slightly imbalanced
#  e.g perhaps 4 Novices IP are required and 3 for each of the other types
# ** NOTE: This method only works well for increase_factor >= 2 . If it's less, increase_factor may already be exceeded
# when samples are first balanced

class IncreaseDatasetBalanced(DataAugmentationInstruction):

    def __init__(self, technique, increase_factor, augment_synthetic=False):

        super().__init__(technique, augment_synthetic)
        self.increase_factor = increase_factor
        self.balance_instruction = BalanceDataset(technique, augment_synthetic)

    def execute(self, original_dataset, synthetic_dataset):

        if self.increase_factor < 2:
            print("Note: Increase factor must be >= 2. No data augmentation performed... (otherwise factor is overshot when balancing)")
            return synthetic_dataset

        # First balance dataset
        synthetic_dataset = self.balance_instruction.execute(original_dataset, synthetic_dataset)

        enhanced_set = join_dataset_dictionaries(original_dataset, synthetic_dataset)
        set_used_for_augmentation = enhanced_set if self.augment_synthetic else original_dataset

        # Find number of surgeries in original and enhanced datasets
        original_size = 0
        cur_size = 0
        for skill_level in ["Novices", "Experts"]:
            for surgery_type in ["IP", "OOP"]:
                original_size += len(original_dataset[skill_level][surgery_type])
                cur_size += len(enhanced_set[skill_level][surgery_type])

        desired_size = round(self.increase_factor * original_size)

        synthetic_samples_required = desired_size - cur_size

        if synthetic_samples_required <= 0:
            return synthetic_dataset

        # Increase each division separately, all by aprx. the same amount
        # After attempting to split data augmentation evenly, may require 1 more of a certain division(s)
        # then others. This occurs if desired_size is not a multiple of 4
        extra_samples_required = synthetic_samples_required % 4
        for skill_level in ["Novices", "Experts"]:
            for surgery_type in ["IP", "OOP"]:
                synthetic_amount = synthetic_samples_required // 4
                if extra_samples_required > 0:
                    synthetic_amount += 1
                    extra_samples_required -= 1

                synthetic_dataset[skill_level][surgery_type] += \
                    self.technique.execute(set_used_for_augmentation[skill_level][surgery_type], synthetic_amount)

        return synthetic_dataset

class DataAugmentationController:

    # Instructions stores list of data augmentation steps to perform
    def __init__(self, instructions=None):
        if instructions is None:
            self.instructions = []
        else:
            self.instructions = instructions

    def add_instruction(self, instruction):
        self.instructions.append(instruction)

    def execute(self, original_dataset):
        synthetic_dataset = dict(
            Novices=dict(IP=[], OOP=[]),
            Experts=dict(IP=[], OOP=[])
        )
        for instruction in self.instructions:
            synthetic_dataset = instruction.execute(original_dataset, synthetic_dataset)

        # print("Matrix multiplication before:")
        # product = np.dot(list_to_matrix(synthetic_dataset["Novices"]["IP"][0][0])[0:3, 0:3],
        #                  list_to_matrix(synthetic_dataset["Novices"]["IP"][0][0])[0:3, 0:3].transpose())
        # np.savetxt(sys.stdout, product, '%.5f')

        # Fix all rotation matrices, for all time series
        for skill_level in synthetic_dataset:
            for surgery_type in synthetic_dataset[skill_level]:
                for i in range(len(synthetic_dataset[skill_level][surgery_type])):
                    fix_rotation_matrices(synthetic_dataset[skill_level][surgery_type][i])

        # print("Matrix multiplication after:")
        # product = np.dot(list_to_matrix(synthetic_dataset["Novices"]["IP"][0][0])[0:3, 0:3],
        #                  list_to_matrix(synthetic_dataset["Novices"]["IP"][0][0])[0:3, 0:3].transpose())
        # np.savetxt(sys.stdout, product, '%.5f')

        return synthetic_dataset

class Results:

    def __init__(self):

        self.averages = dict(
            training=dict(),
            validation=dict(),
            test=dict()
        )
        self.stddevs = dict(
            training=dict(),
            validation=dict(),
            test=dict()
        )

    def __str__(self):

        # Averages
        lists_to_print = []
        for performance_measure in PERFORMANCE_MEASURES:
            lists_to_print.append([performance_measure, self.averages["training"][performance_measure],
                                   self.averages["validation"][performance_measure],
                                   self.averages["test"][performance_measure]])

        averages_table = tabulate(tabular_data=lists_to_print,
                                  headers=["Performance measure", "All training results - mean",
                                           "All validation results - mean", "Tests - mean"])
        # Stddevs
        lists_to_print = []
        for performance_measure in PERFORMANCE_MEASURES:
            lists_to_print.append([performance_measure, self.stddevs["training"][performance_measure],
                                   self.stddevs["validation"][performance_measure],
                                   self.stddevs["test"][performance_measure]])

        stddevs_table = tabulate(tabular_data=lists_to_print,
                                 headers=["Performance measure", "All training results - stddev",
                                          "All validation results - stddev", "Tests - stddev"])

        return averages_table + "\n\n" + stddevs_table + "\n"

    @staticmethod
    def create_averaged_results_object(all_result_objects):

        # Initializing averaged results object
        averaged_results = Results()
        for set in averaged_results.averages:
            for performance_measure in PERFORMANCE_MEASURES:
                averaged_results.averages[set][performance_measure] = 0
                averaged_results.stddevs[set][performance_measure] = 0

        for single_results in all_result_objects:
            for set in averaged_results.averages:
                for performance_measure in PERFORMANCE_MEASURES:
                    averaged_results.averages[set][performance_measure] += \
                        single_results.averages[set][performance_measure] / len(all_result_objects)
                    averaged_results.stddevs[set][performance_measure] += \
                        single_results.stddevs[set][performance_measure] / len(all_result_objects)
        return averaged_results

class Transcript(object):
    """
    Transcript - direct print output to a file, in addition to terminal (from Stack Overflow, but modified).

    Usage:
        import transcript
        transcript.start('logfile.log')
        print("inside file")
        transcript.stop()
        print("outside file")
    """

    def __init__(self, filename):
        self.terminal = sys.stdout
        self.logfile = open(filename, "a")

    def write(self, message):

        self.terminal.write(message)
        self.logfile.write(message)

    def flush(self):
        # this flush method is needed for python 3 compatibility.
        # this handles the flush command by doing nothing.
        # you might want to specify some extra behavior here.
        pass


import re
import numpy as np
from networkx import from_scipy_sparse_matrix, pagerank
from nltk.tokenize.punkt import PunktSentenceTokenizer
from sklearn.feature_extraction.text import TfidfTransformer, CountVectorizer
from Sastrawi.StopWordRemover.StopWordRemoverFactory import ArrayDictionary, StopWordRemoverFactory, StopWordRemover

class TextSummarization():
    def __init__(self):
        with open('./stopwords.txt') as f:
            more_stopword=f.read().split('\n')

        SWfactory = StopWordRemoverFactory()
        stopword_data = ArrayDictionary(more_stopword+SWfactory.get_stop_words())
        self.stopword = StopWordRemover(stopword_data)

    def Preprocessing(self, text):
        clean = re.sub("#[^\W]+|@[^\W]+|http[^*\s]+|<[^>]*>|[0-9]", '', text) #cleansing data
        emoticons = re.findall('(?::|;|=)()(?:-)?(?:\)|\(|D|P)', clean)
        text = (re.sub('[\W]+', ' ', clean.lower()) +  #Case folding
                ' '.join(emoticons).replace('-', ''))
        result=''
        for kata in text.split():
            stop = self.stopword.remove(kata) #Stopword
            result += f"{stop} " if stop else ''
        return result

    def Summary(self, doc, preprocess=False):
        doc_tokenizer = PunktSentenceTokenizer()
        sentences_list = doc_tokenizer.tokenize(doc)

        clean_sentences_list=[]
        for sentence in sentences_list:
            clean_sentences_list.append(self.Preprocessing(sentence))

        cv = CountVectorizer()
        cv_matrix = cv.fit_transform(clean_sentences_list if preprocess else sentences_list)
        normal_matrix = TfidfTransformer().fit_transform(cv_matrix)

        tfidf=normal_matrix.toarray()
        res_graph = normal_matrix * normal_matrix.T # similaritas /adjacency matrix

        nx_graph= from_scipy_sparse_matrix(res_graph)
        pageranks = pagerank(nx_graph)

        sentence_array = sorted(((pageranks[i], s) for i, s in enumerate(sentences_list)), reverse=True)
        sentence_array = np.asarray(sentence_array)

        rank_max = float(sentence_array[0][0])
        rank_min = float(sentence_array[len(sentence_array) - 1][0])

        temp_array = []

        # Jika semua rank sama
        # taking any sentence will give the summary, say the first sentence
        flag = 0
        if rank_max - rank_min == 0:
            temp_array.append(0)
            flag = 1

        # If the sentence has different ranks
        if flag != 1:
            for i in range(0, len(sentence_array)):
                temp_array.append((float(sentence_array[i][0]) - rank_min) / (rank_max - rank_min))

        # Calculation of threshold:
        # We take the mean value of normalized scores
        # any sentence with the normalized score 0.2 more than the mean value is considered to be
        threshold = (sum(temp_array) / len(temp_array))# + 0.2

        # Separate out the sentences that satiasfy the criteria of having a score above the threshold
        sentence_list = []
        if len(temp_array) > 1:
            for i in range(0, len(temp_array)):
                if temp_array[i] > threshold:
                        sentence_list.append(sentence_array[i][1])
        else:
            sentence_list.append(sentence_array[0][1])

        summary = " ".join(str(x) for x in sentence_list)

        return summary


import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

class Data():

    def __init__(self):
        self.read_schedule()

    def read_schedule(self):
        f = open('./txt/scd.txt','r',encoding='UTF-8')
        lines = f.readlines()
        self.scd = [line.rstrip('\n').split('/') for line in lines]
        f.close()

class Action():

    def __init__(self):
        pass

    def getExitAction(obj):
        exitAction = QAction(QIcon('./img/exit.png'), 'Exit', obj)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(qApp.quit)
        return exitAction

class MyApp(QMainWindow):

    def __init__(self, data:Data):
        super().__init__()
        self.data = data
        self.initUI()

    def initUI(self):
        self.set_UI()
        self.show()

    # UI
    def set_UI(self):
        self.wid = QWidget(self)
        self.setCentralWidget(self.wid)
        self.set_statusBar()
        self.set_menuBar()
        self.set_toolBar()
        self.set_daily_scd()
        self.setWindowTitle('Statusbar')
        self.center()
        self.resize(800,600)
    # set window center
    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    # toolbar
    def set_toolBar(self):
        exitAction = Action.getExitAction(self)

        self.tool_exit = self.addToolBar('Exit')
        self.tool_exit.addAction(exitAction)

    # Status Bar
    def set_statusBar(self):
        self.statusBar().showMessage('Ready')

    # Menu Bar
    def set_menuBar(self):
        exitAction = Action.getExitAction(self)

        menubar = self.menuBar()
        filemenu = menubar.addMenu('&File')
        filemenu.addAction(exitAction)

    # daily schedule
    def set_daily_scd(self):
        self.tableWidget = self.daily_scd_table()

        hbox = QHBoxLayout()
        hbox.addWidget(self.tableWidget)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)

        self.wid.setLayout(vbox)

    # daily schedule table
    def daily_scd_table(self)->QTableWidget:
        scd = self.data.scd
        row = len(scd)
        col = len(scd[0])
        header = ['시작','종료','내용']

        tableWidget = QTableWidget(self)
        tableWidget.resize(400,300)
        tableWidget.setRowCount(row)
        tableWidget.setColumnCount(col)
        tableWidget.setHorizontalHeaderLabels(header)
        tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)

        for i,row in enumerate(scd):
            for j,col in enumerate(row):
                item = QTableWidgetItem(scd[i][j])
                tableWidget.setItem(i,j,item)

        return tableWidget

if __name__ == '__main__':
    data = Data()
    app = QApplication(sys.argv)
    ex = MyApp(data)
    sys.exit(app.exec_())


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# df = pd.read_csv ('output.csv', header = None)
# df.columns = ['Name', 'ELO', 'K']

# df.plot(x="Name", y=["ELO", "K"], kind="bar", figsize=(9, 8))

# plt.show()
# print(df)

df = pd.read_csv ('output.csv', header = None)
df.columns = ['Name', 'ELO', 'K']

ax = df.plot(x="Name", y=["ELO", "K"], kind="bar", figsize=(9, 8))

s = df["K"]

for index in range((df.shape[0])):
  ax.text(index, s[index], s[index], size=8)

plt.show()
print(s)


from psychopy import visual, core, event ,monitors
from win32api import GetSystemMetrics
import numpy as np
import time
from itertools import permutations, repeat
from datetime import datetime
import random
import u3

#create a window
width = GetSystemMetrics(0)
height = GetSystemMetrics(1)
print(width)
print(height)
monitor_size = [1280,800]

myMonitor = monitors.Monitor('X1_carbon',width =31)
myMonitor.setSizePix(monitor_size)
myMonitor.saveMon()

refresh_rate = 59 # refresh rate of your current monitor settings in Hz

'=======================DOT PARAMETERS============================'
distance = 0.15 #cm, distance between the screen and larvae's head
direction = 'r'       # starting direction of the dot with respect to fish
x_distance = 160# degrees, full range. Moving distance from left to right in terms of visual angle, which takes 1/2 of total time
speed=200

x_distance=160
if direction == 'r':
    x_distance = np.abs(x_distance)
elif direction == 'l':
    x_distance = -np.abs(x_distance)

moving_time = x_distance/float(speed) # second
position = [-x_distance/2.0, 0]

dt = 10
dev = u3.U3()  # Open first found U3

dev.getCalibrationData()
dev.configIO(EnableCounter1=True,TimerCounterPinOffset=7)

myWin = visual.Window(monitor_size, monitor=myMonitor, units='degFlat', color = (-1,-1,-1), fullscr=True,viewPos=[0,0])

'''Get the the average time per frame'''
frametime = myWin.getMsPerFrame(nFrames=60, showVisual=False, msg='', msDelay=0.0)[0]

# return the the average time per frame, with unit of ms
deg_per_frame = frametime*speed/1000
y_deg_per_frame = frametime*200/1000
count=0
timer = core.Clock()
prev_count=0

while True:
    count = int(np.array(dev.getFeedback(u3.Counter(counter=1))))
    print(count)
    if count != prev_count:
        prev_count = count
        timer = core.Clock()
        time.sleep(3)
        t0 = timer.getTime()
        if direction == 'r' or 'l':
         timer.reset()
         myStim = visual.Circle(win=myWin, lineWidth=0, radius=4/2, units='degFlat',fillColor=[1, 1, 1], pos=position,contrast=1)
         #position = [-x_distance / 2.0, 0]
         while position[0] <= x_distance/2.0:
            position[0] += deg_per_frame
            myStim.setPos(position)
            myStim.draw()
            myWin.update()

        while position[0] >= -x_distance/2.0:
            position[0] -= deg_per_frame
            myStim.setPos(position)
            myStim.draw()
            myWin.update()

        timeUse = timer.getTime()
        print(timeUse)
        myWin.flip(clearBuffer=True)
        myWin.update()
        timeUse = timer.getTime()
        time.sleep(10 - (3+timeUse))
        timeUse1 = timer.getTime()
        print(timeUse1 - timeUse)

    prev_count = count
    if "escape" in event.getKeys():
        core.quit()

#cleanup
core.quit()


from collections import Counter
import bisect

w, h = map(int, input().split())

n = int(input())

points = []

for _ in range(n):
    x, y = map(int, input().split())
    points.append((x, y))

nxcuts = int(input())

xcuts = [0] + list(map(int, input().split())) + [w]

nycuts = int(input())

ycuts = [0] + list(map(int, input().split())) + [h]

ctr = Counter()

minval = float('inf')
maxval = float('-inf')

for x, y in points:
    xx = bisect.bisect_left(xcuts, x)
    yy = bisect.bisect_left(ycuts, y)
    ctr[(xx, yy)] += 1
    maxval = max(maxval, ctr[(xx, yy)])

for xx, yy in ctr:
    minval = min(minval, ctr[(xx, yy)])

if len(ctr) < (nxcuts + 1) * (nycuts + 1) or n < (nxcuts + 1) * (nycuts + 1):
    minval = 0

print(minval, maxval)


from library import Book
import csv

def add_book_to_csv(book: Book, path):
    if not check_if_book_in_csv(path=path, book=book)[0]:
        with open(path, 'r') as file:
            reader = csv.reader(file)
            data = list(reader)
        data.append([book.title, book.author, book.year, book.available, book.count])
        with open(path, 'w') as file:
            writer = csv.writer(file)
            writer.writerows(data)
    elif check_if_book_in_csv(path=path, book=book)[0]:
        row_number = check_if_book_in_csv(path=path, book=book)[1]
        with open(path, 'r') as file:
            reader = csv.reader(file)
            data = list(reader)
        data[row_number][5] = int(data[row_number][5])
        data[row_number][5] += 1
        with open(path, 'w') as file:
            writer = csv.writer(file)
            writer.writerows(data)

def check_if_book_in_csv(path, book):
    with open(path, 'r') as file:
        reader = csv.reader(file)
        reader = list(reader)
        for number_of_row, row in enumerate(reader):
            if book == Book(row[0], row[1], row[2], row[3]):
                return True, number_of_row
        return False, 0


import os
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--checkpoint')
parser.add_argument('--device', default = 'cuda', help = 'TODO: proper device choosing')
parser.add_argument('--iterations', type = int, default = 16)
parser.add_argument('--iterations-warmup', type = int, default = 16)
parser.add_argument('--frontend', action = 'store_true')
parser.add_argument('--fp16', choices = ['', 'O0', 'O1', 'O2', 'O3'], default = None)
parser.add_argument(
	'--num-input-features', default = 64, help = 'num of mel-scale features produced by logfbank frontend'
)
parser.add_argument('--sample-rate', type = int, default = 8_000, help = 'for frontend')
parser.add_argument('--window-size', type = float, default = 0.02, help = 'for frontend, in seconds')
parser.add_argument('--window-stride', type = float, default = 0.01, help = 'for frontend, in seconds')
parser.add_argument('--lang', default = 'ru')
parser.add_argument(
	'--window', default = 'hann_window', choices = ['hann_window', 'hamming_window'], help = 'for frontend'
)
parser.add_argument('--model', default = 'JasperNetBig')
parser.add_argument('--onnx')
parser.add_argument('--onnx-output-node-name', type = str, default = 'logits')
parser.add_argument('--stft-mode', choices = ['conv', ''], default = '')
parser.add_argument('-B', type = int, default = 256)
parser.add_argument('-T', type = float, default = 5.12)
parser.add_argument('--profile-cuda', action = 'store_true')
parser.add_argument('--save-cudnn-cublas-logs', action = 'store_true', help='Save CUDNN CUBLAS logs')
parser.add_argument('--cudnn-logdest', type=str, default = 'cudnn_log.txt', help='Destination path to CUDNN logs')
parser.add_argument('--cublas-logdest', type=str, default = 'cublas_log.txt', help='Destination path to CUBLAS logs')

parser.add_argument('--profile-pyprof', action = 'store_true')
parser.add_argument('--profile-autograd')
parser.add_argument('--data-parallel', action = 'store_true')
parser.add_argument('--backward', action = 'store_true')
parser.add_argument('--input-time-dim-multiple', type = int, default = 128)

parser.add_argument('--output-path', '-o')

args = parser.parse_args()

if args.save_cudnn_cublas_logs:
	os.environ["CUDNN_LOGINFO_DBG"] = '1'
	os.environ["CUBLAS_LOGINFO_DBG"] = '1'
	os.environ["CUDNN_LOGDEST_DBG"] = args.cudnn_logdest
	os.environ["CUBLAS_LOGDEST_DBG"] = args.cublas_logdest

import gc
import math
import time
import torch
import torch.cuda.profiler
import onnxruntime
import models
import datasets
import utils

checkpoint = torch.load(args.checkpoint, map_location = 'cpu') if args.checkpoint else None
if checkpoint:
	args.model, args.lang, args.sample_rate, args.window_size, args.window_stride, args.window, args.num_input_features = map(
		checkpoint['args'].get,
		['model', 'lang', 'sample_rate', 'window_size', 'window_stride', 'window', 'num_input_features'])

use_cuda = 'cuda' in args.device

if args.onnx:
	onnxruntime_session = onnxruntime.InferenceSession(args.onnx)

	def load_batch_to_device(batch, device):
		batch = batch.numpy()
		io_binding = onnxruntime_session.io_binding()
		batch_ortvalue = onnxruntime.OrtValue.ortvalue_from_numpy(batch, device, 0)
		io_binding.bind_input(
			name = 'x',
			device_type = batch_ortvalue.device_name(),
			device_id = 0,
			element_type = batch.dtype,
			shape = batch_ortvalue.shape(),
			buffer_ptr = batch_ortvalue.data_ptr()
		)
		io_binding.bind_output(args.onnx_output_node_name, device)
		return io_binding

	load_batch = lambda batch: load_batch_to_device(batch, args.device)
	model = lambda io_binding: onnxruntime_session.run_with_iobinding(io_binding)

else:
	frontend = models.LogFilterBankFrontend(
		args.num_input_features,
		args.sample_rate,
		args.window_size,
		args.window_stride,
		args.window,
		stft_mode = args.stft_mode,
	) if args.frontend else None
	model = getattr(models, args.model)(
		args.num_input_features, [len(labels)],
		frontend = frontend,
		dict = lambda logits,
		log_probs,
		olen,
		**kwargs: logits[0]
	)
	if checkpoint:
		model.load_state_dict(checkpoint['model_state_dict'], strict = False)
	model.to(args.device)

	if not args.backward:
		model.eval()
		model.fuse_conv_bn_eval()

	model, *_ = models.data_parallel_and_autocast(model, opt_level = args.fp16, data_parallel = args.data_parallel)
	load_batch = lambda x: x.to(args.device, non_blocking = True)

tictoc = lambda: (use_cuda and torch.cuda.synchronize()) or time.time()

batch_shape = [args.B, int(args.T * args.sample_rate)
				] if args.frontend else [args.B, args.num_input_features, int(args.T / args.window_stride)]

if args.input_time_dim_multiple and batch_shape[-1] % args.input_time_dim_multiple != 0:
	batch_shape[-1] = int(math.ceil(batch_shape[-1] / args.input_time_dim_multiple) * args.input_time_dim_multiple)

example_time = batch_shape[-1] / args.sample_rate if args.frontend else batch_shape[-1] * args.window_stride

batch = torch.rand(*batch_shape)

print(args)
print()
print(
	'batch {} | stride {:.02f} sec | audio {:.02f} sec'.format(
		'x'.join(map(str, batch_shape)), args.window_stride, args.B * example_time
	)
)
print()

print('Warming up for', args.iterations_warmup, 'iterations')
tic_wall = tictoc()
if use_cuda:
	torch.backends.cudnn.benchmark = True

torch.set_grad_enabled(args.backward)
loaded_batch = load_batch(batch)
for i in range(args.iterations_warmup):
	y = model(loaded_batch)
	if args.backward:
		y.sum().backward()

print('Warmup done in {:.02f} wall clock seconds'.format(tictoc() - tic_wall))
print()

if args.profile_pyprof or args.profile_cuda:
	import pyprof
	pyprof.nvtx.nvmarker.patch_apex_module = lambda modstr, old = pyprof.nvtx.nvmarker.patch_apex_module: old(
			modstr) if modstr != 'apex.contrib.multihead_attn' else None  # coused by this bug https://github.com/NVIDIA/apex/issues/958 https://github.com/NVIDIA/PyProf/issues/167
	pyprof.nvtx.init()
if args.profile_cuda:
	torch.autograd.profiler.emit_nvtx()
	torch.cuda.profiler.start()
if args.profile_autograd:
	autograd_profiler = torch.autograd.profiler.profile(
		use_cuda = use_cuda, enabled = True, profile_memory = True, record_shapes = True
	)
	autograd_profiler.__enter__()

print('Starting benchmark for', args.iterations, 'iterations:', 'fwd', '+ bwd' if args.backward else '')
tic_wall = tictoc()
times_fwd, times_bwd, fragmentation, global_device_memory_utilisation = \
	torch.zeros(args.iterations), torch.zeros(args.iterations), \
		torch.zeros(args.iterations), torch.zeros(args.iterations)

loaded_batch = load_batch(batch)
for i in range(args.iterations):
	tic = tictoc()
	y = model(loaded_batch)
	toc = tictoc()
	global_device_memory_utilisation[i] = utils.compute_global_device_memory_utilisation()
	fragmentation[i] = utils.compute_memory_fragmentation()
	if args.backward:
		y.sum().backward()
	tac = tictoc()
	times_fwd[i] = toc - tic
	times_bwd[i] = tac - toc
	y = None

mem_reserved = torch.cuda.max_memory_reserved(args.device) if use_cuda else 0
mem_allocated = torch.cuda.max_memory_allocated(args.device) if use_cuda else 0
print('Benchmark done in {:.02f} wall clock seconds'.format(tictoc() - tic_wall))
print()

if args.profile_autograd:
	autograd_profiler.__exit__(None, None, None)
	autograd_profiler.export_chrome_trace(args.profile_autograd)
print(f'B: {args.B}, T: {args.T}')
print(
	'load+fwd {:.02f} msec | bwd {:.02f} msec | cudamemreserved {:.02f} mb | cudamemallocated {:.02f} mb | '
	'cudamemutilization: {:.02f} | global_dev_memutilization: {:.02f} | rtf: {:.02f}'
	.format(
		float(times_fwd.mean()) * 1e3,
		float(times_bwd.mean()) * 1e3,
		mem_reserved * 1e-6,
		mem_allocated * 1e-6,
		float(fragmentation.mean()),
		float(global_device_memory_utilisation.mean()),
		float(args.B * example_time * args.iterations / times_fwd.sum())
	)
)

if args.output:
	with open(args.output, 'a+') as f:
		message = f'{args.B}\t' \
		           f'{args.T}\t' \
		           f'{times_fwd.mean()}\t' \
		           f'{times_fwd.sum()}\t' \
		           f'{fragmentation.mean()}\t' \
		           f'{args.B * example_time * args.iterations / 3600.0}\t' \
		           f'{args.B * example_time * args.iterations / times_fwd.sum()}\t' \
		           f'{args.checkpoint}\t' \
		           f'{args.onnx}\t' \
		           f'\n'
		f.write(message)


from discord.ext.commands import Cog
from discord.ext.commands import command
from discord import Embed

class Tiktok(Cog):
  def __init__(self, bot):
    self.bot = bot

  @command()
  async def tiktok(self, ctx, link, *args):
    title = str(" ".join(args))

    self.ctx = ctx
    embed = Embed(title=f"{title}",colour=0x03A4DB)

    fields = [(f"link:", f"{link}", False)]

    for name, value, inline in fields:
        embed.add_field(name=name, value=value, inline=inline)

    embed.set_author(name='pececito', icon_url=self.ctx.guild.icon_url)
    embed.set_image(url="https://cdn.discordapp.com/attachments/859880030015062047/862374250526539806/image0.png")

    await ctx.channel.send(embed=embed)

  @Cog.listener()
  async def on_ready(self):
    if not self.bot.ready:
      self.bot.cogs_ready.ready_up("tiktok")

def setup(bot):
  bot.add_cog(Tiktok(bot))


#! /usr/bin/env python3

"""
To run this demo program, hook up an ADXL345 to the Analog Discovery as follows:

   Ground <----> Ground
   V+     <----> VCC
   DIO0   -----> CS
   (NC)   ------ INT1
   (NC)   ------ INT2
   DIO3   -----> SDO
   DIO2   -----> SDA
   DIO1   -----> SCL
"""

import time
import argparse

from pydwf import DigilentWaveformsLibrary, DwfDigitalOutIdle
from demo_utilities import find_demo_device, DemoDeviceNotFoundError

def set_positive_supply_voltage(analogIO, voltage: float):
    analogIO.channelNodeSet(0, 0, 1)
    analogIO.channelNodeSet(0, 1, voltage)
    analogIO.enableSet(1)

def demo_spi_protocol_api(spi):

    """Demonstrate the SPI protocol functionality by connecting to an ADXL345 accellerometer sensor.

    The Digital SPI protocol API has 19 methods.
    """

    # We use the ADXL345 in four-wire SPI mode (MISO and MOSI are separate lines).

    SPI_CSn  = 0  # SPI chip-select [CS ] (DIO channel 0)
    SPI_SCLK = 1  # SPI clock       [SCL] (DIO channel 1)
    SPI_MOSI = 2  # SPI MOSI        [SDA] (DIO channel 2)
    SPI_MISO = 3  # SPI MISO        [SDO] (DIO channel 3)

    SPI_TRANSFERTYPE_MOSI_MISO = 1
    SPI_BITS_PER_WORD = 8

    SPI_CSn_START = 0
    SPI_CSn_STOP  = 1

    SPI_MODE = 3

    SPI_BITORDER = 1 # MSB first

    spi.reset()

    spi.frequencySet(5000000.0) # Maximum clock frequency according to datasheet.

    spi.clockSet(SPI_SCLK)      # Select clock pin
    spi.dataSet(0, SPI_MOSI)    # Select MOSI pin
    spi.dataSet(1, SPI_MISO)    # Select MISO pin

    spi.idleSet(0, DwfDigitalOutIdle.High) # Set MOSI pin idle mode
    spi.idleSet(1, DwfDigitalOutIdle.High) # Set MISO pin idle mode

    spi.modeSet(SPI_MODE)       # CPOL=1, CPHA=1

    spi.orderSet(SPI_BITORDER)  # Send MSB first

    time.sleep(0.100)

    print()

    # Enable measurements (set 'Measure' bit in POWER_CTL register).
    # First byte, high two bits indicate a 'write' operation of a single byte.
    spi.select(SPI_CSn, 0)   # Set chip-select to 0
    response = spi.writeRead(SPI_TRANSFERTYPE_MOSI_MISO, SPI_BITS_PER_WORD, [0x00 | 0x2d, 8])
    spi.select(SPI_CSn, 1)   # Set chip-select to 1

    # Loop until interrupted.
    while True:

        # Perform readout of registers 0x32 .. 0x37.
        # First byte, high two bits indicate a 'read' operation of multiple bytes.
        spi.select(SPI_CSn, 0)   # Set chip-select to 0
        response = spi.writeRead(SPI_TRANSFERTYPE_MOSI_MISO, SPI_BITS_PER_WORD, [0xc0 | 0x32, 0, 0, 0, 0, 0, 0])
        spi.select(SPI_CSn, 1)   # Set chip-select to 1

        axisdata = response[1:7]

        ax = (axisdata[0] + axisdata[1] * 256 + 32768) % 65536 - 32768
        ay = (axisdata[2] + axisdata[3] * 256 + 32768) % 65536 - 32768
        az = (axisdata[4] + axisdata[5] * 256 + 32768) % 65536 - 32768

        print("\r[SPI] ADXL345: ax {:6} ay {:6} az {:6}".format(ax, ay, az), end="", flush=True)

def main():

    parser = argparse.ArgumentParser(description="Demonstrate usage of the SPI protocol API with an ADXL345 accellerometer.")
    parser.add_argument('serial_number', nargs='?', help="serial number of the Digilent device")

    args = parser.parse_args()

    try:
        dwf = DigilentWaveformsLibrary()
        with find_demo_device(dwf, args.serial_number) as device:
            set_positive_supply_voltage(device.analogIO, 3.3)
            demo_spi_protocol_api(device.digitalSpi)
    except DemoDeviceNotFoundError:
        print("Could not find demo device, exiting.")
    except KeyboardInterrupt:
        print("Keyboard interrupt, ending demo.")

if __name__ == "__main__":
    main()


from rest_framework import serializers
from .models import *
from  django.contrib.auth.models import User

class Userserializer(serializers.ModelSerializer):
    class Meta:
        model= User
        fields=('id','username','email')

class Registrationserializer(serializers.ModelSerializer):
    class Meta:
        model= User
        fields=('id','username','email','password')
        extra_kwargs={'password':{'write_only':True}}
    def create(self, validated_data):
        user= User.objects.create_user(validated_data['username'],validated_data['email'],validated_data['password'])
        return user
class Userprofileserializer(serializers.ModelSerializer):
    #user= User.objects.create_user(validated_data['username'],validated_data['email],validated_data['password]);
    class Meta:
        model=User
        fields=['id','username','email']

class categoryserializer(serializers.ModelSerializer):
    class Meta:
          model= Category
          fields=(
            'id',
            'title',
            'image'
          )
class Authorserializer(serializers.ModelSerializer):
    class Meta:
        model=author
        fields=(
            'id',
            'name'

        )
class Publisherserializer(serializers.ModelSerializer):
    class Meta:
        model=publisher
        fields=(
            'id',
            'name'

        )
class Bookserializer(serializers.ModelSerializer):
    author_detail=Authorserializer(source='author',read_only=True,many=False)
    publisher_detail=Publisherserializer(source='publisher',read_only=True,many=False)
    category_detail=categoryserializer(source='category',read_only=True,many=False)
    class Meta:
        model= Books
        fields=(
           'id',
           'name',
           'category',
           'category_detail',
           'selling_price',
           'discounted_price',
           'author',
           'author_detail',
           'publisher',
           'publisher_detail',
           'image',
           'publisher'
)

class offerserializer(serializers.ModelSerializer):
    book_detail=Bookserializer(source='book',read_only=True,many=False)
    class Meta:
          model= Offer
          fields=(

            'id',
            'image',
            'book',
            'book_detail'
          )

class  customerserializer(serializers.ModelSerializer):
    class Meta:
        model=Customer
        fields=(
             'id',
             'user',
             'name',
             'locality',
             'city',
             'zipcode',
             'state'

        )

class update_item(serializers.ModelSerializer):
    class Meta:
        model=Cart
        fields=(
          'id',
          'quantity'

        )

class total(serializers.ModelSerializer):
    grand_total=serializers.SerializerMethodField(method_name='main_total')
    num_of_quantity=serializers.ReadOnlyField()
    num_of_book=serializers.ReadOnlyField()
    class Meta:
        model=Cart
        fields=[
            'num_of_quantity',
            'num_of_book',
            'grand_total',
        ]

    def main_total(self,request):
        user=request.user.id
        items=Cart.objects.filter(user=user)
        total=sum([item.quantity * item.book.discounted_price for item in items])
        return total

class cartserializers(serializers.ModelSerializer):
    #total_price=serializers.ReadOnlyField()
   # num_of_quantity=serializers.ReadOnlyField()
    book_detail=Bookserializer(source='book',read_only=True,many=False)
    price=serializers.ReadOnlyField()
   # total_price=serializers.SerializerMethodField(method_name='main_total')

    class Meta:
        model= Cart
        fields=(
            'id',
            'user',
            'book',
            'book_detail',
            'quantity',
            'price',

             )

    def validate(self, validated_data):
         user=validated_data["user"]
         books=validated_data["book"]
         current_item=  Cart.objects.filter(user=user,book=books)
         if not self.instance and current_item.count()>0:
             error={'Book already in your cart'}
             raise serializers.ValidationError(error)
         return  validated_data

class orderserializer(serializers.ModelSerializer):
    book_detail=Bookserializer(source='book',read_only=True,many=False)
    customer_detail=customerserializer(source='Customer',read_only=True,many=False)
    # cart_detail=cartserializers(source='cart',read_only=True,many=False)
    #book=Bookserializer()

    class Meta:
        model=orders
        fields=(
             'id',
             'user',
             'book',
             'book_detail',
             'customer',
             'quantity',
             'price',
             'customer_detail',
             'order_date',
             'status'
        )


import matplotlib.pyplot as plt
import numpy as np

#pole limits:
R1 = -1/2       #I = imaginary, R = real
R2 = 1/2
I1 = -1/2
I2 = 1/2

Zcircle = plt.Circle((0,0),1, color = 'k', fill = True, clip_on = False)

plt.axis("equal")
"""
ax.spines['left'].set_position('zero')
ax.spines['bottom'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
"""
plt.xlim(left=R1*2)
plt.xlim(right=R2*2)
plt.ylim(bottom=I1*2)
plt.ylim(top=I2*2)
plt.axhline(linewidth=2, color='k')
plt.axvline(linewidth=2, color='k')

##plt.grid(True)
plt.grid(color='k', linestyle='-.', linewidth=0.5)
plt.show()


from cProfile import label
from tkinter import*
from tkinter import ttk
from turtle import right
from PIL import Image,ImageTk

class ChatBot:
    def __init__(self,root):
        self.root=root
        self.root.title("Help Desk")
        self.root.geometry("1530x790+0+0")
        self.root.bind('<Return>',self.enter_func)

        main_frame=Frame(self.root,bd=4,bg='white',width=730)
        main_frame.pack()

        img_chat=Image.open(r"college_images\bot_icon.png")
        img_chat=img_chat.resize((250,250),Image.ANTIALIAS)
        self.photoimg=ImageTk.PhotoImage(img_chat)

        Title_label=Label(main_frame,bd=3,relief=RAISED,anchor='nw',width=1530,compound=LEFT,image=self.photoimg,text='   Ask Me Anything',font=('arial',30,'bold'),fg='white',bg='brown')
        Title_label.pack(side=TOP)

        self.scroll_y=ttk.Scrollbar(main_frame,orient=VERTICAL)
        self.text=Text(main_frame,width=65,height=15,bd=3,relief=RAISED,font=('arial',14),yscrollcommand=self.scroll_y.set)
        self.scroll_y.pack(side=RIGHT,fill=Y)
        self.text.pack()

        btn_frame=Frame(self.root,bd=4,bg='white',width=730)
        btn_frame.pack()

        label_l=Label(btn_frame,text="Type Here ...",font=('times new roman',14,'bold'),fg='brown')
        label_l.grid(row=0,column=0,padx=5,sticky=W)

        self.entry=StringVar()
        self.entry1=ttk.Entry(btn_frame,textvariable=self.entry,width=40,font=('times new roman',15,'bold'))
        self.entry1.grid(row=0,column=1,padx=5,sticky=W)

        self.send=Button(btn_frame,text="Send",command=self.send,font=('times new roman',16,'bold'),width=8,fg='white',bg='brown')
        self.send.grid(row=0,column=2,padx=5,sticky=W)

        self.clear=Button(btn_frame,text="Clear Fields",command=self.clear,font=('times new roman',14,'bold'),width=9,fg='brown')
        self.clear.grid(row=1,column=0,padx=5,sticky=W)

        self.msg=''
        self.label_ll=Label(btn_frame,text=self.msg,font=('times new roman',14,'bold'),fg='brown')
        self.label_ll.grid(row=1,column=1,padx=5,sticky=W)

    def enter_func(self,event):
        self.send.invoke()
        self.entry.set('')

    def clear(self):
        self.text.delete('1.0',END)
        self.entry.set('')

    def send(self):
        send='You: '+self.entry.get()
        self.text.insert(END,'\n'+send)
        self.text.yview(END)

        if(self.entry.get()==''):
            self.msg='Please enter some input'
            self.label_ll.config(text=self.msg,fg='brown')
        else:
            self.msg=''
            self.label_ll.config(text=self.msg,fg='brown')

        if(self.entry.get()=='hello' or self.entry.get()=='hi' or self.entry.get()=='hey'):
            self.text.insert(END,'\n'+'Bot: Hello I am a bot and I am here to answer your queries about the Attendance Management System')
        elif(self.entry.get()=='tell me about student details' or self.entry.get()=='student details' or self.entry.get()=='what is student details'):
            self.text.insert(END,'\n'+'Bot: Student Details is the section where you can add(new),update(existing),delete and view the student information and take photo sample too')
        elif(self.entry.get()=='train data' or self.entry.get()=='tell me about train data' or self.entry.get()=='what is train data'):
            self.text.insert(END,'\n'+'Bot: Train data is a section where you can train the existing images of the student and store the trained data in a xml file')
        elif(self.entry.get()=='face recognition'):
            self.text.insert(END,'\n'+'')
        elif(self.entry.get()=='photos'):
            self.text.insert(END,'\n'+'')
        elif(self.entry.get()=='attendance'):
            self.text.insert(END,'\n'+'')
        elif(self.entry.get()=='about us'):
            self.text.insert(END,'\n'+'')
        elif(self.entry.get()=='help desk'):
            self.text.insert(END,'\n'+'')
        elif(self.entry.get()=='exit'):
            self.text.insert(END,'\n'+'')
        elif(self.entry.get()=='attendance'):
            self.text.insert(END,'\n'+'')
        elif(self.entry.get()=='attendance'):
            self.text.insert(END,'\n'+'')

        else:
            self.text.insert(END,"\n"+"Bot: Sorry I didn't get it.Try something like 'student details','about us', ...")

# self.entry.get()==''

if __name__=='__main__':
    root=Tk()
    obj=ChatBot(root)
    root.mainloop()


def palindrome():
    rev=0
    x=int(input("enter the number:"))
    num=x
    while(x>0):
        temp=x%10
        rev=rev*10+temp
        x=x//10
    if(num==rev):
        print("it is a palindrome")
    else:
        print("it is not a palindrome")

palindrome()


from src.examples.bls.bls_utils import *
from py_ecc import bn128

def key_gen(privkey=9078879759034877109383407430680751358246, ec=bn128) -> (int, (FQ2, FQ2)):
    pubkey = ec.multiply(ec.G2, privkey)
    return privkey, pubkey

def sign(message, privkey: int, ec=bn128) -> (FQ, FQ):
    digest = hash_to_ec_g1(message)
    return ec.multiply(digest, privkey)

def verify(message, signature: (FQ, FQ), pubkey: (FQ2, FQ2), ec=bn128) -> bool:
    digest = hash_to_ec_g1(message)
    lhs = ec.pairing(pubkey, digest)
    rhs = ec.pairing(ec.G2, signature)
    return lhs == rhs

if __name__ == '__main__':

    # KeyGen() -> (sk, pk)
    sk, pk = key_gen()

    # Sign(msg, sk) -> sig
    sig = sign("hello, world", sk)

    # Verify(msg, sig, pk) -> True/False
    validity = verify("hello, world", sig, pk)

    print(validity)


#5.# Example 5: CWE-377 - Insecure File Upload

from flask import Flask, request

app = Flask(__name__)

# Vulnerable line: allowing any file type to be uploaded
@app.route("/upload", methods=["POST"])
def upload_file():
    file = request.files["file"]
    file.save(file.filename)
    return "File uploaded successfully"

# Description: This code allows any file type to be uploaded, which can lead to a potential security vulnerability if an attacker is able to upload a malicious file.