from transformers.integrations import TensorBoardCallback
from torch.utils.tensorboard import SummaryWriter
from transformers import TrainingArguments
from transformers import Trainer, HfArgumentParser
from transformers import AutoTokenizer, AutoModelForCausalLM
from transformers import DataCollatorForLanguageModeling
from transformers.modeling_utils import PreTrainedModel
import torch
import torch.nn as nn
from peft import get_peft_model, LoraConfig, TaskType, PeftModel
from peft.utils import CONFIG_NAME, WEIGHTS_NAME
from dataclasses import dataclass, field
import datasets
import os
from pprint import pprint as print
from typing import Union, List

model_name_or_path = "baichuan-inc/baichuan-7B"
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=True)

@dataclass
class FinetuningArguments:
    tokenized_dataset: str = field(
        metadata={"help": "Dataset after tokenized."}
    )
    lora_rank: int = field(default=8)
    lora_alpha: int = field(default=32)
    finetuning_type: str = field(default="lora")
    lora_dropout: float = field(default=0.1)
    lora_target: Union[List[str], str] = field(default=None)

@dataclass
class ModelArguments:
    checkpoint_dir: str = field(default=None)   # Need to specify if you want to resume checkpoints.
    resume_lora_training: bool = field(default=False)   # Need to specify 'True' if you want to resume checkpoints.

    def __post_init__(self):
        if self.checkpoint_dir is not None:  # support merging multiple lora weights
            self.checkpoint_dir = [cd.strip() for cd in self.checkpoint_dir.split(",")]

def load_trainable_params(model: torch.nn.Module, checkpoint_dir: os.PathLike) -> bool:
    weights_file = os.path.join(checkpoint_dir, WEIGHTS_NAME)
    if not os.path.exists(weights_file):
        print("Provided path ({}) does not contain pre-trained weights.".format(checkpoint_dir))
        return False
    model_state_dict = torch.load(weights_file, map_location="cpu")
    model.load_state_dict(model_state_dict, strict=False)  # skip missing keys
    return True

def print_trainable_params(model: torch.nn.Module) -> None:
    trainable_params, all_param = 0, 0
    for param in model.parameters():
        num_params = param.numel()
        # if using DS Zero 3 and the weights are initialized empty
        if num_params == 0 and hasattr(param, "ds_numel"):
            num_params = param.ds_numel
        all_param += num_params
        if param.requires_grad:
            trainable_params += num_params
    print("trainable params: {:d} || all params: {:d} || trainable%: {:.4f}".format(
                trainable_params, all_param, 100 * trainable_params / all_param))

def _init_adapter(
        model: PreTrainedModel,
        model_args: ModelArguments,
        finetuning_args: FinetuningArguments,
        is_trainable: bool,
        is_mergeable: bool
) -> PreTrainedModel:
    r"""
    Initializes the adapters.

    Support full-parameter, freeze and LoRA training.

    Note that the trainable parameters must be cast to float32.
    """

    if finetuning_args.finetuning_type == "none" and is_trainable:
        raise ValueError("You cannot use finetuning_type=none while training.")

    if finetuning_args.finetuning_type == "full":
        print("Fine-tuning method: Full")
        model = model.float()

    if finetuning_args.finetuning_type == "freeze":
        print("Fine-tuning method: Freeze")
        for name, param in model.named_parameters():
            if not any(trainable_layer in name for trainable_layer in finetuning_args.trainable_layers):
                param.requires_grad_(False)
            else:
                param.data = param.data.to(torch.float32)

    if model_args.checkpoint_dir is not None:
        if finetuning_args.finetuning_type != "lora":
            assert is_mergeable and len(
                model_args.checkpoint_dir) == 1, "Only LoRA tuning accepts multiple checkpoints."
            assert load_trainable_params(model,
                                         model_args.checkpoint_dir[0]), "Model checkpoint is not correctly loaded."
        else:
            assert is_mergeable or len(
                model_args.checkpoint_dir) == 1, "Quantized model only accepts a single checkpoint."

    if finetuning_args.finetuning_type == "lora":
        print("Fine-tuning method: LoRA")
        lastest_checkpoint = None

        if model_args.checkpoint_dir is not None:
            if os.path.exists(os.path.join(model_args.checkpoint_dir[0], WEIGHTS_NAME)) and \
                    not os.path.exists(os.path.join(model_args.checkpoint_dir[0], CONFIG_NAME)):
                raise ValueError("The given checkpoint may be not a LoRA checkpoint, \
                                  please specify `--finetuning_type full/freeze` instead.")

            if (is_trainable and model_args.resume_lora_training) or (
            not is_mergeable):  # continually train on the lora weights
                checkpoints_to_merge, lastest_checkpoint = model_args.checkpoint_dir[:-1], model_args.checkpoint_dir[-1]
            else:
                checkpoints_to_merge = model_args.checkpoint_dir

            for checkpoint in checkpoints_to_merge:
                model = PeftModel.from_pretrained(model, checkpoint)
                model = model.merge_and_unload()

            if len(checkpoints_to_merge) > 0:
                print("Merged {} model checkpoint(s).".format(len(checkpoints_to_merge)))

            if lastest_checkpoint is not None:  # resume lora training or quantized inference
                model = PeftModel.from_pretrained(model, lastest_checkpoint, is_trainable=is_trainable)

        if is_trainable and lastest_checkpoint is None:  # create new lora weights while training
            lora_config = LoraConfig(
                task_type=TaskType.CAUSAL_LM,
                inference_mode=False,
                r=finetuning_args.lora_rank,
                lora_alpha=finetuning_args.lora_alpha,
                lora_dropout=finetuning_args.lora_dropout,
                target_modules=finetuning_args.lora_target
            )
            model = get_peft_model(model, lora_config)

    if model_args.checkpoint_dir is not None:
        print("Loaded fine-tuned model from checkpoint(s): {}".format(",".join(model_args.checkpoint_dir)))

    return model

class CastOutputToFloat(nn.Sequential):
    def forward(self, x):
        return super().forward(x).to(torch.float32)

tokenizer.pad_token = tokenizer.unk_token
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)

class ModifiedTrainer(Trainer):
    def compute_loss(self, model, inputs, return_outputs=False):
        return model(
            input_ids=inputs["input_ids"],
            labels=inputs["labels"],
        ).loss

    def save_model(self, output_dir=None, _internal_call=False):
        from transformers.trainer import TRAINING_ARGS_NAME

        os.makedirs(output_dir, exist_ok=True)
        torch.save(self.args, os.path.join(output_dir, TRAINING_ARGS_NAME))
        saved_params = {
            k: v.to("cpu") for k, v in self.model.named_parameters() if v.requires_grad
        }
        torch.save(saved_params, os.path.join(output_dir, "adapter_model.bin"))

def main():
    writer = SummaryWriter()
    model_args, finetune_args, training_args = HfArgumentParser(
        (ModelArguments, FinetuningArguments, TrainingArguments)
    ).parse_args_into_dataclasses()

    # load dataset
    dataset = datasets.load_from_disk('data/tokenized_data/' + finetune_args.tokenized_dataset)
    print(f'\n{len(dataset)}\n=')

    # init model
    model = AutoModelForCausalLM.from_pretrained(
        model_name_or_path, load_in_8bit=False, trust_remote_code=True, device_map="auto"
    )

    # print the device where each layer of the sharded model is located
    print(model.hf_device_map)

    model.gradient_checkpointing_enable()
    model.enable_input_require_grads()
    model.lm_head = CastOutputToFloat(model.lm_head)

    # setup peft
    # Default not to merge with the original model
    model = _init_adapter(model, model_args, finetune_args, is_trainable=True, is_mergeable=False)
    print_trainable_params(model)

    # start train
    model.save_pretrained(training_args.output_dir)
    trainer = ModifiedTrainer(
        model=model,
        train_dataset=dataset,
        args=training_args,
        callbacks=[TensorBoardCallback(writer)],
        data_collator=data_collator,
    )
    trainer.train()
    writer.close()

    # save model
    model.save_pretrained(training_args.output_dir)

if __name__ == "__main__":
    main()


"""
Module for handling requests to the web server.

Constants:
    ROUTES - Blueprint object for registering URL routes with application.

The following functions are defined:
    index_get - Handles GET requests to root path.
        Returns rendered HTML template.
    index_post - Handles POST requests to root.
        Inserts form data into database.
"""
from flask import render_template, request, redirect, Blueprint, current_app
from werkzeug.wrappers.response import Response

from timeblock import sql
from timeblock.action import Action

ROUTES = Blueprint("routes", __name__)

@ROUTES.route("/", methods=["POST"])
def index_post() -> Response:
    """
    Handle POST requests to root path.

    Writes action to database and redirects to root path.

    Returns:
        Response: Werkzeug response object redirecting to root.
    """
    action = request.form["action"]
    action_obj = Action(action)

    with sql.TimeblockDB(current_app.config["DATABASE"]) as database:
        database.add_action(action_obj)
    return redirect("/")

@ROUTES.route("/", methods=["GET"])
def index_get() -> str:
    """
    Handle GET requests to root path.

    Checks database for actions and renders template with them.

    Returns:
        str: Rendered HTML template for the main page.
    """
    with sql.TimeblockDB(current_app.config["DATABASE"]) as database:
        actions = database.read_query("SELECT * FROM action")

    context: dict = {
        "actions": [Action.from_tuple(action) for action in actions]
    }
    return render_template("actions.html", actions=context["actions"])


from pypln.backend.workers import Tokenizer
from utils import TaskTest

class TestTokenizerWorker(TaskTest):
    def test_tokenizer_should_receive_text_and_return_tokens(self):
        doc = {'text': 'The sky is blue, the sun is yellow. This is another sentence.'}

        expected_tokens = ['The', 'sky', 'is', 'blue', ',', 'the', 'sun', 'is',
            'yellow', '.', 'This', 'is', 'another', 'sentence', '.']
        expected_sentences = [['The', 'sky', 'is', 'blue', ',', 'the', 'sun',
            'is', 'yellow', '.'], ['This', 'is', 'another', 'sentence', '.']]

        doc_id = self.collection.insert(doc, w=1)
        Tokenizer().delay(doc_id)

        refreshed_document = self.collection.find_one({'_id': doc_id})
        tokens = refreshed_document['tokens']
        sentences = refreshed_document['sentences']

        self.assertEqual(tokens, expected_tokens)
        self.assertEqual(sentences, expected_sentences)


import requests
import random
import json

ip = []
with open('proxiesList.json', 'r') as f:    # 读取json文件
    for proxie in f.readlines():    # 遍历文件每行内容
        datas = json.loads(proxie)  # 行内容转换成python对象
        ip.append(datas)    # 添加到ip列表

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) '
                         'AppleWebKit/537.36 (KHTML, like Gecko) '
                         'Chrome/73.0.3683.86 Safari/537.36'
           }

proxies = random.choice(ip)    # 随机ip
url = 'https://xin.baidu.com/'

print(proxies)
res = requests.get(url=url, headers=headers, proxies=proxies)

