from verlib import NormalizedVersion as Ver
import numpy as np

__author__ = "Balaji Sriram"
__version__ = "0.0.1"
__copyright__ = "Copyright 2018"
__license__ = "GPL"
__maintainer__ = "Balaji Sriram"
__email__ = "balajisriram@gmail.com"
__status__ = "Production"

class Criterion(object):

    def __init__(self, name='Unknown'):
        self.name = name
        self.ver = Ver('0.0.1')

    def __repr__(self):
        return "Criterion object"

    def check_criterion(self, **kwargs):
        return False

class NumTrialsDoneCriterion(Criterion):
    """
        NUMTRIALDONECRITERION - graduate after 'n' trials are done. Note: because it works on compiled_record and because
        compiled_records are created after checking for graduation, current trial's data will not be available before
        checking for graduation.
    """

    def __init__(self, num_trials=100, num_trials_mode='global', name='Unknown'):
        super(NumTrialsDoneCriterion, self).__init__(name)
        self.ver = Ver('0.0.1')
        self.num_trials = num_trials
        self.num_trials_mode = num_trials_mode

    def __repr__(self):
        return "NumTrialsDoneCriterion object, n:%d mode:%s", (self.num_trials, self.num_trials_mode)

    def check_criterion(self, compiled_record, trial_record, **kwargs):
        # trial_number = np.append(np.asarray(compiled_record['trial_number']),np.asarray(trial_record['trial_number']))
        # current_step = np.append(np.asarray(compiled_record['current_step']),np.asarray(trial_record['current_step']))
        # protocol_name = np.append(np.asarray(compiled_record['protocol_name']),np.asarray(trial_record['protocol_name']))
        # protocol_ver = np.append(np.asarray(compiled_record['protocol_version_number']),np.asarray(trial_record['protocol_version_number']))
        trial_number = np.asarray(compiled_record['trial_number'])
        current_step = np.asarray(compiled_record['current_step'])
        protocol_name = np.asarray(compiled_record['protocol_name'])
        protocol_ver = np.asarray(compiled_record['protocol_version_number'])
        # filter out trial_numbers for current protocol_name and protocol_ver
        current_step = current_step[np.bitwise_and(protocol_name==protocol_name[-1],protocol_ver==protocol_ver[-1])]
        trial_number = trial_number[np.bitwise_and(protocol_name==protocol_name[-1],protocol_ver==protocol_ver[-1])]

        # print('current_step:',current_step)
        # print('current_step[-1]:',trial_record['current_step'])
        # print('current_step==current_step[-1]',current_step==trial_record['current_step'])

        # filter out trial_numbers where step==current_step
        # print('trial_number::',trial_number)
        temp = trial_number[current_step==trial_record['current_step']]
        # print('temp_pre:',temp)
        # print(np.asarray([-1]))
        # print(np.asarray([trial_record['trial_number']]))
        temp = np.append(np.append(np.asarray([-1]),temp),np.asarray([trial_record['trial_number']]))
        # print('temp::',temp)
        if self.num_trials_mode == 'consecutive':
            jumps = np.array(np.where(np.diff(temp)!=1)) # jumps in trial number
            try:
                tr_for_current_sequence = temp[jumps[0,-1]+1]
                nT = trial_record['trial_number'] - tr_for_current_sequence +1
            except IndexError:
                nT = 0
        else:  # 'global'
            nT = np.sum(current_step==current_step[-1])
        # print('nT::',nT)
        if nT >= self.num_trials:
            graduate = True
        else:
            graduate = False
        print("NUMTRIALSDONECRITERION:CHECK_CRITERION::graduate=%s, nT=%d" % (graduate, nT))
        return graduate

class PerformanceCriterion(Criterion):

    def __init__(self, pct_correct=0.8, num_trials=200, num_trials_mode='global', name='Unknown'):
        super(PerformanceCriterion, self).__init__(name)
        self.ver = Ver('0.0.1')
        self.pct_correct = pct_correct
        self.num_trials = num_trials
        self.num_trials_mode = num_trials_mode

    def __repr__(self):
        return "PerformanceCriterion object, (%s in %s trials, mode:%s)", (self.pct_correct, self.num_trials, self.num_trials_mode)

    def check_criterion(self, compiled_record, trial_record, **kwargs):
        trial_number = np.asarray(compiled_record['trial_number'])
        current_step = np.asarray(compiled_record['current_step'])
        correct = np.asarray(compiled_record['correct'])
        protocol_name = np.asarray(compiled_record['protocol_name'])
        protocol_ver = np.asarray(compiled_record['protocol_version_number'])

        # filter out trial_numbers for current protocol_name and protocol_ver
        current_step = current_step[np.bitwise_and(protocol_name==protocol_name[-1],protocol_ver==protocol_ver[-1])]
        trial_number = trial_number[np.bitwise_and(protocol_name==protocol_name[-1],protocol_ver==protocol_ver[-1])]
        correct = correct[np.bitwise_and(protocol_name==protocol_name[-1],protocol_ver==protocol_ver[-1])]

        if self.num_trials_mode == 'consecutive':
            jumps = np.where(np.diff(trial_number)!=1) # jumps in trial number
            if not jumps[0]:
                which_trials = trial_number
            else:
                which_trials = trial_number[jump[0][-1]:] # from the last jump
        else:
            which_trials = trial_number

        if np.size(which_trials)<self.num_trials:
            graduate = False # dont graduate if the number of trials less than num required
        else:
            which_trials = which_trials[-self.num_trials:]
            filter =  np.isin(trial_number,which_trials)
            correct = correct[filter]
            perf = np.sum(correct)/np.size(correct)
            if perf >self.pct_correct:
                graduate = True
            else:
                graduate = False

        return graduate

class RateCriterion(Criterion):

    def __init__(self, trials_per_minute=10, consecutive_minutes=5, name='Unknown'):
        super(PerformanceCriterion, self).__init__(name)
        self.ver = Ver('0.0.1')
        self.trials_per_minute = trials_per_minute
        self.consecutive_minutes = consecutive_minutes

    def __repr__(self):
        return "RateCriterion object, (%s trials/minute for %s minutes)", (self.trials_per_minute, self.consecutive_minutes)

    def check_criterion(self, compiled_record, trial_record, station, **kwargs):
        Graduate = False
        raise NotImplementedError()
        return graduate

class RepeatIndefinitely(Criterion):

    def __init__(self, name='Unknown'):
        self.ver = Ver('0.0.1')
        super(RepeatIndefinitely, self).__init__(name)

    def __repr__(self):
        return "RepeatIndefinitely object"

    def check_criterion(self, **kwargs):
        return False


import os
import math
import numpy as np
from tqdm import tqdm
import pickle
import torch
import torch.nn as nn
from torch.autograd import Variable
from torch.nn import functional as F
from models import l2norm

## Memory
class Memory(nn.Module):
    def __init__(self, mem_size=500000, feat_dim=256, margin=1, topk=1000, update_rate=0.1):
        super(Memory, self).__init__()
        self.mem_size = mem_size
        self.feat_dim = feat_dim
        self.Mem = nn.Parameter(torch.zeros(mem_size, feat_dim))
        self.Ages = nn.Parameter(torch.zeros(mem_size, 1))
        self.topk = topk
        self.margin = margin
        self.update_rate = update_rate
        # At this time, we don't train mem by gradient descent
        self.Mem.requires_grad = False
        self.Ages.requires_grad = False

    def update_mem(self, x, labels):
        with torch.no_grad():
            self.Mem[labels] = l2norm(self.update_rate * x.data + (1 - self.update_rate) * self.Mem[labels])

    def update_mem_with_ages(self, x, labels):
        with torch.no_grad():
            self.Ages[labels] += 1.
            self.Mem[labels] = l2norm(x.data + self.Mem[labels] * self.Ages[labels])

    def search_l2(self, x, topk):
        batch_size = x.size(0)
        distmat = torch.pow(x, 2).sum(dim=1, keepdim=True).expand(batch_size, self.mem_size) + \
                  torch.pow(self.Mem, 2).sum(dim=1, keepdim=True).expand(self.mem_size, batch_size).t()
        distmat.addmm_(x, self.Mem.t(), beta=1, alpha=-2)
        distances, indices = torch.topk(distmat, topk, largest=False)
        return distances, indices

    def compute_l2loss(self, x, labels):
        """ L2 Distance
        Args:
            x: feature matrix with shape (batch_size, feat_dim).
            labels: ground truth labels with shape (batch_size).
        """
        batch_size = x.size(0)
        distmat = torch.pow(x, 2).sum(dim=1, keepdim=True).expand(batch_size, self.mem_size) + \
                  torch.pow(self.Mem, 2).sum(dim=1, keepdim=True).expand(self.mem_size, batch_size).t()
        distmat.addmm_(x, self.Mem.t(), beta=1, alpha=-2)
        classes = torch.arange(self.mem_size).long()
        if labels.is_cuda:
            classes = classes.cuda()
        labels = labels.unsqueeze(1).expand(batch_size, self.mem_size)
        mask = labels.eq(classes.expand(batch_size, self.mem_size))

        dist1 = distmat * mask.float()
        min_loss = dist1.clamp(min=1e-12, max=1e+12).sum(1)

        dist2 = distmat * (1.0 - mask.float())
        max_loss = torch.topk(dist2, self.topk, dim=1, largest=False)[0].sum(1) /  (self.topk - 1)
        loss = F.relu(min_loss - max_loss + self.margin)
        return loss.mean(), min_loss.mean(), max_loss.mean()


"""
Project 2A:

Write a program that takes as inputs the hourly wage, total regular hours, and total overtime hours and displays an employee's total weekly pay.

Overtime pay equals the total overtime hours multiplied by 1.5 times the hourly wage.
An employee's total weekly pay equals the hourly wage multiplied by the total number of regular hours plus any overtime pay.
"""

