'''
    构建B-树提供单词查找，输入单词返回单词的倒排记录
'''
import operator
from RetrivalSys import DictBuild
from functools import cmp_to_key

class BTree(object):
    """具有插入、搜索、打印的B树。"""

    class Node(object):
        """B树的节点"""

        def __init__(self, t):
            self.keys = []
            self.children = []
            # 是否为叶子节点
            self.leaf = True
            # t是树的度，节点的最大关键字数量是2t-1
            self._t = t

        def split(self, parent, payload):
            """分裂节点，调整key与children"""
            new_node = self.__class__(self._t)
            # _class_获得已有当前对象的类

            mid_point = self.size // 2
            # " / "表示 浮点数除法，返回浮点结果;" // "表示整数除法
            split_value = self.keys[mid_point]
            parent.add_key(split_value)

            # 将key与孩子节点添加到合适的节点
            new_node.children = self.children[mid_point + 1:]
            self.children = self.children[:mid_point + 1]
            # 将中间点之后的所有孩子节点赋给新的节点,[a:]表示将列表里a之后元素，[:a]表示列表里a之前的元素，包括a
            # 将中间点之前的所有孩子节点留给原节点
            new_node.keys = self.keys[mid_point + 1:]
            self.keys = self.keys[:mid_point]

            # 新节点有孩子，将它设为内节点
            if len(new_node.children) > 0:
                new_node.leaf = False

            parent.children = parent.add_child(new_node)
            # 将key与提升的关键字比较，决定返回关键字应该插入的分支
            if cmp_precode(payload, split_value) is -1:
                return self
            else:
                return new_node

        @property
        def _is_full(self):
            return self.size == 2 * self._t - 1

        @property
        def size(self):
            return len(self.keys)

        def add_key(self, value):
            """
            将key的值为value添加keys列表
            """
            self.keys.append(value)
            self.keys.sort(key=cmp_to_key(cmp_precode), reverse=False)  # 对keys重新排序

        def add_child(self, new_node):
            """
            给节点添加一个孩子. 对节点的孩子节点重新排序. allowing for children
            to be ordered even after middle nodes are split.
            返回: 一个有序的孩子节点列表
            """
            i = len(self.children) - 1
            while i >= 0 and cmp_precode(self.children[i].keys[0], new_node.keys[0]) is 1:
                i -= 1
            return self.children[:i + 1] + [new_node] + self.children[i + 1:]

    def __init__(self, t):
        """
        Create the B-tree. t是树的度.（算法导论里的定义，度为内节点最少的孩子数目，所以每个节点最少有t个孩子，最少有t-1个key
        最多有2t个孩子，2t-1个key）Tree 刚建立时没有key
        允许重复的key
        """
        self._t = t
        if self._t <= 1:
            raise ValueError("B-Tree must have a degree of 2 or more.")
        self.root = self.Node(t)

    def insert(self, payload):
        """在B-Tree中插入值为payload的关键字"""
        node = self.root
        # 根节点比较特殊，需要单独定义
        if node._is_full:
            # 根节点满，生成一个节点作为新的根节点，将原有根节点分裂为两个节点，作为孩子放入新的根节点孩子列表
            new_root = self.Node(self._t)
            new_root.children.append(self.root)
            new_root.leaf = False

            node = node.split(new_root, payload)
            self.root = new_root
        while not node.leaf:
            i = node.size - 1
            while i > 0 and cmp_precode(payload, node.keys[i]) is -1:  # 找到key在当前node哪个key之间
                i -= 1
            if cmp_precode(payload, node.keys[i]) is 1:  # 在当前key的右分支
                i += 1

            next = node.children[i]
            if next._is_full:
                node = next.split(node, payload)
            else:
                node = next
        # 将路径上的所有满的节点都分裂，就可以轻松地插入key.
        node.add_key(payload)

    def search(self, value, node=None):
        """如果B树包含查询的key，返回node"""
        if node is None:
            node = self.root
        if node is not None:
            h = node.size
            i = 0
            while i < h:
                w = cmp_key(value, node.keys[i])
                if w is not -1 and w is not -2:
                    return w
                elif w is -2:
                    i += 1
                elif w is -1:
                    break
            if node.leaf:
                return False
            return self.search(value, node.children[i])

    def print_order(self):
        """按每层打印B树."""
        this_level = [self.root]
        while this_level:
            next_level = []
            output = ""
            for node in this_level:
                if node.children:
                    next_level.extend(node.children)
                output += str(node.keys) + " "
            print(output)
            this_level = next_level

# 比较压缩词典行precode1和precode2的关系
def cmp_precode(precode1, precode2):
    """前缀编码比较函数"""
    pre1 = precode1.split('*')[0]
    pre2 = precode2.split('*')[0]
    if pre1 == '':
        pre1 = DictBuild.LineDecompress(precode1)[0][0]
    if pre2 == '':
        pre2 = DictBuild.LineDecompress(precode2)[0][0]
    mlen = min(len(pre1), len(pre2))
    pre1 = pre1[0:mlen]
    pre2 = pre2[0:mlen]
    if operator.lt(pre1, pre2):
        return -1
    elif operator.gt(pre1, pre2):
        return 1

    elif operator.eq(pre1, pre2):
        word1 = DictBuild.LineDecompress(precode1)[0][0]
        word2 = DictBuild.LineDecompress(precode2)[0][0]
        if operator.lt(word1, word2):
            return -1
        elif operator.gt(word1, word2):
            return 1
        elif operator.eq(word1, word2):
            return 0

# 单词比当前前缀小时，返回-1
# 单词比当前前缀大时，返回-2
# 找到时，返回偏移量
def cmp_key(key, precode):
    """key与前缀编码的比较函数"""
    pre = precode.split('*')[0]
    decode, offset = DictBuild.LineDecompress(precode)
    if pre == '':
        pre = decode[0]
    mlen = min(len(key), len(pre))
    prekey = key[0:mlen]
    pre = pre[0:mlen]
    if operator.lt(prekey, pre):
        if operator.ge(key, decode[0]):
            juge = find(decode, key)
            if juge is not -1:
                return offset[juge]
        return -1
    # key的前缀小于编码的前缀，key小于前缀
    elif operator.gt(prekey, pre):
        if operator.le(key, decode[len(decode) - 1]):
            juge = find(decode, key)
            if juge is not -1:
                return offset[juge]
        return -2
    elif operator.eq(pre, prekey):
        juge = find(decode, key)
        if juge is not -1:
            return offset[juge]
        elif operator.gt(key, decode[len(decode) - 1]):
            return -2
        elif operator.lt(key, decode[0]):
            return -1

def find(decode, key):
    """解码后，在块中二分查找"""
    low = 0
    high = len(decode) - 1
    while low <= high:
        mid = (low + high) // 2
        if operator.eq(decode[mid], key):
            return mid
        elif operator.gt(decode[mid], key):
            high = mid - 1
        elif operator.lt(decode[mid], key):
            low = mid + 1
    return -1

def FindWord(tree, word):
    return tree.search(word)

# 构建B-树
def createTree(args, key=2.5):
    cpn_path = args.cpn_dir
    dict_path = cpn_path + 'CompressedDict.txt'
    c = BTree(key)
    dict_file = open(dict_path, "r", encoding="utf-8")
    for line in dict_file:
        line = line.strip('\n')
        c.insert(line)
    dict_file.close()
    return c


#
# @lc app=leetcode.cn id=82 lang=python3
#
# [82] 删除排序链表中的重复元素 II
#
from typing import List
from utils import *
# @lc code=start

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        hyper = ListNode(0)
        hyper.next = head

        #
        ptr = hyper
        while ptr.next:
            val = ptr.next.val
            # count
            p, cnt = ptr, 0
            while p.next and p.next.val == val:
                p = p.next
                cnt += 1

            if cnt == 1:
                ptr = ptr.next
            else:
                # unlink
                ptr.next = p.next

        return hyper.next

# @lc code=end
if __name__ == '__main__':
    def test(input, expected):
        calc = Solution().deleteDuplicates(ListNode.from_list(input))
        if str(calc) != str(ListNode.from_list(expected)):
            print(f'case failed: `{input}`')
            print(f'  calc     = `{calc}`')
            print(f'  expected = `{expected}`')
            exit(1)
    test([1, 2, 3, 3, 4, 4, 5], [1, 2, 5])
    test([1, 1, 1, 2, 3], [2, 3])
    test([1, 1], [])
    test([1, 1, 1, 2, 3, 3], [2])

82.删除排序链表中的重复元素-ii.py


import os
import sys
import datetime
import grading_stats
import re

import discord
from discord.utils import get
from discord.ext import commands
from dotenv import load_dotenv

from sheets_parser import uploadOhTemplate, get_creds, uploadGaTemplate,read_grading_assignments
from grading_stats import getQuestions #,get_message
from reminders import notify_user, notify_user_str

CLASSES = ["CMSC330"]

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

intents = discord.Intents.all()
intents.members = True

bot = commands.Bot(command_prefix='!', intents=intents)

courseIDs = {}
graders = {}
member_ids = {}
tas = {}
semester = {}

CREDS = get_creds()

def loadCourseIDs():
  for c in CLASSES:
    courseIDs[c] = os.getenv(c)

def loadMemberIDs():
  ids = {}
  for guild in bot.guilds:
    members = guild.members
    for member in members:
      ids[member.name] = member.id
  return ids

def load_graders():
  people = grading_stats.loadGraders()
  for name in people:
    discord_name = people[name][1]
    tas[discord_name] = (people[name][0],name)
    tas[name] = people[name]
  return people

########## USER COMMANDS ##################
'''
@bot.command(name="grading",help='Reponds with what you have left to grade')
async def grader_notify(ctx):
  grader_name = ctx.message.author.name
  if grader_name == "profaccident":
    for g in graders:
      ta = tas[g]
      to_send = single_grader_notify(str(ta[1]),ta)
      if to_send != "":
        await ctx.send(to_send)
  else:
    ta = tas[grader_name]
    to_send = single_grader_notify(grader_name,ta)
    if to_send == "":
      to_send = "Congraulations! You graded everything!"
    await ctx.send(to_send)
'''

########## ADMIN COMMANDS ##################
@bot.command(name="oh",help='creates template of OH schedule')
async def oh_template(ctx):
  uploadOhTemplate(4,CREDS)
  to_send = "Wrote template!"
  await ctx.send(to_send)

@bot.command(name="ga",help='creates template of GA for assignment')
async def ga_template(ctx,assignment):
  match = re.search('\d{3}',str(ctx.guild))
  if not match:
    await ctx.send("You are not in a valid guild or the name needs to change :(")
  else:
    uploadGaTemplate(assignment,CREDS,"CMSC"+match.group())
    to_send = "Wrote " + assignment + " template!"
    await ctx.send(to_send)

@bot.command(name="get_ga",help='gets the grading assignments for assignment')
async def ga_template(ctx,assignment):
  match = re.search('\d{3}',str(ctx.guild))
  if not match:
    await ctx.send("You are not in a valid guild or the name needs to change :(")
  else:
    a = read_grading_assignments(assignment,CREDS,"CMSC"+match.group())
    if a != 0:
      await ctx.send("Error:\n"+a)
    else:
      to_send = "Got grading assignment for " + assignment
      await ctx.send(to_send)

@bot.command(name="notify",help='notifies TAs about grading')
async def ga_template(ctx,assignment):
  match = re.search('\d{3}',str(ctx.guild))
  if not match:
    await ctx.send("You are not in a valid guild or the name needs to change :(")
  else:
    course = "CMSC"+match.group()
    a = get_messages(course,assignment)
    to_send = "Notified TAs about grading " + assignment
    ids=loadMemberIDs()
    #TODO
    await ctx.send(to_send)