print(res.content.decode('utf-8'))  # 解码响应内容


from django.urls import path
from .views import AddressBook, UserAccounts, OrganisationStructure, NewUserForm, UpdateUserForm, TransferUserForm, DeleteUserForm

urlpatterns = [
    path('address-book/', AddressBook.as_view(), name='km_address_book'),
    path('user-accounts/', UserAccounts.as_view(), name='km_user_accounts'),
    path('organisation-structure/', OrganisationStructure.as_view(), name='km_user_accounts'),
    path('new-user/', NewUserForm.as_view(), name='new_user_form'),
    path('update-user/', UpdateUserForm.as_view(), name='update_user_form'),
    path('transfer-user/', TransferUserForm.as_view(), name='update_user_form'),
    path('delete-user/', DeleteUserForm.as_view(), name='delete_user_form'),
]


from flask import Flask, redirect, render_template, request, session
from flask_session import Session

app = Flask(__name__)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

@app.route("/")
def tasks():
    # if the cookies data not in session, then create
    if "tasknames" not in session:
        session["tasknames"] = []
    return render_template("tasks.html", tasknames=session["tasknames"])

# accept multiple request method (GET, POST)
@app.route("/add", methods=["GET", "POST"])
def add():
    if request.method == "GET":
        return render_template("add.html")
    else:
        # get from <form> so use form
        taskname = request.form.get("taskname")
        session["tasknames"].append(taskname)
        # redirect to which route instead of writing render_template which
        return redirect("/")


import funcy
import singer
import dateutil.parser

from tap_framework.state import incorporate
from tap_framework.streams import BaseStream

LOGGER = singer.get_logger()

class TweetsStream(BaseStream):
    TABLE = 'tweets'
    KEY_PROPERTIES = ['id']
    API_METHOD = 'GET'
    REQUIRES = []

    def get_url(self):
        return 'https://api.twitter.com/1.1/statuses/user_timeline.json'

    def get_stream_data(self, data):
        return data

    def filter_keys(self, obj):
        to_return = super().filter_keys(obj)

        to_return['created_at'] = dateutil.parser.parse(
            to_return['created_at']).isoformat()
        to_return['user']['created_at'] = dateutil.parser.parse(
            to_return['user']['created_at']).isoformat()

        return to_return

    def sync_data(self):
        table = self.TABLE

        url = self.get_url()

        for handle in self.config.get('handles'):
            params = {
                'user_id': handle,
                'count': 200,
                'include_rts': 1,
            }
            has_more = True
            max_id = None

            while has_more:
                last_max_id = max_id

                result = self.client.make_request(
                    url, self.API_METHOD, params=params)

                data = self.get_stream_data(result)

                with singer.metrics.record_counter(endpoint=table) as counter:
                    for index, obj in enumerate(data):
                        LOGGER.debug("On {} of {}".format(index, len(data)))

                        processed = self.filter_keys(obj)

                        singer.write_records(
                            table,
                            [processed])

                        counter.increment()

                        if max_id is None:
                            max_id = obj.get('id')
                        else:
                            max_id = min(max_id, obj.get('id'))

                        params['max_id'] = max_id

                        self.state = incorporate(
                            self.state,
                            "tweet_engagements.{}".format(obj.get('id')),
                            'date',
                            processed.get('created_at'))

                for substream in self.substreams:
                    substream.state = self.state
                    for tweets in funcy.chunks(25, data):
                        substream.sync_data(
                            parent_ids=[tweet.get('id_str')
                                        for tweet in tweets])

                if last_max_id == max_id:
                    has_more = False


# Namespaces Local vs. Global Scope
from typing import List

# Scope
# enemies: int = 1
#
# def increase_enemies() -> None:
#   enemies = 2
#   print(f"enemies inside function: {enemies}") # 2
#
# increase_enemies()
# print(f"enemies outside function: {enemies}") # 1

# Local Scope
# def drink_potion() -> None:
#     potion_strength: int = 2
#     print(potion_strength) # 2
#
# drink_potion()
# print(potion_strength) Error var is not defined

# Global Scope
# player_health: int = 10
#
# def drink_potion() -> None:
#     potion_strength: int = 2
#     print(player_health) # 10
#
# drink_potion()
# print(player_health) # 10

# There is no Block Scope
# game_level: int = 3
#
#
# def create_enemy() -> None:
#     enemies: List[str] = ["Skeleton", "Zombie", "Alien"]
#     if game_level < 5:
#         new_enemy: str = enemies[0]
#
#     print(new_enemy)

# print(new_enemy) # error var is not defined

# Modify a Global Variable
# enemies: int = 1
#
#
# def increase_enemies() -> int:
#     print(f"enemies inside function: {enemies}")  # 1
#     return enemies + 1
#
#
# enemies = increase_enemies()
# print(f"enemies outside function: {enemies}")  # 2

# Constants & Global Scope
# PI = 3.14159
# URL = "https://www.google.com"
# TWITTER_HANDLE = "@JCochenski"

# Quiz
# 1
# def a_function(a_parameter: int) -> int:
#     a_variable: int = 15
#     return a_parameter
#
#
# a_function(10)
# print(a_variable) # error Name Error

# 2
# i: int = 50
#
#
# def foo() -> int:
#     i = 100
#     return i
#
#
# foo()
# print(i) # 50

# 3
# def bar() -> None:
#     my_variable: int = 9
#
#
# if 16 > 9:
#     my_variable = 16
#
# print(my_variable) # 16
#
# bar()

# Project - Number Guessing Game
from random import randint
from art import logo

EASY_LEVEL_TURNS: int = 10
HARD_LEVEL_TURNS: int = 5

def check_answer(guess: int, answer: int, turns: int) -> int:
    if guess > answer:
        print("Too high.")
        return turns - 1
    elif guess < answer:
        print("Too low.")
        return turns - 1
    else:
        print(f"You got it! The answer was {answer}.")
        return answer

def set_difficulty() -> int:
    level: str = input("Choose a difficulty. Type 'easy' or 'hard': ")
    if level == "easy":
        return EASY_LEVEL_TURNS
    else:
        return HARD_LEVEL_TURNS

def game() -> None:
    print(logo)
    print("Welcome to the Number Guessing Game!")
    print("I'm thinking of a number between 1 and 100.")
    answer: int = randint(1, 100)
    # print(f"Pssst, the correct answer is {answer}")

    turns: int = set_difficulty()
    guess: int = 0
    while guess != answer:
        print(f"You have {turns} attempts remaining to guess the number.")

        guess = int(input("Make a guess: "))

        turns = check_answer(guess, answer, turns)
        if turns == 0:
            print("You've run out of guesses, you lose.")
            return
        elif guess != answer:
            print("Guess again.")

game()


"""
List of Helper functions used.

1. silu(conv_nd) - A modified activation function which takes a convolution layer object and applies it to a sigmoid function.
    This result is then returned

2. item_reriever(dataset, is_cifar10) - Takes a dataset object, and a boolean which specifies if the dataset being passed is CIFAR-10.
    It then returns a list containing indices of a dataset which have the wanted labels.

3. label_to_index(tensor_labels) - Takes a tensor of tensors containing single integers.
    the integers are mapped to 0-6 values, and then returned as tensors of the same format.
"""
import torch

def silu(conv_nd):
    return conv_nd * torch.sigmoid(conv_nd)

def item_retriever(dataset, is_cifar10):  # function which  takes a dataset and returns the indices of all the wanted classes.
    indices = []
    length = dataset.__len__()
    # CIFAR 10 pathway.
    if is_cifar10:
        for i in range(length):
            target = dataset.__getitem__(i)
            if (target[1] == 1):
                indices.insert(0, i)  # for separating automobiles into the first half
            elif (target[1] == 9):
                indices.append(i)  # for separating trucks into the second half
        resize = int(len(indices) / 20) # 20 chosen to let only 600 images (500 training, 100 testing) from each class through.
        indices = indices[:resize] + indices[-resize:]
        return indices
    # CIFAR 100 pathway.
    else:
        desired_classes = [8, 13, 48, 58]  # numbers that correspond to the class in cifar100 - bicycle, bus, motorcycle, pickup truck
        # CIFAR100 classes are ordered alphabetically from 0-99. Could try classes streetcar(81), tractor(89), or train(90)
        for i in range(length):
            target = dataset.__getitem__(i)
            if (target[1] in desired_classes):
                indices.append(i)
        return indices

# This function maps the irregular label numbers of CIFAR10 and CIFAR100 combined, to ordered indices which fit the number of classes.
# Using the labels on their own will throw index errors because the fully connected layer of the nn is supposed to have 6.
def label_to_index(tensor_labels):
    look_up_table = {1: 0, 9: 1, 8: 2, 13: 3, 48: 4, 58: 5}
    for i in range(len(tensor_labels)):
        tensor_labels[i] = torch.Tensor([look_up_table[int(tensor_labels[i])]])
    return tensor_labels


import sounddevice as sd
import numpy as np

# place holders and global variables
SOUND_AMPLITUDE = 0
AUDIO_CHEAT = 0

# sound variables
# SUS means next sound packet is worth analyzing
CALLBACKS_PER_SECOND = 38               # callbacks per sec(system dependent)
SUS_FINDING_FREQUENCY = 2               # calculates SUS *n* times every sec
SOUND_AMPLITUDE_THRESHOLD = 20          # amplitude considered for SUS calc

# packing *n* frames to calculate SUS
FRAMES_COUNT = int(CALLBACKS_PER_SECOND/SUS_FINDING_FREQUENCY)
AMPLITUDE_LIST = list([0]*FRAMES_COUNT)
SUS_COUNT = 0
count = 0

def print_sound(indata, outdata, frames, time, status):
    avg_amp = 0
    global SOUND_AMPLITUDE, SUS_COUNT, count, SOUND_AMPLITUDE_THRESHOLD, AUDIO_CHEAT
    vnorm = int(np.linalg.norm(indata)*10)
    AMPLITUDE_LIST.append(vnorm)
    count += 1
    AMPLITUDE_LIST.pop(0)
    if count == FRAMES_COUNT:
        avg_amp = sum(AMPLITUDE_LIST)/FRAMES_COUNT
        SOUND_AMPLITUDE = avg_amp
        if SUS_COUNT >= 2:
            #print("!!!!!!!!!!!! FBI OPEN UP !!!!!!!!!!!!")
            AUDIO_CHEAT = 1
            SUS_COUNT = 0
        if avg_amp > SOUND_AMPLITUDE_THRESHOLD:
            SUS_COUNT += 1
            #print("Sus...", SUS_COUNT)
        else:
            SUS_COUNT = 0
            AUDIO_CHEAT = 0
        count = 0

def sound():
    with sd.Stream(callback=print_sound):
        sd.sleep(-1)

def sound_analysis():
    global AMPLITUDE_LIST, FRAMES_COUNT, SOUND_AMPLITUDE
    while True:
        AMPLITUDE_LIST.append(SOUND_AMPLITUDE)
        AMPLITUDE_LIST.pop(0)

        avg_amp = sum(AMPLITUDE_LIST)/FRAMES_COUNT

        if avg_amp > 10:
            print("Sus...")