""" This generally looks good! I would split the weekly_pay function into three different ones: get_hourly_wage, get_regular_hours, and get_overtime_hours in order to make the program flow a bit more readable. The the actual program would look something like

hourly_wage = get_hourly_wage()
regular_hours = get_regular_hours()
overtime_hours = get_overtime_hours()

weekly_pay = hourly_wage * (regular_hours + 1.5 * overtime_hour)

print(f"\nTotal Weekly Pay: ${weekly_pay}")
input('')

Also, you end up doing basically the same thing (get an input,check that it's a number, check that it's non-negative) quit a few times, both in this program and in the others. It might be a good idea to write a general function to abstract this process. Something like

def get_non_negative_number(prompt: str) -> float:
    while True:
        input_result = input(prompt)
        if not is_valid_number(input_result):
            print("Not valid! (or something)")
            continue
        return str(input_result)
"""

def is_valid_number(num: str):
    try:
        float(num)
        return True
    except ValueError:
        return False

def Weekly_Pay():
    while True:
        hourly_wage = input("Please enter your hourly wage: ")
        if not is_valid_number(hourly_wage):
            print("Invalid character(s) detected.")
        elif float(hourly_wage) < 0:
            print("Your hourly wage must be a positive number.")
        else:
            hourly_wage = float(hourly_wage)
            break

    while True:
        total_regular_hours = input("Please enter your total regular hours: ")
        if not is_valid_number(total_regular_hours):
            print("Invalid character(s) detected.")
        elif float(total_regular_hours) < 0:
            print("Your total regular hours must be a positive number.")
        else:
            total_regular_hours = float(total_regular_hours)
            break

    while True:
        total_overtime_hours = input("Please enter your total overtime hours: ")
        if not is_valid_number(total_overtime_hours):
            print("Invalid character(s) detected.")
        elif float(total_overtime_hours) < 0:
            print("Your total overtime hours must be a positive number.")
        else:
            total_overtime_hours = float(total_overtime_hours)
            break

    overtime_pay = total_overtime_hours * (1.5 * hourly_wage)
    total_weekly_pay = (hourly_wage * total_regular_hours) + overtime_pay
    return total_weekly_pay

weekly_pay = Weekly_Pay()
weekly_pay = "{:,}".format(round(weekly_pay,2))

print(f"\nTotal Weekly Pay: ${weekly_pay}")
input('')


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import copy
import datetime
import locale
import os
from tqdm import tqdm
from collections import *
from typing import Optional,List,Tuple

from trident.backend.common import *
from trident.backend.pytorch_ops import *
from trident.backend.pytorch_backend import to_tensor, get_device, load,fix_layer,set_device
from trident.data.utils import download_model_from_google_drive,download_file_from_google_drive
from trident.layers.pytorch_layers import *
from trident import context
from trident.context import make_dir_if_need,split_path,sanitize_path

ctx=context._context()

__all__ = ['Word2Vec','ChineseWord2Vec']

_trident_dir = get_trident_dir()
dirname = os.path.join(_trident_dir, 'models')
if not os.path.exists(dirname):
    try:
        os.makedirs(dirname)
    except OSError:
        # Except permission denied and potential race conditions
        # in multi-threaded environments.
        pass

download_path= os.path.join(_trident_dir, 'download','vocabs_tw.txt')
make_dir_if_need(download_path)

class Word2Vec(Embedding):
    """中文詞向量
        繼承Embedding Layer

    """

    def __init__(self, pretrained=False, embedding_dim: Optional[int] = None, num_embeddings: Optional[int] = None, vocabs: Optional[List[str]] = None,
                 padding_idx: Optional[int] = None,
                 max_norm: Optional[float] = None, norm_type: float = 2., scale_grad_by_freq: bool = False,
                 sparse: bool = False, _weight: Optional[Tensor] = None, filter_index=-1, keep_output: bool = False, name: Optional[str] = None) -> None:

        """
        Py Word2vec结构
        """
        super().__init__(num_embeddings=num_embeddings, embedding_dim=embedding_dim, max_norm=max_norm, norm_type=norm_type, scale_grad_by_freq=scale_grad_by_freq, sparse=sparse,
                         _weight=_weight,padding_idx=padding_idx, keep_output=keep_output, name=name)
        self.pretrained=pretrained
        self.filter_index=filter_index
        self.locale =ctx.locale
        print('locale:', self.locale)

        self._vocabs = OrderedDict()
        if vocabs is not None:
            for k in range(len(vocabs)):
                self._vocabs[vocabs[k]] = k
        download_file_from_google_drive(file_id='16yDlJJ4-O9pHF-ZbXy7XPZZk6vo3aw4e', dirname=os.path.join(_trident_dir, 'download'), filename='vocabs_tw.txt')

    @property
    def vocabs(self):
        # 詞彙表
        return self._vocabs

    def word2idx(self, word: str):
        # 文字轉索引(根據locale處理繁簡轉換)
        if self.locale != 'zh_cn' and word in self.tw2cn:
            word = self.tw2cn[word]
        if word in self._vocabs:
            return self._vocabs[word]
        else:
            return None

    def idx2word(self, index: int):
        # 索引轉文字(根據locale處理繁簡轉換)
        if index < len(self._vocabs):
            word = self._vocabs.key_list[index]
            if self.locale != 'zh_cn' and word in self.cn2tw:
                word = self.cn2tw[word]
            return word
        else:
            return None

    @classmethod
    def load(cls):
        # 從google drive載入模型
        st = datetime.datetime.now()
        set_device('cpu')
        dirname = os.path.join(get_trident_dir(), 'models')

        download_model_from_google_drive('13XZPWh8QhEsC8EdIp1niLtZz0ipatSGC', dirname, 'word2vec_chinese.pth')
        recovery_model = load(os.path.join(dirname, 'word2vec_chinese.pth'))
        recovery_weight=recovery_model.state_dict()['weight']
        shp=int_shape(recovery_weight)

        v = cls(pretrained=True,num_embeddings=shp[0], embedding_dim=shp[-1],_weight=recovery_weight,name='word2vec_chinese')
        v._vocabs=copy.deepcopy(recovery_model._vocabs)
        v.tw2cn =copy.deepcopy(recovery_model.tw2cn)
        v.cn2tw = copy.deepcopy(recovery_model.cn2tw)
        del recovery_model
        v.locale =ctx.locale
        v.to(get_device())
        et = datetime.datetime.now()
        print('total loading time:{0}'.format(et - st))
        return v

    def find_similar(self, reprt: (str, Tensor), n: int = 10, ignore_indexes=None):
        # 根據文字或是向量查詢空間中最近文字
        reprt_idx = None
        if ignore_indexes is None:
            ignore_indexes = []
        if isinstance(reprt, str):
            reprt_idx = self.word2idx(reprt)
            ignore_indexes.append(reprt_idx)
            reprt = self.weight[reprt_idx].expand_dims(0) if reprt in self._vocabs else None
        if is_tensor(reprt):
            correlate = element_cosine_distance(reprt, self.weight)[0]
            sorted_idxes = argsort(correlate, descending=True)

            sorted_idxes = sorted_idxes[:n + len(ignore_indexes)]
            sorted_idxes = to_tensor([idx for idx in sorted_idxes if idx.item() not in ignore_indexes]).long()
            probs = to_list(correlate[sorted_idxes])[:n]
            words = [self.idx2word(idx.item()) for idx in sorted_idxes][:n]
            return OrderedDict(zip(words, probs))
        else:
            raise ValueError('Valid reprt should be a word or a tensor .')

    def analogy(self, reprt1: (str, Tensor, list), reprt2: (str, Tensor, list), reprt3: (str, Tensor, list), n: int = 10):
        # 類比關係 (男人之於女人等於國王之於皇后)
        reprt1_idx = None
        reprt2_idx = None
        reprt3_idx = None
        reprt1_arr = None
        reprt2_arr = None
        reprt3_arr = None
        exclude_list = []
        if isinstance(reprt1, str):
            reprt1_idx = self.word2idx(reprt1)
            exclude_list.append(reprt1_idx)
            reprt1_arr = self.weight[reprt1_idx].expand_dims(0) if reprt1_idx is not None else None
        elif isinstance(reprt1, Tensor):
            reprt1_arr = reprt1
        elif isinstance(reprt1, list):
            if isinstance(reprt1[0], str):
                reprt1_arr = self.get_words_centroid(*reprt1)
                for item in reprt1:
                    exclude_list.append(self.word2idx(item))

        if isinstance(reprt2, str):
            reprt2_idx = self.word2idx(reprt2)
            exclude_list.append(reprt2_idx)
            reprt2_arr = self.weight[reprt2_idx].expand_dims(0) if reprt2_idx is not None else None
        elif isinstance(reprt2, Tensor):
            reprt2_arr = reprt2
        elif isinstance(reprt2, list):
            if isinstance(reprt2[0], str):
                reprt2_arr = self.get_words_centroid(*reprt2)
                for item in reprt2:
                    exclude_list.append(self.word2idx(item))

        if isinstance(reprt3, str):
            reprt3_idx = self.word2idx(reprt3)
            exclude_list.append(reprt3_idx)
            reprt3_arr = self.weight[reprt3_idx].expand_dims(0) if reprt3_idx is not None else None
        elif isinstance(reprt3, Tensor):
            reprt3_arr = reprt3
        elif isinstance(reprt3, list):
            if isinstance(reprt3[0], str):
                reprt3_arr = self.get_words_centroid(*reprt3)
                for item in reprt3:
                    exclude_list.append(self.word2idx(item))

        if reprt1_arr is not None and reprt2_arr is not None and reprt3_arr is not None:
            reprt4 = reprt2_arr - reprt1_arr + reprt3_arr
            return self.find_similar(reprt4, n=n, ignore_indexes=exclude_list)
        else:
            not_find = []
            if reprt1_arr is None:
                not_find.append(reprt1)
            if reprt2_arr is None:
                not_find.append(reprt2)
            if reprt3_arr is None:
                not_find.append(reprt3)
            raise ValueError(' ,'.join(not_find) + ' was not in vocabs.')

    def get_words_centroid(self, *args):
        # 取得數個文字的向量均值
        centroid = 0
        for arg in args:
            reprt_idx = self.word2idx(arg)
            if reprt_idx is not None:
                centroid += self.weight[reprt_idx].expand_dims(0) if reprt_idx is not None else None
        return centroid / len(args)

    def get_words_vector(self, word):
        # 取得單一文字的向量
        reprt_idx = self.word2idx(word)
        if reprt_idx is not None:
            return self.weight[reprt_idx].expand_dims(0) if reprt_idx is not None else None
        return None

    def get_enumerators(self, *args, negative_case=None, n=10, exclude_samples=True):
        # 取得整體距離輸入案例最接近，但是離負案例最遠(negative_case)的文字列表
        positive_correlate = 0
        negative_correlate = 0
        exclude_list = []
        for arg in args:
            positive_correlate += element_cosine_distance(self.get_words_vector(arg), self.weight)[0]

        correlate = positive_correlate
        if negative_case is None:
            pass
        else:
            if isinstance(negative_case, str):
                negative_case = [negative_case]
            if isinstance(negative_case, (list, tuple)):
                for arg in negative_case:
                    negative_correlate += element_cosine_distance(self.get_words_vector(arg), self.weight)[0]
                correlate = positive_correlate - negative_correlate
        sorted_idxes = argsort(correlate, descending=True)
        sorted_idxes = sorted_idxes[:n + len(exclude_list)]
        sorted_idxes = to_tensor([idx for idx in sorted_idxes if idx.item() not in exclude_list]).long()
        probs = to_list(correlate[sorted_idxes])[:n]
        words = [self.idx2word(idx.item()) for idx in sorted_idxes][:n]
        return OrderedDict(zip(words, probs))