################ FUN STUFF ########################33
@bot.event
async def on_message(message):
    if not message.mention_everyone and bot.user.mentioned_in(message):# and message.author.name == 'profaccident':
      emoji = get(message.guild.emojis, name='cringe')
      await message.add_reaction(emoji)
    await bot.process_commands(message)

################ MAIN ########################33

@bot.event
async def on_ready():
  loadCourseIDs()
  global graders
  graders = load_graders()
  global member_ids
  member_ids = loadMemberIDs()
  semester = grading_stats.loadSemester()
  print("done connecting")

bot.run(TOKEN)

############# TRASH #####################
'''
def single_grader_notify(author,ta):
  to_send = notify_grader(ta[0],author)
  if to_send != "":
    to_send = "<@!"+str(member_ids[author])+">"+to_send+"\n"
  return to_send

async def grading_reminder():
  messages = grading_stats.send_notify(semester,graders)
  for course in messages:
    channel = bot.get_channel(int(courseIDs[course]))
    for assignment in messages[course]:
      for name in messages[course][assignment]:
        to_send = notify_grader(ctx,course,name)
        if to_send != "":
          await channel.send("<@!"+name+">\n"+to_send)

def notify_grader(course,name):
  messages = grading_stats.send_notify()
  to_send = ""
  print(messages)
  if course in messages:
    for assignment in messages[course]:
      if name in messages[course][assignment]:
        to_send = to_send + "\nFor "+assignment+":"
        for message in messages[course][assignment][name]:
          to_send = to_send + "\n - "+message
  return to_send
'''


# -*- coding: utf-8 -*-

import sys
import os
import numpy as np
import argparse
import random
import openslide
import PIL.Image as Image
import torch
import torch.nn as nn
import torch.optim as optim
import torch.backends.cudnn as cudnn
import torch.nn.functional as F
import torch.utils.data as data
import torchvision.transforms as transforms
import torchvision.transforms.functional as functional
import torchvision.models as models
import time
from sklearn.metrics import balanced_accuracy_score,recall_score,confusion_matrix,classification_report
import matplotlib.pyplot as plt
from tqdm import tqdm as tqdm
#import pickle
from mark_result import result_excel_origin

def main(parser):
    global args, best_acc
    args = parser.parse_args()
    best_acc = 0

    #cnn
    model = models.resnet34(pretrained = False)
    model_dict = torch.load('/your_dir/resnet34-333f7ec4.pth')
#   如果加载自己模型就改为使用上述两句命令
    model.fc = nn.Linear(model.fc.in_features, 2)
    model.cuda()
    model = nn.DataParallel(model)
    model.load_state_dict(model_dict['state_dict'])

#    if args.weights==0.5:
#        criterion = nn.CrossEntropyLoss().cuda()
#    else:
#        w = torch.Tensor([1-args.weights, args.weights])
#        criterion = nn.CrossEntropyLoss(w).cuda()
#    optimizer = optim.Adam(model.parameters(), lr=1e-4, weight_decay=1e-4)
#
#    cudnn.benchmark = True

    #normalization
    normalize = transforms.Normalize(mean=[0.485,0.456,0.406],std=[0.229,0.224,0.225])

    val_trans = transforms.Compose([transforms.ToTensor(), normalize])

    #load data
    val_dset = MILdataset(args.val_lib, 0,val_trans)
    val_loader = torch.utils.data.DataLoader(
            val_dset,
            batch_size=args.batch_size, shuffle=False,
            num_workers=args.workers, pin_memory=False)

    time_mark = time.strftime('%Y_%m_%d',time.localtime(time.time()))
#    time_mark = '2020_03_06_'
    #以当前时间作为保存的文件名标识

    #open output file
    fconv = open(os.path.join(args.output, time_mark + 'Test_CNN_convergence_512.csv'), 'w')
    fconv.write('test,,\n')
    fconv.write('acc,recall,fnr')
    fconv.close()
    start_time = time.time()
    val_dset.setmode(1)
    val_probs = inference(val_loader, model, args.batch_size, 'test')
    v_topk = group_argtopk(np.array(val_dset.slideIDX), val_probs[:,1], 1)
    v_pred = group_max(val_probs,v_topk,1)

    metrics_meters = calc_accuracy(v_pred, val_dset.targets)
    str_logs = ['{} - {:.4}'.format(k, v) for k, v in metrics_meters.items()]
    s = ', '.join(str_logs)
    print('\tTest  metrics: ' + s)
    result = '\t'+str(metrics_meters['acc']) + ',' + str(metrics_meters['recall']) + ','\
                 + str(metrics_meters['fnr'])
    fconv = open(os.path.join(args.output, time_mark + 'CNN_convergence_512.csv'), 'a')
    fconv.write(result)
    fconv.close()

    result_excel_origin(val_dset,v_pred,time_mark + '_test')
    np.save('output/numpy_save/test_infer_probs_' + time_mark + '.npy',val_probs)

    print('\test has been finished, needed %.2f sec.' % (time.time() - start_time))

def inference(loader, model, batch_size,phase):
    model.eval()
    probs = np.zeros((1,2))
#    logs = {}
    whole_probably = 0.

    with torch.no_grad():
        with tqdm(loader, desc = phase + '\'s inferencing', \
                  file=sys.stdout, disable = False) as iterator:
            for i, input in enumerate(iterator):
#                print('Inference\tEpoch: [{}/{}]\tBatch: [{}/{}]'.format(run+1, args.nepochs, i+1, len(iterator)))
                input = input.cuda()
                output = F.softmax(model(input), dim=1)
                prob = output.detach().clone()
                prob = prob.cpu().numpy()
                batch_proba = np.mean(prob,axis=0)
                probs = np.row_stack((probs,prob))
                whole_probably = whole_probably + batch_proba
#                temp_log = {'batch proba ': str(batch_proba)}
#                logs.update(temp_log)
#
#                str_logs = ['{} - {:.4}'.format(k, v) for k, v in logs.items()]
#                s = ', '.join(str_logs)
                iterator.set_postfix_str('batch proba :' + str(batch_proba))

            whole_probably = whole_probably / (i+1)
            iterator.set_postfix_str('Whole average probably is ' + str(whole_probably))

    probs = np.delete(probs, 0, axis=0)
    return probs.reshape(-1,2)

def train(run, loader, model, criterion, optimizer):
    model.train()
    whole_loss = 0.
    whole_acc = 0.
    whole_recall = 0.
    whole_fnr = 0.
    logs = {}

    with tqdm(loader, desc = 'Epoch:' + str(run+1) + ' is trainng', \
                  file=sys.stdout, disable= False) as iterator:
        for i, (input, target) in enumerate(iterator):
            input = input.cuda()
            target = target.cuda()
            output = model(input)
            loss = criterion(output, target)
            _, pred = torch.max(output, 1)
            pred = pred.data.cpu().numpy()
            metrics_meters = calc_accuracy(pred, target.cpu().numpy())
            logs.update(metrics_meters)
            logs.update({'loss':loss.item()})
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            str_logs = ['{} - {:.4}'.format(k, v) for k, v in logs.items()]
            s = ', '.join(str_logs)
            iterator.set_postfix_str(s)

            whole_acc += metrics_meters['acc']
            whole_recall += metrics_meters['recall']
            whole_fnr += metrics_meters['fnr']
            whole_loss += loss.item()
    return round(whole_acc/(i+1),3),round(whole_recall/(i+1),3),round(whole_fnr/(i+1),3),round(whole_loss/(i+1),3)

def calc_accuracy(pred,real):
    if str(type(pred)) !="<class 'numpy.ndarray'>":
        pred = np.array(pred)
    if str(type(real)) !="<class 'numpy.ndarray'>":
        real = np.array(real)
    neq = np.not_equal(pred, real)
#    err = float(neq.sum())/pred.shape[0]
#    fpr = float(np.logical_and(pred==1,neq).sum())/(real==0).sum()
    fnr = float(np.logical_and(pred==0,neq).sum())/(real==1).sum()
    balanced_acc = balanced_accuracy_score(real,pred)
    recall = recall_score(real,pred,average='weighted')
    metrics_meters = {'acc': round(balanced_acc,3),'recall':round(recall,3),'fnr':round(fnr,3)}
    label_list = ["MSS","MSI"]
    cr = classification_report(real, pred, target_names = label_list, digits = 2)
    print(cr, "\n")

    cm = confusion_matrix(real, pred)
    plt.imshow(cm, interpolation='nearest', cmap='Pastel1')
    plt.title('Confusion matrix', size=15)
    plt.colorbar()
    tick_marks = np.arange(2)
    plt.xticks(tick_marks, label_list,rotation=45, size=10)
    plt.yticks(tick_marks, label_list,size=10)
    plt.tight_layout()
    plt.ylabel('Actual label',size=15)
    plt.xlabel('Predicted label',size=15)
    width, height=cm.shape
    for x in range(width):
        for y in range(height):
            plt.annotate(str(cm[x][y]),xy=(y,x),horizontalalignment='center',verticalalignment='center')
    plt.show()

    return metrics_meters

def group_argtopk(groups, data,k=1):
    #该方法用于新一轮训练前进行所有图像全图region块预测,提取指定的top k的index
    # 假设group(slideIDX)列表为[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2],以top k=2为例
    # 对应预测label=1的概率为np.array([0,0.32,0.45,0.56,0.1,0.23,0.47,0.55,0.76,0.98,0.99,0.2,0.39,0.6], dtype=np.float64)
    # 通过np.lexsort((data, groups))计算的order为np.array([3,2,0,1,7,8,9,6,10,5,4,11,13,12])
    # 根据下面的index计算过程,最终得出index为np.array([False, False,  True,  True, False, False, False, False, False,\
    #    True,  True, False,  True,  True], dtype=bool),最终得出的结果如下:
    # np.array([ 0,  1,  5,  4, 13, 12], dtype=np.int64),即选出结果概率数组中第3(0.56),2(0.45),8(0.99),7(0.98),12(0.39),13(0.6)
    order = np.lexsort((data, groups))
    groups = groups[order]
    data = data[order]
    index = np.empty(len(groups), 'bool')
    index[-k:] = True
    index[:-k] = groups[k:] != groups[:-k]
    return list(order[index])

def group_max(probs,topk,k):
    #该方法计算过程大致和group_argtopk类似，不过指定top k为1,于Validation过程使用
    # 同样以上述的group(slideIDX)和预测的概率array为例,最终计算到的结果是array([0.56,0.99,0.6], dtype=float64)
    # 即每个WSI中,选择所有region中预测label=1的概率最高值作为当前WSI预测label=1的概率
#    out = np.empty(nmax)
#    out[:] = np.nan
##    whole_mean_proba = np.zeros((1,2))
#    order = np.lexsort((data, groups))
#    groups = groups[order]
#    data = data[order]
#    index = np.empty(len(groups), 'bool')
#    index[-1] = True
#    index[:-1] = groups[1:] != groups[:-1]
#    out[groups[index]] = data[index]
    #######################################
    #上述说明仅针对原来的group_max方法,下面重新编写的validation评估的方法,对于每一张图片来说, \
    # 预测的label取决于所有region截图分类概率相加后最大值者为准
    select_probs = np.array([probs[x,:] for x in topk])
    predict_result = []
#    groups = np.array(groups)
#    for i in np.unique(groups):
##        mean_proba = np.mean(data[groups==i],axis=0)
##        whole_mean_proba = np.row_stack((whole_mean_proba,mean_proba))
##        out[i] = np.argmax(mean_proba)
    for j in range(0,select_probs.shape[0],k):
        if np.sum(np.argmax(select_probs[j:j+k,:],axis=1)) >= k/2 :
            predict_result.append(1)
        else:
            predict_result.append(0)

#    return np.delete(whole_mean_proba, 0, axis=0)
    return np.array(predict_result)