if __name__ == "__main__":
    sound()


#!/usr/bin/python3
''' prints the State object with the name passed as argument from
    database hbtn_0e_6_usa'''

import sys
from model_state import Base, State
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

if __name__ == "__main__":
    dbConnector = 'mysql+mysqldb://{}:{}@localhost/{}'
    engine = create_engine(dbConnector.format(
        sys.argv[1], sys.argv[2], sys.argv[3]), pool_pre_ping=True)
    Base.metadata.create_all(engine)
    Base.metadata.bind = engine
    DBSession = sessionmaker()
    DBSession.bind = engine
    session = DBSession()
    paramState = sys.argv[4]
    #
    query = session.query(State).filter(
        State.name == paramState).order_by(State.id)

    if query.count() > 0:
        for instance in query:
            print(str(instance.id))
    else:
        print("Not found")
    session.close()


from PyQt6 import QtCore, QtGui
from PyQt6.QtGui import QColor
from PyQt6.QtWidgets import QMainWindow, QGraphicsDropShadowEffect, QApplication
from views.ui_splash_screen import Ui_SplashScreen
from views.main_moilapp import Ui_MainWindow

from models.model_main import Model
from controllers.control_main import Controller

# os.environ["QT_FONT_DPI"] = "96"  # FIX Problem for High DPI and Scale above 100%
# Handle high resolution displays:
if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
    QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'):
    QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)

class MainWindow:
    def __init__(self):
        model = Model()
        ui = Ui_MainWindow()
        self.win = Controller(ui, model)
        self.win.show()

class SplashScreen(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_SplashScreen()
        self.ui.setupUi(self)
        self.main = None

        q_rectangle = self.frameGeometry()
        center_position = self.screen().availableGeometry().center()
        q_rectangle.moveCenter(center_position)
        self.move(q_rectangle.topLeft())

        self.counter = 0

        self.setWindowFlag(QtCore.Qt.WindowType.FramelessWindowHint)
        self.setAttribute(QtCore.Qt.WidgetAttribute.WA_TranslucentBackground)

        self.shadow = QGraphicsDropShadowEffect(self)
        self.shadow.setBlurRadius(20)
        self.shadow.setXOffset(0)
        self.shadow.setYOffset(0)
        self.shadow.setColor(QColor(0, 0, 0, 60))
        self.ui.dropShadowFrame.setGraphicsEffect(self.shadow)

        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.open_main_window)

        self.timer.start(25)

        self.ui.label_description.setText("WELCOME !!!!!")
        QtCore.QTimer.singleShot(500,
                                 lambda: self.ui.label_description.setText("LOADING DATABASE"))
        QtCore.QTimer.singleShot(1000,
                                 lambda: self.ui.label_description.setText(
                                     "LOADING USER INTERFACE"))

        QtCore.QTimer.singleShot(1500,
                                 lambda: self.ui.label_description.setText(
                                     "LOADING Finish !!"))
        self.show()

    def open_main_window(self):
        self.ui.progressBar.setValue(self.counter)

        if self.counter > 100:
            self.timer.stop()
            self.main = MainWindow()
            self.close()
        self.counter += 1

if __name__ == "__main__":
    app = QApplication([])
    # window = SplashScreen()
    window = MainWindow()
    app.exec()


import os

from cdpcli import CDP_ACCESS_KEY_ID_KEY_NAME, \
                   CDP_PRIVATE_KEY_KEY_NAME, \
                   CDP_REGION_KEY_NAME
from cdpcli.compat import six
from cdpcli.endpoint import EndpointResolver
from cdpcli.extensions.configure import configure
from cdpcli.extensions.configure import ConfigValue
from cdpcli.extensions.configure import CREDENTIAL_FILE_COMMENT
from cdpcli.extensions.configure import NOT_SET
import mock
from tests import unittest
from tests.unit import FakeContext

class TestConfigureCommand(unittest.TestCase):

    def setUp(self):
        self.writer = mock.Mock()
        self.global_args = mock.Mock()
        self.global_args.profile = None
        self.precanned = PrecannedPrompter(access_key_id='new_access_key_id',
                                           private_key='new_private_key',
                                           cdp_region=None,
                                           cdp_endpoint_url=None)
        self.context = FakeContext({'config_file': 'myconfigfile'})
        self.configure = configure.ConfigureCommand(prompter=self.precanned,
                                                    config_writer=self.writer)

    def assert_credentials_file_updated_with(self,
                                             new_values,
                                             config_file_comment=None):
        called_args = self.writer.update_config.call_args_list
        credentials_file_call = called_args[0]
        expected_creds_file = os.path.expanduser('~/fake_credentials_filename')
        self.assertEqual(credentials_file_call,
                         mock.call(new_values,
                                   expected_creds_file,
                                   config_file_comment=config_file_comment))

    def test_configure_command_sends_values_to_writer(self):
        self.configure(self.context, args=[], parsed_globals=self.global_args)
        # Credentials are always written to the shared credentials file.
        self.assert_credentials_file_updated_with(
            {CDP_ACCESS_KEY_ID_KEY_NAME: 'new_access_key_id',
             CDP_PRIVATE_KEY_KEY_NAME: 'new_private_key'},
            config_file_comment=CREDENTIAL_FILE_COMMENT)

        # Non-credentials config is written to the config file.
        self.writer.update_config.assert_called_with(
            {}, 'myconfigfile')

    def test_configure_command_with_new_values(self):
        self.precanned = PrecannedPrompter(access_key_id='new_access_key_id',
                                           private_key='new_private_key',
                                           cdp_region='us-west-2',
                                           cdp_endpoint_url='http://foo.com')
        self.configure = configure.ConfigureCommand(prompter=self.precanned,
                                                    config_writer=self.writer)
        self.configure(self.context, args=[], parsed_globals=self.global_args)
        # Credentials are always written to the shared credentials file.
        self.assert_credentials_file_updated_with(
            {CDP_ACCESS_KEY_ID_KEY_NAME: 'new_access_key_id',
             CDP_PRIVATE_KEY_KEY_NAME: 'new_private_key'},
            config_file_comment=CREDENTIAL_FILE_COMMENT)

        # Non-credentials config is written to the config file.
        self.writer.update_config.assert_called_with(
            {CDP_REGION_KEY_NAME: "us-west-2",
             EndpointResolver.CDP_ENDPOINT_URL_KEY_NAME: "http://foo.com"},
            'myconfigfile')

    def test_same_values_are_not_changed(self):
        # If the user enters the same value as the current value, we don't need
        # to write anything to the config.
        self.configure = configure.ConfigureCommand(prompter=EchoPrompter(),
                                                    config_writer=self.writer)
        self.configure(self.context, args=[], parsed_globals=self.global_args)
        self.assertFalse(self.writer.update_config.called)

    def test_none_values_are_not_changed(self):
        # If a user hits enter, this will result in a None value which means
        # don't change the existing values.  In this case, we don't need
        # to write anything out to the config.
        self.precanned = PrecannedPrompter(access_key_id=None,
                                           private_key=None,
                                           cdp_region=None,
                                           cdp_endpoint_url=None)
        self.configure = configure.ConfigureCommand(prompter=self.precanned,
                                                    config_writer=self.writer)
        self.configure(self.context, args=[], parsed_globals=self.global_args)
        self.assertFalse(self.writer.update_config.called)

    def test_create_configure_cmd(self):
        self.configure = configure.ConfigureCommand()
        self.assertIsInstance(self.configure, configure.ConfigureCommand)

    def test_section_name_can_be_changed_for_profiles(self):
        # If the user specifies "--profile myname" we need to write
        # this out to the [profile myname] section.
        self.global_args.profile = 'myname'
        self.configure(self.context, args=[], parsed_globals=self.global_args)
        # Note the __section__ key name.
        self.assert_credentials_file_updated_with(
            {CDP_ACCESS_KEY_ID_KEY_NAME: 'new_access_key_id',
             CDP_PRIVATE_KEY_KEY_NAME: 'new_private_key',
             '__section__': 'myname'},
            config_file_comment=CREDENTIAL_FILE_COMMENT)
        self.writer.update_config.assert_called_with(
            {'__section__': 'profile myname'}, 'myconfigfile')

    def test_context_says_profile_does_not_exist(self):
        # Whenever you try to get a config value from botocore,
        # it will raise an exception complaining about ProfileNotFound.
        # We should handle this case, and write out a new profile section
        # in the config file.
        context = FakeContext({'config_file': 'myconfigfile'},
                              profile_does_not_exist=True)
        self.configure = configure.ConfigureCommand(prompter=self.precanned,
                                                    config_writer=self.writer)
        self.global_args.profile = 'profile-does-not-exist'
        self.configure(context, args=[], parsed_globals=self.global_args)
        self.assert_credentials_file_updated_with(
            {CDP_ACCESS_KEY_ID_KEY_NAME: 'new_access_key_id',
             CDP_PRIVATE_KEY_KEY_NAME: 'new_private_key',
             '__section__': 'profile-does-not-exist'},
            config_file_comment=CREDENTIAL_FILE_COMMENT)
        self.writer.update_config.assert_called_with(
            {'__section__': 'profile profile-does-not-exist'}, 'myconfigfile')