def ChineseWord2Vec(pretrained=True, freeze_features=True, **kwargs):
    if pretrained==True:
        model=Word2Vec.load()
        if freeze_features:
            model.trainable=False
        return model
    else:
        return Word2Vec()


import datetime
import random
import yaml

from requests import get

def compute_median(lst):
    """
    Вычисление медианты списка
    :param lst: входящий список значений
    :return: медиана
    """
    quotient, remainder = divmod(len(lst), 2)
    return lst[quotient] if remainder else sum(sorted(lst)[quotient - 1:quotient + 1]) / 2

def compute_avg(lst):
    """
    Вычисление среднего арифметические значения списка
    :param lst: входящий список значений
    :return: среднее арифметические значение
    """
    return sum(lst) / len(lst)

def usage_type(avg, median):
    """
    Вычисление типа использования
    :param avg: среднее занечение метрик
    :param median: медианное значение метрик
    :return: возврат значения типа использования
    """
    if (avg < 1.25 * median) and (avg > 0.75 * median):
        return "стабильна"
    elif avg > 1.25 * median:
        return "скачки"
    else:
        return "снижения"

def intensity(median):
    """
    Вычисление интенсивности использования
    :param median: медианное значение метрик
    :return: возврат значения интенсивности
    """
    if (0 < median) and (median <= 30):
        return "низкая"
    if (30 < median) and (median <= 60):
        return "умеренная"
    if (60 < median) and (median <= 90):
        return "высокая"
    return "запредельная"

def decision(usage, intens):
    """
    Принятие решения о дальнецшем использовании ресурса
    :param usage: тип использования
    :param intens: интенсивности использованя
    :return: возврат решения
    """
    if intens == "низкая":
        return "отказаться"
    if intens == "запредельная":
        return "усилить"
    if intens == "умеренная" and usage in ("стабильна", "скачки"):
        return "отсавить"
    if intens == "высокая" and usage in ("снижения", "стабильна"):
        return "отсавить"
    if usage == "снижения" and intens == "умеренная":
        return "отказаться"
    if usage == "скачки" and intens == "высокая":
        return "усилить"

def obj_creator(data):
    """
    Генератор обьекта заданной структуры из сырых данных
    :param data: сырые данные
    :return: Обект заданной тсруктуры
    """
    final_data = {}
    for msg in data:
        team_name, project, resource, due, resource_metric = msg
        a = {"time": due, "value": int(resource_metric)}
        final_data.setdefault(team_name, {}).setdefault(project, {}).setdefault(resource, []).append(a)
    return final_data

def get_data_from_http(url):
    """
    Генерация списка метрик по HTTP
    :param url: адресс веб сервера источника метрик
    :return: лист метрик
    """
    rnd_seed = random.randint(1, 3)
    team_raw = get(url + f"/monitoring/infrastructure/using/summary/{rnd_seed}").text.split("$")
    final_list = []
    for team_raw_data in team_raw:
        team_name, team_data = team_raw_data.split("|")
        team_data = team_data.split(";")
        for team_data_split_data in team_data:
            project, resource, due, resource_metric = team_data_split_data[1:-1].split(",")
            yr, mt, dy = due[0:10].split("-")
            date = datetime.date(year=int(yr), month=int(mt), day=int(dy))
            final_list.append((team_name, project, resource, date, int(resource_metric)))
    return final_list

if __name__ == '__main__':
    print("start")

    full_msg = get_data_from_http("http://127.0.0.1:21122/")
    final_data = obj_creator(full_msg)

    yaml_price = get("http://127.0.0.1:21122/monitoring/infrastructure/using/prices").text
    price_full = yaml.safe_load(yaml_price)["values"]

    print("Ресурс|Значение|среднее|медиана|использование|интенсивность|решение|дата последний метрики|цена")
    for name, prj in final_data.items():
        print(f"команда {name}")
        for prj_name, res_values in prj.items():
            summ = 0
            for res, values in res_values.items():
                value_list = []
                time = []
                for value in values:
                    value_list.append(value["value"])
                    time.append(value["time"])
                last_time = time[-1] + datetime.timedelta(14)
                median = compute_median(value_list)
                avg = compute_avg(value_list)
                usage = usage_type(avg, median)
                intens = intensity(median)
                final_decision = decision(usage, intens)
                cost = price_full[prj_name]
                summ += int(cost[res])
                print(f"{prj_name} | {res} | {avg} | {median} | {usage} | {intens} | {final_decision} | {last_time} | {cost[res]}")
            print(f"Цена за ресурс = {summ}")


# -*- coding: utf-8 -*-
from __future__ import division
import scrapy
from scrapy import Request
# from street_food.items import StreetFoodItem, StreetFoodDatTimeItem
from street_food.items import StreetFoodDatTimeItem
from street_food.spiders import tools
import json
from urllib import urlopen
# import random
from street_food.tools import basic_tools

class GetFoodOffTheGrid(scrapy.Spider):
    name = "offthegrid"
    allowed_domains = ["offthegridmarkets.com", "offthegrid.com"]

    start_urls = [
        'https://offthegrid.com/otg-api/passthrough/markets.json/?latitude=37.7749295&longitude=-122.41941550000001&sort-order=distance-asc'
    ]

    custom_settings = {
        "ITEM_PIPELINES": {
            "street_food.pipelines.ApiUploader": 10,
        }
    }

    def parse(self, response):
        ''' Parse list of markets '''

        markets = json.loads(response.text)

        market_url = "https://offthegrid.com/otg-api/passthrough/markets/{}.json/"

        # Get list of markets in San Francisco.
        for market in [market for market in markets["Markets"]]:
            market = market['Market']

            market_id = market['id']

            yield Request(market_url.format(market_id),
                          callback=self.parse_market)

    def parse_market(self, response):
        ''' Parse a market '''

        # load Maize Vendors.
        maizeresp = urlopen('http://yumbli.herokuapp.com/api/v1/allkitchens/?format=json')
        vendors = json.loads(maizeresp.read().decode('utf8'))
        maizevendors = {}
        for v in vendors:
            maizevendors[v['name'].lower()] = v['id']

        item = StreetFoodDatTimeItem()

        market = json.loads(response.text)
        market_detail = market["MarketDetail"]["Market"]["Market"]
        market_events = market["MarketDetail"]["Events"]

        # Market Address.
        market_address = market_detail["address"].strip()
        market_city = market_detail["city"].strip()
        full_address = "{} {}".format(market_address, market_city)

        # Market location.
        market_latitude = market_detail['latitude']
        market_longitude = market_detail['longitude']
        # geolocation = "{} {}".format(market_latitude, market_longitude)

        # Add data to item.

        item['address'] = full_address

        # Parse market events.
        for event in market_events:

            start_datetime, end_datetime = tools.get_start_end_datetime(event['Event'])

            item['start_datetime'] = start_datetime
            item['end_datetime'] = end_datetime

            # Parse vendors of event.
            for vendor in event['Vendors']:
                vendor_name = vendor['name']
                item['VendorName'] = vendor_name
                # randlongpos = random.randint(-150, 150) / 1000000
                # randlatpos = random.randint(-200, 200) / 1000000

                # item['latitude'] = abs(float(market_latitude)) + randlatpos
                # abs then *-1 b/c off the grid has some wrong values
                # item['longitude'] = abs(float(market_longitude))*-1 + randlongpos

                item['latitude'] = basic_tools.mix_location(market_latitude)
                item['longitude'] = basic_tools.mix_location(market_longitude)

                if vendor_name and vendor_name.lower() in maizevendors.keys():
                    item['maize_status'] = 'found'
                    item['maize_id'] = maizevendors[vendor_name.lower()]
                else:
                    item['maize_status'] = 'not found'
                    item['maize_id'] = 'n/a'

                yield item


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

# ## App Creation
#
# First, import all necessary libraries:

# In[1]:

#App Libraries
import json
import dash
from dash import html, dcc, Input, Output, State, dash_table
import dash_bootstrap_components as dbc

#Distributions
from scipy.stats import gamma
from scipy.stats import lognorm
from scipy.stats import weibull_min

#Calculation libraries
import math
import pandas as pd
import numpy as np
import ast
import statsmodels.api as sm
import matplotlib.pyplot as plt
import scipy.stats as stats
from scipy.optimize import minimize
from scipy.integrate import odeint
from scipy.optimize import fsolve
#from sympy import symbols, Eq, solve

#Plot libraries
import plotly.express as px
import plotly.graph_objs as go
import plotly.figure_factory as ff
from plotly.subplots import make_subplots

# In[2]:

#==================================================================#
#                 CREATE GENERATION INTERVAL DATA                  #
#==================================================================#
def create_gi(pop_mean, sd, m):
    '''
    pop_mean: population mean of the standard deviation
    '''

    #Set seed for consistency:
    np.random.seed(1234)

    #=========GAMMA============
    gamma_shape = (pop_mean**2)/(sd**2)
    gamma_scale = (sd**2)/(pop_mean)
    gi_gamma_obs = np.random.gamma(gamma_shape, gamma_scale, m)

    #=========LOGNORMAL============
    log_mean = pop_mean
    log_sd = sd
    log_var = log_sd**2
    norm_mean = np.log(log_mean)-0.5*np.log((log_sd/log_mean)**2+1) #scale=e^norm_mean
    norm_var = np.log((log_sd/log_mean)**2+1)
    norm_sd = np.sqrt(norm_var) # equivalent to the shape
    gi_lognorm_obs = lognorm.rvs(s=norm_sd, scale=math.exp(norm_mean), size=m)

    #=========WEIBULL============
    weibull_mean = pop_mean
    weibull_std = sd

    def G(k):
        return math.gamma(1+2/k)/(math.gamma(1+1/k)**2)
    def f(k,b):
        return G(k)-b #function solves for k

    b = (weibull_std**2)/(weibull_mean**2)+1

    init = 1 # The starting estimate for the root of f(x) = 0.
    weibull_shape = fsolve(f,init,args=(b))[0]
    weibull_scale = weibull_mean/math.gamma(1+1/weibull_shape)
    gi_weibull_obs = weibull_min.rvs(weibull_shape,scale=weibull_scale, size=m)

    return gi_gamma_obs, gi_lognorm_obs, gi_weibull_obs

#==================================================================#
#               VISUALIZE GENERATION INTERVAL DATA                 #
#==================================================================#

def gi_visualize(gi_gamma, gi_lognorm, gi_weibull):

    color=["skyblue","darkorange","green"]

    fig = make_subplots(rows=2, cols=2,)

    fig.append_trace(go.Histogram(x=gi_gamma, histnorm='percent', name='Gamma',
                                marker_color=color[0], opacity=1,),row=1,col=1)

    fig.append_trace(go.Histogram(x=gi_lognorm, histnorm='percent', name='Lognorm',
                                marker_color=color[1], opacity=1), row=1,col=2)

    fig.append_trace(go.Histogram(x=gi_weibull, histnorm='percent', name='Weibull',
                                marker_color=color[2], opacity=1), row=2,col=1)

    group_labels = ['Gamma Curve', 'Lognormal Curve', 'Weibull Curve']
    hist_data = [gi_gamma, gi_lognorm, gi_weibull]
    distplfig = ff.create_distplot(hist_data, group_labels, colors=color,
                             bin_size=.2, show_hist=False, show_rug=False)

    for k in range(len(distplfig.data)):
        fig.append_trace(distplfig.data[k],
        row=2, col=2
    )
    fig.update_layout(barmode='overlay')

    return(fig)

#==================================================================#
#                          OBJECTIVE FUNCTION                      #
#==================================================================#

def objective(w_lamb,tau):
    '''
    Objective: To maximize the log likelihood of W(u) (ie min(-W(u)))

    Inputs:
        w_lamb= weights [w_1, w_2,...,w_n] and lambda in one list
        tau = set of times since infection [tau_1, tau_2,...,tau_m]
    Outputs:
        objective: value (-W(u))
    '''

    w=w_lamb[:-1]
    lamb=w_lamb[-1]

    n=len(w)

    objective = 0

    for tau_i in tau: #FOR EACH TIME SINCE EXPOSURE
        wlog_val = w[0]
        for j in range(1,n): #CALCULATE TERMS WITHIN LOG
            wlog_val = wlog_val + (w[j]*(((lamb*tau_i)**j)/math.factorial(j)))
        objective = objective + (math.log(wlog_val) - (lamb*tau_i) + math.log(lamb))

    return(-1 *objective)

#==================================================================#
#                         CONSTRAINT FUNCTION                      #
#==================================================================#
def constraint(w_lamb):
    '''
    Constraint 1:  Weights must sum to 1
    Inputs:
        w: list of weights

    Outputs:
        constraint1: value of 1 - sum of the weights
    '''
    w=w_lamb[:-1]
    n = len(w)

    constraint1 = 1

    for j in range(n):
        constraint1 = constraint1 - w[j]
    return constraint1

#==================================================================#
#              CALCULATE WEIGHTS, HOLDING PERIOD, RATES            #
#==================================================================#
def solver(tau, R_0, n, dist_type):
    '''
    The following function returns a list of weights given the 5 inputs.

    Inputs:
        tau: list of generation intervals times (in days)
        R_0: basic reproduction number
        n: number of infectious comparments

    Output:
        w_val: list of weights (based on minimization)
        lambda: lambda value   (based on minimization)
        b_val: list of betas   (based on minimization)
    '''

    wl_0 = np.zeros(n+1)

    if dist_type == "gamma" or dist_type == "lognorm":
        shape = (np.mean(tau)**2)/np.var(tau) #shape of the disribution
        w2 = shape - math.trunc(shape)        #expected weight of "second" compartment
        w1 = 1 - w2                           #expected weight of "first" compartment
        comps = [math.trunc(shape)-1, math.trunc(shape)] #location of the "first" and "second" compartments where weights should exceed one
        weights = [w1, w2]

        for c, w in zip(comps,weights):
            wl_0[c] = w

        wl_0[-1]= np.mean(tau)/np.var(tau)

    #elif dist_type == "lognorm":
    #    for i in range(n):
    #        wl_0[i] = 1/n

    #    log_mean = np.mean(tau)
    #    log_std = np.std(tau)
    #    norm_mean = np.log(log_mean)-0.5*np.log((log_std/log_mean)**2+1)
    #    wl_0[-1]=  norm_mean

    elif dist_type == "weibull":
        for i in range(n):
            wl_0[i] = 1/n

        wl_0[-1]= np.std(tau)

    b = (0, 1)
    bnds=()
    for i in range(n):
        bnds = bnds + (b,)

    b_lamb = (0.00000000001, None)
    bnds = bnds + (b_lamb,)

    #specify constraints
    con1 = {'type': 'eq', 'fun': constraint}
    cons = ([con1])

    #optimize
    solution = minimize(objective, wl_0, method='SLSQP',                        args=(tau), bounds=bnds,constraints=cons)

    #get weights
    w_val = solution.x[:-1]
    lamb = solution.x[-1]
    b_val = [weight*lamb*R_0 for weight in w_val]

    return(w_val, lamb, b_val)

#==================================================================#
#                          OBJECTIVE FUNCTION                      #
#==================================================================#
def solutions(gi_data,min_n, max_n, R_0, dist_type):

    weight = []
    lambda_n = []
    beta = []
    obj = []

    for n_val in list(range(min_n, max_n+1)):
        if n_val == min_n:
            str_p = "Solving: "+ str(dist_type)+ " with R_0="+str(R_0)+" for n in "+ str(min_n)+",...,"+str(max_n)
            print(str_p)

        w, l, b = solver(gi_data, R_0, n_val, dist_type)
        o = objective(list(w)+[l],gi_data)

        if n_val == int((max_n+1-min_n)/4+min_n):
            print("n=",str(n_val)," is done. 25% Done!")

        if n_val == int((max_n+1-min_n)/2+min_n):
            print("n=",str(n_val)," is done. Half way there!")

        if n_val == int(3*(max_n+1-min_n)/4 + min_n):
            print("n=",str(n_val)," is done. 75% Done!")

        if n_val == max_n:
            print("Done!")

        weight.append(w)
        lambda_n.append(l)
        beta.append(b)
        obj.append(o)

    return weight, lambda_n, beta, obj

#==================================================================#
#                       EXPECTED INFECTIOUS CURVE                  #
#==================================================================#
def beta_u(u_i,beta_vals, lambda_n):
    '''
    Beta(u): Find transmission rate for every time in u_i

    Inputs:
        u_i: list of generation intervals times (in days)
        beta_vals: list of betas (based on minimization)
        lambda_n: rate that infected move to the next compartment

    Outputs:
        y:
    '''
    n = len(beta_vals)
    y = []

    for u in u_i:
        transmission=0
        for j in range(n):
            transmission = transmission + beta_vals[j]*((np.exp(-lambda_n*u)*(lambda_n*u)**j)/math.factorial(j))

        y.append(transmission)

    return(y)

#==================================================================#
#                 VISUALIZE EXPECTED INFECTIOUS CURVE              #
#==================================================================#
def beta_u_plot(lambda_n, beta_vals):

    #create x axis
    x = np.linspace(0, 15, 100)

    #create df of x, y data
    beta_df = pd.DataFrame(x, columns=["x"])

    beta_df[str(len(beta_vals))] = [float(b) for b in beta_u(x,beta_vals,lambda_n)]

    fig = go.Figure()
    fig.add_trace(go.Scatter(x=beta_df.x, y=beta_df.iloc[:, 1]))

    #format graph
    fig.update_layout(legend_title_text='Compartment')
    fig.update_xaxes(title_text='Days', nticks=20)
    fig.update_yaxes(title_text='Transmission Rate')

    return(fig)

#==================================================================#
#               VISUALIZE EXPECTED INFECTIOUS CURVE                #
#==================================================================#
def plot_beta_dist(betas, lambdas):

    color=["skyblue","darkorange","green"]
    dist = ["Gamma", "Lognormal","Weibull"]
    count = 0

    fig = make_subplots(rows=1, cols=1)

    for beta,lamb in zip(betas,lambdas):
        data = beta_u_plot(lamb, beta)

        fig.add_trace(
            go.Scatter(x=data['data'][0]['x'], y=data['data'][0]['y'],
                      name=dist[count], line_color=color[count],
                      line=dict(width=3)),
            row=1, col=1
        )
        count+=1

    #-----STYLING--------
    fig.update_layout(
        title="Estimated Infectious Curve  of each Distribution", #β(𝜏)
        xaxis_title="Duration of Infection (days)",
        yaxis_title="Transmission Rate", legend_title="Legend", font=dict(size=14),
        legend=dict(yanchor="top", y=0.99, xanchor="right", x=0.99))

    return(fig)