class MILdataset(data.Dataset):
    def __init__(self, libraryfile='', k=0, transform=None):
        lib = torch.load(libraryfile)
        slides = []
        patch_size = []
        for i,name in enumerate(lib['slides']):
            sys.stdout.write('Opening SVS headers: [{}/{}]\r'.format(i+1, len(lib['slides'])))
            sys.stdout.flush()
            slides.append(openslide.OpenSlide(name))
            patch_size.append(int(lib['patch_size'][i]))
            #获取WSI文件对应的切片大小,因为在生成lib时,已经确保lib['slides']和lib['patch_size']顺序是对应的,\
            # 所以可以在一个循环中使用相同的index进行定位
        print('')
        #Flatten grid
        grid = []
        slideIDX = []
        #slideIDX列表存放每个WSI以及其坐标列表的标记,假设有0,1,2号三个WSI图像,分别于grid中记录4,7,3组提取的坐标,\
        # 返回为[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2]
        for i,g in enumerate(lib['grid']):
            if len(g) < k:
                g = g + [(g[x]) for x in np.random.choice(range(len(g)), k-len(g))]
            grid.extend(g)
            slideIDX.extend([i]*len(g))

        print('Number of tiles: {}'.format(len(grid)))
        self.slidenames = lib['slides']
        self.slides = slides
        self.targets = lib['targets']
        self.grid = grid
        self.slideIDX = slideIDX
        self.transform = transform
        self.mode = None
        self.patch_size = patch_size
        self.level = lib['level']
    def setmode(self,mode):
        self.mode = mode
    def maketraindata(self, idxs,repeat=0):
        #repeat这个参数用于是否对采样进行复制,如果进行复制,就会在下面的_getitem_方法中对重复的样本进行不一样的颜色增强
        if abs(repeat) == 0:
            self.t_data = [(self.slideIDX[x],self.grid[x],self.targets[self.slideIDX[x]],0) for x in idxs]
        else:
            repeat = abs(repeat) if repeat % 2 == 1 else abs(repeat) + 1
            self.t_data = [(self.slideIDX[x],self.grid[x],self.targets[self.slideIDX[x]],0) for x in idxs]
            for y in range(-100,int(100 + repeat/2),int(100*2/repeat)):
                self.t_data = self.t_data + [(self.slideIDX[x],self.grid[x],self.targets[self.slideIDX[x]],y/1000) for x in idxs]
    def shuffletraindata(self):
        self.t_data = random.sample(self.t_data, len(self.t_data))
    def __getitem__(self,index):
        if self.mode == 1:
            # mode =1 为预测时使用，会从所有WSI文件中返回全部的region的图像
            slideIDX = self.slideIDX[index]
            coord = self.grid[index]

            img = self.slides[slideIDX].read_region(coord,self.level,(self.patch_size[slideIDX],\
                                                    self.patch_size[slideIDX])).convert('RGB')
            if img.size != (224,224):
                img = img.resize((224,224),Image.BILINEAR)
            if self.transform is not None:
                img = self.transform(img)
            return img

        elif self.mode == 2:
            # mode =2 为训练时使用，只会根据指定的index(经过上一轮MIL过程得出) \
            #   从全部WSI文件中筛选对应的坐标列表,返回相应的训练图像和label
            slideIDX, coord, target,h_value = self.t_data[index]
            img = self.slides[slideIDX].read_region(coord,self.level,(self.patch_size[slideIDX],\
                                                    self.patch_size[slideIDX])).convert('RGB')
            if h_value > 0:
                hue_factor = random.uniform(h_value,0.1)
            elif h_value == 0:
                hue_factor = random.uniform(0,0)
            elif h_value < 0:
                hue_factor = random.uniform(-0.1,h_value)
            img = functional.adjust_hue(img,hue_factor)
            # 只有在训练模式下才进行H通道变换的颜色增强方法
            # 如果在maketraindata方法设置采样复制,那么就会针对h_value的值进行不同方向的hue_factor生成,\
            #    从而达到复制的样本和原来的样本有不一样的增强的效果
            if img.size != (224,224):
                img = img.resize((224,224),Image.BILINEAR)
            if self.transform is not None:
                img = self.transform(img)
            return img, target
    def __len__(self):
        if self.mode == 1:
            return len(self.grid)
        elif self.mode == 2:
            return len(self.t_data)

if __name__ == '__main__':
    os.environ["CUDA_VISIBLE_DEVICES"] = "2"
    # parser = argparse.ArgumentParser(description='MIL-nature-medicine-2019 tile classifier training script')
    # parser.add_argument('--train_lib', type=str, default='', help='path to train MIL library binary')
    # parser.add_argument('--val_lib', type=str, default='', help='path to validation MIL library binary. If present.')
    # parser.add_argument('--output', type=str, default='.', help='name of output file')
    # parser.add_argument('--batch_size', type=int, default=512, help='mini-batch size (default: 512)')
    # parser.add_argument('--nepochs', type=int, default=100, help='number of epochs')
    # parser.add_argument('--workers', default=4, type=int, help='number of data loading workers (default: 4)')
    # parser.add_argument('--test_every', default=10, type=int, help='test on val every (default: 10)')
    # parser.add_argument('--weights', default=0.5, type=float, help='unbalanced positive class weight (default: 0.5, balanced classes)')
    # parser.add_argument('--k', default=1, type=int, help='top k tiles are assumed to be of the same class as the slide (default: 1, standard MIL)')

    parser = argparse.ArgumentParser(description='MIL-nature-medicine-2019 tile classifier training script')
#    parser.add_argument('--train_lib', type=str, default='output/lib/512/cnn_train_data_lib.db', help='path to train MIL library binary')
    parser.add_argument('--val_lib', type=str, default='output/lib/512/cnn_val_data_lib.db', help='path to validation MIL library binary. If present.')
    parser.add_argument('--output', type=str, default='output/', help='name of output file')
    parser.add_argument('--batch_size', type=int, default=256, help='mini-batch size (default: 512)')
    parser.add_argument('--nepochs', type=int, default=14, help='number of epochs')
    parser.add_argument('--workers', default=0, type=int, help='number of data loading workers (default: 4)')
    # 如果是在docker中运行时需注意,因为容器设定的shm内存不够会出现相关报错,此时将num_workers设为0则可
    #parser.add_argument('--test_every', default=10, type=int, help='test on val every (default: 10)')
    parser.add_argument('--weights', default=0.79, type=float, help='unbalanced positive class weight (default: 0.5, balanced classes)')
    parser.add_argument('--k', default=10, type=int, help='top k tiles are assumed to be of the same class as the slide (default: 1, standard MIL)')
    #parser.add_argument('--tqdm_visible',default = True, type=bool,help='keep the processing of tqdm visible or not, default: True')

    main(parser)


from odoo import tools
from odoo import api, fields, models

class report_of_shop_keeper(models.AbstractModel):
    _name = 'report.shop_keeper.report_of_shop_keeper'

    @api.multi
    def get_report_values(self, docids, data=None):
        docs = self.env['shipping.details'].browse(docids)
        print("=========", docs)
        return {
            'doc_ids': docs.ids,
            'doc_model': 'shipping.details',
            'docs': docs,
            'proforma': True
        }

class report_of_customer_feedback(models.AbstractModel):
    _name = 'report.shop_keeper.report_of_customer_feedback'

    @api.multi
    def get_report_values(self, docids, data=None):
        docs = self.env['customer.detail'].browse(docids)
        print("=========", docs)
        return {
            'doc_ids': docs.ids,
            'doc_model': 'customer.detail',
            'docs': docs,
            'proforma': True
        }


#!/Users/elijahsutton/opt/anaconda3/envs/wod_collector/bin/python
import requests
from bs4 import BeautifulSoup
import pandas as pd

URL = 'https://www.wordnik.com/word-of-the-day' # URL which to scrape for WoD data
WoD_FNAME = '/Users/elijahsutton/Google-Drive/Professional/Portfolio/Word-of-the-Day-Collector/wod_data.txt' # file where WoD data is stored

def scrape_url(url):
    """
    This funtion takes a URL as a string to scrape for word-of-the-day data element
    and returns the data elements (word, part of speech, definiton, and example)
    as a dictionary.

    Parameters
    ----------
    url : string which is a URL to scrape

    Returns
    -------
    res : dictionary of data elements scraped
    """
    # Send HTTP request to specified URL and save response from server
    r = requests.get(url)

    # Create BeautifulSoup object from raw HTML with HTML parser
    soup = BeautifulSoup(r.content, 'html.parser')

    # Get word, part of speech, definition and example
    word = soup.find(name='h1').text
    pos = soup.find(name='abbr').text
    def_ = soup.find(name='div', attrs={'class':'guts active'}).li.contents[-1].strip()
    eg = soup.find(name='p', attrs={'class':'text'}).text

    # Store scraped data elements as a dictionary
    res = {'word' : word,
           'part_of_speech' : pos,
           'definition' : def_,
           'example' : eg}
    return res

def display_word_data(word_dict):
    """
    This function takes in a dictionary containing data elements of a word and
    displays each of the key-value pairs.

    Parameters
    ----------
    word_dict : tuple which contains four data elements of a word

    Returns
    -------
    None.

    """
    for k,v in word_dict.items():
        print('{key} : {value}\n'.format(key=k.upper(), value=v))
    return

def get_wod_df():
    """
    This functions reads in the Word of the Day TXT file from the provided path,
    where previous WoD data is stored, into a DataFrame and returns it.

    Parameters
    ----------
    fname : string which is the filename of file where previous WoD data is stored

    Returns
    -------
    df : pandas DataFrame of word of the day data

    """
    df = pd.read_csv(WoD_FNAME, sep='\t')
    return df

def update_wod_df(df, wod):
    """
    This function takes the WoD DataFrame (df) and the day's WoD (wod) as input
    and appends wod to df if the wod does not already exist in df.

    Parameters
    ----------
    df : pandas DataFrame containing all WoD data
    wod : dict containing today's WoD data

    Returns
    -------
    None.

    """
    # Check for presence of wod in df
    if wod['word'] in df['word'].values:
        # Print that the word has already by captured
        print('"{}" has already be captured.'.format(wod['word']))
    else:
        # Append new WoD to DataFrame
        df = df.append(wod, ignore_index=True)

        # Save DataFrame to file
        df.to_csv(WoD_FNAME, index=False, sep='\t')

        print('{} updated successfully.'.format(WoD_FNAME))
    return

def main():

    # Scrape URL
    word_dict = scrape_url(URL)

    # Display all elements of word_tuple
    display_word_data(word_dict)

    # Read in Word of the Day file to be updated as a DataFrame
    words_df = get_wod_df()

    # Append new word (word_dict) to DataFrame (words_df) and write back to file
    update_wod_df(words_df, word_dict)
    return

main()


import time
import board
import busio
from digitalio import DigitalInOut, Direction, Pull
from adafruit_pm25.i2c import PM25_I2C
import adafruit_bme680

class ConcentrationUnits:
    def __init__(self, pm10um, pm25um, pm100um) -> None:
        self.pm10um = pm10um
        self.pm25um = pm25um
        self.pm100um = pm100um

    def print(self) -> None:
        print("PM 1.0: %d\tPM2.5: %d\tPM10: %d" % (self.pm10um, self.pm25um, self.pm100um))

class Particles:
    def __init__(self, p03um, p05um, p10um, p25um, p50um, p100um) -> None:
        self.p03um = p03um
        self.p05um = p05um
        self.p10um = p10um
        self.p25um = p25um
        self.p50um = p50um
        self.p100um = p100um

    def print(self):
        print("Particles > 0.3um / 0.1L air:", self.p03um)
        print("Particles > 0.5um / 0.1L air:", self.p05um)
        print("Particles > 1.0um / 0.1L air:", self.p10um)
        print("Particles > 2.5um / 0.1L air:", self.p25um)
        print("Particles > 5.0um / 0.1L air:", self.p50um)
        print("Particles > 10 um / 0.1L air:", self.p100um)