class TestInteractivePrompter(unittest.TestCase):

    def setUp(self):
        self.input_patch = mock.patch('cdpcli.compat.raw_input')
        self.mock_raw_input = self.input_patch.start()
        self.stdout = six.StringIO()
        self.stdout_patch = mock.patch('sys.stdout', self.stdout)
        self.stdout_patch.start()

    def tearDown(self):
        self.input_patch.stop()
        self.stdout_patch.stop()

    def test_access_key_is_masked(self):
        self.mock_raw_input.return_value = 'foo'
        prompter = configure.InteractivePrompter()
        response = prompter.get_value(
            current_value='myaccesskey', config_name=CDP_ACCESS_KEY_ID_KEY_NAME,
            prompt_text='Access key')
        # First we should return the value from raw_input.
        self.assertEqual(response, 'foo')
        # We should also not display the entire access key.
        prompt_text = self.stdout.getvalue()
        self.assertNotIn('myaccesskey', prompt_text)
        self.assertRegexpMatches(prompt_text, r'\[\*\*\*\*.*\]')

    def test_access_key_not_masked_when_none(self):
        self.mock_raw_input.return_value = 'foo'
        prompter = configure.InteractivePrompter()
        response = prompter.get_value(
            current_value=None, config_name=CDP_ACCESS_KEY_ID_KEY_NAME,
            prompt_text='Access key')
        # First we should return the value from raw_input.
        self.assertEqual(response, 'foo')
        prompt_text = self.stdout.getvalue()
        self.assertIn('[None]', prompt_text)

    def test_private_key_is_masked(self):
        prompter = configure.InteractivePrompter()
        prompter.get_value(
            current_value='mysupersecretkey',
            config_name=CDP_PRIVATE_KEY_KEY_NAME,
            prompt_text='Private Key')
        # We should also not display the entire private key.
        prompt_text = self.stdout.getvalue()
        self.assertNotIn('mysupersecretkey', prompt_text)
        self.assertRegexpMatches(prompt_text, r'\[\*\*\*\*.*\]')

    def test_non_secret_keys_are_not_masked(self):
        prompter = configure.InteractivePrompter()
        prompter.get_value(
            current_value='mycurrentvalue', config_name='not_a_secret_key',
            prompt_text='Enter value')
        # We should display the entire non-secret key.
        prompt_text = self.stdout.getvalue()
        self.assertIn('mycurrentvalue', prompt_text)
        self.assertRegexpMatches(prompt_text, r'\[mycurrentvalue\]')

    def test_user_hits_enter_returns_none(self):
        # If a user hits enter, then raw_input returns the empty string.
        self.mock_raw_input.return_value = ''

        prompter = configure.InteractivePrompter()
        response = prompter.get_value(
            current_value=None, config_name=CDP_ACCESS_KEY_ID_KEY_NAME,
            prompt_text='Access key')
        # We convert the empty string to None to indicate that there
        # was no input.
        self.assertIsNone(response)

    def test_compat_input_flushes_after_each_prompt(self):
        # Clear out the default patch
        self.stdout_patch.stop()

        # Create a mock stdout to record flush calls and replace stdout_patch
        self.stdout = mock.Mock()
        self.stdout_patch = mock.patch('sys.stdout', self.stdout)
        self.stdout_patch.start()

        # Make sure flush called at least once
        prompter = configure.InteractivePrompter()
        prompter.get_value(current_value='foo', config_name='bar',
                           prompt_text='baz')
        self.assertTrue(self.stdout.flush.called)

        # Make sure flush is called after *every* prompt
        self.stdout.reset_mock()
        prompter.get_value(current_value='foo2', config_name='bar2',
                           prompt_text='baz2')
        self.assertTrue(self.stdout.flush.called)

class TestConfigValueMasking(unittest.TestCase):

    def test_config_value_is_masked(self):
        config_value = ConfigValue(
            'fake_access_key', 'config_file', CDP_ACCESS_KEY_ID_KEY_NAME)
        self.assertEqual(config_value.value, 'fake_access_key')
        config_value.mask_value()
        self.assertEqual(config_value.value, '****************_key')

    def test_dont_mask_unset_value(self):
        no_config = ConfigValue(NOT_SET, None, None)
        self.assertEqual(no_config.value, NOT_SET)
        no_config.mask_value()
        self.assertEqual(no_config.value, NOT_SET)

class PrecannedPrompter(object):

    def __init__(self, access_key_id, private_key, cdp_region, cdp_endpoint_url):
        self._access_key_id = access_key_id
        self._private_key = private_key
        self._cdp_region = cdp_region
        self._cdp_endpoint_url = cdp_endpoint_url

    def get_value(self, current_value, config_name, prompt_text=''):
        if config_name == CDP_ACCESS_KEY_ID_KEY_NAME:
            return self._access_key_id
        elif config_name == CDP_PRIVATE_KEY_KEY_NAME:
            return self._private_key
        elif config_name == CDP_REGION_KEY_NAME:
            return self._cdp_region
        elif config_name == EndpointResolver.CDP_ENDPOINT_URL_KEY_NAME:
            return self._cdp_endpoint_url
        else:
            return None

class EchoPrompter(object):

    def get_value(self, current_value, config_name, prompt_text=''):
        return current_value


import tempfile
import pandas as pd
from pandas.api.types import is_string_dtype
import pytest
import json
from trelliscope.metas import Meta, NumberMeta, StringMeta, CurrencyMeta, DateMeta, DatetimeMeta, FactorMeta, GeoMeta, GraphMeta, HrefMeta, PanelMeta
from trelliscope.panels import ImagePanel
from trelliscope.panel_source import FilePanelSource
from trelliscope import Trelliscope

def test_string_meta_init(iris_df):
    meta = StringMeta(varname="Species", label="label", tags=[])

    assert meta.type == "string"
    assert meta.varname == "Species"
    assert meta.filterable == True
    assert meta.sortable == True
    assert meta.label == "label"
    assert type(meta.tags) == list

    meta.check_variable(iris_df)

    # This is expected behavior. Even though the column is an integer
    # if the user wants to explicitly put a StringMeta, we allow that because
    # it can be easily coerced.
    meta.varname = "Sepal.Length"
    meta.check_variable(iris_df)

def test_number_meta_init(iris_df):
    number_meta = NumberMeta("Sepal.Length")
    assert number_meta.type == "number"
    assert number_meta.varname == "Sepal.Length"
    assert number_meta.filterable == True
    assert number_meta.sortable == True
    assert number_meta.label is None
    assert number_meta.tags == []

    number_meta.check_variable(iris_df)

def test_number_meta_with_string(iris_df):
    number_meta = NumberMeta("Species")
    assert number_meta.type == "number"
    assert number_meta.varname == "Species"
    assert number_meta.filterable == True
    assert number_meta.sortable == True
    assert number_meta.label == None
    assert number_meta.tags == []

    with pytest.raises(ValueError):
        number_meta.check_variable(iris_df)

def test_check_varname(iris_df):
    meta = NumberMeta("Sepal.Length", tags="stuff")
    meta.check_with_data(iris_df)

    meta.varname = "abcdef"
    with pytest.raises(ValueError):
        meta.check_with_data(iris_df)

def test_check_with_data(iris_df):
    meta = NumberMeta("Sepal.Length", tags="stuff")

    # This should not cause an exception
    meta.check_with_data(iris_df)

    meta.varname = "abcdef"
    with pytest.raises(ValueError):
        # Now an exception should be raised
        meta.check_with_data(iris_df)

    meta.varname = "Species"
    with pytest.raises(ValueError):
        # Now an exception should be raised
        meta.check_with_data(iris_df)

    meta.varname = "Sepal.Length"

    meta.check_variable(iris_df)

def test_number_meta(iris_df):
    meta = NumberMeta("Sepal.Length", tags="stuff")

    meta.check_with_data(iris_df)

    assert meta.tags == ["stuff"]

    actual_json = meta.to_json()
    expected_json = '{"locale":true,"digits":null,"sortable":true,"filterable":true,"tags":["stuff"],"label":"Sepal.Length","type":"number","varname":"Sepal.Length"}'
    assert json.loads(actual_json) == json.loads(expected_json)

    meta = NumberMeta("Sepal.Length", label="Sepal length of the iris")
    assert meta.label == "Sepal length of the iris"

    meta = NumberMeta("whatever", digits = 2, locale = False)
    assert meta.digits == 2
    assert meta.locale == False

    with pytest.raises(ValueError, match=r"Could not find variable"):
        meta.check_with_data(iris_df)

    meta = NumberMeta("Species")
    with pytest.raises(ValueError, match=r"must be numeric"):
        meta.check_with_data(iris_df)

    with pytest.raises(TypeError, match=r"must be an integer"):
        meta = NumberMeta("Sepal.Length", digits = "a")

    with pytest.raises(TypeError, match=r"must be logical"):
        meta = NumberMeta("Sepal.Length", locale = "a")

def test_currency_meta(iris_df):
    meta = CurrencyMeta("Sepal.Length", label="Sepal length of the iris",
                tags="a tag", code="EUR")
    assert meta.varname == "Sepal.Length"
    assert meta.label == "Sepal length of the iris"
    assert meta.tags == ["a tag"]
    assert meta.code == "EUR"

def test_currency_meta(iris_df):
    meta = CurrencyMeta("Sepal.Length", tags="stuff")

    meta.check_with_data(iris_df)
    assert meta.tags == ["stuff"]

    actual_json = meta.to_json(pretty=False)
    expected_json = '{"code":"USD","sortable":true,"filterable":true,"tags":["stuff"],"label":"Sepal.Length","type":"currency","varname":"Sepal.Length"}'
    assert json.loads(actual_json) == json.loads(expected_json)

    meta2 = CurrencyMeta("Sepal.Length", label="Sepal length of the iris")
    assert meta2.varname == "Sepal.Length"
    assert meta2.label == "Sepal length of the iris"

    meta3 = CurrencyMeta("whatever")
    with pytest.raises(ValueError, match=r"Could not find variable"):
        meta3.check_with_data(iris_df)

    meta4 = CurrencyMeta("Species")
    with pytest.raises(ValueError, match=r"must be numeric"):
        meta4.check_with_data(iris_df)

    with pytest.raises(ValueError, match=r"must be one of"):
        meta5 = CurrencyMeta("Sepal.Length", code="ASD")

def test_string_meta(iris_df):
    meta = StringMeta("Species")
    meta.check_with_data(iris_df)

    # For the following test, even though Sepal.Length is NOT a string
    # this should work, because this type can be easily coerced to a string.
    # So if the user has explicitly used a StringMeta and it can work,
    # we should let it work.
    meta2 = StringMeta("Sepal.Length")
    meta2.check_with_data(iris_df)

    assert not is_string_dtype(iris_df["Sepal.Length"])
    new_df = meta2.cast_variable(iris_df)

    # verify changed in the returned value
    assert is_string_dtype(new_df["Sepal.Length"])

    # verify changed in the original df
    # NOTE: This may be a "feature" that is altered in the future
    # to make it so the original data frame is left unchanged
    assert is_string_dtype(iris_df["Sepal.Length"])

def test_factor_meta(iris_df):
    # Try a case where we don't specify the levels but they get inferred
    meta = FactorMeta("Species")
    meta.check_with_data(iris_df)
    assert set(meta.levels) == set(["setosa", "virginica", "versicolor"])

    # Try a case where the levels don't contain all the data (Error)
    meta2 = FactorMeta("Species", levels=["setosa", "virginica"])
    with pytest.raises(ValueError, match=r"contains values not specified"):
        meta2.check_with_data(iris_df)

    # Try a case where the levels have extra items (this is ok)
    meta3 = FactorMeta("Species", levels=["setosa", "virginica", "versicolor", "stuff"])
    meta3.check_with_data(iris_df)

@pytest.mark.skip("Feature is not implemented yet")
def test_date_meta(iris_plus_df):
    meta = DateMeta("date")
    meta.check_with_data(iris_plus_df)

@pytest.mark.skip("Feature is not implemented yet")
def test_datetime_meta(iris_plus_df):
    meta = DatetimeMeta("datetime")
    meta.check_with_data(iris_plus_df)

def test_geo_meta(iris_plus_df):
    meta = GeoMeta("coords", latvar="lat", longvar="long")
    meta.check_with_data(iris_plus_df)

@pytest.mark.skip("Feature is not implemented yet")
def test_graph_meta(iris_plus_df):
    #TODO: The iris_plus_df will need to have extra columns added for this

    meta = GraphMeta("lst", "id", "to")
    meta.check_with_data(iris_plus_df)