#==================================================================#
#                          SInR(S) MODEL                           #
#==================================================================#
def SInR(y, t, N, c, h, beta, lambda_n):
    '''
    Inputs:
        y: initial condition vector (S, I, R)
        t: time points (in days)
        N: total population
        c: contact rate
        h: waning immunity rate
        beta: transmission rate
        lambda_n: optimized holding period

    Outputs:
        pop_status: returns a list of how many people are in each compartment
    '''
    S = y[0]
    I = y[1:-1]
    R = y[-1]

    npI = np.array(I)
    npBeta = np.array(beta)

    #Calculate dSdt
    dSdt = -S/N * np.sum(npI * npBeta)*c+ h*R

    #Calculate dI1dt
    dI1dt = S/N* np.sum(npI * npBeta)*c - lambda_n* I[0]

    #Calculate dI_dt values from n=2,..,n
    dIndt = []
    for index in range(len(I)-1):
        dIndt.append(lambda_n* I[index] - lambda_n* I[index+1])

    #Calculate dRdt
    dRdt = lambda_n * I[len(I)-1] - h*R

    #Create list of results for S through R
    pop_status = [dSdt, dI1dt]
    pop_status.extend(dIndt)
    pop_status.append(dRdt)

    return pop_status

#==================================================================#
#                      VISUALIZE SInR(S) MODEL                     #
#==================================================================#
def SInR_plot(y_t0, t, N, c, h, beta, lambda_n):
    # Integrate the SIR equations over the time grid, t.
    ret = odeint(SInR, y_t0, t, args=(N, c, h, beta, lambda_n))

    S = ret.T[0]
    I = sum(ret.T[1:-1])
    R = ret.T[-1]

    fig = go.Figure()
    fig.add_trace(go.Scatter(x=t, y=S/N,name="Susceptible"))
    fig.add_trace(go.Scatter(x=t, y=I/N,name="Sum of Infected Compartments"))
    fig.add_trace(go.Scatter(x=t, y=R/N,name="Recovered"))#

    fig.update_layout(legend_title_text='Compartment')
    fig.update_xaxes(title_text='Time (Days)')#,nticks=20)
    fig.update_yaxes(title_text='Percentage of the Population')

    return(fig)

# In[3]:

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

##########################################################################
#                           HELPER FUNCTIONS                             #
##########################################################################
def create_dropdown_options(series):
    options = [{'label': i, 'value': i} for i in series.sort_values().unique()]
    return options
def create_dropdown_value(series):
    value = series.sort_values().unique().tolist()
    return value
def create_slider_marks(values): #NEED
    marks = {i: {'label': str(i)} for i in values}
    return marks

##########################################################################
#                    ADD ONS TO APP (images, files,etc)                  #
##########################################################################
#pull Gamma Data
gi_df = pd.read_excel ('GI_Values.xlsx')[["Source", "Mean","SD", "Dist_Type"]]
gi_df.sort_values(by=["Dist_Type",'Mean'], inplace=True)
gi_df.reset_index(drop=True, inplace=True)

colors = {'background': '#111111','text': 'black'}
subheader_size = 20

##########################################################################
#                             DASHBOARD APP                              #
##########################################################################
app.layout = html.Div(children=[
    dcc.Location(id="url",refresh=False),
    html.Div(id="output-div")
])

##########################################################################
#                               HOME PAGE                                #
##########################################################################
home_layout = html.Div(

    #==========Create "Header" Data=================
    children=[

    html.Div(
        [
            html.Img(src=app.get_asset_url("edinburgh.png"), height=50),
            html.Div([html.H4(children=('SI',html.Sub("n"),'R Covid-19 Modeling'), style={'textAlign': 'center', "font-weight": "bold"}),]),
        ], style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center'}
    ),

    #---Page Links---
    html.Div([dbc.Row(
    [
        dbc.Col(html.Div(dcc.Link('Home',href="/")), style={'textAlign': 'center'}),
        dbc.Col(html.Div(dcc.Link('Simulate Data',href="/simulate")), style={'textAlign': 'center'}),
        dbc.Col(html.A("Github Code", href='https://github.com/annette-bell/SInR-Covid-Dissertation',
                       target="_blank"), style={'textAlign': 'center'}),
    ],
    className="g-0",
    )]),

    #---Line Break---
    html.Div([html.Hr(style={'borderWidth': "0.3vh", "color": "#FEC700"}),]),

    #===============Home Page Information==========
    html.Div(
            [
                html.H6("About this app", style={"margin-top": "0","font-weight": "bold","text-align": "left"}),
                #html.Hr(),
                html.P("The Susceptible-Infected-Recovered (SIR) compartmental model is used in epidemiology to identify\
                        and categorize members of a population based on their status with regards to a disease. Less\
                        studied variations of this problem are the SInR and SInRS models. These models, which have applications\
                        in latent infection and varying transmission rates, will be used on three different generation\
                        interval—the time between primary exposure and secondary infection—distributions: gamma, lognormal,\
                        and Weibull. The distributions are ultimately tested against one another to see not only \
                        which provides most realistic data, but how these data-sets interact.\
                        This app is meant to help people understand dynamics of COVID-19 modeling through a simply dashboard application.\
                        To see a more in-depth explanation, please see the Github repository which includes my dissertation.",
                       className="control_label",style={"text-align": "justify"}),
            ],
            className="pretty_container almost columns",
        ),

    #============AUTHOR=============
    html.Div(
            [
                html.H6("Authors", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),

                html.P("Annette Bell (nettebell97@gmail.com)", style={"text-align": "center", "font-size":"10pt"}),

            ],
            className="pretty_container almost columns",
        ),

    #============ACKNOWLEDGEMENTS=============
    html.Div(
            [
                html.H6("Acknowledgements", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),

                html.P("John Dagpunar: Dr. Dagpunar was my thesis advisor and extremely helpful throughout the project.)", style={"text-align": "left", "font-size":"10pt"}),

            ],
            className="pretty_container almost columns",
        ),

    #============SOURCES=============
    html.Div(
            [
                html.H6("Sources", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),
                dcc.Markdown(
                    """\
                         - Code Layout was used from Plotly public dash application: https://dash.gallery/dash-food-consumption/
                         - I examined another dash application to better understand how to use it. In addition to dash application resources, I analyzed the source code to clarify how to implement dash: https://github.com/FranzMichaelFrank/health_eu
                         - Edinburgh PNG: https://uploads-ssl.webflow.com/5eb13d58c8c08b73773d6b1c/600ea3810bde89c60e317be7_uni-of-edinburgh.png
                        """
                ,style={"font-size":"10pt"}),

            ],
            className="pretty_container almost columns",
        ),

    ])