class QualityData:
    def __init__(self, std_concentration, env_concentration, particles) -> None:
        self.std_concentration = std_concentration
        self.env_concentration = env_concentration
        self.particles = particles

    def print(self) -> None:
        print()
        print("Concentration Units (standard)")
        print("---------------------------------------")
        self.std_concentration.print()
        print("Concentration Units (environmental)")
        print("---------------------------------------")
        self.std_concentration.print()
        print("---------------------------------------")
        self.particles.print()
        print("---------------------------------------")

class SensorReader:
    def __init__(self, i2c) -> None:
        reset_pin = None
        # If you have a GPIO, its not a bad idea to connect it to the RESET pin
        # reset_pin = DigitalInOut(board.G0)
        # reset_pin.direction = Direction.OUTPUT
        # reset_pin.value = False

        # Create library object, use 'slow' 100KHz frequency!
        # i2c = busio.I2C(board.SCL, board.SDA, frequency=100000)
        # Connect to a PM2.5 sensor over I2C
        self.pm25 = PM25_I2C(i2c, reset_pin)

    def read_data(self):
        try:
            aqdata = self.pm25.read()
            std_concent = ConcentrationUnits(
                pm10um=aqdata["pm10 standard"],
                pm25um=aqdata["pm25 standard"],
                pm100um=aqdata["pm100 standard"],
            )
            env_concent = ConcentrationUnits(
                pm10um=aqdata["pm10 env"],
                pm25um=aqdata["pm25 env"],
                pm100um=aqdata["pm100 env"],
            )
            parts = Particles(
                p03um=aqdata["particles 03um"],
                p05um=aqdata["particles 05um"],
                p10um=aqdata["particles 10um"],
                p25um=aqdata["particles 25um"],
                p50um=aqdata["particles 50um"],
                p100um=aqdata["particles 100um"],
            )

            return QualityData(
                std_concentration=std_concent, env_concentration=env_concent, particles=parts
            )
        except RuntimeError:
            print("Unable to read from sensor, retrying...")
            return None

class BMEWrapper:
    def __init__(self, i2c) -> None:
        self._bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c, address=0x76)
        self._bme680.sea_level_pressure = 1013.25
        # self._bme680.temperature_oversample = 8
        # self._bme680.humidity_oversample = 2
        # self._bme680.pressure_oversample = 4
        # self._bme680.filter_size = 3

        gas_reference = 0.0
        iters = 10
        for _ in range(iters):
            gas_reference += self._bme680.gas
        gas_reference /= iters
        self.gas_reference = gas_reference

    @property
    def temperature(self):
        return self._bme680.temperature

    @property
    def humidity(self):
        return self._bme680.humidity

    @property
    def relative_humidity(self):
        return self._bme680.relative_humidity

    @property
    def altitude(self):
        return self._bme680.altitude

    @property
    def gas(self):
        return self._bme680.gas

    @property
    def pressure(self):
        return self._bme680.pressure

def get_humidity_score(value, reference=40.0):
    if value < 38:
        return value / reference * 100

    if value <= 42:
        return 100

    return


# Created by: Gavin Zhou
# Created on: Dec 2017
# Created for: ICS3U

from enum import Enum

# 1. about street
street_type = Enum('Avenue', 'Boulevard', 'Crescent', 'Lane', 'Road')

# 2. about provinces
provinces = Enum('AB', 'BC', 'MB', 'NB', 'NL', 'NT', 'NS', 'NU', 'ON', 'PE', 'QC', 'SK', 'YT')

class Address():
    def __init__(self, name, street_number, street_name, street_type, province, city, postal_code):
        self.name = name
        self.street_number = street_number
        self.street_name = street_name
        self.street_type = street_type
        self.province = province
        self.city = city
        self.postal_code = postal_code

user_name = raw_input("Enter your name: ")

user_street_number = raw_input("Enter your street number: ")

user_street_name = raw_input("Enter your street name: ")

print("Choose your street type: Street, Boulevard, Road, Avenue, Crescent")
user_street_type = raw_input("Enter your street type: ")
if user_street_type in street_type:
    print('Valid street type')

    print("Enter the abbreviation of the province in this list: AB (Alberta), BC (British Columbia), MB (Manitoba), NB (New Brunswick), NL (Newfoundland and Labrador), NT (Northwest Territories), NS (Nova Scotia), NU (Nunavut), ON (Ontario), PE (Prince Edward Island), QC (Quebec), SK (Saskatchewan)")
user_province= raw_input("Enter your province(abbreviation): ")
if user_province in provinces:
        print('Valid province')

user_city = raw_input("Enter your city: ")

user_postal_code = raw_input("Enter your postal code: ")

user_input = Address(user_name, user_street_number, user_street_name, user_street_type, user_city, user_province, user_postal_code)
print(user_input.name + '\n' + user_input.street_number + ' ' + user_input.street_name + ' ' +  user_input.street_type + '\n' +  ' ' + user_input.province + ' ' + user_input.city + ' ' + user_input.postal_code)


import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate
from pdb import set_trace
import pickle

# import prettyjson file from parent dir
import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)
import prettyjson as prettyjson

outdir = os.getcwd()+'/Plots'

fname = 'median_Mtt_Mthad.json'
median_dict = prettyjson.loads(open(fname).read())

mtt_ranges_to_centers = {
	'M($t\\overline{t}$) 200-350' : 275, 'M($t\\overline{t}$) 350-400' : 375, 'M($t\\overline{t}$) 400-500' : 450,
	'M($t\\overline{t}$) 500-700' : 600, 'M($t\\overline{t}$) 700-1000' : 850, 'M($t\\overline{t}$) $\geq$1000' : 1200
}
mthad_ranges_to_centers = {
	'M($t_{h}$) 0.9-1.1' : 1.0, 'M($t_{h}$) 1.1-1.3' : 1.2, 'M($t_{h}$) 1.3-1.5' : 1.4, 'M($t_{h}$) 1.5-1.7' : 1.6,
	'M($t_{h}$) 1.7-1.9' : 1.8, 'M($t_{h}$) 1.9-2.1' : 2.0, 'M($t_{h}$) 2.1-2.3' : 2.2, 'M($t_{h}$) 2.3-2.5' : 2.4
}

mttbar_ranges = [ 'Mttbar200to350', 'Mttbar350to400', 'Mttbar400to500', 'Mttbar500to700', 'Mttbar700to1000', 'Mttbar1000toInf']

mthad_bin_edges = np.arange(0.9, 2.7, 0.2).tolist()
mttbar_bin_edges = [200, 350, 400, 500, 700, 1000]
alpha_bin_edges = [0.5, 1.0, 1.5, 2.0, 2.5, 3.0]

colors = ['green', 'red', 'black', 'blue', 'orange', 'magenta', 'cyan', 'yellow']

### create grid of ( x = 173.1/Mthad, y = mttbar, z = medians )

x = np.array([1.0 , 1.2, 1.4, 1.6, 1.8, 2. , 2.2, 2.4]) # 173.1/mthad vals
y = np.array([275, 375, 450, 600, 850, 1200]) # mttbar bins

for alpha_key in median_dict.keys():
	z = np.array([median_dict[alpha_key][mtt_range]['medians'] for mtt_range in mttbar_ranges]) # median alpha values

	f = interpolate.interp2d(x, y, z, kind='cubic')

		## save interpolation function for each alpha
	with open('%s/Alpha_%s_Interpolation.pkl' % (outdir, alpha_key), 'wb') as pkl_file:
		pickle.dump(f, pkl_file)

	#interp_loaded = 0
	#with open('%s/Alpha_%s_Interpolation.pkl' % (outdir, alpha_key), 'rb') as interpolate:
	#	interp_loaded = pickle.load(interpolate)

	xnew = np.linspace(0.9,3.0, 500)
	z500 = f(xnew, 500) ## estimate new alphas for mttbar = 500
	z350 = f(xnew, 350) ## estimate new alphas for mttbar = 350

	## make alpha vs 173.1/MTHad plots
	fig, ax = plt.subplots()
	for i in range(len(y)):
		leg_label = [ k for k,v in mtt_ranges_to_centers.items() if v == y[i] ][0]
		plt.plot(x, z[i,:], linestyle='None', color=colors[i], marker='.', label=leg_label)

	plt.plot(xnew, z500, linestyle='-', color='cyan', label='M($t\\overline{t}$)=500 Est.')
	plt.plot(xnew, z350, linestyle='-', color='black', label='M($t\\overline{t}$)=350 Est.')

	ax.set_xticks(mthad_bin_edges)
	ax.xaxis.grid(True, which='major')
	ax.set_yticks(alpha_bin_edges)
	ax.yaxis.grid(True, which='major')
	plt.xlabel('173.1/Reco M($t_{h}$)')
	if alpha_key == 'THad_E':
		plt.ylabel('$\\alpha_{E}$ = Gen E($t_{h}$)/Reco E($t_{h}$)')
	elif alpha_key == 'THad_P':
	    plt.ylabel('$\\alpha_{P}$ = Gen P($t_{h}$)/Reco P($t_{h}$)')
	else: # 'THad_M'
	    plt.ylabel('$\\alpha_{M}$ = Gen M($t_{h}$)/Reco M($t_{h}$)')

	plt.ylim(0.5, 3.0)
	plt.legend(loc='upper left',fontsize=8, numpoints=1)
	fig.savefig('%s/Alpha_%s_vs_MTHad.png' % (outdir, alpha_key) )
	#set_trace()
	#plt.show()

	ynew = np.linspace(200, 1300, 1100)
	z1p3 = f(1.3, ynew) ## estimate new alphas for mthad = 1.3
	z2p1 = f(2.1, ynew) ## estimate new alphas for mthad = 2.1
	## make alpha vs /Mttbar plots
	fig, ax = plt.subplots()
	for i in range(len(x)):
		leg_label = [ k for k,v in mthad_ranges_to_centers.items() if v == x[i] ][0]
		plt.plot(y, z[:,i], linestyle='None', color=colors[i], marker='.', label=leg_label)

	plt.plot(ynew, z1p3, linestyle='-', color='green', label='M($t_{h}$)=1.3 Est.')
	plt.plot(ynew, z2p1, linestyle='-', color='red', label='M($t_{h}$)=2.1 Est.')

	ax.set_xticks(mttbar_bin_edges)
	ax.xaxis.grid(True, which='major')
	ax.set_yticks(alpha_bin_edges)
	ax.yaxis.grid(True, which='major')
	plt.xlabel('M($t\\overline{t}$)')
	if alpha_key == 'THad_E':
		plt.ylabel('$\\alpha_{E}$ = Gen E($t_{h}$)/Reco E($t_{h}$)')
	elif alpha_key == 'THad_P':
	    plt.ylabel('$\\alpha_{P}$ = Gen P($t_{h}$)/Reco P($t_{h}$)')
	else: # 'THad_M'
	    plt.ylabel('$\\alpha_{M}$ = Gen M($t_{h}$)/Reco M($t_{h}$)')

	plt.ylim(0.5, 3.0)
	plt.legend(loc='upper right',fontsize=8, numpoints=1)
	fig.savefig('%s/Alpha_%s_vs_MTTBar.png' % (outdir, alpha_key) )
	#set_trace()


from abc import abstractmethod, ABCMeta
from typing import List, Union
from app.dto.permission_dto import *
from app.models import Permission, Person, Role