def test_href_meta(iris_plus_df):
    # First use a proper href category
    meta = HrefMeta("href")
    meta.check_with_data(iris_plus_df)

    # Try a numeric category (error)
    meta2 = HrefMeta("Sepal.Length")
    with pytest.raises(ValueError, match="Data type is not a string"):
        meta2.check_with_data(iris_plus_df)

def test_panel_meta(iris_df_no_duplicates: pd.DataFrame):
    iris_df = iris_df_no_duplicates

    with tempfile.TemporaryDirectory() as temp_dir_name:
        # this is test code that just sets all images to this test_image.png string
        # it is not a proper use of the images, but gives us something to use in testing.
        iris_df["img_panel"] = "test_image.png"

        pnl = ImagePanel("img_panel", source=FilePanelSource(is_local=True), aspect_ratio=1.5, should_copy_to_output=False)

        tr = (Trelliscope(iris_df, "Iris", path=temp_dir_name)
                .add_panel(pnl)
                )

        meta = PanelMeta(pnl, "img_panel")

        meta.check_with_data(iris_df)

        actual_json = meta.to_json(pretty=False)
        expected_json = """
        {
            "source": {
                "isLocal": true,
                "type": "file"
            },
            "aspect": 1.5,
            "paneltype": "img",
            "sortable": false,
            "filterable": false,
            "tags": [],
            "label": "img_panel",
            "type": "panel",
            "varname": "img_panel"
            }"""

        assert json.loads(actual_json) == json.loads(expected_json)


import os
import sys
import time
import logging
import inspect
import importlib
from typing import List
from pathlib import Path
from datetime import datetime

from utils.config import config
from utils.adapter.abstract_adapter import AbstractAdapter
from utils.email import send_email
from utils.fetcher.abstract_fetcher import AbstractFetcher
from utils.validation import validate_incoming_data
from utils.decorators import timeit
from utils.diagnostics import Diagnostics

logger = logging.getLogger(__name__)

__all__ = ('Plugins')

class Plugins:

    def __init__(self):
        self.validate_input_data = config.VALIDATE_INPUT_DATA
        self.available_plugins = self.search_for_plugins()
        self.run_only_plugins = self.get_only_selected_plugins()

    @staticmethod
    def search_for_plugins() -> List:
        plugins_path = os.path.join(os.path.dirname(__file__), "..", "plugins")
        sys.path.append(plugins_path)
        available_plugins = []

        for path in Path(plugins_path).rglob('*.py'):
            module_path = path.relative_to(plugins_path).with_suffix('')
            module_name = str(module_path).replace('/', '.').replace('\\', '.')
            try:
                module = importlib.import_module(module_name)
                for item_name in dir(module):
                    obj = getattr(module, item_name)
                    if inspect.isclass(obj) and issubclass(obj, AbstractFetcher) and obj != AbstractFetcher:
                        if hasattr(obj, 'LOAD_PLUGIN') and obj.LOAD_PLUGIN:
                            logger.debug(f"Loading plugin: {obj.__name__}")
                            available_plugins.append(obj)
            except Exception as ex:
                logger.error(f'Unable to load plugin: {module_name}, error: {ex}')

        return sorted(available_plugins, key=lambda x: x.__name__)

    @staticmethod
    def get_only_selected_plugins() -> List:
        run_only_plugins = config.RUN_ONLY_PLUGINS
        if run_only_plugins:
            return run_only_plugins.split(",")
        return None

    def should_run_plugin(self, plugin_name: str) -> bool:
        if not self.run_only_plugins:
            return True

        for plugin in self.run_only_plugins:
            if plugin.startswith('-') and '-' + plugin_name == plugin:
                return False
            if plugin_name == plugin or plugin == '*':
                return True

        return False

    @staticmethod
    def validate_consistency(plugin: AbstractFetcher, plugin_instance: AbstractFetcher,
                             data_adapter: AbstractAdapter) -> bool:
        fetcher_type = plugin_instance.TYPE if hasattr(plugin_instance, 'TYPE') else None

        if fetcher_type.value not in ['epidemiology']:
            # Exit without verification - fetcher type not supported yet
            return True

        source_name = plugin_instance.SOURCE if hasattr(plugin_instance, 'SOURCE') else None
        validation_success = validate_incoming_data(data_adapter, fetcher_type, source_name)
        if validation_success:
            logger.info(f"Validating source data for: {plugin.__name__}, source_name: {source_name} "
                        f"result: {validation_success}")
        else:
            logger.warning(f"Validating source data for: {plugin.__name__}, source_name: {source_name} "
                           f"result: {validation_success}")
            logger.warning(f"Plugin {plugin.__name__} failed due to data discrepancy, email was sent")

        return validation_success

    @staticmethod
    def validate_latest_timestamp(plugin: AbstractFetcher, plugin_instance: AbstractFetcher):
        if not config.VALIDATE_LATEST_TS_DAYS:
            return

        latest_timestamp = plugin_instance.get_latest_timestamp()
        if latest_timestamp:
            days = (datetime.now().date() - latest_timestamp).days
            if days > config.VALIDATE_LATEST_TS_DAYS:
                message = f"Plugin {plugin.__name__} has latest_timestamp {days} days old, " \
                          f"max is {config.VALIDATE_LATEST_TS_DAYS}"
                logger.info(message)
                subject = f"Covid19db fetchers-python latest_timestamp validation error"
                try:
                    send_email(plugin_instance.SOURCE, subject, message)
                except Exception as ex:
                    logger.error(f'Unable to send an email {plugin.__name__}', exc_info=True)

    @timeit
    def run_plugins_job(self, data_adapter: AbstractAdapter):
        Diagnostics.send_post_request(data={"type": "jobs_start", "ts": time.time()})
        for plugin in self.available_plugins:
            if self.should_run_plugin(plugin.__name__):
                self.run_single_plugin(data_adapter, plugin)

        Diagnostics.send_post_request(data={"type": "jobs_finish", "ts": time.time()})

    @timeit
    def run_single_plugin(self, data_adapter: AbstractAdapter, plugin: AbstractFetcher):
        logger.info(f'Running plugin {plugin.__name__} ')
        error = False
        validation_success = None
        start_time = time.time()
        try:
            if self.validate_input_data:
                data_adapter.truncate_staging()
            plugin_instance = plugin(data_adapter)
            plugin_instance.run()
            data_adapter.publish_missing_gids()
            data_adapter.flush()
            validation_success = self.validate_consistency(plugin,
                                                           plugin_instance,
                                                           data_adapter) if self.validate_input_data else True
            self.validate_latest_timestamp(plugin, plugin_instance)

            if validation_success:
                logger.info(f"Plugin {plugin.__name__} finished successfully")

        except Exception as ex:
            error = True
            logger.error(f'Error running plugin {plugin.__name__}, exception: {ex}', exc_info=True)

        Diagnostics(plugin_instance).update_diagnostics_info(
            validation=validation_success,
            error=error,
            start_time=start_time,
            end_time=time.time()
        )


from utils import ListNode

def mergeTwoLists(l1, l2):
    """
    Straight forward merge
    Time: O(m+n), m = len(l1), n = len(l2)
    Space: O(1)
    """
    # Assignment such as a = l1 (l1 is a ListNode)
    # will assign the address to start, change of a's `next` or `val` will result in change in l1's `next` or `val`
    # because the changes were made to the object stored in the common address
    # similarly if two assignments were made of the same variable: a, b =l1, l1
    # then change of a's `next` or `val` will result in change in b's and l1's
    # If reassign a to another ListNode say l2, a = l2, then change of a will not affect that of b and l1

    # Summary: Changing an object's properties through one of its assigned variable will change the object itself and
    # all the other assigned variables

    curr = ListNode(-1)  # auxiliary head pointer to retrieve the whole list
    start = curr
    while l1 is not None or l2 is not None:
        # if one of them is empty and then append the other to the end of the result and return
        if l1 is None:
            curr.next = l2
            return start.next
        elif l2 is None:
            curr.next = l1
            return start.next
        # if both are non-empty
        if l1.val < l2.val:
            # below will append all nodes of l1 to curr, `start` will change at the same time
            # e.g. curr = [3, 5], l1 = [4, 6], l2 = [5], start = [-1, 1, 2, 3, 5]
            # then after the execution, curr = [3, 4, 6], start = [-1, 1, 2, 3, 4, 6]
            curr.next = l1
            # below will advance l1 by 1 node
            # following the above example, after execution, l1 = [6]
            l1 = l1.next
            # below will advance curr by 1 node, and has no effect on `start`
            # since curr will be assigned to a new ListNode (curr.next)
            # and no changes were made to existing nodes
            # following the above example, after execution, curr = [4, 6], l1 = [6], l2 = [5]
            # in the next iteration, enter l2.val < l1.val and curr will be [4, 5]...
            curr = curr.next
        else:
            curr.next = l2
            l2 = l2.next
            curr = curr.next

    return start.next

def mergeTwoLists_recur(l1, l2):
    """
    Recursion
    Time: O(m+n), m = len(l1), n = len(l2)
    Space: O(m+n), size of the recursion stack
    """
    # res =
    # 1) l1[0] + merge(l1[1:], l2) if (l1[0] < l2[0])
    # 2) l2[0] + merge(l1, l2[1:]) if (l1[0] >= l2[0])
    # if l1 or l2 empty, append the non-empty list
    # recursion ends if either one of the two is empty
    if l1 is None:
        return l2
    elif l2 is None:
        return l1
    elif l1.val < l2.val:
        l1.next = mergeTwoLists_recur(l1.next, l2)
        # return the merged list
        return l1
    else:
        l2.next = mergeTwoLists_recur(l1, l2.next)
        # return the merged list
        return l2


import pytest

from teamleader.api import Teamleader
from teamleader.exceptions import InvalidInputError

def test_validate_type():
    for arg, t in ((['item'], list), ({'key': 'value'}, dict)):
        assert Teamleader._validate_type(arg, t) == arg

    for t in (list, dict):
        assert Teamleader._validate_type(None, t) == t()

    with pytest.raises(InvalidInputError):
        Teamleader._validate_type('not a list', list)

def test_convert_custom_fields():
    data = {
        'key': 'value',
        'custom_fields': {
            'key': 'value',
            'foo': 'bar'
        }
    }

    Teamleader._convert_custom_fields(data)

    assert data == {
        'key': 'value',
        'custom_field_key': 'value',
        'custom_field_foo': 'bar'
    }


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

import sqlite3
import os