##########################################################################
#                           SIMULATION PAGE                             #
##########################################################################
sim_layout = html.Div(

    #==========Create "Header" Data=================
    children=[

    #---Title---
    html.Div(
        [
            html.Img(src=app.get_asset_url("edinburgh.png"), height=50),
            html.Div([html.H4(children=('SI',html.Sub("n"),'R Covid-19 Modeling'), style={'textAlign': 'center', "font-weight": "bold"}),]),
        ], style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center'}
    ),

    #---Page Links---
    html.Div([dbc.Row(
    [
        dbc.Col(html.Div(dcc.Link('Home',href="/")), style={'textAlign': 'center'}),
        dbc.Col(html.Div(dcc.Link('Simulate Data',href="/simulate")), style={'textAlign': 'center'}),
        dbc.Col(html.A("Github Code", href='https://github.com/annette-bell/SInR-Covid-Dissertation',
                       target="_blank"), style={'textAlign': 'center'}),
    ], className="g-0",
    )]),

    #---Line Break---
    html.Div([html.Hr(style={'borderWidth': "0.3vh", "color": "#FEC700"}),]),

    #============OVERIEW OF THE SIMULATION DATA=================
        html.Div(
            [
                html.H6(["Overview of Distributions", html.Br()], style={"margin-top": "0","font-weight": "bold","text-align": "left"}),

                html.Div(
                [
                dbc.Row(
                    [#---Table of Previous Analysis---:
                        dbc.Col(dash_table.DataTable(gi_df.to_dict('records'), [{"name": i, "id": i} for i in gi_df.columns],
                                                     style_header={'text-align': 'center', 'fontWeight': 'bold',},
                                                     style_table={'height': '200px', 'overflowY': 'auto'},
                                                     style_cell={'textAlign': 'left'},), width=3),

                    #---Commentary on the table
                        dbc.Col(html.Div([html.P("There are three main commonly used distributions to model the generation interval-\
                        the time from primary exposure to secondary infectiousness. These distributions include gamma, weibull, and log-normal.\
                        To the left, you can see a table of means and standard deviations from others previous work.",className="control_label",style={"text-align": "justify"}),]))]),]),
            ],
            className="pretty_container",
        ),

    #================= GENERATION INTERVAL SIMULATION =====================
        html.Div(
            [
                html.Div(
                    #----------------INPUTS-----------
                    [
                    html.H6("Generation Interval Distribution:", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),
                    html.P("Please select the distribution you wish to base your simulated generation interval data off of. Note: Seed=1234.", className="control_label",style={"text-align": "justify"}),
                    html.Br(),

                    #Shows the inputs for the specified distribution
                    html.Div(
                        [

                            dbc.Row([
                                dbc.Col(html.Div([
                                    #---Mean---
                                    html.P("Input the population mean:", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='pop_mean',placeholder='', type='number', value= 4.9),

                                ])),
                                dbc.Col(html.Div([
                                    #---SD---
                                    html.P("Input the standard deviation:", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='stan_dev',placeholder='', type='number', value= 2),

                                ])),
                            ],),

                            #---Data Set Size---
                            html.P("Select size of data:", className="control_label", style={"font-weight": "bold", "text-align": "center"}),
                            dcc.Slider(id='gi_size', min=1000, max=10000, step=500, value=5000,
                                       marks=create_slider_marks(list(range(1000,10001))[::1000])),

                            html.Br(),

                            #---Update Button---
                            html.Button(id='update_button', children="Simulate", n_clicks=0,style=dict(width='220px')),
                        ],),

                    ],
                    className="pretty_container four columns",
                ),

                #----------------GI Plot-----------
                html.Div(
                    [
                        html.H6("Generation Interval Simulations", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),

                        #---Information Regarding Shape and Scale---
                        html.P(id='shape_scale', style={"text-align": "justify"}),

                        #---GI Histogram---
                        html.Div(id='gammaplot_container',children=[
                        dcc.Graph(id="gi_plots", style={'height': '80vh'}),
                        ]),

                    ],

                    className="pretty_container seven columns",
                ),

            ],
            className="row flex-display",
        ),

    #===============Transmission Rate==========
    html.Br(),
    html.Div([dbc.Row(
    [
        dbc.Col(html.Div(html.Hr(style={'borderWidth': "0.3vh", "color": "#FEC700", 'align':'right'},)), width=5),
        dbc.Col(html.Div(html.H6("Transmission Rate", style={"text-align": "center", "font-weight": "bold",
                                                            "margin-top": "14px", "color": "#384142"})), width=1.5),
        dbc.Col(html.Div(html.Hr(style={'borderWidth': "0.3vh", "color": "#FEC700", 'align':'left'},)), width=5),
    ],
    )]),

    html.Div(
            [
                html.Div(
                    [#----------------Parameters of Beta(u)-----------
                        html.H6("Parameters of \u03b2(u):", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),
                        html.P("As the transmission rate is not constant, we create a function that simulates transmission a non constant transmission rate.", className="control_label",style={"text-align": "justify"}),

                        #---R_0---
                        html.P("Input the basic reproduction number:", className="control_label", style={"font-weight": "bold", "text-align": "center"}),
                        dcc.Input(id='R0', placeholder='', type='number', value= 2.3),

                        html.Br(),
                        html.Br(),

                        #---Update Button---
                        html.Button(id='beta_update_button', children="Calculate B(u)", n_clicks=0, style=dict(width='220px')),

                        ], className="pretty_container four columns",
                ),

                html.Div(
                    [#----------------Beta(u) Plot-----------
                        html.H6("Expected Infectious Curve", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),
                        #html.P("Visualize the transmission rates. Note: the following results are based on the parameters and the GI Data simulated above.", className="control_label",style={"text-align": "justify"}),

                        html.Br(),

                        #---return weights and betas---
                        #html.P(id='weights_beta_info', style={"text-align": "justify"}),
                        #html.P(id='lambdas', style={"text-align": "justify"}),
                        #html.P(id='weights', style={"text-align": "justify"}),
                        #html.P(id='betas', style={"text-align": "justify"}),

                        dcc.Graph(id="beta_plot", style={'height': '60vh'}),
                    ],
                    className="pretty_container seven columns",
                ),
            ],
            className="row flex-display",
        ),

    #=====================SI(n)R Model=====================

    html.Br(),
    html.Div([dbc.Row(
    [
        dbc.Col(html.Div(html.Hr(style={'borderWidth': "0.3vh", "color": "#FEC700", 'align':'right'},)), width=5),
        dbc.Col(html.Div(html.H6("Modeling COVID-19", style={"text-align": "center", "font-weight": "bold",
                                                            "margin-top": "14px", "color": "#384142"})), width=1.5),
        dbc.Col(html.Div(html.Hr(style={'borderWidth': "0.3vh", "color": "#FEC700", 'align':'left'},)), width=5),
    ],
    )]),

    html.Div(
            [
                html.Div(
                    [#----------------Parameters of SInR Model-----------
                        html.H6("Parameters of the Model:", style={"margin-top": "0","font-weight": "bold","text-align": "center"}),
                        #html.P("Beta(u) was last calculated using the following:", className="control_label",style={"text-align": "justify"}),

                        html.Div([
                        dcc.RadioItems(
                            id='distribution-dropdown',
                            options=[
                                {'label': 'gamma', 'value': 'gamma'},
                                {'label': 'weibull', 'value': 'weibull'},
                                {'label': 'log-normal','value': 'lognorm'},
                                {'label': 'all','value': 'all'}],

                            value='all',

                            labelStyle={"display": "inline-block"},
                            style={"font-weight": "bold", "text-align": "center"},
                        ),],),

                        dbc.Row(
                            [
                                dbc.Col(html.Div([
                                     #---Total Population---
                                    html.P("Total Population (N):", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='N_size', placeholder='', type='number', value = 67886011),
                                ])),
                                dbc.Col(html.Div([
                                    #---simulated days---
                                    html.P("Total Days to Simulate Over:", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='t_days', placeholder='', type='number', value = 180),

                                ])),

                            ], className="g-0",
                            ),

                        dbc.Row(
                            [
                                dbc.Col(html.Div([
                                    #---Recovered---
                                    html.P("Initial Recovered (R):", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='R_size', placeholder='', type='number', value = 0),

                                ])),
                                dbc.Col(html.Div([
                                    #---simulated days---
                                    html.P("Contact Rate:", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='c', placeholder='', type='number', value = 1),

                                ])),
                            ], className="g-0",
                            ),

                        dbc.Row(
                            [
                                dbc.Col(html.Div([
                                    #---Infected---
                                    html.P("Initail Infected (I):", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='I_size', placeholder='', type='number', value = 1),

                                ])),
                                dbc.Col(html.Div([
                                    #---simulated days---
                                    html.P("Waning Immunity Rate:", className="control_label", style={"font-weight": "bold", "text-align": "left"}),
                                    dcc.Input(id='h', placeholder='', type='number', value = 0),

                                ])),
                            ], className="g-0",
                            ),

                        #---n_slider---
                        html.P("Select the compartment size: ", className="control_label", style={"font-weight": "bold", "text-align": "center"}),
                        dcc.Slider(1, 20, step=1, value=10, id='n_val'),

                        #---SInR Button---
                        html.Br(),
                        html.Br(),
                        html.Button(id='model_button', children="Model", n_clicks=0, style=dict(width='220px')),

                        ], className="pretty_container four columns",
                ),

                html.Div(
                    [#----------------SInR Plot-----------
                        html.H6(('SI',html.Sub("n"),'R Covid-19 Modeling'), style={"margin-top": "0","font-weight": "bold","text-align": "center"}),
                        html.P(id='model_parameters', style={"text-align": "justify"}),
                        #html.P("Visualize the how th population shifts.", className="control_label",style={"text-align": "justify"}),

                        dcc.Graph(id="SInR_plot", style={'height': '60vh'}),

                        html.Div([ ], id='plot1'),
                    ],
                    className="pretty_container seven columns",
                ),
            ],
            className="row flex-display",
        ),

    ],
    id="mainContainer",
    style={"display": "flex", "flex-direction": "column"},
)

##########################################################################
#                          LINK TO EACH PAGE                             #
##########################################################################
@app.callback(
    Output(component_id="output-div",component_property="children"),
    Input(component_id="url",component_property="pathname"))

def update_page_layout(pathname):
    if pathname == "/simulate":
        return  sim_layout
    else:
        return home_layout

##########################################################################
#             SIMULATE AND VISUALIZE DISTRIBUTION DATA SETS              #
##########################################################################
@app.callback(
    [Output('gi_plots', 'figure'),
     Output('shape_scale', 'children')],
    [Input(component_id='update_button', component_property='n_clicks')],
    [State('stan_dev', 'value'),
    State('pop_mean', 'value'),
    State('gi_size', 'value')]
)

def update_sim_gi(n_clicks, sd, mean, size):
    '''
    This callback and function combination simulates
    a desired distribution (either gamma, weibull, or log-normal)
    given the information.
    '''
    #----------CREATE DISTRIBUTIONS---------
    gamma_data, lognorm_data, weibull_data = create_gi(mean, sd, size)

    mean_vals = [np.mean(gamma_data), np.mean(lognorm_data), np.mean(weibull_data)]
    std_vals = [np.std(gamma_data), np.std(lognorm_data), np.std(weibull_data)]

    #--------------VISUALIZE----------------
    gi_fig = gi_visualize(gamma_data, lognorm_data, weibull_data)

    return gi_fig, f'Given the input mean and standard deviation of {mean} and {sd} respectively,    the distributions are as follows: Gamma (x\u0305={round(mean_vals[0],3)}, s={round(std_vals[0],3)}).    Lognormal(x\u0305 ={round(mean_vals[1],3)}, s={round(std_vals[1],3)}).    Weibull(x\u0305={round(mean_vals[2],3)}, s={round(std_vals[2],3)}).'

##########################################################################
#                         CREATE AND PLOT BETA(u)                        #
##########################################################################
@app.callback(
    [Output('beta_plot', 'figure')],  #Output('weights_beta_info', 'children'), Output('lambdas', 'children'), Output('weights', 'children'), Output('betas', 'children')],
    [Input(component_id='beta_update_button', component_property='n_clicks')],
    [State('R0', 'value'),  #DISTRIBUTION STATES
     State('stan_dev', 'value'),
     State('pop_mean', 'value'),
     State('gi_size', 'value'),
    ]
)

def update_beta_u_plot(n_click, R0, sd, mean, size):
    '''
    Function will run beta_u function once "Calculate Beta(u)" button is clicked
    '''

    #----------CREATE DISTRIBUTIONS---------
    gamma_data, lognorm_data, weibull_data = create_gi(mean, sd, size)

    #----determine mimnimal acceptable size -----
    g_min_comp = math.ceil((np.mean(gamma_data)**2)/(np.var(gamma_data)))
    l_min_comp = math.ceil((np.mean(lognorm_data)**2)/(np.var(lognorm_data)))
    w_min_comp = math.ceil((np.mean(weibull_data)**2)/(np.var(weibull_data)))

    min_acceptable = max(g_min_comp, l_min_comp, w_min_comp)

    #----------------CALC VALS------------------
    w_gamma, l_gamma, b_gamma = solver(gamma_data, R0, min_acceptable, "gamma")
    w_lognorm, l_lognorm, b_lognorm = solver(lognorm_data, R0, min_acceptable, "lognorm")
    w_weibull, l_weibull, b_weibull = solver(weibull_data, R0, min_acceptable, "weibull")

    #----------------PLOT Beta(u)------------------
    b_n = [b_gamma, b_lognorm, b_weibull]
    l_n = [l_gamma, l_lognorm, l_weibull]
    w_n = [w_gamma, w_lognorm, w_weibull]

    beta_plot = plot_beta_dist(b_n, l_n)

    return [go.Figure(data=beta_plot)]

##########################################################################
#                           UPDATE SInR MODEL                            #
##########################################################################
@app.callback(
    [Output('SInR_plot', 'figure'),],#Output(component_id="plot1", component_property="children"),],
    #Output(component_id='model_parameters', component_property='children')],
    [Input(component_id='model_button', component_property='n_clicks')],
    [State('stan_dev', 'value'),
    State('pop_mean', 'value'),
    State('gi_size', 'value'),
    State('distribution-dropdown', 'value'),
    State('N_size', 'value'),
    State('I_size', 'value'),
    State('R_size', 'value'),
    State('t_days', 'value'),
    State('n_val', 'value'),
    State('R0', 'value'),
    State('c', 'value'),
    State('h', 'value')]
)