class PermissionRepository(metaclass=ABCMeta):
    @abstractmethod
    def create_permission(self, model: CreatePermissionDto):
        """Create Permission Object"""
        raise NotImplementedError

    @abstractmethod
    def edit_permission(self, permission_id: int, model: EditPermissionDto):
        """Edit Permission Object"""
        raise NotImplementedError

    @abstractmethod
    def list_permission(self) -> List[ListPermissionDto]:
        """List Permission Objects"""
        raise NotImplementedError

    @abstractmethod
    def get_permission(self, permission_id: int) -> GetPermissionDto:
        """Get Permission Object"""
        raise NotImplementedError

    @abstractmethod
    def assign_permission_to_role(self, model: AssignPermissionToRoleDto):
        """Assign Permission to Role"""
        raise NotImplementedError

    @abstractmethod
    def assign_permission_to_person(self, model: AssignPermissionToUserDto):
        """Assign Permission to Person"""
        raise NotImplementedError

class DjangoORMPermissionRepository(PermissionRepository):
    def create_permission(self, model: CreatePermissionDto):
        permission = Permission()
        permission.id = model.id
        permission.name = model.name
        permission.description = model.description
        permission.save()

    def edit_permission(self, permission_id: int, model: EditPermissionDto):
        try:
            permission = Permission.objects.get(id=permission_id)
            permission.name = model.name
            permission.description = model.description
            permission.save()
        except Permission.DoesNotExist as e:
            return e

    def list_permission(self) -> List[ListPermissionDto]:
        permissions = Permission.objects.all()
        result: List[ListPermissionDto] = []

        for permission in permissions:
            item = ListPermissionDto()
            item.name = permission.name
            result.append(item)
        return result

    def get_permission(self, permission_id: int) -> GetPermissionDto:
        permission = Permission.objects.get(id=permission_id)
        item = GetPermissionDto()
        item.id = permission.id
        item.name = permission.name
        item.description = permission.description
        return item

    def assign_permission_to_person(self, model: AssignPermissionToUserDto):
        try:
            permission = Permission.objects.get(id=model.permission_id)
            Person.objects.get(id=model.person_id).permission.add(permission)
        except Exception as e:
            return e

    def assign_permission_to_role(self, model: AssignPermissionToRoleDto):
        try:
            permission = Permission.objects.get(id=model.permission_id)
            Role.objects.get(id=model.role_id).permission.add(permission)
        except Exception as e:
            return e


# -*- coding: utf-8 -*-
import os

import tensorflow as tf
from keras import backend as K
from tensorflow.python.tools import freeze_graph
from tensorflow.python.tools import optimize_for_inference_lib

def export_model(saver: tf.train.Saver, input_names: list, output_name: str, model_name: str):
    """
    You can find node names by using debugger: just connect it right after model is created and look for nodes in the inspec
    :param saver:
    :param input_names:
    :param output_name:
    :param model_name:
    :return:
    """
    os.makedirs("./out", exist_ok=True)
    tf.train.write_graph(K.get_session().graph_def, 'out',
                         model_name + '_graph.pbtxt')

    saver.save(K.get_session(), 'out/' + model_name + '.chkp')

    # pbtxt is human readable representation of the graph
    freeze_graph.freeze_graph('out/' + model_name + '_graph.pbtxt', None,
                              False, 'out/' + model_name + '.chkp', output_name,
                              "save/restore_all", "save/Const:0",
                              'out/frozen_' + model_name + '.pb', True, "")

    input_graph_def = tf.GraphDef()
    with tf.gfile.Open('out/frozen_' + model_name + '.pb', "rb") as f:
        input_graph_def.ParseFromString(f.read())

    # optimization of the graph so we can use it in the android app
    output_graph_def = optimize_for_inference_lib.optimize_for_inference(
        input_graph_def, input_names, [output_name],
        tf.float32.as_datatype_enum)

    # This is archived optimal graph in the protobuf format we'll use in our android App.
    with tf.gfile.FastGFile('out/opt_' + model_name + '.pb', "wb") as f:
        f.write(output_graph_def.SerializeToString())

    print("graph saved!")


from osgeo import gdal, osr

def float2int(src_raster, dst_raster):
    """
    Converts Float number pixels of a GeoTiff raster in Integer numbers
    WARNING: FUNCTION NOT YET FULLY TESTED - MAY NOT WORK UNDER ALL CIRCUMSTANCES
    :param src_raster: STR of full directory for the source raster (TIFF)
    :param dst_raster:STR of full directory for the output raster (TIFF)
    :return: None
    """
    # Open existing dataset
    src_ds = gdal.Open(src_raster)

    # Open output format driver, see gdal_translate --formats for list
    format = "GTiff"
    driver = gdal.GetDriverByName(format)
    srs = osr.SpatialReference()
    srs.ImportFromWkt(src_ds.GetProjection())

    # Output to new format
    ds = gdal.Translate(dst_raster, src_raster, projWin=src_ds.GetProjection())

    # Properly close the datasets to flush to disk
    ds = None
    src_ds = None


from .invoke import astr, arepr, Func, Table, Scope, Nothing, callfunc, S
from .visitor import fixtags, flattenbody
from .parse import parseFile
from .serialize import serialize

def isle_serialize(stack, callstack, arg):
    return serialize(arg[1])

def isle_apply(stack, callstack, arg):
    assert isinstance(arg[2], Table)
    callfunc(arg[1], arg[2], stack, callstack)
    return Nothing

def isle_puts(stack, callstack, arg):
    n = 1
    while n in arg:
        print(astr(arg[n]))
        n += 1

def isle_show(stack, callstack, arg):
    print(', '.join(arepr(x) for x in _iter_args(arg)))

def isle_assert(stack, callstack, arg):
    assert arg[1] is not None

def isle_assert_error(stack, callstack, arg):
    callstack.append(Scope(arg[1], 0, Table()))
    #something something error handling

def isle_replace_closure(stack, callstack, arg):
    assert(isinstance(arg[1], Func))
    assert(isinstance(arg[2], Table))
    new_closure = tuple(_iter_args(arg[2]))
    for env in new_closure:
        assert(isinstance(env, Table))
    return Func(body=arg[1].body, closure=new_closure)

def isle_get_closure(stack, callstack, arg):
    assert(isinstance(arg[1], Func))
    closure = Table()
    for i, v in enumerate(arg[1].closure):
        closure[i + 1] = v
    return closure

def _iter_args(t, start=1):
    n = start
    while n in t:
        yield t[n]
        n += 1

def next_item(stack, callstack, arg):
    try:
        return Table({S.func: next_item, 1: arg[1](stack, callstack, arg), S.arg: Table([(1, arg[1])])})
    except StopIteration:
        return None

def isle_args(stack, callstack, arg):
    it = _iter_args(arg[1], start=arg.get(S.start, 1))
    return next_item(stack, callstack, arg={1:lambda s,c,a:next(it)})

def isle_chars(stack, callstack, arg):
    assert isinstance(arg[1], str)
    it = iter(arg[1])
    return next_item(stack, callstack, arg={1:lambda s,c,a:next(it)})

def isle_range(stack, callstack, arg):
    start = arg[S.start] if S.start in arg else arg[1] if 2 in arg else 1
    stop = arg[S.stop] if S.stop in arg else arg[2] if 2 in arg else arg[1]
    step = arg.get(S.step, 1)
    if start <= stop:
        return Table({S.func: isle_range, 1: start, S.arg: Table({S.start: start + step, S.step: step, S.stop: stop})})

def isle_require(stack, callstack, arg):
    env = Table()
    useenv = arg.get(S.useret) is None
    callstack.append(Scope(Func(fixtags(flattenbody(parseFile(arg[1]), droplast=useenv)), ()), 0, env))
    return env if useenv else Nothing

def isle_slice(stack, callstack, arg):
    string = arg[1]
    start = arg[2]
    if start < 0:
        start = len(string) + start + 1
    end = arg.get(3, start)
    if end < 0:
        end = len(string) + end + 1
    assert 1 <= start <= len(string)
    assert start <= end <= len(string)
    return string[start - 1:end]

def isle_delkey(stack, callstack, arg):
    table = arg[1]
    key = arg[2]
    if key in table:
        del table[key]

def stdlib():
    lib = Table()
    for key, value in globals().items():
        if key.startswith('isle_'):
            lib[S[key[5:]]] = value
    return lib

stdlib = stdlib()


# -*- coding: utf-8 -*-
"""
Created on Wed Nov 14 18:11:12 2018

@author: Kathrine
"""
import numpy as np
import matplotlib.pyplot as plt

N=25               #Число игроков
Coins = 100             #Число монеток
times = 10000
Players=[]               #Число итераций
CoinsOfPlayers=[]           #Массив монеток у игроков
Remain=[]
Taken=[]                  #Сколько монеток взяли у игрока
Transfer=[]

def DrawThis(Array, a): #Рисуем всякую графику
    dpi = 80
    plt.figure(dpi = dpi, figsize = (512 / dpi, 384 / dpi) )
    plt.title('здесь могла быть ваша реклама')
    ax = plt.axes()
    ax.set_ylim( min(range(1)), max(range(350)) )
    plt.bar([x  for x in Players], Array,
        width = 0.3, color = 'red',
        zorder = 2)
    plt.savefig('zbars%d.png' % a)
    ax.clear()
    plt.close()

for i in range(N):
    CoinsOfPlayers.append(Coins)
    Players.append(i)

t=0
while t < times :
    for i in range(N):
        #xi= rnd.uniform(0.2 ,0.5)    #Генерируем случайную величину
        #xi = rnd.gauss(0,1)
        xi= np.abs(np.random.normal(0,0.27))
        #print(xi)
        Taken.append(CoinsOfPlayers[i]*xi)
        Remain.append( CoinsOfPlayers[i] - ( CoinsOfPlayers[i] * xi ))

    sum=0
    for i in range(N):
        if i != 0:
            Transfer.append(Remain[i]+Taken[i-1])
        else:
            Transfer.append(Remain[i]+Taken[N-1])
        sum=Transfer[i]+sum
    CoinsOfPlayers.clear()
    CoinsOfPlayers=Transfer[:]
    DrawThis(CoinsOfPlayers, t)
    Remain.clear()
    Taken.clear()
    Transfer.clear()
    #ax.clear()
    #print("Итерации" + str(t))
    t+=1

#print(Transfer)
#print(CoinsOfPlayers)
#print(Taken)
#print(Remain)


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

import json
import myJson as myjson

class GroceryController:
    def __init__(self):
        self.filename = "json.txt"
        self.jsonObject = myjson.loadJSON("json.txt")
        self.groceryID = self.jsonObject["groceryID"] if "groceryID" in self.jsonObject else 0

    def add(self, brand, name, amount, calories, carbs, protein, fat, sugar):
        self.jsonObject["grocery"] = {
            "groveryID": self.groceryID,
            "brand": brand,
            "name": name,
            "amount": amount,
            "calories": calories,
            "carbs": carbs,
            "protein": protein,
            "fat": fat,
            "sugar": sugar
        }

        self.groceryID += 1

    def typeOut(self):
        if "grocery" in self.jsonObject:
            print(self.jsonObject["grocery"])


from __future__ import print_function
from Model.e2e import End2EndMPNet
import Model.mlp as mlp
import Model.CAE as CAE_2d
import numpy as np
import argparse
import os
import torch
from data_loader import data_loader_2d
from utility import *
from torch.autograd import Variable
import copy
import os
import random
import progressbar
from Model.complete_model import MLPComplete
import psutil
import datetime
from tqdm import tqdm
from torch.optim.lr_scheduler import StepLR
from torch.optim.lr_scheduler import ReduceLROnPlateau

from tensorboardX import SummaryWriter