class Shakespeare(object):
    ''' Shakespeare translator class '''
    def __init__(self, dictionary=None):
        self.dictionary = dictionary or os.path.abspath(
                          os.path.join(os.path.dirname(__file__), 'dict.db'))
        self.connection = sqlite3.connect(self.dictionary)
        self.connection.execute('PRAGMA case_sensitive_like = OFF;')
        self.cursor = self.connection.cursor()

    def __del__(self):
        self.connection.close()

    def search(self, word, searchtype=0, exact=False, reverse=False):
        """
        English to spanish
        word = word to search
        searchtype = [startswith, endswith, contains]
        exact = exact search
        reverse = translate from spanish to english
        The query is limited to 200 for performance reasons
        """
        if not word:
            return
        if exact:
            sql_search = u'{}'
        else:
            if searchtype == 0:
                sql_search = u'{}%%' # starts with
            elif searchtype == 1:
                sql_search = u'%%{}' # ends with
            else:
                sql_search = u'%%{}%%' # contains
        sql_search = sql_search.format(word)
        word_a, word_b = ('sword', 'eword') if reverse else ('eword', 'sword')
        search_string = '''select {a}, {b} from dict where {a} like\
        ? order by {a} limit 200'''.format(a=word_a, b=word_b)
        self.cursor.execute(search_string, (sql_search,))
        result = self.cursor.fetchall()
        return result

if __name__ == '__main__':
    s = Shakespeare()
    # first, search for some love :)
    print(s.search('love'))


import matplotlib.pyplot as plt

from skimage import data
from skimage.filters import threshold_otsu, threshold_local
from skimage.io import imread
from skimage.color import rgb2gray

image = imread('image.jpg')
image = rgb2gray(image)

global_thresh = threshold_otsu(image)
binary_global = image > global_thresh

block_size = 35
binary_adaptive = threshold_local(image, block_size, offset=10)

fig, axes = plt.subplots(nrows=3, figsize=(7, 8))
ax0, ax1, ax2 = axes
plt.gray()

ax0.imshow(image)
ax0.set_title('Image')

ax1.imshow(binary_global)
ax1.set_title('Global thresholding')

ax2.imshow(binary_adaptive)
ax2.set_title('Adaptive thresholding')

for ax in axes:
    ax.axis('off')

plt.show()


from collections import deque

def bfs(graph, n, m):
    queue = deque()
    queue.append((0, 0))
    graph[0][0] = 0

    while queue:
        x, y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            if nx < 0 or nx >= m or ny < 0 or ny >= n:
                continue
            if graph[nx][ny] == 1:
                graph[nx][ny] = graph[x][y]+1
                queue.append((nx, ny))
    return graph[m-1][n-1]

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

M, N = map(int, input().split())
graph = []
for i in range(M):
    graph.append(list(map(int, input())))

answer = bfs(graph, N, M)
print(answer+1)


from typing import Dict, List
from Modules import Logger
from Modules.dbVersioning import GuildUpgrades

import json
import random
import sqlite3

MaxCache = 250
DBSTORE = "./Data/Database.db"
SETTINGS_STORE = "./Data/Settings.json"

Log = Logger.Get("Guilds")
conn = sqlite3.connect(DBSTORE)

Guilds = {}

class Guild:
    rEnabled:bool = True
    rDelete:bool = True
    rTimeout:int = 604800
    rThreshold:int = 10
    rChannels:List[int] = [865270701753892896]
    rDetected_msg:List[str] = ["> {AUTHOR},You seem to have posted a repost"]

    def __init__(self, ID):
        Log.debug(f"Guild {ID} retrieved")
        self.ID = ID
        with conn:
            Settings = conn.execute(
                "Select SETTINGS from GUILDS where ID = ?",
                (self.ID,),).fetchone()

        if Settings:
            self.LoadJSON(Settings[0])
        else:
            with conn:
                conn.execute(
                    "Insert into GUILDS values(?,?);",
                    (self.ID, self.Settingjson)
                )

    @property
    def Settingjson(self) -> str:
        return json.dumps(self.Settings, indent=4, sort_keys=True)

    @property
    def Settings(self) -> dict:
        return {
            "Version": "1.1",
            "rEnabled": self.rEnabled,
            "rDelete": self.rDelete,
            "rTimeout": self.rTimeout,
            "rThreshold": self.rThreshold,
            "rChannels": self.rChannels,
            "rDetected_msg": self.rDetected_msg
        }

    @property
    def msgRepostDetected(self) -> str:
        return random.choice(self.rDetected_msg)

    def Save(self):
        Log.debug(f"Saving guild {self.ID}'s Settings")
        with conn:
            conn.execute(
                "Update GUILDS set SETTINGS = ? where ID = ?;",
                (self.Settingjson, self.ID)
            )

    def LoadJSON(self, JSON: str):
        TypeLookup = {
            "rEnabled": [bool],
            "rDelete": [bool],
            "rTimeout": [int],
            "rThreshold": [list,str],
            "rChannels": [list,int],
            "rDetected_msg": [list,int]
            }

        Log.debug(f"Loading Guild {self.ID} from JSON")
        JSON:dict = json.loads(JSON)

        Version = JSON.get("Version",None)
        JSON = GuildUpgrades[Version](JSON)

        #! Data Validation Turned Off
        # for key,value in JSON.items():
        #     if isinstance(TypeLookup[key][0], list):
        #         for x in value:
        #             assert isinstance(x,TypeLookup[key][1])
        #     else:
        #         assert isinstance(value,TypeLookup[key][0])

        self.rEnabled = JSON["rEnabled"]
        self.rDelete = JSON["rDelete"]
        self.rTimeout = JSON["rTimeout"]
        self.rThreshold = JSON["rThreshold"]
        self.rChannels = JSON["rChannels"]
        self.rDetected_msg = JSON["rDetected_msg"]

        self.Save()

def Get(ID: int) -> Guild:
    if len(Guilds) > MaxCache:
        Guilds.popitem()
    if ID not in Guilds:
        Guilds[ID] = Guild(ID)
    return Guilds[ID]

def Check(ID: int) -> Guild:
    with conn:
        Settings = conn.execute(
            "Select SETTINGS from SERVERS where ID = ?",
            (ID,),)

    return len(Settings.fetchall()) == 1


'''
Sample Command:-
python detect_aruco_images.py --image Images/1.png --type DICT_6X6_250
'''
import numpy as np
from utils import ARUCO_DICT, aruco_display, get_rec_points, get_centre
import argparse
import cv2
import sys

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image containing ArUCo tag")
ap.add_argument("-t", "--type", type=str, default="DICT_ARUCO_ORIGINAL", help="type of ArUCo tag to detect")
args = vars(ap.parse_args())

print("Loading image...")
image = cv2.imread(args["image"])
h, w, _ = image.shape
width = 1000
height = int(width*(h/w))
frame = cv2.resize(image, (width, height), interpolation=cv2.INTER_CUBIC)
img_gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

# verify that the supplied ArUCo tag exists and is supported by OpenCV
if ARUCO_DICT.get(args["type"], None) is None:
    print(f"ArUCo tag type '{args['type']}' is not supported")
    sys.exit(0)

# load the ArUCo dictionary, grab the ArUCo parameters, and detect the markers
print("Detecting '{}' tags....".format(args["type"]))
arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[args["type"]])
arucoParams = cv2.aruco.DetectorParameters_create()

corners, ids, rejected = cv2.aruco.detectMarkers(img_gray, arucoDict, parameters=arucoParams)
detected_markers = cv2.aruco.drawDetectedMarkers(frame, corners, ids)

camera_matrix = np.load("calibration_matrix.npy")
dist_coeffs = np.load("distortion_coefficients.npy")

points = get_rec_points(corners)
if points is not None:
    for point in points:
        cv2.circle(frame, tuple(point), 4, (0, 0, 255), -1)

    org_h, org_w = 16.5, 18.5 #in cm
    points_3D = np.array([[-org_w/2, org_h/2, 0], [org_w/2, org_h/2, 0], [org_w/2, -org_h/2, 0], [-org_w/2, -org_h/2, 0]], dtype="double")

    points_2D = points.astype('float32')
    points_3D = points_3D.astype('float32')

    success, rvecs, tvecs = cv2.solvePnP(points_3D, points_2D, camera_matrix, dist_coeffs)

    len = 5 #in cm
    axis = np.float32([[-len/2, -len/2, 0], [-len/2, len/2, 0], [len/2, len/2, 0], [len/2, -len/2, 0],
                        [-len/2, -len/2, len], [-len/2, len/2, len], [len/2, len/2, len],[len/2, -len/2, len]])

    imgpts_2d, jac = cv2.projectPoints(axis, rvecs, tvecs, camera_matrix, dist_coeffs)
    imgpts_2d = np.int32(imgpts_2d).reshape(-1, 2)

    frame = cv2.drawContours(frame, [imgpts_2d[:4]], -1, (255, 0, 0), 2)
    for i, j in zip(range(4), range(4, 8)):
        frame = cv2.line(frame, tuple(imgpts_2d[i]), tuple(imgpts_2d[j]), (255, 0, 0), 2)
    frame = cv2.drawContours(frame, [imgpts_2d[4:]], -1, (255, 0, 0), 2)

    # points = np.float32(points)
    # width = 800
    # height = int(width*(org_h/org_w))
    # target_points = np.float32([[0, 0], [width, 0], [width, height], [0, height]])

    # M = cv2.getPerspectiveTransform(points, target_points)
    # warped = cv2.warpPerspective(frame, M, (width, height))

    # # cv2.imshow("Warped", warped)

cv2.imshow("Image", frame)

# # Uncomment to save
# cv2.imwrite("output_sample.png",detected_markers)

cv2.waitKey(0)


import cv2
import numpy as np

CORNER_COUNT = 6, 8
SHRINK_CONST = 6

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

objp = np.zeros((CORNER_COUNT[0]*CORNER_COUNT[1],3), np.float32)
objp[:,:2] = np.mgrid[0:CORNER_COUNT[0],0:CORNER_COUNT[1]].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

images = []

for i in range(1, 21):
    img = cv2.imread(f"images/img{i}.jpg")
    # img = cv2.imread(f"images/img{i}.jpg", cv2.IMREAD_GRAYSCALE)
    # img = cv2.imread(f"../AssignmentIII/AssignmentIII/PartA/images/img{i}.jpg", cv2.IMREAD_GRAYSCALE)
    # img = cv2.resize(img, (img.shape[1]//4, img.shape[0]//4))
    images.append(img)
    # print(img.shape)
    # exit()
    # print(img)
    # cv2.imshow("corners", img)
    # cv2.waitKey(0)

    # cv2.destroyAllWindows()

for img in images:
    # print(img.shape[::-1])
    # img = cv2.resize(img, (img.shape[1]//10, img.shape[0]//10))
    # print(img.shape)
    # cv2.imshow("corners", img)
    # cv2.waitKey(0)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # cv2.destroyAllWindows()
    ret, corners = cv2.findChessboardCorners(img, CORNER_COUNT, None)
    # print(ret)
    # print(corners)
    if ret == True:
        objpoints.append(objp)

        corners2 = cv2.cornerSubPix(img, corners, (11, 11), (-1, -1), criteria)
        imgpoints.append(corners2)
        # blank = np.zeros(img.shape, dtype=np.uint8)
        # cv2.drawChessboardCorners(img, CORNER_COUNT, corners2, ret)
        # cv2.drawChessboardCorners(blank, CORNER_COUNT, corners2, ret)

        # cv2.imshow("corners", img)
        # cv2.waitKey(0)

        # cv2.destroyAllWindows()

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img.shape[::-1], None, None)

newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,img.shape[::-1],1,img.shape[::-1])
# newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,img.shape[::-1],0,img.shape[::-1])
# ret: RMS reprojection error
# mtx: camera matrix
# dist: distortion coefficients [k1, k2, p1, p2, k3]
# k: radial distortion values
# p: tangential distortion values
# rvecs: rotation vector
# tvecs: tranlation vector
img2 = cv2.imread(f"images/img21.jpg")
# img2 = cv2.resize(img2, (img2.shape[1]//4, img2.shape[0]//4))
# img2 = cv2.resize(img2, img2.shape)
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# blk_dst = cv2.undistort(blank, mtx, dist, None, newcameramtx)
# print(ret)
# print("camera matrix", mtx, sep="\n")
print("distortion values", dist, sep="\n")
# print(rvecs)
# print(tvecs)
print("new camera matrix", newcameramtx, sep="\n")
# print(roi)
print(img2.shape, dst.shape)
img2 = cv2.resize(img2, (img2.shape[1]//SHRINK_CONST, img2.shape[0]//SHRINK_CONST))
dst = cv2.resize(dst, (dst.shape[1]//SHRINK_CONST, dst.shape[0]//SHRINK_CONST))
print(img2.shape, dst.shape)

# cv2.imshow("img2", img2)
# cv2.imshow("undistort", dst)

cv2.imwrite(f"calibrated_images/img{21}.jpg", img2)
cv2.imwrite(f"calibrated_images/undistort{21}.jpg", dst)
# cv2.waitKey(0)

# cv2.destroyAllWindows()

# for img in images:
for i in range(1, 21):
    img = images[i-1]
    # img = img[roi[2]:roi[3], roi[0]:roi[1]]
    dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
    img = cv2.resize(img, (img.shape[1]//SHRINK_CONST, img.shape[0]//SHRINK_CONST))
    dst = cv2.resize(dst, (dst.shape[1]//SHRINK_CONST, dst.shape[0]//SHRINK_CONST))

    cv2.imshow("img2", img)
    cv2.imshow("undistort", dst)
    cv2.imwrite(f"calibrated_images/img{i}.jpg", img)
    cv2.imwrite(f"calibrated_images/undistort{i}.jpg", dst)
    # cv2.waitKey(0)

    cv2.destroyAllWindows()


import numpy as np
import torch
from lib.delay_copy_task import DelayCopyData
from torch.utils.data import DataLoader

seed=3000
length=10
width=3
initial_delay=0
initial_delay_fixed_length=True
delay=100
delay_fixed_length=True
batch_size=10
binary_encoding=True
blank_symbol=True

dataset = DelayCopyData(seed, length, width, initial_delay, initial_delay_fixed_length, delay,
                        delay_fixed_length, batch_size, binary_encoding, blank_symbol)

print(dataset)
loader = DataLoader(dataset, batch_size=batch_size)

data_iter = iter(loader)

data = next(data_iter)

# print(data[0])

inputs = (np.asarray(data['x']))
targets = (np.asarray(data['y']))
masks = (np.asarray(data['mask']))

print(inputs.shape)
print(type(inputs))
# print(inputs)

print(targets.shape)
print(type(targets))

print(masks.shape)
print(type(masks))


from enum import Enum

import typer
from environs import Env

import src.clientApp.app as clientApp
import src.legacy.serverApp.app as serverAppLegacy
import src.mailApp.app as mailApp
import src.mailServer.server as server
import src.serverApp.app as serverApp

TService = Enum(  # type: ignore
    "Service",
    {
        k: k
        for k in [
            "server",
            "server:mail",
            "server:legacy",
            "client",
            "mail",
        ]
    },
)

env = Env()
# Read .env into os.environ
env.read_env()

def main(service: TService = typer.Argument("server", help="Service to run")):
    if str(service) == "Service.server":
        serverApp.main()
    elif str(service) == "Service.server:mail":
        server.main()
    elif str(service) == "Service.server:legacy":
        serverAppLegacy.main()
    elif str(service) == "Service.client":
        clientApp.main()
    elif str(service) == "Service.mail":
        mailApp.main()

if __name__ == "__main__":
    typer.run(main)


import os
import time
import socket
# copied from here https://github.com/googleapis/python-pubsub/blob/master/samples/snippets/publisher.py#L43

def create_topic(project_id, topic_id):
    from google.cloud import pubsub_v1

    publisher = pubsub_v1.PublisherClient()
    topic_path = publisher.topic_path(project_id, topic_id)
    topic = publisher.create_topic(request={"name": topic_path})

def is_open(ip, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
        s.connect((ip, int(port)))
        s.shutdown(2)
        return True
    except:
        return False

if __name__ == "__main__":
    project_id = os.environ["PUBSUB_PROJECT_ID"]
    # topics should be ':' separated
    topics = os.environ.get("PUBSUB_TOPICS", '')

    host, port = os.environ["PUBSUB_EMULATOR_HOST"].split(":")

    while not is_open(host, port):
        print("Waiting for pubsub ...")
        time.sleep(1)

    if topics:
        for topic in topics.split(":"):
            create_topic(project_id, topic)
            print(f"created topic: {topic}")


import pygame
import random

pygame.init()

# Màu sắc
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

# Các cài đặt màn hình
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption('Piano Game')

# Khởi tạo đồng hồ
clock = pygame.time.Clock()

# Khởi tạo font chữ
font = pygame.font.Font(None, 36)

# Danh sách các phím
keys = ['C', 'D', 'E', 'F', 'G', 'A', 'B']

# Danh sách các bài hát
songs = [['C', 'D', 'E', 'C', 'E', 'F', 'G', 'C', 'D', 'E', 'C', 'E', 'F', 'G'],
         ['G', 'F', 'E', 'D', 'C', 'D', 'E', 'F', 'G', 'G', 'F', 'E', 'D', 'C'],
         ['C', 'C', 'G', 'G', 'A', 'A', 'G', 'F', 'F', 'E', 'E', 'D', 'D', 'C']]

# Chế độ chọn bài hát
song_index = 0

# Biến điểm số
score = 0

# Biến đếm số lần nhấn sai hoặc bỏ qua
misses = 0

# Hàm kiểm tra xem phím có đúng với phím trong bài hát không
def check_key(key):
    global misses, song_index, score
    if key == songs[song_index][0]:
        songs[song_index].pop(0)
        score += 10
        if len(songs[song_index]) == 0:
            song_index = (song_index + 1) % len(songs)
    else:
        misses += 1
        if misses >= 3:
            game_over()

# Hàm kết thúc trò chơi
def game_over():
    global score
    screen.fill(WHITE)
    text = font.render('Game over! Score: ' + str(score), True, BLACK)
    screen.blit(text, [screen_width/2 - text.get_width()/2, screen_height/2 - text.get_height()/2])
    pygame.display.flip()
    pygame.time.wait(3000)
    pygame.quit()
    quit()

# Vòng lặp chính
done = False
while not done:
    # Xử lý các sự kiện
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                done = True
            elif event.key == pygame.K_a:
                check_key('C')
            elif event.key == pygame.K_s:
                check_key('D')
            elif event.key == pygame.K_d:
                check_key('E' )
            elif event.key == pygame.K_f:
                check_key('F')
            elif event.key == pygame.K_g:
                check_key('G')
            elif event.key == pygame.K_h:
                check_key('A')
            elif event.key == pygame.K_j:
                check_key('B')
            elif event.key == pygame.K_SPACE:
                song_index = (song_index + 1) % len(songs)

                # Cập nhật màn hình
screen.fill(WHITE)

                # Vẽ các cột phím
pygame.draw.rect(screen, BLACK, [0, 0, 100, screen_height])
pygame.draw.rect(screen, BLACK, [screen_width - 100, 0, 100, screen_height])
pygame.draw.rect(screen, BLACK, [screen_width / 2 - 50, 0, 100, screen_height])

                # Vẽ các phím
key_width = 100
key_height = 50
key_padding = 10
for i in range(7):
    pygame.draw.rect(screen, BLACK,
    [key_padding + i * (key_width + key_padding), 350, key_width, key_height])
    text = font.render(keys[i], True, WHITE)
    screen.blit(text, [key_padding + i * (key_width + key_padding) + key_width / 2 - text.get_width() / 2,
    350 + key_height / 2 - text.get_height() / 2])

                # Hiển thị bài hát đang chơi
text = font.render('Song: ' + str(song_index + 1), True, BLACK)
screen.blit(text, [10, 10])

                # Hiển thị điểm số
text = font.render('Score: ' + str(score), True, BLACK)
screen.blit(text, [screen_width - 10 - text.get_width(), 10])

                # Hiển thị số lần nhấn sai hoặc bỏ qua
text = font.render('Misses: ' + str(misses), True, BLACK)
screen.blit(text, [screen_width / 2 - text.get_width() / 2, 10])

                # Nếu bài hát đã kết thúc thì hiển thị thông báo
if song_index == 0 and len(songs[song_index]) == 0:
    text = font.render('You won! Final score: ' + str(score), True, GREEN)
screen.blit(text, [screen_width / 2 - text.get_width() / 2, screen_height / 2 - text.get_height() / 2])
pygame.display.flip()
pygame.time.wait(3000)
pygame.quit()
quit()

pygame.display.flip()
clock.tick(60)


import eth_abi
import pytest
from brownie import Contract, MockDAI, MockUSDC, MockUSDT, VyperMock3CRV, web3

USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
USDT_ADDRESS = "0xdAC17F958D2ee523a2206206994597C13D831ec7"
DAI_ADDRESS = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
E_CRV_ADDRESS = "0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490"
FRAX_CRV_ADDRESS = "0xd632f22692FaC7611d2AA1C0D552930D43CAEd3B"

@pytest.fixture(scope="function", autouse=True)
def mock_dai(admin, alice):
    _mock_dai = admin.deploy(MockDAI)
    yield _mock_dai

@pytest.fixture(scope="function", autouse=True)
def mock_usdc(admin, alice):
    _mock_usdc = admin.deploy(MockUSDC)
    yield _mock_usdc

@pytest.fixture(scope="function", autouse=True)
def mock_usdt(admin, alice):
    _mock_usdt = admin.deploy(MockUSDT)
    yield _mock_usdt

@pytest.fixture(scope="function", autouse=True)
def mock_three_crv(admin):
    three_crv = admin.deploy(VyperMock3CRV, "3CRV", "3CRV", 18, 0)
    yield three_crv

@pytest.fixture(scope="function", autouse=True)
def mint_mock_token(mock_dai, mock_usdc, mock_usdt, admin, alice, bob):
    for account in [admin, alice, bob]:
        for token in [mock_dai, mock_usdc, mock_usdt]:
            token.faucet({"from": account})

@pytest.fixture(scope="function")
def usdc(admin):
    yield Contract(USDC_ADDRESS)

@pytest.fixture(scope="function")
def usdt(admin):
    yield Contract(USDT_ADDRESS)

@pytest.fixture(scope="function")
def dai(admin):
    yield Contract(DAI_ADDRESS)

@pytest.fixture(scope="function")
def E_CRV(admin):
    yield Contract(E_CRV_ADDRESS)

@pytest.fixture(scope="function")
def FRAX_CRV(admin):
    yield Contract(FRAX_CRV_ADDRESS)

def mint_dai(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["address", "uint256"], (account.address, 0x2)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [DAI_ADDRESS, slot.hex(), amount]
    )

def mint_usdc(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["address", "uint256"], (account.address, 0x9)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [USDC_ADDRESS, slot.hex(), amount]
    )

def mint_usdt(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["address", "uint256"], (account.address, 0x2)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [USDT_ADDRESS, slot.hex(), amount]
    )

def mint_3crv(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["uint256", "address"], (0x3, account.address)).hex()
    )
    hex_ = '0x' + slot.hex()[2:].lstrip('0')
    web3.provider.make_request(
        "hardhat_setStorageAt", [E_CRV_ADDRESS, hex_, amount]
    )

def mint_frax_crv(account, amount):
    amount = f"{amount:#0{66}x}"
    slot = web3.keccak(
        hexstr=eth_abi.encode_abi(["uint256", "address"], (15, account.address)).hex()
    )
    web3.provider.make_request(
        "hardhat_setStorageAt", [FRAX_CRV_ADDRESS, slot.hex(), amount]
    )


from events.movement import player_movement, display_valid_move_description
from events.event_checker import pick_available_foe, check_for_predetermined_events
from events.game_ending import game_over, goal_achieve, easter_egg

from combat.enemy_info import update_enemy_info
from combat.combat_widget import activate_battle_button, toggle_battle_buttons
from combat.player_info import drop_item
from combat.combat_result import escape_from_fight, win_fight, mid_boss_killed

from GUI import GAME_LOCATION_IMAGE_PATH
from GUI.create_widgets import update_image_label

from GUI_update.update_map_widget import map_widget_update
from GUI_update.update_status_frame import update_status_message

import pathlib
from functools import partial

def game(overall_gui_info: dict, game_info: dict, event) -> None:
    """
    Drive the game flow.
    """
    battle_round = 0
    saved_coordinate = (game_info['character']["X-coordinate"], game_info['character']["Y-coordinate"])
    progress_switch = {"move": '', "event": False, "opponent": False, "battle": False, "result": False}
    pass_value = event if type(event) is str else event.keysym
    shortcut_list = ("a", "A", "d", "D", "w", "W", "s", "S")

    if pass_value in shortcut_list:
        if player_movement(game_info, shortcut_list.index(pass_value) // 2 + 1, overall_gui_info):
            map_widget_update(game_info['character'], overall_gui_info)
            triggered_event = check_for_predetermined_events(game_info)
            progress_switch['move'] = (game_info['character']["X-coordinate"], game_info['character']["Y-coordinate"])
            progress_switch['event'] = triggered_event
            progress_switch['opponent'] = pick_available_foe(triggered_event, game_info)
            display_valid_move_description(game_info['character'], overall_gui_info)
        else:
            overall_gui_info['Event Bar'].config(text="Invalid Move!")
    if progress_switch['opponent']:
        update_enemy_info(overall_gui_info, progress_switch['opponent'],
                          f"Encountered {progress_switch['opponent']['Name']}\n\n"
                          f"{progress_switch['opponent']['Slogan']}")
        progress_switch['battle'] = True

    if progress_switch['battle']:
        toggle_battle_buttons(overall_gui_info, "enable")
        activate_battle_button(overall_gui_info, game_info['character'], progress_switch['opponent'])
        overall_gui_info['pause'].set(True)

    while progress_switch['battle']:
        battle_round += 1
        overall_gui_info['GUI'].wait_variable(overall_gui_info['pause'])
        message = "Took the hit!"
        if game_info['character']['Status'] == "Poisoned":
            game_info['character']['Current HP'] = int(game_info['character']['Current HP'] * 0.9)
            message = "You feel the poison coursing through your veins. \n You take additional damage!!"
        update_enemy_info(overall_gui_info, progress_switch['opponent'], f"Round {battle_round}\n{message}")
        overall_gui_info['Status Frame'].children['character_status'].config(
            text=update_status_message(game_info['character'], 4, -7))
        if progress_switch['opponent']['HP'] <= 0 or \
                game_info['character']['Current HP'] <= 0 or game_info['character']['Escape']:
            progress_switch['battle'] = False

    if progress_switch['opponent'] and game_info['character']['Current HP'] <= 0:
        game_over(overall_gui_info)

    if progress_switch['opponent'] and game_info['character']['Current HP'] > 0:
        overall_gui_info['Buttons Frame'].bind("<KeyPress>", partial(game, overall_gui_info, game_info))

    if progress_switch['opponent'] and progress_switch['opponent']['HP'] <= 0 < game_info['character']['Current HP']:
        win_fight(overall_gui_info, game_info, progress_switch)
        drop_item(overall_gui_info, game_info['character'], progress_switch['opponent'])
        progress_switch['result'] = "win"

    if progress_switch['opponent'] and game_info['character']['Escape']:
        escape_from_fight(overall_gui_info, game_info, saved_coordinate)
        progress_switch['result'] = "run"

    if progress_switch['move']:
        game_info['character']['Escape'] = False
        image_file = 'Default'
        if pathlib.Path(GAME_LOCATION_IMAGE_PATH.format(progress_switch['move'])).is_file():
            image_file = str(progress_switch['move'])
        if pathlib.Path(GAME_LOCATION_IMAGE_PATH.format(image_file)).is_file():
            update_image_label(overall_gui_info['Script Frame'], "image_box",
                               GAME_LOCATION_IMAGE_PATH.format(image_file))
        else:
            raise FileNotFoundError("Location image cannot be found! Please check the path!")

    if progress_switch['opponent']:
        mid_boss_killed(progress_switch, game_info['environment'], overall_gui_info, (4, 2))
        goal_achieve(progress_switch, game_info['environment'], overall_gui_info)

    if progress_switch['move'] == (0, 4):
        easter_egg(overall_gui_info)

def main():
    """
    Drive the program.
    """

if __name__ == "__main__":
    main()


from itertools import groupby
from typing import Generator, List, Optional, TypeVar

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import and_

from exceptions.exceptions import ActionNotAllowed, ObjectsDuplicated
from handlers import BaseHandler
from handlers.utils import assert_name_is_valid
from models.database_models import RootTopic, Topic
from models.response_models.topic_model import RootTopicResponseModel, TopicResponseModel

SqlAlchemyModel = TypeVar('SqlAlchemyModel', bound=SQLAlchemy)

class RootTopicHandler(BaseHandler):
    _model = RootTopic

    def __init__(self, id: int = None) -> None:
        super().__init__(id)
        self.error_msg = f'Root Topic <{id}> 不存在'

    def get_topic(self) -> Generator[RootTopicResponseModel, None, None]:
        instance = self._get_sqlalchemy_instance()

        condition = and_(Topic.deleted == False, Topic.root_topic_id == self.id)
        child_topics = (TopicResponseModel(**topic.as_dict()) for topic in Topic.query.filter(condition))

        yield RootTopicResponseModel(child_topics=child_topics, **instance.as_dict())

    @staticmethod
    def sort_and_group_child_topic(
        root_topic_ids,
    ) -> Generator[List[SqlAlchemyModel], None, None]:
        child_topics = Topic.query.filter_by(deleted=False).filter(Topic.root_topic_id.in_(root_topic_ids))
        child_topics = sorted(child_topics, key=lambda x: x.root_topic_id)

        groups = {k: list(v) for k, v in groupby(child_topics, key=lambda x: x.root_topic_id)}
        yield from map(lambda k: groups.get(k, []), root_topic_ids)

    def get_topics(self) -> Generator[RootTopicResponseModel, None, None]:
        root_topics = self._model.query.filter_by(deleted=False)
        root_topic_ids = [ins.id for ins in root_topics]
        child_topics = self.sort_and_group_child_topic(root_topic_ids)

        for root_topic, topic in zip(root_topics, child_topics):
            ch_topics = (TopicResponseModel(**t.as_dict()) for t in topic)
            yield RootTopicResponseModel(child_topics=ch_topics, **root_topic.as_dict())

    def create_topic(self, **kwargs) -> Generator[RootTopicResponseModel, None, None]:
        assert_name_is_valid(message='根主题名不能为空', **kwargs)

        name = kwargs['name']
        condition = and_(self._model.deleted == False, self._model.name == name)
        instance = self._model.query.filter(condition).first()
        if instance:
            raise ObjectsDuplicated(f'名称为 <{name}> 的根 Topic 已经创建')

        instance = self._model.create(**kwargs)
        yield RootTopicResponseModel(child_topics=[], **instance.as_dict())

    def update_topic(self, **kwargs) -> Generator[RootTopicResponseModel, None, None]:
        assert_name_is_valid(message='主题名不能为空', **kwargs)
        name = kwargs['name']
        condition = and_(
            self._model.deleted == False,
            self._model.id != self.id,
            self._model.name == name,
        )
        instance = self._model.query.filter(condition).first()
        if instance:
            raise ObjectsDuplicated(f'名称为 <{name}> 的 Topic 已经创建')

        instance = self._get_sqlalchemy_instance()
        instance.update(name=name)

        yield RootTopicResponseModel(child_topics=[], **instance.as_dict())

    def delete_topic(self) -> None:
        raise ActionNotAllowed('根主题不允许被删除')


from django.contrib import admin
from .models import UserProfile, UserActivity, Languages, Newsletter
# Register your models here.

@admin.register(Languages)
class LanguagesSpokenAdmin(admin.ModelAdmin):
    list_display = [
        'title'
    ]

@admin.register(Newsletter)
class NewsletterAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'email',
        'country',
        'subscription_date'
    )
    search_fields = ['email']
    list_filter = ['country']

@admin.register(UserActivity)
class ProviderAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'user',
        'ip_address',
        'path',
        'method',
        'location_latitude',
        'location_longitude',
        'city',
        'body'
    )
    readonly_fields = ()
    search_fields = ['user__email']
    list_filter = ['city']

@admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin):
    list_display = (
        'user_email',
        'company_name',
        'phone_number',
        'city',
        'state',
        'zip_code',
        'country',

    )
    list_filter = ('city','state', 'country','company_name')
    search_fields = ['user__email']


import logging
from codeitsuisse import app
from codeitsuisse.routes import square
from codeitsuisse.routes import bryan
from codeitsuisse.routes import deeplearn_linreg
logger = logging.getLogger(__name__)

@app.route('/', methods=['GET'])
def default_route():
    return deeplearn_linreg.kk()

logFormatter = logging.Formatter("%(asctime)s [%(filename)s] [%(funcName)s] [%(lineno)d] [%(levelname)-5.5s]  %(message)s")
rootLogger = logging.getLogger()

rootLogger.setLevel(logging.INFO)

fileHandler = logging.FileHandler("team.log")
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)

consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)

logger.info("Starting application ...")
# comment out when push to heroku
# app.run()