def update_SInR_plot(n_click, sd, mean, size, show, N, I1_t0, R_t0, days, n, R0, c_val, h_val):
    '''
    Visualize the SInR(S) plot
    '''

    gamma_data, lognorm_data, weibull_data = create_gi(mean, sd, size)

    #----determine mimnimal acceptable size -----
    g_min_comp = math.ceil((np.mean(gamma_data)**2)/(np.var(gamma_data)))
    l_min_comp = math.ceil((np.mean(lognorm_data)**2)/(np.var(lognorm_data)))
    w_min_comp = math.ceil((np.mean(weibull_data)**2)/(np.var(weibull_data)))

    #----------------CALC VALS------------------
    w_gamma, l_gamma, b_gamma = solver(gamma_data, R0, n, "gamma")
    w_lognorm, l_lognorm, b_lognorm = solver(lognorm_data, R0, n, "lognorm")
    w_weibull, l_weibull, b_weibull = solver(weibull_data, R0, n, "weibull")

    #-------Create lists of data-----
    b_n = [b_gamma, b_lognorm, b_weibull]
    l_n = [l_gamma, l_lognorm, l_weibull]
    w_n = [w_gamma, w_lognorm, w_weibull]

    print(b_n)

    color=["skyblue","darkorange","green"]
    dist = ["Gamma", "Lognormal","Weibull"]
    count=0

    #----specify compartments-------
    I_t0 = [I1_t0]+(n-1)*[0]
    S_t0 = N - sum(I_t0) - R_t0
    y_t0 = [S_t0]+ I_t0 +[R_t0]
    t = np.array(list(range(0,days+1)))

    #----specify model type-----
    if h_val== 0:
        model_type = "SI\u2099R Model of "
    else:
        model_type = "SI\u2099RS Model of "

    if show == "all":
        SInR_compare = go.Figure()
        dash = ["dot","dash"]

        for b,l in zip(b_n, l_n):
            #SIR MODEL
            if count == 0:
                fig = SInR_plot(y_t0, t, N, c_val, h_val, b, l)

                s_data = list(fig['data'][0]['y'])
                i_data = list(fig['data'][1]['y'])
                r_data = list(fig['data'][2]['y'])

                SInR_compare.update_layout(title=model_type+" for all Generation Intervals",
                                 legend=dict(yanchor="top", y=-0.2, xanchor="left",x=0.02, orientation="h"),
                                           font_size=14)

                SInR_compare.add_trace(go.Scatter(x=t, y= s_data, name= "Susceptible: " +dist[count]+" GI",
                                         line_color="blue",))
                SInR_compare.add_trace(go.Scatter(x=t, y= i_data, name= "Infected:     " +dist[count]+" GI",
                                         line_color="red",))
                SInR_compare.add_trace(go.Scatter(x=t, y= r_data, name= "Recovered:  " +dist[count]+" GI",
                                         line_color="green"))

                count+=1

            else:
                fig2 = SInR_plot(y_t0, t, N, c_val, h_val, b, l)
                s_data = list(fig2['data'][0]['y'])
                i_data = list(fig2['data'][1]['y'])
                r_data = list(fig2['data'][2]['y'])

                SInR_compare.add_trace(go.Scatter(x=t, y= s_data, name= "Susceptible: " +dist[count]+" GI",
                                         line_color="blue", line_dash=dash[count-1]))
                SInR_compare.add_trace(go.Scatter(x=t, y= i_data, name= "Infected:     " +dist[count]+" GI",
                                         line_color="red", line_dash=dash[count-1]))
                SInR_compare.add_trace(go.Scatter(x=t, y= r_data, name= "Recovered:  " +dist[count]+" GI",
                                         line_color="green", line_dash=dash[count-1]))

                count+=1
        SInR_compare.update_xaxes(title_text='Time (Days)')#,nticks=20)
        SInR_compare.update_yaxes(title_text='Percentage of the Population')

        return [go.Figure(data=SInR_compare)]

    else:
        if show == "gamma":
            index = 0
        if show == "lognorm":
            index = 1
        else:
            index=2

        I_t0 = [I1_t0]+(n-1)*[0]
        S_t0 = N - sum(I_t0) - R_t0
        y_t0 = [S_t0]+ I_t0 +[R_t0]
        t = np.array(list(range(0,days+1)))

        #SIR MODEL
        fig = SInR_plot(y_t0, t, N, c_val, h_val, b_n[index], l_n[index])
        fig.update_layout(title=model_type+" of "+dist[index]+" Generation Interval",
                         legend=dict(yanchor="top", y=0.35, xanchor="left", x=0.01),font_size=14)
        return [go.Figure(data=fig)]

##########################################################################
#                             RUN THE APP                                #
##########################################################################
if __name__ == "__main__":
    app.run_server(debug=False)

#TABLE STYLING:
#https://dash.plotly.com/datatable/style

# <br><br><br><br>


'''
boss class
'''

import pygame

class Boss(pygame.sprite.Sprite):

    def __init__(self,laser):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/Boss.gif").convert()
        self.rect = self.image.get_rect()
        self.rect.x = 500
        self.rect.y = 0
        self.health = 200
        self.laser = laser
        self.lasertimer = 0
        self.left = False
        self.right = True

    #update the boss
    def update(self):
        self.movement()
        self.attack()

    #get the health
    def getHealth(self):
        return self.health

    #set the health
    def setHealth(self):
        self.health = self.health - 10

    #laser attack of the boss
    def attack(self):

        self.lasertimer += 1

        if self.lasertimer == 20:
            self.laser.rect.x = self.rect.x + 50
            self.laser.rect.y = self.rect.y

        if self.lasertimer > 20:
            self.laser.rect.y += 15
            if self.laser.rect.y > 600:
                self.lasertimer = 0
                self.laser.rect.x = -500
                self.laser.rect.y = -500

    #set up movement for boss
    def movement(self):
        if self.rect.x > 900:
            self.right = False
            self.left = True

        if self.rect.x < 50:
            self.left = False
            self.right = True

        if self.left:
            self.rect.x -= 10
        if self.right:
            self.rect.x += 10


#!/usr/bin/env python
from Bio import SeqIO
import argparse
import json
import os
from CPT_GFFParser import gffParse, gffWrite

def parse_xmfa(xmfa):
    """Simple XMFA parser until https://github.com/biopython/biopython/pull/544
    """
    current_lcb = []
    current_seq = {}
    for line in xmfa.readlines():
        if line.startswith("#"):
            continue

        if line.strip() == "=":
            if "id" in current_seq:
                current_lcb.append(current_seq)
                current_seq = {}
            yield current_lcb
            current_lcb = []
        else:
            line = line.strip()
            if line.startswith(">"):
                if "id" in current_seq:
                    current_lcb.append(current_seq)
                    current_seq = {}
                data = line.strip().split()
                # 0 1           2 3      4 5
                # > 1:5986-6406 + CbK.fa # CbK_gp011
                id, loc = data[1].split(":")
                start, end = loc.split("-")
                current_seq = {
                    "rid": "_".join(data[1:]),
                    "id": id,
                    "start": int(start),
                    "end": int(end),
                    "strand": 1 if data[2] == "+" else -1,
                    "seq": "",
                    "comment": "",
                }
                if len(data) > 5:
                    current_seq["comment"] = " ".join(data[5:])
            # else:
            # current_seq['seq'] += line.strip()

def percent_identity(a, b):
    """Calculate % identity, ignoring gaps in the host sequence
    """
    match = 0
    mismatch = 0
    for char_a, char_b in zip(list(a), list(b)):
        if char_a == "-":
            continue
        if char_a == char_b:
            match += 1
        else:
            mismatch += 1

    if match + mismatch == 0:
        return 0.0
    return 100 * float(match) / (match + mismatch)

def get_fasta_ids(sequences):
    """Returns a list of fasta records in the order they appear
    """
    ids = []
    for seq in SeqIO.parse(sequences, "fasta"):
        ids.append(seq.id)
    return ids

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="parse xmfa file")
    parser.add_argument("gff3", type=argparse.FileType("r"), help="Multi-GFF3 File")
    parser.add_argument("fasta", type=argparse.FileType("r"), help="Multi-FA file")
    parser.add_argument("xmfa", type=argparse.FileType("r"), help="XMFA File")
    parser.add_argument("output_dir", type=str, help="output directory")
    args = parser.parse_args()

    fasta_list = get_fasta_ids(args.fasta)
    lcbs = parse_xmfa(args.xmfa)

    if not os.path.exists(args.output_dir):
        os.makedirs(args.output_dir)

    output = {"fasta": [], "gff3": [], "xmfa": None}

    processed_xmfa = os.path.join(args.output_dir, "regions.json")
    with open(processed_xmfa, "w") as handle:
        json.dump([lcb for lcb in lcbs if len(lcb) > 1], handle, sort_keys=True)

    output["xmfa"] = processed_xmfa

    # Have to seek because we already access args.fasta once in id_tn_dict
    args.fasta.seek(0)
    # Load up sequence(s) for GFF3 data
    seq_dict = SeqIO.to_dict(SeqIO.parse(args.fasta, "fasta"))
    # Parse GFF3 records
    gffs = gffParse(args.gff3, base_dict=seq_dict)
    for record in sorted(gffs, key=lambda rec: fasta_list.index(rec.id)):
        gff_output = os.path.join(args.output_dir, record.id + ".gff")
        with open(gff_output, "w") as handle:
            gffWrite([record], handle)
        output["gff3"].append(gff_output)

        fa_output = os.path.join(args.output_dir, record.id + ".txt")
        with open(fa_output, "w") as handle:
            handle.write(str(record.seq))
            output["fasta"].append(
                {"path": fa_output, "length": len(record.seq), "name": record.id}
            )

    print(json.dumps(output, sort_keys=True))


from flask import Flask, request, abort

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import *

# My Code
from util import *

app = Flask(__name__)