def main(args):

    timestamp = datetime.datetime.now().strftime("%d_%H%M%S")
    print('timestamp: ', timestamp)

    # set seed
    torch_seed = np.random.randint(low=0, high=1000)
    np_seed = np.random.randint(low=0, high=1000)
    py_seed = np.random.randint(low=0, high=1000)
    torch.manual_seed(torch_seed)
    np.random.seed(np_seed)
    random.seed(py_seed)
    # Build the models
    if torch.cuda.is_available():
        torch.cuda.set_device(args.device)
    # decide dataloader, MLP, AE based on env_type
    if args.env_type == '2d':
        AE_output_size = 28
        if args.with_start:
            total_input_size = 2800+6
            AE_input_size = 2800
            mlp_input_size = 28+6
        else:
            total_input_size = 2800+4
            AE_input_size = 2800
            mlp_input_size = 28+4

        if not args.point_cloud:
            total_input_size -= 2800 - 28
            AE_input_size -= 2800 - 28

        output_size = 1
        load_train_dataset = data_loader_2d

        CAE = CAE_2d
        MLP = mlp.MLP
        # mpc = MLPComplete
    elif args.env_type == '3d':

        AE_output_size = 21

        output_size = 3
        # load_train_dataset = data_loader_2d
        CAE = CAE_2d
        MLP = mlp.MLP
        if args.with_start:
            total_input_size = 1400 * 3 + 9
            AE_input_size = 1400 * 3
            AE_output_size = 21
            mlp_input_size = 21 + 9
        else:
            total_input_size = 1400 * 3 + 6
            AE_input_size = 1400 * 3
            mlp_input_size = 21 + 6
            AE_output_size = 21

        if not args.point_cloud:
            total_input_size -= 1400 * 3 - 21
            AE_input_size -= 1400 * 3 - 21

        output_size = 1
        load_train_dataset = data_loader_2d

        CAE = CAE_2d
        MLP = mlp.MLP

    if args.activation == 'relu':
        activation_f = torch.nn.ReLU
    elif args.activation == 'tanh':
        activation_f = torch.nn.Tanh
    elif args.activation == 'selu':
        activation_f = torch.nn.SELU
    elif args.activation == 'elu':
        activation_f = torch.nn.ELU
    elif args.activation == 'leaky_relu':
        activation_f = torch.nn.LeakyReLU
    elif args.activation == 'prelu':
        activation_f = torch.nn.PReLU

    model = End2EndMPNet(total_input_size, AE_input_size, mlp_input_size,
                         output_size, CAE, MLP, activation_f=activation_f, dropout=args.dropout, AE_output_size=AE_output_size)

    if args.env_type == '2d' or args.env_type == '3d':
        loss_f = model.loss

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

    model_path = 'model_env_{}_epoch_{}.pkl'.format(
        args.env_type, args.start_epoch)

    if args.start_epoch > 0:
        print('Loading model from {}'.format(model_path))
        load_net_state(model, os.path.join(args.model_path, model_path))
        torch_seed, np_seed, py_seed = load_seed(
            os.path.join(args.model_path, model_path))
        # set seed after loading
        torch.manual_seed(torch_seed)
        np.random.seed(np_seed)
        random.seed(py_seed)

    process = psutil.Process(os.getpid())
    print('Physical Memory Usage: ', process.memory_info().rss/1024**3, 'GB')

    print('psutil.virtual_memory().total : ',
          psutil.virtual_memory().total/1024**3, 'GB')

    if torch.cuda.is_available():
        print('Available devices ', torch.cuda.device_count())
        print('Current cuda device ', torch.cuda.current_device())
        print('Current cuda device name ',
              torch.cuda.get_device_name(torch.cuda.current_device()))

        model.cuda()

        if hasattr(model, 'encoder'):
            model.encoder.cuda()

    if args.opt == 'Adagrad':
        optimizer = torch.optim.Adagrad(model.parameters(), lr=args.learning_rate, weight_decay=args.weight_decay)
    elif args.opt == 'Adam':
        optimizer = torch.optim.Adam(model.parameters(), lr=args.learning_rate, weight_decay=args.weight_decay)
    elif args.opt == 'SGD':
        optimizer = torch.optim.SGD(model.parameters(), lr=args.learning_rate, momentum=0.9, weight_decay=args.weight_decay)
    elif args.opt == 'ASGD':
        optimizer = torch.optim.ASGD(model.parameters(), lr=args.learning_rate, weight_decay=args.weight_decay)
    elif args.opt == 'RMSprop':
        optimizer = torch.optim.RMSprop(model.parameters(), lr=args.learning_rate, weight_decay=args.weight_decay)

    model.opt = optimizer

    # scheduler = StepLR(model.opt, step_size=args.decay_step, gamma=args.decay_rate, verbose=True)
    # scheduler = ReduceLROnPlateau(model.opt, mode='min', factor=args.decay_rate, patience=args.decay_step, verbose=True)

    if args.start_epoch > 0:
        load_opt_state(model, os.path.join(args.model_path, model_path))

    # load train and test data
    print('loading...')
    obstacles, dataset, targets, env_indices = data_loader_2d(
        N=args.N, with_start=args.with_start, samples=args.samples,
        get_together=False, point_cloud=args.point_cloud, env_type=args.env_type)

    print('obstacles.shape', np.array(obstacles).shape, flush=True)
    print('dataset.shape', np.array(dataset).shape, flush=True)
    print('target.shape', np.array(targets).shape, flush=True)
    print('env_indices.shape', np.array(env_indices).shape, flush=True)

    # 0.9 train, val split
    val_size = int(0.1*len(dataset))

    # val_dataset = dataset[:-val_size]
    # val_targets = targets[:-val_size]
    # val_env_indices = env_indices[:-val_size]

    dataset = dataset[:-val_size]
    targets = targets[:-val_size]
    env_indices = env_indices[:-val_size]

    val_dataset = dataset[-val_size:]
    val_targets = targets[-val_size:]
    val_env_indices = env_indices[-val_size:]

    print('dataset.shape', np.array(dataset).shape, flush=True)
    print('val_dataset.shape', np.array(val_dataset).shape, flush=True)

    # Train the Models
    print('training...')
    writer_fname = '%s_%f_%s' % (args.env_type, args.learning_rate, args.opt)
    writer = SummaryWriter('./runs/'+writer_fname)
    record_loss = 0.
    record_i = 0
    val_record_loss = 0.
    val_record_i = 0

    print(model)
    print(model.opt)
    model.train()
    # print number of parameters
    total_params = sum(
        param.numel() for param in model.parameters()
    )

    trainable_params = sum(
        param.numel() for param in model.parameters() if param.requires_grad
    )
    print('Total number of trainable parameters: {}'.format(trainable_params))

    print('Total number of parameters: {}'.format(total_params))

    for epoch in range(args.start_epoch, args.epochs+1):

        sum_train_loss = 0.0
        sum_val_loss = 0.0

        # widgets = [f'epoch{epoch} ',
        #            progressbar.Bar(),
        #            ' (batch ', progressbar.SimpleProgress(), ') ',
        #            progressbar.ETA(),
        #            ' train/val loss ',
        #            progressbar.Variable(
        #                'train_loss', format='{formatted_value}'), '/',
        #            progressbar.Variable(
        #                'val_loss', format='{formatted_value}'),
        #            ]
        # bar = progressbar.ProgressBar(widgets=widgets)
        for i in range(0, len(dataset), args.batch_size):
            # randomly pick 100 data
            #bi = np.concatenate( (obstacles[env_indices[i:i+100]], dataset[i:i+100]), axis=1).astype(np.float32)
            bi = np.array(dataset[i:i+args.batch_size]).astype(np.float32)

            batch_data = np.array(
                dataset[i:i+args.batch_size]).astype(np.float32)
            batch_target = np.array(
                targets[i:i+args.batch_size]).astype(np.float32)
            batch_env_indices = np.array(
                env_indices[i:i+args.batch_size]).astype(np.float32)
            batch_obstacles = np.array(
                obstacles[env_indices[i:i+args.batch_size]]).astype(np.float32)

            batch_data = torch.FloatTensor(batch_data)
            batch_target = np.array(batch_target).astype(np.float32)
            batch_target = torch.FloatTensor(batch_target)
            batch_env_indices = torch.FloatTensor(batch_env_indices)
            batch_obstacles = torch.FloatTensor(batch_obstacles)

            model.zero_grad()

            batch_data = to_var(batch_data)
            batch_target = to_var(batch_target)
            batch_env_indices = to_var(batch_env_indices)
            batch_obstacles = to_var(batch_obstacles)

            # print('batch_data.shape', batch_data.shape)
            # print('batch_target.shape', batch_target.shape)
            # print('batch_env_indices.shape', batch_env_indices.shape)
            # print('batch_obstacles.shape', batch_obstacles.shape)

            model.zero_grad()
            # print('batch_data.shape', batch_data.shape)
            # print('batch_obstacles.shape', batch_obstacles.shape)
            loss = loss_f(model(batch_data, batch_obstacles), batch_target)
            loss.backward()
            loss = loss.item()
            optimizer.step()

            # model.step(batch_data, batch_target)

            # loss = loss_f(model(batch_data),
            #               batch_target).item()

            sum_train_loss += loss * args.batch_size
            record_loss += loss
            record_i += 1
            if record_i % 100 == 0:
                writer.add_scalar('train_loss', record_loss / 100, record_i)
                record_loss = 0.

            ######################################
            # loss on validation set
            idx = i % val_size

            batch_data = np.array(
                val_dataset[idx:idx+args.batch_size]).astype(np.float32)
            batch_target = np.array(
                val_targets[idx:idx+args.batch_size]).astype(np.float32)
            batch_env_indices = np.array(
                val_env_indices[idx:idx+args.batch_size]).astype(np.float32)
            batch_obstacles = np.array(
                obstacles[val_env_indices[idx:idx+args.batch_size]]).astype(np.float32)

            batch_data = torch.FloatTensor(batch_data)
            batch_target = np.array(batch_target).astype(np.float32)
            batch_target = torch.FloatTensor(batch_target)
            batch_env_indices = torch.FloatTensor(batch_env_indices)
            batch_obstacles = torch.FloatTensor(batch_obstacles)

            model.zero_grad()
            batch_data = to_var(batch_data)
            batch_target = to_var(batch_target)
            batch_env_indices = to_var(batch_env_indices)
            batch_obstacles = to_var(batch_obstacles)

            # temp = model(batch_data, batch_obstacles)

            loss = loss_f(model(batch_data, batch_obstacles),
                          batch_target).item()
            sum_val_loss += loss * args.batch_size

            val_record_loss += loss
            val_record_i += 1
            if val_record_i % 100 == 0:
                writer.add_scalar(
                    'val_loss', val_record_loss / 100, val_record_i)
                val_record_loss = 0.

            # if i % 500 == 0:
            #     bar.update(train_loss=sum_train_loss / (i + args.batch_size),
            #            val_loss=sum_val_loss / (i + args.batch_size))

            # if i % 250 == 0:
            #     print('epoch {}, batch: {}/{}, train loss {}, val loss {}'.format(epoch, i / args.batch_size, len(dataset) / args.batch_size, sum_train_loss / (i + args.batch_size), sum_val_loss / (i + args.batch_size)), flush=True)

        print('epoch {}/{}, train loss {}, val loss {}'.format(epoch, args.epochs,
              sum_train_loss * 40 / len(dataset), sum_val_loss * 40 / len(dataset)), flush=True)

        # scheduler.step()

        # Save the models every 50 epochs
        if epoch % 50 == 0:

            # create a time stamp folder
            if not os.path.exists('models/{}'.format(timestamp)):
                os.makedirs('models/{}'.format(timestamp))

            model_path = "{}/model_env_{}_epoch_{}.pkl".format(
                timestamp, args.env_type, epoch)
            print(model_path)
            # model_path='mpnet_epoch_%d.pkl' %(epoch)
            save_state(model, torch_seed, np_seed, py_seed,
                       os.path.join(args.model_path, model_path))

            entire_model_path = "{}/entire_model_env_{}_epoch_{}.pt".format(
                timestamp, args.env_type, epoch)

            torch.save(model, os.path.join(args.model_path, entire_model_path))
            # test
    writer.export_scalars_to_json("./all_scalars.json")
    writer.close()

parser = argparse.ArgumentParser()

parser.add_argument('--model-path', type=str,
                    default='./models/', help='path for saving trained models')
parser.add_argument('--N', type=int, default=10,
                    help='number of environments')

parser.add_argument('--batch-size', type=int, default=100)
parser.add_argument('--learning-rate', type=float, default=0.01)
parser.add_argument('--epochs', type=int, default=500)

parser.add_argument('--start-epoch', type=int, default=0)
parser.add_argument('--device', type=int, default=0, help='cuda device')

parser.add_argument('--env-type', type=str, default='2d',
                    help='2d')
parser.add_argument('--world-size', nargs='+', type=float,
                    default=20., help='boundary of world')
parser.add_argument('--decay-step', type=int, default=20)
parser.add_argument('--decay-rate', type=float, default=0.5)
parser.add_argument('--opt', type=str, default='Adagrad')
parser.add_argument('--with-start', action='store_true')
parser.add_argument('--samples', type=int, default=10000)
parser.add_argument('--point-cloud', action='store_true')
parser.add_argument('--activation', type=str, default='relu')
parser.add_argument('--dropout', type=float, default=0.5)
parser.add_argument('--weight-decay', type=float, default=0.0001)

args = parser.parse_args()
print(args)
main(args)


"""
This module is responsible for processing the data.  Each function in this module will take a list of reviews,
process it and return the desired result.
"""

"""
Task 16 - 20: Write suitable functions to process the data.

Each of the functions below should follow the pattern:
- Take a list of reviews (where each review is a list of data values) as a parameter.
- Process the list of reviews appropriately.  You may use the module 'tui' to retrieve any additional information
required from the user to complete the processing.
- Return a suitable result

The required functions are as follows:
- Retrieve the total number of reviews that have been loaded.
- Retrieve the reviews for a hotel where the hotel name is specified by the user.
- Retrieve the reviews for the dates specified by the user.
- Retrieve all the reviews grouped by the reviewer’s nationality.
- Retrieve a summary of all the reviews. This should include the following information for each date in ascending order:
    - the total number of negative reviews on that date
    - the total number of positive reviews on that date
    - the average rating on that date
"""

# TODO: Your code here

from typing import List
from tui import hotel_name, review_dates
from main import read_csv
import csv

filename = 'data/hotel_reviews.csv'
reviews_data = []

def get_total_reviews(reviews: List[List[str]]) -> int:
    """
    Task 16: Retrieve the total number of reviews that have been loaded.

    :param reviews: A list of reviews
    :return: The total number of reviews
    """
    read_csv()
    total_reviews_index = read_csv.header.index('Total_Reviews_By_Reviewer')
    total_reviews_sum = 0

    # Iterate over each row in the CSV file
    for i, row in enumerate(read_csv.csv_reader):
        # Add the value from the "Total_Reviews_By_Reviewer" column to the sum
        total_reviews_sum += int(row[total_reviews_index])

        # Append the entire row to the reviews_data list
        reviews_data.append(row)

        # Print the total sum of the "Total_Reviews_By_Reviewer" column
        print("Total reviews:", total_reviews_sum)

    return len(reviews)

def get_reviews_by_hotel(reviews: List[List[str]]) -> List[List[str]]:
    """
    Task 17: Retrieve the reviews for a hotel where the hotel name is specified by the user.

    :param reviews: A list of reviews
    :return: The reviews for the specified hotel
    """
    hotel_name = hotel_name()
    return [review for review in reviews if review[1] == hotel_name]

def get_reviews_by_dates(reviews: List[List[str]]) -> List[List[str]]:
    """
    Task 18: Retrieve the reviews for the dates specified by the user.

    :param reviews: A list of reviews
    :return: The reviews for the specified dates
    """
    review_dates = review_dates()
    return [review for review in reviews if review[0] in review_dates]

def group_reviews_by_nationality(reviews: List[List[str]]) -> dict:
    """
    Task 19: Retrieve all the reviews grouped by the reviewer's nationality.

    :param reviews: A list of reviews
    :return: A dictionary where the keys are nationalities and the values are lists of reviews for each nationality
    """
    grouped_reviews = {}
    for review in reviews:
        nationality = review[2]
        if nationality in grouped_reviews:
            grouped_reviews[nationality].append(review)
        else:
            grouped_reviews[nationality] = [review]
    return grouped_reviews

def summarize_reviews(reviews: List[List[str]]) -> List[dict]:
    """
    Task 20: Retrieve a summary of all the reviews.

    :param reviews: A list of reviews
    :return: A list of dictionaries containing the summary information for each date
    """
    summary = []
    dates = set(review[0] for review in reviews)
    for date in sorted(dates):
        positive_reviews = 0
        negative_reviews = 0
        total_rating = 0
        num_reviews = 0
        for review in reviews:
            if review[0] == date:
                rating = float(review[5])
                total_rating += rating
                num_reviews += 1
                if rating >= 3.0:
                    positive_reviews += 1
                else:
                    negative_reviews += 1
        average_rating = total_rating / num_reviews if num_reviews > 0 else 0
        summary.append({
            'date': date,
            'positive_reviews': positive_reviews,
            'negative_reviews': negative_reviews,
            'average_rating': average_rating
        })
    return summary


from __future__ import print_function
import importlib.util
import xml.etree.ElementTree as et
import pandas as pd
from shutil import copyfile
import pickle
import os

"""Curation/Utils
"""
spec = importlib.util.spec_from_file_location(
    "__main__", os.path.abspath("./metaboverse_cli/curate/__main__.py"))
curate = importlib.util.module_from_spec(spec)
spec.loader.exec_module(curate)

spec = importlib.util.spec_from_file_location(
    "__main__", os.path.abspath("./metaboverse_cli/curate/load_reactions_db.py"))
load_reactions = importlib.util.module_from_spec(spec)
spec.loader.exec_module(load_reactions)

spec = importlib.util.spec_from_file_location(
    "__main__", os.path.abspath("./metaboverse_cli/curate/load_complexes_db.py"))
load_complexes = importlib.util.module_from_spec(spec)
spec.loader.exec_module(load_complexes)

spec = importlib.util.spec_from_file_location(
    "__main__", os.path.abspath("./metaboverse_cli/curate/fetch_species.py"))
fetch_species = importlib.util.module_from_spec(spec)
spec.loader.exec_module(fetch_species)

spec = importlib.util.spec_from_file_location(
    "get_table", os.path.abspath("./metaboverse_cli/curate/utils.py"))
get_table = importlib.util.module_from_spec(spec)
spec.loader.exec_module(get_table)

spec = importlib.util.spec_from_file_location(
    "unpack_table", os.path.abspath("./metaboverse_cli/curate/utils.py"))
unpack_table = importlib.util.module_from_spec(spec)
spec.loader.exec_module(unpack_table)

spec = importlib.util.spec_from_file_location(
    "", os.path.abspath("./metaboverse_cli/curate/load_reactions_db.py"))
load_reactions_db = importlib.util.module_from_spec(spec)
spec.loader.exec_module(load_reactions_db)

# test __main__() -- functional test
args_dict = {
    'organism_id': 'SCE',
    'output': os.path.abspath(
        os.path.join(".", "metaboverse_cli", "curate", "test")) + os.path.sep}

# load_reactions_db.py
args_dict, pathway_database, reaction_database, species_database, \
name_database, compartment_dictionary, \
components_database = load_reactions.__main__(
        species_id=args_dict['organism_id'],
        output_dir=args_dict['output'],
        database_source='reactome',
        sbml_url='None',
        args_dict=args_dict)

assert type(pathway_database) == dict, "load_reactions_db.py failed"
assert type(pathway_database[list(pathway_database.keys())[
            0]]) == dict, "load_reactions_db.py failed"

assert type(reaction_database) == dict, "load_reactions_db.py failed"
assert type(reaction_database[list(reaction_database.keys())[
            0]]) == dict, "load_reactions_db.py failed"

assert type(species_database) == dict, "load_reactions_db.py failed"
assert type(species_database[list(species_database.keys())[
            0]]) == str, "load_reactions_db.py failed"

assert type(name_database) == dict, "load_reactions_db.py failed"
assert type(name_database[list(name_database.keys())[0]]
            ) == str, "load_reactions_db.py failed"

assert type(compartment_dictionary) == dict, "load_reactions_db.py failed"
assert type(compartment_dictionary[list(compartment_dictionary.keys())[
            0]]) == str, "load_reactions_db.py failed"

assert type(components_database) == dict, "load_reactions_db.py failed"
assert type(components_database[list(components_database.keys())[
            0]]) == dict, "load_reactions_db.py failed"

# load_complexes_db.py
d = load_complexes.__main__(
    output_dir=args_dict['output'])
assert type(d['complex_participants']
            ) == pd.DataFrame, "load_complexes_db.py failed"
assert type(d['complex_pathway']
            ) == pd.DataFrame, "load_complexes_db.py failed"

# fetch_species.py
organisms = fetch_species.__main__()
assert type(organisms) == list, "fetch_species.py failed"

# write_database()
args_dict = {
    'output': os.path.abspath(
        os.path.join(".", "metaboverse_cli", "curate", "test")) + os.path.sep,
    'file': 'test.mvdb'}
database = {
    'chebi_reference': {
        'R-HSA-0000': {
            'analyte_id': 'R-ANA-1017',
            'source_id': '0017',
            'other': None
        }
    },
    'uniprot_reference': {
        'R-HSA-0000': {
            'analyte_id': 'R-ANA-1015',
            'source_id': '0015',
            'other': None
        }
    },
    'ensembl_reference': {
        'R-HSA-0001': {
            'analyte_id': 'R-ANA-1014',
            'source_id': '0014',
            'other': None
        }
    },
    'ncbi_reference': {
        'R-HSA-0000': {
            'analyte_id': 'R-ANA-1013',
            'source_id': '0013',
            'other': None
        }
    },
    'mirbase_reference': {
        'R-HSA-0000': {
            'analyte_id': 'R-ANA-1012',
            'source_id': '0012',
            'other': None
        }
    }
}
curate.write_database(
    output=args_dict['output'],
    file=args_dict['file'],
    database=database)

assert os.path.exists(args_dict['output'] + args_dict['file']
                      ) == True, 'Failed to write database to pickle file'
os.remove(args_dict['output'] + args_dict['file'])

# unpack_table()
url = 'https://reactome.org/download/current/'
test_file = 'models2pathways.tsv'
file = unpack_table.unpack_table(
    url + test_file,
    output_dir=args_dict['output'])
assert file == args_dict['output'] + test_file, 'unpack_table() failed'
os.remove(args_dict['output'] + test_file)