# Channel Access Token
line_bot_api = LineBotApi('++7wQ1tXdLomUPrrUbvcKEE12HAh+eeIh1s46ynQESIAH2zkobGXkk19oxFSHS/5fgOju9fHnX3wu02ALT70wQSYcrFuE5ZoKd5vYwkr+VRIdTiMfFSVFerWzr5j1Syf5YlS5NGCFoXbPBiF730F3AdB04t89/1O/w1cDnyilFU=')
# Channel Secret
handler = WebhookHandler('095348740b93fb668776aa36c9571a44')

# 監聽所有來自 /callback 的 Post Request
@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']
    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)
    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'

# 處理訊息
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    msg = event.message.text
    if '聯絡方式' in msg:
        message = imagemap_message()
        line_bot_api.reply_message(event.reply_token, message)
    elif '你是誰' in msg:
        message = TextSendMessage(text= "嗨我是吳岳，很高興認識你！")
        line_bot_api.reply_message(event.reply_token, message)
    elif '你會什麼' in msg:
        message = Carousel_Template()
        line_bot_api.reply_message(event.reply_token, message)
    elif '你喜歡什麼' in msg:
        message = image_gallery()
        line_bot_api.reply_message(event.reply_token, message)
    elif "你想去哪裡工作" in msg:
        line_bot_api.reply_message(event.reply_token,LocationSendMessage(title='LINE Taiwan', address='No. 333號, Ruiguang Rd, Neihu District, Taipei City, 114', latitude=25.07726625171245, longitude=121.57513202616131))
    else:
        message = TextSendMessage(text='echo: ' + msg)
        line_bot_api.reply_message(event.reply_token, message)

import os
if __name__ == "__main__":
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port)


# @PascalPuchtler

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

import json
import time
from sys import platform
import serial

class MoveControllerCommunication:
    def __init__(self,carModel, com = None, baudrate= 9600, changeMoveCallback = None):
        self.radiusBig = 0.55
        self.radiusSmall = 0.365
        self.error = False
        self.carModel = carModel
        self.changeMoveCallback = changeMoveCallback
        if com is None:
            if platform == "win32":
                com = 'COM7'
            else:
                com ='/dev/ttyACM0'
        try:
            self.communication = serial.Serial(com, baudrate= 9600,
            timeout=2.5,
            parity=serial.PARITY_NONE,
            bytesize=serial.EIGHTBITS,
            stopbits=serial.STOPBITS_ONE)

            time.sleep(1)
            self.communication.reset_input_buffer()
        except:
            print('Error: No Move controller available over port ' + com)
            self.error = True

    def turnLeft(self):
        self.driveCircle(self.radiusSmall,True, True)

    def turnRight(self):
        self.driveCircle(self.radiusSmall,True, False)

    def drive(self):
        self.driveCircle(float('inf'),True, False)

    def driveLeft(self):
        self.driveCircle(self.radiusBig,True, True)

    def driveRight(self):
        self.driveCircle(self.radiusBig,True, False)

    def backwardLeft(self):
        self.driveCircle(self.radiusBig,False, True)

    def backwardRight(self):
        self.driveCircle(self.radiusBig,False, False)

    def backward(self):
        self.driveCircle(float('inf'), False, False)

    def stop(self):
        if self.changeMoveCallback is not None:
            self.changeMoveCallback(0, 0)
        self.move([0,0])

    def fullLeft(self):
        self.move([-100,100])
        time.sleep(0.2)
        self.stop()

    def driveCircle(self,  radius, forward, left):
        motor, gear, speed = self.carModel.getMotorSpeedFromRadius(radius, forward, left)
        print('l:', round(motor[0]), 'r:', round(motor[1]), 'g:', round(gear,4), 's:', round(speed,4))
        if self.changeMoveCallback is not None:
            self.changeMoveCallback(gear, speed)
        self.move(motor)

    def move(self, motor):
        if not self.error:
            command = {}
            command["command"] = "move"
            command["left"] = int(motor[0])
            command["right"] = int(motor[1])
            self.communication.write(json.dumps(command).encode('ascii'))

    def getSonic(self):
        if not self.error:
            inputBuffer = self.communication.readline()

            command = {}
            command["command"] = "sonic"
            self.communication.write(json.dumps(command).encode('ascii'))
            try:
                sonic = json.loads(inputBuffer)
                return sonic
            except:
                print("exception in get Sonic")
                return {"left": 0, "right": 0, "middle":0}


#!/usr/bin/env python3
import sys
if(len(sys.argv) < 2):
	sys.exit("Usage: makeMetadata.py ebook_title path_to_write_metadata")
output = ''
output += '---\n'
output += 'title: ' + sys.argv[1].split('/')[len(sys.argv[1].split('/'))-1].title() + '\n'
output += 'author: ' + 'Kyle Simpson' + '\n'
output += 'rights: ' + 'Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License' + '\n'
output += 'language: ' + 'en-US' + '\n'
output += '...'
try:
	if(sys.argv[3] == '--debug' or sys.argv[3] == '-d'):
		print(output)
except Exception as e:
	pass
with open(sys.argv[2] + '/title.txt', 'w') as metadata:
	try:
		metadata.write(output)
	except Exception as e:
		print(str(e))


import unittest
from unittest import mock

from pydis_core.site_api import ResponseCodeError

from bot.exts.backend.sync._syncers import Syncer
from tests import helpers

class TestSyncer(Syncer):
    """Syncer subclass with mocks for abstract methods for testing purposes."""

    name = "test"
    _get_diff = mock.AsyncMock()
    _sync = mock.AsyncMock()

class SyncerSyncTests(unittest.IsolatedAsyncioTestCase):
    """Tests for main function orchestrating the sync."""

    def setUp(self):
        patcher = mock.patch("bot.instance", new=helpers.MockBot(user=helpers.MockMember(bot=True)))
        self.bot = patcher.start()
        self.addCleanup(patcher.stop)

        self.guild = helpers.MockGuild()

        TestSyncer._get_diff.reset_mock(return_value=True, side_effect=True)
        TestSyncer._sync.reset_mock(return_value=True, side_effect=True)

        # Make sure `_get_diff` returns a MagicMock, not an AsyncMock
        TestSyncer._get_diff.return_value = mock.MagicMock()

    async def test_sync_message_edited(self):
        """The message should be edited if one was sent, even if the sync has an API error."""
        subtests = (
            (None, None, False),
            (helpers.MockMessage(), None, True),
            (helpers.MockMessage(), ResponseCodeError(mock.MagicMock()), True),
        )

        for message, side_effect, should_edit in subtests:
            with self.subTest(message=message, side_effect=side_effect, should_edit=should_edit):
                TestSyncer._sync.side_effect = side_effect
                ctx = helpers.MockContext()
                ctx.send.return_value = message

                await TestSyncer.sync(self.guild, ctx)

                if should_edit:
                    message.edit.assert_called_once()
                    self.assertIn("content", message.edit.call_args[1])

    async def test_sync_message_sent(self):
        """If ctx is given, a new message should be sent."""
        subtests = (
            (None, None),
            (helpers.MockContext(), helpers.MockMessage()),
        )

        for ctx, message in subtests:
            with self.subTest(ctx=ctx, message=message):
                await TestSyncer.sync(self.guild, ctx)

                if ctx is not None:
                    ctx.send.assert_called_once()


"""
    An AI agent that will explore its environment and perform certain tasks (mining, smelting, forging, and buying/selling items)
    """
import sys
from time import sleep
import traceback
import cv2
import pyautogui
from game_map import GameMap
import utilities as utils
from user_interface import UserInterface
from player import Player

# Set defaults
task = Player.TASKS.MINE
if len(sys.argv) > 1:
    task = Player.TASKS[sys.argv[1].upper()]

# Initialize classes
game_map = GameMap()
player = Player(game_map, task)
user_interface = UserInterface()

utils.log("INIT", "====================================================")
utils.log("INIT", "Initializing...")
utils.log("INIT", F"Default task set to {task}")

# Find blocking window in screenshot
screenshot = utils.take_screenshot(False)
result = cv2.matchTemplate(screenshot, user_interface.templates['sponsored'], cv2.TM_CCORR_NORMED)
_, max_val, _, max_loc = cv2.minMaxLoc(result)

# Found the blocking window window with high confidence
if max_val > 0.9:
    click_at = (max_loc[0] + 428, max_loc[1] + 144)
    utils.log("INIT", "Closed blocking window")
    pyautogui.moveTo(click_at[0], click_at[1], 0.15)
    pyautogui.click()
    sleep(5)

# Bring game to foreground
utils.bring_game_to_foreground()

# Detect environment
screenshot = utils.take_screenshot()
game_map.update_player_position(screenshot)
utils.log("INIT", F"Player location initialized")
game_map.update_map()
utils.log("INIT", "Field of view mapped")
utils.log("INIT", "Initialization complete")
utils.log("INIT", "====================================================")
try:
    while utils.bring_game_to_foreground():
        player.perform_task()
except Exception as exception:
    utils.log("SEVERE", exception)
    utils.log("SEVERE", traceback.format_exc())
    utils.quit_game()


import pandas as pd
import subprocess
import os
df = pd.read_csv(snakemake.input.predictions, sep="\t")
cells_unselected = df.loc[df["prediction"] == 0, "cell"].tolist()

# ADDING NEW COLUMN TO CONFIG FILE
df_config = pd.read_csv("{data_location}/config/config_df_ashleys.tsv".format(data_location=snakemake.config["data_location"]), sep='\t')
df_config["Selected"] = True
df_config.loc[df_config["Cell"].isin([e.split('.')[0] for e in cells_unselected]), "Selected"] = False
df_config.to_csv("{data_location}/config/config_df_ashleys.tsv".format(data_location=snakemake.config["data_location"]), sep='\t', index=False)

with open(snakemake.output[0], 'w') as out:
    out.write("data_location processed: {data_location}\n".format(data_location=snakemake.params.path))
    out.write("Removed following cells:\n")
    for cell in cells_unselected:
        # print("rm {path}/{sample}/selected/{cell}".format(path=snakemake.params.path, sample=snakemake.wildcards.sample, cell=cell))
        subprocess.call("rm {path}/{sample}/selected/{cell}".format(path=snakemake.params.path, sample=snakemake.wildcards.sample, cell=cell), shell=True)
        subprocess.call("rm {path}/{sample}/selected/{cell}.bai".format(path=snakemake.params.path, sample=snakemake.wildcards.sample, cell=cell), shell=True)
        out.write("- {cell}\n".format(cell=cell))