# get_table()
url = 'https://reactome.org/download/current/'
test_file = 'models2pathways.tsv'
table = get_table.get_table(
    args_dict['output'],
    url + test_file,
    column_names=[
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7'],
    organism='Homo sapiens',
    organism_key='7')  # Key for testing purposes only
assert 'Homo sapiens' in table['7'].tolist(), 'Problem getting table download'
os.remove(args_dict['output'] + test_file)

# parse_table()

def run_checks(
        ref_dict):

    if ref_dict['R-ALL-00000']['analyte_id'] != 'R-ALL-00000' \
            or ref_dict['R-ALL-00000']['reaction_id'] != 'R-HSA-00000' \
            or ref_dict['R-ALL-00000']['reaction_name'] != 'fake_reaction' \
            or ref_dict['R-ALL-00000']['analyte'] != 'fake_molecule' \
            or ref_dict['R-ALL-00000']['compartment'] != 'organelle':
        return False

    else:
        return True

data_1 = [
    ['analyte_id', 'analyte_name', 'reaction_id',
        'reaction_name', 'source_id', 'extra_column'],
    ['R-ALL-00000', 'fake_molecule [organelle]',
        'R-HSA-00000', 'fake_reaction', '0101', '????']
]
table = pd.DataFrame(data_1, columns=data_1[0])
table = table.drop(0, axis=0)
reference = {
    'this_one': table,
    'not_this_one': False}
ref_dict = curate.parse_table(
    reference=reference,
    key='this_one')
assert run_checks(ref_dict) == True, 'Problem parsing Reactome table'

# Test unpacking of a reaction file
species_id = 'HSA'
path = args_dict['output']
file = 'R-HSA-realtest.sbml'
test_db = args_dict['output'] + file
sbml_namespace = '{{http://www.sbml.org/sbml/level{0}/version{1}/core}}'
rdf_namespace = '{http://www.w3.org/1999/02/22-rdf-syntax-ns#}'
bqbiol_namespace = '{http://biomodels.net/biology-qualifiers/}'
sbml_level = '3'
sbml_version = '1'

path_list = load_reactions_db.get_pathways(
    species_id=species_id,
    pathways_dir=path)
assert path_list == ['R-HSA-realtest'], 'get_pathways() failed'

contents = load_reactions_db.get_database(
    pathways_dir=path,
    pathway_name=path_list[0])
assert type(contents) == et.Element, 'get_database() failed'

args_dict, pathway_database, reaction_database, species_database, \
name_database, compartment_database, compartment_dictionary, \
components_database = load_reactions_db.process_components(
        output_dir=args_dict['output'],
        pathways_dir=args_dict['output'],
        pathways_list=path_list,
        species_id=species_id,
        args_dict=args_dict,
        bqbiol_namespace=bqbiol_namespace,
        rdf_namespace=rdf_namespace)

assert 'R-HSA-realtest' in pathway_database.keys(), 'process_components() failed'
assert pathway_database['R-HSA-realtest']['id'] == 'pathway_168268', 'process_components() failed'
assert pathway_database['R-HSA-realtest']['reactome'] == 'R-HSA-realtest', 'process_components() failed'
assert pathway_database['R-HSA-realtest']['name'] == 'Virus Assembly and Release', 'process_components() failed'
assert len(pathway_database['R-HSA-realtest']
           ['reactions']) == 21, 'process_components() failed'
truth_d = set([
    'reaction_168884',
    'reaction_168875',
    'reaction_168882',
    'reaction_195733',
    'reaction_169919',
    'reaction_195739',
    'reaction_168894',
    'reaction_168870',
    'reaction_168871',
    'reaction_195734',
    'reaction_168858',
    'reaction_168862',
    'reaction_168895',
    'reaction_168860',
    'reaction_195726',
    'reaction_169921',
    'reaction_195926',
    'reaction_195730',
    'reaction_168869',
    'reaction_188544',
    'reaction_169847'])
assert set(pathway_database['R-HSA-realtest']['reactions']
           ) == truth_d, 'process_components() failed'

assert reaction_database['reaction_195733']['compartment'] == 'compartment_17957', 'process_components() failed'
assert reaction_database['reaction_195733']['id'] == 'reaction_195733', 'process_components() failed'
assert reaction_database['reaction_195733']['name'] == 'M2 protein synthesis', 'process_components() failed'
assert reaction_database['reaction_195733']['reversible'] == 'false', 'process_components() failed'
assert type(reaction_database['reaction_195733']
            ['notes']) == str, 'process_components() failed'
assert reaction_database['reaction_195733']['reactants'] == [
], 'process_components() failed'
assert reaction_database['reaction_195733']['products'] == [
    'species_195756'], 'process_components() failed'
assert reaction_database['reaction_195733']['modifiers'] == [
], 'process_components() failed'
assert reaction_database['reaction_168870']['reactants'] == [
    'species_195945'], 'process_components() failed'
assert reaction_database['reaction_168870']['products'] == [
    'species_195941'], 'process_components() failed'
assert reaction_database['reaction_168870']['modifiers'] == [
    ['species_195915', 'catalyst']], 'process_components() failed'

assert species_database['species_195752'] == 'NP', 'process_components() failed'
assert species_database['species_195915'] == 'NA', 'process_components() failed'

assert name_database['NP'] == 'species_195752', 'process_components() failed'
assert name_database['NA'] == 'species_195915', 'process_components() failed'

assert compartment_database['species_195752'] == 'compartment_876', 'process_components() failed'
assert compartment_database['species_195915'] == 'compartment_984', 'process_components() failed'

assert compartment_dictionary['compartment_876'] == 'plasma membrane', 'process_components() failed'
assert compartment_dictionary['compartment_984'] == 'extracellular region', 'process_components() failed'

assert components_database['species_195752']['id'] == 'species_195752', 'process_components() failed'
assert components_database['species_195752']['reactome_id'] == 'R-FLU-195752', 'process_components() failed'
assert components_database['species_195752']['name'] == 'NP', 'process_components() failed'
assert components_database['species_195752']['is'] == 'P03466', 'process_components() failed'
assert components_database['species_195752']['hasPart'] == [
], 'process_components() failed'
print(components_database['species_195752'])
assert components_database['species_195752']['type'] == 'protein_component', 'process_components() failed'
assert components_database['species_195752']['compartment'] == 'compartment_876', 'process_components() failed'

print(components_database['species_195941'])

assert set([
    'P03466',
    'P03428',
    'P03433',
    'P03431',
    'P03485',
    'P03508',
    'P03468',
    'P03452',
    'P06821']).issubset(set(components_database['species_195941']['hasPart'])), 'process_components() failed'

# BioModels tests
src = os.path.abspath(os.path.join(".", "metaboverse_cli",
                                   "curate", "test", "test_session_data.json"))
dst = os.path.abspath(os.path.join(".", "metaboverse_cli",
                                   "curate", "test", "test_session_data_copy.json"))
s_out = copyfile(src, dst)

args_dict = {
    'organism_id': 'find',
    'output': os.path.abspath(
        os.path.join(".", "metaboverse_cli", "curate", "test")) + os.path.sep,
    'session_data': os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data_copy.json"))}

args_dict, pathway_database, reaction_database, species_database, \
name_database, compartment_dictionary, \
components_database = load_reactions.__main__(
    species_id=args_dict['organism_id'],
    output_dir=args_dict['output'],
    database_source='biomodels/bigg',
    sbml_url=os.path.abspath(os.path.join(
        ".", "metaboverse_cli", "curate", "test", "iIS312.xml")),
    args_dict=args_dict)

if 'All' in pathway_database:
    print("Pass")
else:
    raise Exception("BioModels/BiGG database curation failed")
assert reaction_database['R_PROt2r_copy2']['reactants'] == [
    'M_h_e', 'M_pro__L_e'], "BioModels/BiGG database curation failed"
assert species_database['M_pro__L_e'] == 'L-Proline', "BioModels/BiGG database curation failed"
assert name_database['M_pro__L_e'] == 'M_pro__L_e', "BioModels/BiGG database curation failed"
assert name_database['L-Proline'] == 'M_pro__L_e', "BioModels/BiGG database curation failed"
assert compartment_dictionary['c'] == 'cytosol', "BioModels/BiGG database curation failed"
assert components_database['M_pro__L_e']['is'] == 'D00035', "BioModels/BiGG database curation failed"

os.remove(dst)

# BiGG tests
src = os.path.abspath(os.path.join(".", "metaboverse_cli",
                                   "curate", "test", "test_session_data.json"))
dst = os.path.abspath(os.path.join(".", "metaboverse_cli",
                                   "curate", "test", "test_session_data_copy.json"))
s_out = copyfile(src, dst)

args_dict = {
    'organism_id': 'find',
    'database_source': 'biomodels/bigg',
    'output': os.path.abspath(
        os.path.join(".", "metaboverse_cli", "curate", "test")) + os.path.sep,
    'session_data': os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data_copy.json"))}

args_dict, pathway_database, reaction_database, species_database, \
name_database, compartment_dictionary, \
components_database = load_reactions.__main__(
    species_id=args_dict['organism_id'],
    output_dir=args_dict['output'],
    database_source='biomodels/bigg',
    sbml_url=os.path.abspath(os.path.join(
        ".", "metaboverse_cli", "curate", "test", "BMID000000141967_url.xml")),
    args_dict=args_dict)

if 'All' in pathway_database:
    print("Pass")
else:
    raise Exception("BioModels/BiGG database curation failed")
assert reaction_database['MNXR42496_i']['reactants'] == [
    'MNXM2885_i', 'bigg_gthrd_i'], "BioModels/BiGG database curation failed"
assert species_database['MNXM2885_i'] == '(1S,2R)-Naphthalene 1,2-oxide', "BioModels/BiGG database curation failed"
assert species_database['MNXM2885_e'] == '(1S,2R)-Naphthalene 1,2-oxide', "BioModels/BiGG database curation failed"
assert name_database['(1S,2R)-Naphthalene 1,2-oxide'] == 'MNXM2885_e', "BioModels/BiGG database curation failed"
assert compartment_dictionary['i'] == 'intracellular', "BioModels/BiGG database curation failed"
assert components_database['MNXM2885_e']['is'] == 'MNXM2885_e', "BioModels/BiGG database curation failed"

os.remove(dst)

# test all
"""
src = os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data.json"))
dst = os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data_copy.json"))
s_out = copyfile(src, dst)

args_dict = {
    'organism_id': 'SCE',
    'database_source': 'reactome',
    'organism_curation': "None",
    'output': os.path.abspath(
        os.path.join(".", "metaboverse_cli", "curate", "test")) + os.path.sep,
    'session_data':os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data_copy.json"))}
curate.__main__(
    args_dict=args_dict
)
os.remove(dst)
os.remove(args_dict['output'] + "SCE.mvdb")
"""

# test all bigg
#src = os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data.json"))
#dst = os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data_copy.json"))
#s_out = copyfile(src, dst)
# args_dict = {
#    'organism_id': 'find',
#    'database_source': 'biomodels/bigg',
#    'organism_curation': os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "BMID000000141967_url.xml")),
#    'output': os.path.abspath(
#        os.path.join(".", "metaboverse_cli", "curate", "test")) + os.path.sep,
#    'session_data':os.path.abspath(os.path.join(".", "metaboverse_cli", "curate", "test", "test_session_data_copy.json"))}
# curate.__main__(
#    args_dict=args_dict
# )
# os.remove(dst)
#os.remove(args_dict['output'] + "BMID000000141967.mvdb")

print('Tests completed')


# coding=utf-8
"""
    @project: Everyday_LeetCode
    @Author：Charles
    @file： 300.最长递增子序列.py
    @date：2022/12/30 23:42
"""

class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # 核心思想：动态规划
        # dp[i]：表示以nums[i]结尾得最长子序列长度
        # 动态转移方程：
        #   nums[i]之前的序列为nums[0:i]，记作nums[j]
        #   如果nums[i] > nums[j]
        #   计算每一个dp[j]到nums[i]的最长递增子序列长度，即dp[j]+1，并取最大值
        #   动态转移方程为
        #   if nums[i] > nums[j]:
        #       dp[i] = max(dp[i], dp[j]+1)
        # 初始化：
        #   有数字时最少长度为1，所以全部初始化为1

        if len(nums) <= 1:
            return len(nums)

        dp = [1] * len(nums)
        res = 0

        for i in range(len(nums)):
            for j in range(i):
                if nums[i] > nums[j]:
                    dp[i] = max(dp[i], dp[j]+1)
            res = max(res, dp[i])
        return res

300.最长递增子序列.py

300.最长递增子序列.py


# Arthur Vasconcellos <contatoarthursilveira@gmail.com>
# github.com/arthursvpb
# linkedin.com/in/arthursvpb
# facebook.com/arthursvpb
# twitter.com/arthursvpb

nome = str(input())
salario = float(input())
vendas = float(input())
comissao = vendas * 0.15

salariofinal = salario + comissao

print("TOTAL = R$ {:.2f}".format(salariofinal))