"""This module handles the generation of the Gerber files, the BOM and the POS file."""

import csv
import logging
import os
import re
from pathlib import Path
from zipfile import ZIP_DEFLATED, ZipFile

from pcbnew import (  # pylint: disable=import-error
    EXCELLON_WRITER,
    PCB_PLOT_PARAMS,
    PLOT_CONTROLLER,
    PLOT_FORMAT_GERBER,
    ZONE_FILLER,
    B_Cu,
    B_Mask,
    B_Paste,
    B_SilkS,
    Cmts_User,
    Edge_Cuts,
    F_Cu,
    F_Mask,
    F_Paste,
    F_SilkS,
    GetBoard,
    Refresh,
    ToMM,
)

# Compatibility hack for V6 / V7 / V7.99
try:
    from pcbnew import DRILL_MARKS_NO_DRILL_SHAPE  # pylint: disable=import-error

    NO_DRILL_SHAPE = DRILL_MARKS_NO_DRILL_SHAPE
except ImportError:
    NO_DRILL_SHAPE = PCB_PLOT_PARAMS.NO_DRILL_SHAPE

from .helpers import get_exclude_from_pos, get_footprint_by_ref, get_smd

class Fabrication:
    """This class contains all functionality to generate the JLCPCB production files."""

    def __init__(self, parent):
        self.parent = parent
        self.logger = logging.getLogger(__name__)
        self.board = GetBoard()
        self.corrections = []
        self.path, self.filename = os.path.split(self.board.GetFileName())
        self.create_folders()

    def create_folders(self):
        """Create output folders if they not already exist."""
        self.outputdir = os.path.join(self.path, "jlcpcb", "production_files")
        Path(self.outputdir).mkdir(parents=True, exist_ok=True)
        self.gerberdir = os.path.join(self.path, "jlcpcb", "gerber")
        Path(self.gerberdir).mkdir(parents=True, exist_ok=True)

    def fill_zones(self):
        """Refill copper zones following user prompt."""
        if self.parent.settings.get("gerber", {}).get("fill_zones", True):
            filler = ZONE_FILLER(self.board)
            zones = self.board.Zones()
            filler.Fill(zones)
            Refresh()

    def fix_rotation(self, footprint):
        """Fix the rotation of footprints in order to be correct for JLCPCB."""
        original = footprint.GetOrientation()
        # `.AsDegrees()` added in KiCAD 6.99
        try:
            rotation = original.AsDegrees()
        except AttributeError:
            # we need to divide by 10 to get 180 out of 1800 for example.
            # This might be a bug in 5.99 / 6.0 RC
            rotation = original / 10
        if footprint.GetLayer() != 0:
            # bottom angles need to be mirrored on Y-axis
            rotation = (180 - rotation) % 360
        # First check if the value aka part name matches
        for regex, correction in self.corrections:
            if re.search(regex, str(footprint.GetValue())):
                return self.rotate(footprint, rotation, correction)
        # Then if the package matches
        for regex, correction in self.corrections:
            if re.search(regex, str(footprint.GetFPID().GetLibItemName())):
                return self.rotate(footprint, rotation, correction)
        # If no correction matches, return the original rotation
        return rotation

    def rotate(self, footprint, rotation, correction):
        """Calculate the actual correction"""
        if footprint.GetLayer() == 0:
            rotation = (rotation + int(correction)) % 360
            self.logger.info(
                "Fixed rotation of %s (%s / %s) on Top Layer by %d degrees",
                footprint.GetReference(),
                footprint.GetValue(),
                footprint.GetFPID().GetLibItemName(),
                correction,
            )
        else:
            rotation = (rotation - int(correction)) % 360
            self.logger.info(
                "Fixed rotation of %s (%s / %s) on Bottom Layer by %d degrees",
                footprint.GetReference(),
                footprint.GetValue(),
                footprint.GetFPID().GetLibItemName(),
                correction,
            )
        return rotation

    def get_position(self, footprint):
        """Calculate position based on center of bounding box"""
        if get_smd(footprint):
            return footprint.GetPosition()
        bbox = footprint.GetBoundingBox(False, False)
        return bbox.GetCenter()

    def generate_geber(self, layer_count=None):
        """Generating Gerber files"""
        # inspired by https://github.com/KiCad/kicad-source-mirror/blob/master/demos/python_scripts_examples/gen_gerber_and_drill_files_board.py
        pctl = PLOT_CONTROLLER(self.board)
        popt = pctl.GetPlotOptions()

        # https://github.com/KiCad/kicad-source-mirror/blob/master/pcbnew/pcb_plot_params.h
        popt.SetOutputDirectory(self.gerberdir)

        # Plot format to Gerber
        # https://github.com/KiCad/kicad-source-mirror/blob/master/include/plotter.h#L67-L78
        popt.SetFormat(1)

        # General Options
        popt.SetPlotValue(
            self.parent.settings.get("gerber", {}).get("plot_values", True)
        )
        popt.SetPlotReference(
            self.parent.settings.get("gerber", {}).get("plot_references", True)
        )
        popt.SetPlotInvisibleText(False)

        popt.SetSketchPadsOnFabLayers(False)

        # Gerber Options
        popt.SetUseGerberProtelExtensions(False)

        popt.SetCreateGerberJobFile(False)

        popt.SetSubtractMaskFromSilk(True)

        popt.SetPlotViaOnMaskLayer(False)  # Set this to True if you need untented vias

        popt.SetUseAuxOrigin(True)

        # Tented vias or not, selcted by user in settings
        popt.SetPlotViaOnMaskLayer(
            not self.parent.settings.get("gerber", {}).get("tented_vias", True)
        )

        popt.SetUseGerberX2format(True)

        popt.SetIncludeGerberNetlistInfo(True)

        popt.SetDisableGerberMacros(False)

        popt.SetDrillMarksType(NO_DRILL_SHAPE)

        popt.SetPlotFrameRef(False)

        # delete all existing files in the output directory first
        for f in os.listdir(self.gerberdir):
            os.remove(os.path.join(self.gerberdir, f))

        # if no layer_count is given, get the layer count from the board
        if not layer_count:
            layer_count = self.board.GetCopperLayerCount()

        plot_plan_top = [
            ("CuTop", F_Cu, "Top layer"),
            ("SilkTop", F_SilkS, "Silk top"),
            ("MaskTop", F_Mask, "Mask top"),
            ("PasteTop", F_Paste, "Paste top"),
        ]
        plot_plan_bottom = [
            ("CuBottom", B_Cu, "Bottom layer"),
            ("SilkBottom", B_SilkS, "Silk top"),
            ("MaskBottom", B_Mask, "Mask bottom"),
            ("PasteBottom", B_Paste, "Paste bottom"),
            ("EdgeCuts", Edge_Cuts, "Edges"),
            ("VScore", Cmts_User, "V score cut"),
        ]

        plot_plan = []

        # Single sided PCB
        if layer_count == 1:
            plot_plan = plot_plan_top + plot_plan_bottom[-2:]
        # Double sided PCB
        elif layer_count == 2:
            plot_plan = plot_plan_top + plot_plan_bottom
        # Everything with inner layers
        else:
            plot_plan = (
                plot_plan_top
                + [
                    (f"CuIn{layer}", layer, f"Inner layer {layer}")
                    for layer in range(1, layer_count - 1)
                ]
                + plot_plan_bottom
            )

        for layer_info in plot_plan:
            if layer_info[1] <= B_Cu:
                popt.SetSkipPlotNPTH_Pads(True)
            else:
                popt.SetSkipPlotNPTH_Pads(False)
            pctl.SetLayer(layer_info[1])
            pctl.OpenPlotfile(layer_info[0], PLOT_FORMAT_GERBER, layer_info[2])
            if pctl.PlotLayer() is False:
                self.logger.error("Error plotting %s", layer_info[2])
            self.logger.info("Successfully plotted %s", layer_info[2])
        pctl.ClosePlot()

    def generate_excellon(self):
        """Generate Excellon files."""
        drlwriter = EXCELLON_WRITER(self.board)
        mirror = False
        minimalHeader = False
        offset = self.board.GetDesignSettings().GetAuxOrigin()
        mergeNPTH = False
        drlwriter.SetOptions(mirror, minimalHeader, offset, mergeNPTH)
        drlwriter.SetFormat(False)
        genDrl = True
        genMap = True
        drlwriter.CreateDrillandMapFilesSet(self.gerberdir, genDrl, genMap)
        self.logger.info("Finished generating Excellon files")

    def zip_gerber_excellon(self):
        """Zip Gerber and Excellon files, ready for upload to JLCPCB."""
        zipname = f"GERBER-{self.filename.split('.')[0]}.zip"
        with ZipFile(
            os.path.join(self.outputdir, zipname),
            "w",
            compression=ZIP_DEFLATED,
            compresslevel=9,
        ) as zipfile:
            for folderName, _, filenames in os.walk(self.gerberdir):
                for filename in filenames:
                    if not filename.endswith(("gbr", "drl", "pdf")):
                        continue
                    filePath = os.path.join(folderName, filename)
                    zipfile.write(filePath, os.path.basename(filePath))
        self.logger.info("Finished generating ZIP file")

    def generate_cpl(self):
        """Generate placement file (CPL)."""
        cplname = f"CPL-{self.filename.split('.')[0]}.csv"
        self.corrections = self.parent.library.get_all_correction_data()
        aux_orgin = self.board.GetDesignSettings().GetAuxOrigin()
        add_without_lcsc = self.parent.settings.get("gerber", {}).get(
            "lcsc_bom_cpl", True
        )
        with open(
            os.path.join(self.outputdir, cplname), "w", newline="", encoding="utf-8"
        ) as csvfile:
            writer = csv.writer(csvfile, delimiter=",")
            writer.writerow(
                ["Designator", "Val", "Package", "Mid X", "Mid Y", "Rotation", "Layer"]
            )
            for part in self.parent.store.read_pos_parts():
                for fp in get_footprint_by_ref(self.board, part[0]):
                    if get_exclude_from_pos(fp):
                        continue
                    if not add_without_lcsc and not part[3]:
                        continue
                    position = self.get_position(fp) - aux_orgin
                    writer.writerow(
                        [
                            part[0],
                            part[1],
                            part[2],
                            ToMM(position.x),
                            ToMM(position.y) * -1,
                            self.fix_rotation(fp),
                            "top" if fp.GetLayer() == 0 else "bottom",
                        ]
                    )
        self.logger.info("Finished generating CPL file")

    def generate_bom(self):
        """Generate BOM file."""
        bomname = f"BOM-{self.filename.split('.')[0]}.csv"
        add_without_lcsc = self.parent.settings.get("gerber", {}).get(
            "lcsc_bom_cpl", True
        )
        with open(
            os.path.join(self.outputdir, bomname), "w", newline="", encoding="utf-8"
        ) as csvfile:
            writer = csv.writer(csvfile, delimiter=",")
            writer.writerow(["Comment", "Designator", "Footprint", "LCSC"])
            for part in self.parent.store.read_bom_parts():
                if not add_without_lcsc and not part[3]:
                    continue
                writer.writerow(part)
        self.logger.info("Finished generating BOM file")


import kivy

import utils

kivy.require('2.1.0')

from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.properties import StringProperty

class WelcomeWindow(Screen):
    """
    Welcome Window.
    This window will pop the first time the player starts to play and ask for the player's name.
    """
    WELCOME_NEW_PLAYER_TXT = StringProperty("ברוך הבא! מה שמך?"[::-1])
    CONTINUE_TXT = StringProperty("המשך"[::-1])

    def __init__(self, name):
        super().__init__()
        self.name = name

        self.trigger = True
        self.input_text = ''

    def on_pre_enter(self, *args):
        # Hide the hidden name input
        self.ids.name_input_hidden.size_hint_y = None
        self.ids.name_input_hidden.height = 0

        # Set size of the name input
        self.ids.name_txt_input.size_hint_y = None
        self.ids.name_txt_input.height = utils.get_str_pixel_height() * 2

        # Set pref name if exsists
        prefs = utils.get_prefrences()
        if 'player_name' in prefs:
            self.ids.name_input_hidden.text = prefs['player_name']

    def fix_string(self, txt):
        if not self.trigger:
            return

        self.trigger = False
        self.ids.name_txt_input.text = utils.fix_string(txt)
        self.trigger = True

    def redirect_focus(self):
        self.ids.name_input_hidden.focus = True

    def continue_to_game(self):
        App.get_running_app().player_name = self.ids.name_input_hidden.text
        utils.save_prefrences(player_name=self.ids.name_input_hidden.text)
        self.manager.current = 'main'


from flask.helpers import make_response
from ML.ml_predictor import predictor
import json
import pandas as pd
import sqlite3
from flask import send_file
import io
from pandas.io.excel import ExcelWriter
db_filename = 'hr.db'
professions=["sdn","sde","nfit","ne"]
list_of_names=[[[]for i in range(5)]for i in range(len(professions))]#maxlvls NOTEEEEEEE THIS IS ONE BASED INDEXING. 1 to 4
def check(no_of_people):
    ind=-1
    hist=dict()
    with sqlite3.connect(db_filename) as conn:
        cursor = conn.cursor()
        rows=cursor.execute("""SELECT profession, count(profession) FROM employee GROUP BY profession""")
        for proflvl,count in rows:
            hist[proflvl]=count
    # print("hello",no_of_people)
    for p in professions:
        for i in range(1,5):
            var=p+str(i)
            if(hist[var]<no_of_people[ind][i-1]):
                return 0
    # print("weee",hist,"weee")
    ind=-1
    with sqlite3.connect(db_filename) as conn:
        cursor = conn.cursor()
        for p in professions:
            ind=ind+1
            for i in range(1,5):#lvl
                var=p+str(i)
                rows=cursor.execute("""SELECT  name, id FROM employee WHERE profession=(?) limit (?)""",[var,no_of_people[ind][i-1]])
                rows=list(rows)
                # print("weeerows",rows[:],"noofp=",no_of_people[ind][i-1],"weee")
                #change available in db
                for r in rows:
                    name,id =r
                    name=str(id)+'_'+name
                    list_of_names[ind][i].append(tuple([name,var])) #ind is the prof , and i is the lvl
                    # no_of_people[ind][i-1]-=1
                # print("weee",list_of_names[ind]," Prof=",ind,"weee")
                # print(ind,i)

    return 1

"""" 1ram  sde1
    2shyam  sde1
    3kam    sde2

req:[sde1:3,sde2:1]
existing:{count(sde1):2, return 0}
req:[sde1:2,sde2:1]
existing:{count(sde1):2,count(sde1):1 return 1}

output:
    list[profession_enum][lvl].append([(1ram,sde1),(2shyam,sde1)])

    [[],[],[]] #first lvl abstraction proffesion
    [[[employees in lvl 1 of this profession  ]#(lvl1),[]#(lvl2),[]#(lvl3)] #(sde),[]#(sdn),[]]
input
csv :a employesert([0:a])   l=l[a:]
es csv[SDE].in
iterate push , break sheet iterate
[ a: ] , a[]
{
    T1:{
        sde:{
            1:[names]
        }
    }

}
dict["Team1"]["sde"]["lvl"]=[(names)]
list_of_names[index][i].append(tuple(name,var))
"""

def ExtractMaxlevels(reqr):
    list_maxlvls=reqr["teamRequirements"]

    # print(list_maxlvls)
    maxlvls=list()
    for maxlvl_dict in list_maxlvls:
        maxlvl_dict=dict(maxlvl_dict)
        for keys,vals in maxlvl_dict.items():
            if(keys.find("lvl_type")!=-1):
                maxlvls.append(int(vals))
    result=list(predictor(maxlvls)) #the number of people in each prof lvl is returned
    #extracting using table col formula, instead of getting from list
    Teams=[]
    max_posible_no_teams=10
    maxprofessions=4
    max_possible_lvls=4
    index=0
    teamsize=16
    prof=[]# list of lists consististing a list of lvls for each profession
    temp=[]
    non_zeroteam=0
    no_of_ppl_perlvl=[[0  for i in range(max_possible_lvls)] for i in range(maxprofessions)]
    print("weee")
    for i in range(len(result)):
        if(i/16==2):
            break
        if(i%16==0):
            print(" ")
        print(result[i],end=" ")

    print("weee")

    for i in range(max_posible_no_teams):
        index=i*teamsize
        prof=[] # will have the team by proffesions
        non_zeroteam=0
        for j in range(0,maxprofessions):
            index=index + int((j!=0))*max_possible_lvls
            temp=[]
            for k in range(0,max_possible_lvls):
                if(result[index+k]>0):
                    non_zeroteam=1
                no_of_ppl_perlvl[j][k]+=result[index+k] #
                temp.append(result[index+k])
            prof.append(temp)
        if(non_zeroteam):
            Teams.append(prof)
    flag=check(no_of_ppl_perlvl)
    #print("weeee no of ppl per lvl, in block profs for all teams",no_of_ppl_perlvl,"weee")
    for p in range(len(no_of_ppl_perlvl)):
        for i in range(len(no_of_ppl_perlvl[p])):
            if(len(list_of_names[p][i+1])!=no_of_ppl_perlvl[p][i]):
                print("error in given and fetch from db")
                # print("wee  P=",p,"I=",i,"weee")
    if(flag==0):
        return {"result":"number of peeople is less"}
    Df_main=[pd.DataFrame(index=range(20)) for i in range(len(Teams))]
    ind=-1
    # print("wee teams ",Teams,"weeee")
    for team in Teams:
        ind=ind+1
        for prof_ind in range(len(team)) :
            prof=team[prof_ind]
            temp=[]
            for lvl in range(max_possible_lvls):
                count=int(prof[lvl])
                # print("Extend: ",list_of_names[prof_ind][lvl][0:count],professions[prof_ind])
                temp.extend(list_of_names[prof_ind][lvl+1][0:count]) #tlist of names is one based
                list_of_names[prof_ind][lvl+1]=list_of_names[prof_ind][lvl+1][count:] #remaining is assigned #one based
            try:
                # print("weeee Team =",ind,"professiion=",prof_ind,temp," weeee ")
                temp=pd.Series(temp)
                # print("weeee Team =",ind,"professiion=",prof_ind,temp," weeee ")
                Df_main[ind][professions[prof_ind]]=temp
                # print(Df_main[ind].head())
                # print(ind,professions[prof_ind])
                temp=[]
            except Exception as e:
                print("Exception: ", temp,e)
    # print("came last")
    path = "../Web Application - Front End/OutputFile/"
    writer = pd.ExcelWriter('pandas_multiple1.xlsx', engine='xlsxwriter')
    Team_sizes=[]
    for i in range(len(Df_main)):
        # print("created")
        # print(Df_main[i].head())
        Df_main[i].to_excel(writer,sheet_name='Team{}'.format(i))
        Team_sizes.append(str(Df_main[i].count().sum()))
    writer.save()
    print("saved")
    RetJson=dict()
    RetJson["status"] ="ok"
    RetJson["data"]=Team_sizes
    return RetJson
    # return send_file(open(path+"pandas_multiple.xlsx",'rb'),attachment_filename="pandas_multiple.xlsx")
    # resp = make_response(file)
    # return resp
    # return
    # res=make_response(file)
    # return res
    # return {"result":result}

def ExtractData(jsondata):
    simplified_data = []
    teamRequirements = jsondata["data"]["teamRequirements"]
    for team in teamRequirements:
        data = {
            "sde":0,
            "sdn":0,
            "ne":0,
            "nfit":0
        }
        data[team['type1']] = team['lvl_type1']
        data[team['type2']] = team['lvl_type2']
        data[team['type3']] = team['lvl_type3']
        data[team['type4']] = team['lvl_type4']
        del data[""]
        simplified_data.append(data)
    return simplified_data

Web Application - Back End/Jsonprocessor.py


import numpy as np
from sklearn.metrics.pairwise import rbf_kernel

# def linearKernel_dist (in1, in2):
#     dist = in1-in2
#     return np.dot(dist,np.transpose(dist))

def distance(x1, x2, y1, y2, idx1, idx2, C, kernel, gamma=None):
    dist = 0
    if(idx1 != idx2):
        if (kernel == 'linear'):
            dist_vec = y1*x1 - y2*x2
            dist = 2*(1+1/C-y1*y2) + np.dot(dist_vec, np.transpose(dist_vec))
        elif (kernel == 'rbf'):
            dist_vec = x1-x2
            dist = 2 * (2+1/C - y1*y2*(np.exp(-gamma*np.dot(dist_vec, np.transpose(dist_vec)))+1))
    else:
        dist = 0

    return dist

def inner_product(x1, x2, y1, y2, idx1, idx2, C, kernel, gamma=None):
    prod = 0
    delta = 0
    if(idx1 != idx2):
        delta = 0
    else:
        delta = 1

    if (kernel == 'linear'):
        prod = y1*y2*np.dot(x1, np.transpose(x2))+y1*y2+delta/C
    elif (kernel == 'rbf'):
        prod = y1*y2*np.exp(-gamma * np.dot(x1, np.transpose(x2)))+y1*y2+delta/C

    return prod

def MEB (core_set, y_core, core_size, epsilon, C, kernel, gamma=None):

    first_index = np.random.randint(0, core_size, 1)[0]

    dist_list = np.zeros(core_size)

    bias_term = np.zeros(core_size)

    dist_max = 0

    p = core_set[first_index]
    py = y_core[first_index]

    bias_term[first_index] = bias_term[first_index] + 1/C

    far_list = []
    far_y_list = []
    far_index_list = []
    far_list.append(p)
    far_y_list.append(py)
    far_index_list.append(first_index)

    kernel_contant = np.ones(core_size) * (4+2/C)

    # initialize farthest point p away from the center c
    core_rbf = rbf_kernel(np.array(far_list), core_set, gamma) + 1
    core_rbf_sum = np.multiply(np.dot(np.array(far_y_list).reshape(-1), core_rbf), y_core) + bias_term
    dist_list = kernel_contant - core_rbf_sum * 2
    index = np.argmax(dist_list).reshape(-1)[0]

    p = core_set[index]
    py = y_core[index]

    bias_term[index] = bias_term[index] + 1 / C

    far_list.append(p)
    far_y_list.append(py)
    far_index_list.append(index)

    # iteration for constructing the core-set
    for cnt in range(int(2/epsilon)):
        core_rbf = np.multiply(rbf_kernel([p], core_set, gamma) + 1, y_core) * py
        core_rbf_sum = core_rbf_sum + core_rbf[0]
        core_rbf_sum[index] = core_rbf_sum[index] + 1 / C
        dist_list = kernel_contant - core_rbf_sum * 2 / (cnt+1)
        index = np.argmax(dist_list).reshape(-1)[0]

        p = core_set[index]
        py = y_core[index]

        bias_term[index] = bias_term[index] + 1 / C

        far_list.append(p)
        far_y_list.append(py)
        far_index_list.append(index)

    dist_max = dist_list[index]

    far_index_list = np.unique(far_index_list)

    return dist_max, dist_list, far_index_list

if __name__ == "__main__":
    dim = 10
    theta = 0.1
    data_size = 1000
    inp = np.random.rand(data_size,dim)
    y_core = np.ones(data_size)

    inp_re = np.random.rand(0,dim)
    y_re = np.ones(0)

    # R, dist_re, dist_core = MEB(inp, y_core, inp_re, y_re, data_size, 0, theta, 1.0, 'linear')
    # R, dist_re, dist_core = MEB(inp, y_core, inp_re, y_re, data_size, 0, theta, 1.0, 'rbf', 0.5)
    #
    # print('Smallest R is '+ str(R))
    # print ('dist_core is ' + str(dist_core))
    # print ('dist_re is ' + str(len(dist_re)))


#!/usr/bin/env python
import math
import sys
import time
import pybullet as p
from time import sleep

class Simulation:
    def __init__(self, directory):
        self.t = 0
        self.dt = 0.001

        # Instanciation de Bullet
        physicsClient = p.connect(p.GUI)
        p.setGravity(0, 0, -10)

        # Chargement du sol
        planeId = p.loadURDF(directory+'environment/plane.urdf')

        # Chargement du robot
        cubeStartPos = [0, 0, 0.0]
        cubeStartOrientation = p.getQuaternionFromEuler([0, 0, 0])
        self.robot = p.loadURDF(directory+"/robot.urdf",
                            cubeStartPos, cubeStartOrientation)

        # Engine parameters
        p.setPhysicsEngineParameter(fixedTimeStep=self.dt)
        p.setRealTimeSimulation(1)
        # p.setPhysicsEngineParameter(numSolverIterations=5)
        # p.setPhysicsEngineParameter(numSubSteps=1)

        # Retrieving joints and frames
        self.joints = {}
        self.frames = {}

        # Collecting the available joints
        for k in range(p.getNumJoints(self.robot)):
            jointInfo = p.getJointInfo(self.robot, k)
            name = jointInfo[1].decode('utf-8')
            if '_fixing' not in name:
                if '_frame' in name:
                    self.frames[name] = k
                else:
                    self.joints[name] = k

        print('* Found '+str(len(self.joints))+' DOFs')
        print('* Found '+str(len(self.frames))+' frames')

    def getFrames(self):
        frames = {}

        for name in self.frames.keys():
            jointState = p.getLinkState(self.robot, self.frames[name])
            pos = jointState[0]
            orientation = p.getEulerFromQuaternion(jointState[1])
            frames[name] = [pos, orientation]

        return frames

    def setJoints(self, joints):
        for name in joints.keys():
            if name in self.joints:
                p.setJointMotorControl2(
                    self.robot, self.joints[name], p.POSITION_CONTROL, joints[name])
            else:
                raise Exception("Can't find joint %s" % name)

    def getJoints(self):
        return self.joints.keys()

    def execute(self):
        while True:
            self.tick()

    def tick(self):
        self.t += self.dt
        p.stepSimulation()


import sys
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QLineEdit, QPushButton, QTextEdit
from PyQt5.QtCore import QCoreApplication, Qt, QSize, pyqtSignal, pyqtSlot, QObject
from PyQt5.QtGui import QPixmap, QFont, QIcon
from SystemModule import User
from SystemModule import img_folder
from SystemModule import Date
import os

class MainWindow (QWidget):

   def __init__(self):
      super().__init__()
      self.setWindowTitle('Activity Manager')
      self.setGeometry(100, 100, 480, 500)

      self.user = None
      self.menu = Menu(self)
      self.sign_in_window = EnterName(self)
      self.init_gui()

   def keyPressEvent(self, event):
      key_code = event.key()
      if key_code == 16777220:
         if self.sign_in_window.active:
            self.sign_in_window.press_enter()

   def mousePressEvent(self, event):
      x = event.pos().x()
      y = event.pos().y()
      if self.menu.active:
         self.menu.press_mouse(x, y)

   def init_gui(self):
      self.show()
      self.sign_in_window.show()

   def enter_main_menu(self):
      self.sign_in_window.hide()
      self.menu.set()

   def close_app(self):
      pass

   def open_history(self):
      self.history_viewer = HistoryViewer()

class WindowManager:

   def __init__(self, main_window):
      self.main_window = main_window
      self.objects = []
      self.active = False
      self.init_gui()

   def init_gui(self):
      pass

   def width(self):
      return self.main_window.width()

   def show(self):
      self.active = True
      for obj in self.objects:
         obj.show()

   def hide(self):
      self.active = False
      for obj in self.objects:
         obj.hide()

class EnterName (WindowManager):

   def init_gui(self):
      self.title = QLabel("Welcome to ActivityManager!", self.main_window)
      font = QFont()
      font.setPointSize(17)
      self.title.setFont(font)
      self.title.move(15, 10)

      self.sign_in_msg = QLabel("Username:", self.main_window)
      font = QFont()
      font.setPointSize(12)
      self.sign_in_msg.setFont(font)
      self.sign_in_msg.move(20, 60)
      self.sign_in_box = QLineEdit(self.main_window)
      font = QFont()
      font.setPointSize(10)
      self.sign_in_box.setFont(font)
      self.sign_in_box.setFixedWidth(280)
      self.sign_in_box.move(20, 100)
      self.button_sign_in = QPushButton("ENTER", self.main_window)
      self.button_sign_in.clicked.connect(self.enter_username)
      font = QFont()
      font.setPointSize(8)
      self.button_sign_in.setFont(font)
      self.button_sign_in.setFixedHeight(self.sign_in_box.height())
      self.button_sign_in.move(335, 100)

      self.new_acc_msg = QLabel("Create new account:", self.main_window)
      font = QFont()
      font.setPointSize(12)
      self.new_acc_msg.setFont(font)
      self.new_acc_msg.move(20, 143)
      self.new_acc_box = QLineEdit(self.main_window)
      font = QFont()
      font.setPointSize(10)
      self.new_acc_box.setFont(font)
      self.new_acc_box.setFixedWidth(280)
      self.new_acc_box.move(20, 183)
      self.button_new_acc = QPushButton("ENTER", self.main_window)
      self.button_new_acc.clicked.connect(self.enter_new_account)
      font = QFont()
      font.setPointSize(8)
      self.button_new_acc.setFont(font)
      self.button_new_acc.setFixedHeight(self.new_acc_box.height())
      self.button_new_acc.move(335, 183)

      calendar_img = QPixmap(os.path.join("Interface", "calendar.png"))
      calendar_img = calendar_img.scaled(300, 300, Qt.KeepAspectRatio)
      self.calendar_label = QLabel(self.main_window)
      self.calendar_label.setPixmap(calendar_img)
      self.calendar_label.move(80, 210)

      self.objects.append(self.title)
      self.objects.append(self.sign_in_msg)
      self.objects.append(self.sign_in_box)
      self.objects.append(self.button_sign_in)
      self.objects.append(self.new_acc_msg)
      self.objects.append(self.new_acc_box)
      self.objects.append(self.button_new_acc)
      self.objects.append(self.calendar_label)

      self.hide()

   def process_new_username(self, username):
      if not User.not_used_username(username):
         self.error = ExistentUserError()
         print("ya usado")
      elif not User.well_written_username(username):
         self.error = InvalidNameError()
         print("no es valido")
      else:
         User.load_new_user(username)
         self.main_window.user = User.current_user
         self.main_window.enter_main_menu()

   def process_old_username(self, username):
      if User.valid_old_username(username):
         print("usuario valido")
         User.load_user(username)
         self.main_window.user = User.current_user
         self.main_window.enter_main_menu()
      else:
         self.error = InexistentUserError()
         print("no hay un usuario llamado asi")

   def enter_new_account(self):
      print("new")
      username = self.new_acc_box.text()
      print(username)
      self.process_new_username(username)

   def enter_username(self):
      print("old")
      username = self.sign_in_box.text()
      print(username)
      self.process_old_username(username)

   def press_enter(self):
      print("enter was pressed")
      new_username = self.new_acc_box.text()
      old_username = self.sign_in_box.text()
      if new_username == "" and old_username != "":
         self.process_old_username(old_username)
      elif new_username != "" and old_username == "":
         self.process_new_username(new_username)
      else:
         print("invalid enter")

class ErrorMessage (QWidget):

   def __init__(self):
      super().__init__()
      self.setWindowTitle('Error')
      self.setGeometry(100, 100, 300, 200)
      self.init_gui()

   def init_gui(self):
      self.message = QLabel(self)
      self.message.move(20, 20)
      font = QFont()
      font.setPointSize(10)
      self.message.setFont(font)

      self.close_button = QPushButton("Close", self)
      self.close_button.clicked.connect(self.close_window)
      self.close_button.move(give_position(self.width(), self.close_button.width()), 135)
      self.close_button.show()
      self.show()

   def close_window(self):
      self.close()

   def keyPressEvent(self, event):
      key_code = event.key()
      if key_code == 16777220:
         self.close_window()

class InvalidNameError (ErrorMessage):

   def init_gui(self):
      super().init_gui()
      self.message.setText("This username is not valid.\nUsernames can only contain\nletters (a-z).")
      self.message.resize(self.message.sizeHint())

class InexistentUserError (ErrorMessage):

   def init_gui(self):
      super().init_gui()
      self.message.setText("That username does not\nexist!")
      self.message.resize(self.message.sizeHint())

class ExistentUserError (ErrorMessage):

   def init_gui(self):
      super().init_gui()
      self.message.setText("Unfortunately, that\nusername is already taken!")
      self.message.resize(self.message.sizeHint())

class Menu (WindowManager):

   valid_entry_length = 100

   def init_gui(self):

      self.title = QLabel("Menu", self.main_window)
      font = QFont()
      font.setPointSize(17)
      self.title.setFont(font)
      self.title.move(15, 10)

      """
      self.info_img = QPixmap(os.path.join("Interface", "Info_icon.png"))
      self.info_img = self.info_img.scaled(25, 25, Qt.KeepAspectRatio)
      self.more_information = QLabel(self.main_window)
      self.more_information.setPixmap(self.info_img)
      self.more_information.move(110, 20)
      """

      self.instruction = QLabel("To register your progress enter a comment bellow and \nhit SUBMIT!", self.main_window)
      font = QFont()
      font.setPointSize(12)
      self.instruction.setFont(font)
      self.instruction.setFixedWidth(445)
      self.instruction.move(15, 65)

      calendar_img = QPixmap(os.path.join("Interface", "calendar.png"))
      calendar_img = calendar_img.scaled(75, 75, Qt.KeepAspectRatio)
      calendar_icon = QIcon()
      calendar_icon.addPixmap(calendar_img)
      self.change_date_button = QPushButton(self.main_window)
      self.change_date_button.clicked.connect(self.change_date)
      self.change_date_button.setIcon(calendar_icon)
      self.change_date_button.resize(self.change_date_button.sizeHint())
      self.change_date_button.move(15, 121)

      self.date_obj = Date.get_today()
      self.date = QLabel("Date: " + str(self.date_obj), self.main_window)
      font = QFont()
      font.setPointSize(12)
      self.date.setFont(font)
      self.date.move(50, 121)

      self.enter_text = MyTextEditor(self)
      self.enter_text.setFont(font)
      self.enter_text.setFixedWidth(445)
      self.enter_text.setFixedHeight(175)
      self.enter_text.move(15, 165)

      font = QFont()
      font.setPointSize(11)

      self.submit_button = QPushButton("Submit", self.main_window)
      self.submit_button.clicked.connect(self.submit)
      self.submit_button.setFont(font)
      self.submit_button.resize(self.submit_button.sizeHint())
      self.submit_button.move(give_position(self.width(), self.submit_button.width()), 370)

      self.edit_button = QPushButton("Submit", self.main_window)
      self.edit_button.setText("Edit")
      self.edit_button.clicked.connect(self.edit)
      self.edit_button.setFont(font)
      self.edit_button.resize(self.edit_button.sizeHint())
      self.edit_button.move(give_position(self.width(), self.edit_button.width()), 370)
      self.edit_button.hide()

      self.open_history_button = QPushButton("  View History  ", self.main_window)
      self.open_history_button.clicked.connect(self.open_history)
      self.open_history_button.setFont(font)
      self.open_history_button.resize(self.open_history_button.sizeHint())
      self.open_history_button.move(give_position(self.width(), self.open_history_button.width()), 430)

      font = QFont()
      font.setPointSize(13)
      self.notice = QLabel("Entry already posted.", self.main_window)
      self.notice.setStyleSheet('color: red')
      self.notice.setFont(font)
      self.notice.move(150, 14)
      self.notice.hide()

      font = QFont()
      font.setPointSize(12)
      self.rank = QLabel("Rank #", self.main_window)
      self.rank.setFont(font)
      self.rank.setFixedWidth(300)
      self.rank.move(17, 430)

      font = QFont()
      font.setPointSize(10)
      self.char_count = QLabel("0/" + str(Menu.valid_entry_length), self.main_window)
      self.char_count.setFont(font)
      self.char_count.move(405, 347)
      # que cambie de posicion según crece el primer numero

      self.objects.append(self.title)
      # self.objects.append(self.more_information)
      self.objects.append(self.instruction)
      self.objects.append(self.enter_text)
      self.objects.append(self.submit_button)
      self.objects.append(self.open_history_button)
      self.objects.append(self.rank)
      self.objects.append(self.char_count)
      self.objects.append(self.change_date_button)
      self.objects.append(self.date)

      self.hide()

   def set(self):
      self.hide()
      self.open = self.main_window.user.is_box_open()
      if self.rank.text() == "Rank #":
         self.rank.setText("Rank #" + self.main_window.user.get_rank())
      if not self.open:
         self.enter_text.setText(self.main_window.user.get_last_entry())
         self.set_char_count()
         if not (self.notice in self.objects):
            self.objects.remove(self.submit_button)
            self.objects.append(self.notice)
            self.objects.append(self.edit_button)
            self.rank.setText("Rank #" + self.main_window.user.get_rank())
      self.show()

   def set_char_count(self):
      text = self.enter_text.toPlainText()
      self.char_count.setText(str(len(text)) + "/" + str(Menu.valid_entry_length))
      self.char_count.resize(self.char_count.sizeHint())
      if len(text) <= Menu.valid_entry_length:
         self.char_count.setStyleSheet('color: black')
      else:
         self.char_count.setStyleSheet('color: red')

   def press_key(self):
      text = self.enter_text.toPlainText()
      #print(text, len(text))
      if len(text) <= Menu.valid_entry_length:
         self.enter_text.setStyleSheet('color: black')
      else:
         self.enter_text.setStyleSheet('color: red')
      self.set_char_count()

   def submit(self):
      print("submit")
      text = self.enter_text.toPlainText()
      if len(text) <= Menu.valid_entry_length:
         self.main_window.user.add_entry(text, self.date_obj)
         self.set()
      else:
         print("too long!")

   def edit(self):
      print("edit")
      text = self.enter_text.toPlainText()
      if len(text) <= Menu.valid_entry_length:
         self.main_window.user.edit_entry(text, self.date_obj)
         self.set()
      else:
         print("too long!")

   def open_history(self):
      print("open history")
      self.main_window.open_history()

   def open_info(self):
      print("info requested")
      self.info = Info()

   def change_date(self):
      self.selector = SelectDate(self)

   def press_mouse(self, x, y):
      """
      info_x = self.more_information.x()
      info_y = self.more_information.y()
      #print(info_x, info_y)
      width = self.info_img.width()
      if x >= info_x and x < (info_x + width) and y >= info_y and y < (info_y + width):
         self.open_info()
         pass
      else:
         pass
      """
      pass

   def update_date(self):
      entries = User.current_user.history[::-1]
      dict_entries = {}
      date_list = []
      for entry in entries:
         dict_entries[str(entry.date)] = entry
      if str(self.date_obj) in dict_entries.keys():
         entry = dict_entries[str(self.date_obj)]
         self.enter_text.setText(entry.message)
         self.notice.show()
         self.edit_button.show()
         self.submit_button.hide()
         if not (self.notice in self.objects):
            self.objects.append(self.notice)
      else:
         self.enter_text.setText("")
         self.notice.hide()
         self.submit_button.show()
         self.edit_button.hide()
         if self.notice in self.objects:
            self.objects.remove(self.notice)

class Info (QWidget):

   def __init__(self):
      super().__init__()
      self.setWindowTitle('More information')
      self.setGeometry(100, 100, 300, 400)
      self.init_gui()

   def init_gui(self):

      font = QFont()
      font.setPointSize(10)
      text = "this it\nso much\ninfo i can't belive it"
      self.information = QLabel(text, self)
      self.information.setFont(font)
      self.information.resize(self.information.sizeHint())
      self.information.move(20, 20)
      self.information.show()

      self.close_button = QPushButton("Close", self)
      self.close_button.clicked.connect(self.close_window)
      self.close_button.move(give_position(self.width(), self.close_button.width()), 300)
      self.close_button.show()

      self.show()

   def close_window(self):
      self.close()

   def keyPressEvent(self, event):
      key_code = event.key()
      if key_code == 16777220:
         self.close_window()

class SelectDate(QWidget):

   def __init__(self, manager):
      super().__init__()
      self.setWindowTitle('Select Date')
      self.setGeometry(100, 100, 170, 120)
      self.manager = manager
      self.init_gui()

   def init_gui(self):
      self.day_text = QLabel("Day:", self)
      self.day_text.move(10, 10)
      self.day_text.show()

      self.day_box = DayEditor(self)
      self.day_box.setFixedWidth(65)
      self.day_box.move(65, 10)
      self.day_box.show()

      self.month_text = QLabel("Month:", self)
      self.month_text.move(10, 40)
      self.month_text.show()

      self.month_box = MonthEditor(self)
      self.month_box.setFixedWidth(65)
      self.month_box.move(65, 40)
      self.month_box.show()

      self.select_button = QPushButton("Select", self)
      self.select_button.resize(self.select_button.sizeHint())
      print(self.width())
      print(self.select_button.width())
      print(give_position(self.width(), self.select_button.width()))
      self.select_button.move(give_position(self.width(), self.select_button.width()), 80)
      self.select_button.clicked.connect(self.select_date)
      self.select_button.show()

      self.show()

   def select_date(self):
      if self.is_a_date_selected():
         print("date selected")
         day = int(self.day_box.text())
         month = int(self.month_box.text())
         self.manager.date_obj = Date(day, month)
         self.manager.date.setText("Date: " + str(self.manager.date_obj))
         self.manager.update_date()
         self.close()
      else:
         print("Invalid date.")

   def keyPressEvent(self, event):
      key_code = event.key()
      if key_code == 16777220:
         self.select_date()
         self.close()

   def is_a_date_selected(self):
      day = self.day_box.text()
      month = self.month_box.text()
      if is_number(day) and is_number(month):
         if Date.is_day(int(day)) and Date.is_month(int(month)):
            if Date.is_a_date(int(day), int(month)):
               return True
      return False

class DayEditor (QLineEdit):

   def __init__(self, widget):
      super().__init__(widget)
      #self.editor = widget.day_box

   def keyPressEvent(self,e):
      #print('key pressed')
      super().keyPressEvent(e)
      text = self.text()
      if len(text) > 0:
         if not is_number(text):
            self.setStyleSheet('color: red')
         else:
            number = int(text)
            print(number)
            if Date.is_day(number):
               self.setStyleSheet('color: black')
            else:
               self.setStyleSheet('color: red')

class MonthEditor (QLineEdit):

   def __init__(self, widget):
      super().__init__(widget)
      #self.editor = widget.month_box

   def keyPressEvent(self,e):
      #print('key pressed')
      super().keyPressEvent(e)
      text = self.text()
      if len(text) > 0:
         if not is_number(text):
            self.setStyleSheet('color: red')
         else:
            number = int(text)
            if Date.is_month(number):
               self.setStyleSheet('color: black')
            else:
               self.setStyleSheet('color: red')

class MyTextEditor(QTextEdit):

   def __init__(self, window_manager):
      super().__init__(window_manager.main_window)
      self.window_manager = window_manager

   def keyPressEvent(self,e):
      #print('key pressed')
      super().keyPressEvent(e)
      self.window_manager.press_key()

class HistoryViewer (QWidget):

   horizontal_border = 15
   vertical_difference = 12

   def __init__(self):
      super().__init__()
      self.setWindowTitle('History')
      self.setGeometry(50, 50, 550, 600)
      self.entries = User.current_user.history[::-1]
      self.pages = []
      self.current_page = 1
      self.init_gui()

   def init_gui(self):
      self.title = QLabel("History", self)
      font = QFont()
      font.setPointSize(17)
      self.title.setFont(font)
      self.title.move(15, 10)
      self.title.show()
      self.show()

      self.prev_button = QPushButton("<<", self)
      self.prev_button.clicked.connect(self.prev)
      self.prev_button.move(280, 550)
      #self.prev_button.show()

      self.next_button = QPushButton(">>", self)
      self.next_button.clicked.connect(self.next)
      self.next_button.move(400, 550)
      #self.next_button.show()

      self.labels = []
      font = QFont()
      font.setPointSize(10)

      self.dict_entries = {}
      self.date_list = []
      for entry in self.entries:
         self.dict_entries[str(entry.date)] = entry
         self.date_list.append(entry.date)
      self.date_list.sort()

      for date in self.date_list:
         entry = self.dict_entries[str(date)]
         label = QLabel(entry.text(), self)
         label.setFont(font)
         label.resize(label.sizeHint())
         self.labels.append(label)

      self.load_pages()
      self.set_page()

   def load_pages(self):
      for i in range(0, len(self.labels)):
         current = self.labels[i]
         if len(self.pages) == 0:
            new = Page(self)
            self.pages.append(new)
         if self.pages[len(self.pages) - 1].enough_space(current):
            self.pages[len(self.pages) - 1].add(current)
         else:
            new = Page(self)
            self.pages.append(new)
            self.pages[len(self.pages) - 1].add(current)

   def set_page(self):
      for label in self.labels:
         label.hide()

      last_border = 10 + self.title.height() + 10
      entries = self.pages[self.current_page - 1].get_entries()
      for entry in entries:
         entry.move(HistoryViewer.horizontal_border, last_border + HistoryViewer.vertical_difference)
         entry.show()
         last_border += entry.height() + HistoryViewer.vertical_difference

      if self.current_page > 1:
         self.prev_button.show()
      else:
         self.prev_button.hide()
      if self.current_page < len(self.pages):
         self.next_button.show()
      else:
         self.next_button.hide()

   def next(self):
      if self.current_page < len(self.pages):
         self.current_page += 1
         self.set_page()

   def prev(self):
      if self.current_page > 1:
         self.current_page -= 1
         self.set_page()

   def keyPressEvent(self, event):
      print("se apretó algo")
      key_code = event.key()
      print(key_code)

class Page:

   max_border = 525

   def __init__(self, viewer):
      self.entries = []
      self.viewer = viewer

   @property
   def height(self):
      x = 10 + self.viewer.title.height() + 10
      for entry in self.entries:
         x += entry.height() + HistoryViewer.vertical_difference
      return x

   def get_entries(self):
      return self.entries

   def enough_space(self, new_label):
      if len(self.entries) == 0:
         return True
      label_height = new_label.height()
      if self.height + label_height <= Page.max_border:
         return True
      else:
         return False

   def add(self, label):
      self.entries.append(label)

def give_position(window_width, object_width):
   half_window = window_width//2
   half_obj = object_width//2
   #print(window_width)
   #print(object_width)
   #print(half_window)
   #print(half_obj)
   #print(half_window - half_obj)
   return half_window - half_obj

def is_number(text):
   for char in text:
      if char in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]:
         pass
      else:
         return False
   return True

if __name__ == '__main__':
   def hook(type, value, traceback):
      print(type)
      print(traceback)
   sys.__excepthook__ = hook

   app = QApplication(sys.argv)
   main_window = MainWindow()
   sys.exit(app.exec_())


import subprocess
import os
import time

import uiautomator2 as u2
from tool import get_activity

def launch_app(apk_url, package_name, activity_name):
    print("设备root")
    os.system("adb root")
    time.sleep(2)

    launch_activity = get_activity.get_launch_activity(apk_url)
    if launch_activity == '':
        return

    print("启动" + package_name)
    if package_name not in activity_name:
        activity_name = package_name + activity_name
    # cmd = "adb shell am start -n " + package_name + '/' + activity_name.split(package_name)[1].replace(activity_name.split(package_name)[1].split('.')[-1], 'MainActivity')
    cmd = "adb shell am start -S -n " + package_name + '/' + launch_activity
    console_result = subprocess.check_output(cmd, shell=True)
    time.sleep(3)
    print(console_result.decode("utf8"))

def launch_act(package_name, activity_name):
    # 这里如果activity正确但是fragment不对就不会变，所以需要重新启动activity哦
    # if 'MainActivity' not in activity_name:
        # 先启动app
        # print("启动" + package_name)
        # if package_name not in activity_name:
        #     activity_name = package_name + activity_name
        # 先关闭app
        # cmd = "adb shell am force-stop " + package_name
        # console_result = subprocess.check_output(cmd, shell=True)
        # print(console_result.decode("utf8"))
        # time.sleep(2)
        # 再冷启动活动
    cmd = "adb shell am start -S -n " + package_name + '/' + activity_name
    console_result = subprocess.check_output(cmd, shell=True)
    time.sleep(4)
    print(console_result.decode("utf8"))
    if get_activity.get_current_package() != package_name:
        # 这里可以调取StoryDroid的启动方法
        return False
    return True
    # else:
    #     # 启动Main
    #     cmd = "adb shell am start -S -n " + package_name + '/' + activity_name.split(package_name)[1]
    #     console_result = subprocess.check_output(cmd, shell=True)
    #     time.sleep(3)
    #     print(console_result.decode("utf8"))

# 这个代码后期要改变，因为不一定是activity
def lead_to_function(package_name, activity_name, search_action_list):
    '''
    print("回到功能入口")
    # 启动功能活动，其中活动名要去掉其中的包名，命令为 “adb shell am start -n {包名 / 活动名}”
    # adb需要自己添加路径？？这里要该到自己的adb去
    cmd = "adb shell am start -n " + package_name + '/' + activity_name.replace(package_name, '')
    console_result = subprocess.check_output(cmd, shell=True)
    print(console_result.decode("utf8"))
    '''
    device = u2.connect()
    device.press("back")
    time.sleep(0.5)
    launch_act(package_name, activity_name)
    for search_result_action in search_action_list:
        try:
            exec(search_result_action)
        except:
            device.press("back")
            lead_to_function(package_name, activity_name, search_action_list)
        time.sleep(1)

def perform_the_action(action_list):
    # 执行action跳转到制定entry
    device = u2.connect()
    print("执行的跳转活动：", action_list)
    if len(action_list) != 0:
        for action in action_list:
            print(action)
            exec(action)
            time.sleep(0.7)

def to_entry(action_list, package_name, activity_name):
    '''
    # 先跳转到特定的activity
    if 'MainActivity' not in activity_name:
        cmd = "adb shell am start -n " + package_name + '/' + activity_name.replace(package_name, '')
        console_result = subprocess.check_output(cmd, shell=True)
        print(console_result.decode("utf8"))
        # 执行action跳转到指定entry
        perform_the_action(action_list)
    else:
        print(package_name, activity_name)
        # 不知道为什么，MainActivity不能冷启动
        cmd = "adb shell am start -n " + package_name + '/' + activity_name.replace(package_name, '')
        console_result = subprocess.check_output(cmd, shell=True)
        time.sleep(2)
        print(console_result.decode("utf8"))

        cmd = "adb shell am force-stop " + package_name
        console_result = subprocess.check_output(cmd, shell=True)
        time.sleep(2)
        print(console_result.decode("utf8"))

        cmd = "adb shell am start -n " + package_name + '/' + activity_name.replace(package_name, '')
        console_result = subprocess.check_output(cmd, shell=True)
        time.sleep(2)
        print(console_result.decode("utf8"))
    '''
    launch_act(package_name, activity_name)
    perform_the_action(action_list)

if __name__ == '__main__':
    # lead_to_function("gov.anzong.androidnga", "gov.anzong.androidnga.activity.SettingsActivity")
    # launch_app("gov.anzong.androidnga", "gov.anzong.androidnga.activity.SettingsActivity")
    # to_entry(["device(text='USER AGENT').click()", "device(text='CANCEL').click()"], "gov.anzong.androidnga", "gov.anzong.androidnga.activity.SettingsActivity")
    to_entry([""], "gov.anzong.androidnga", "gov.anzong.androidnga.activity.MainActivity")


import cv2 as cv2
import numpy as np
import pandas as pd
from PIL import Image
import os
import SimpleITK as sitk
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from pathlib import Path
import argparse
import random
import numpy as np
import matplotlib.cm as cm
import glob

import re

import matplotlib.pyplot as plt
from matplotlib.cbook import get_sample_data
from skimage.transform import resize
import torch

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    '''
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]

if __name__ == "__main__":
    # dataset = 2
    # bag_num = [1000, 200]
    dataset = 2
    bag_num = [1000, 200]
    bag_size = 8
    MIL = 1
    pos_ratio = 0.5

    bag_folder = '/Data3/GCA_Demo/Dataset%d_Bag_%d_%d_%d' % (dataset, bag_num[0],bag_size, MIL)

    data_folder = ['/Data3/GCA_Demo/Dataset%d_demo' % (dataset),'/Data3/GCA_Demo/Dataset%d_demo_val' % (dataset)]

    mode = ['Train','Val']
    r = np.random.RandomState(1)

    for mi in range(len(mode)):
        save_root = os.path.join(bag_folder, mode[mi])
        if not os.path.exists(save_root):
            os.makedirs(save_root)

        img_root = data_folder[mi]
        now_bag_num = int(bag_num[mi])

        for bi in range(now_bag_num):
            now_label = np.random.randint(0, 2, 1)[0]
            pos_list = glob.glob(os.path.join(img_root,'1','*size1024.png'))
            neg_list = glob.glob(os.path.join(img_root,'0','*size1024.png'))

            if now_label == 0:
                indices = torch.LongTensor(r.randint(0, len(neg_list), bag_size))

                if bag_size == 1:
                    now_images = [neg_list[indices]]
                else:
                    now_images = list(np.array(neg_list)[indices])

            else:
                if MIL:
                    pos_length = r.randint(1, int(pos_ratio * bag_size), 1)
                else:
                    pos_length = bag_size
                neg_length = bag_size - pos_length

                indices_pos = torch.LongTensor(r.randint(0, len(pos_list), pos_length))
                indices_neg = torch.LongTensor(r.randint(0, len(neg_list), neg_length))

                if len(indices_pos) == 1:
                    now_images_pos = [pos_list[indices_pos]]
                    now_images_neg = list(np.array(neg_list)[indices_neg])
                else:
                    now_images_pos = list(np.array(pos_list)[
                                              indices_pos])  # + list(np.array(self.image_list_class0)[indices_neg])   # self.image_list_class0[indices_neg]
                    now_images_neg = list(np.array(neg_list)[indices_neg])

                now_images = now_images_pos + now_images_neg
                random.shuffle(now_images)

            df = pd.DataFrame(columns = ['img_root', 'class'])
            for ki in range(len(now_images)):
                df.loc[ki] = [now_images[ki], now_label]

            df.to_csv(os.path.join(save_root, 'bag_%d.csv' % (bi)), index = False)


from django.shortcuts import render,get_object_or_404,redirect, render_to_response
from jocs.models import Joc
from .forms import JocForm
from django.forms import modelform_factory
from django.contrib import messages
from django.conf import settings
from django.contrib.auth.decorators import login_required
# Create your views here.

def index(request):
    jocs= Joc.objects.all();
    ctx={'llista_jocs': jocs}
    return render(request, "jocs/index.html",ctx)

def joc(request,id_joc):
    joc = get_object_or_404(Joc,pk=id_joc)
    ctx={'joc': joc}
    return render(request,"jocs/joc.html",ctx)

@login_required (login_url='jocs:index')
def crear_joc(request):
    if request.method == 'POST':
        form = JocForm(request.POST,request.FILES)

        if form.is_valid():
           nom= form.cleaned_data['nom']
           preuE=form.cleaned_data['preuE']
           preuG=form.cleaned_data['preuG']
           descripcio=form.cleaned_data['descripcio']
           imatge=form.cleaned_data['imatge']
           #creem l'objecte Joc amb les dades rebudes
           Joc.objects.create( nom=nom,
                                        preuE=preuE,
                                        preuG=preuG,
                                        descripcio=descripcio,
                                        imatge=imatge,)
           messages.info(request,"joc pujat correctament")
           return redirect("usuaris:menu_usuari")
    else:
        nova_id=Joc.objects.latest('id'); #Haig de sumar un, o baixar el contador general
        nova_id.id += 1
        form= JocForm()

    for f in form.fields:
        form.fields[f].widget.attrs['class'] = 'formulari'

    return render (request, 'jocs/crear_joc.html', {'form': form, "nova_id":nova_id} )

@login_required (login_url='jocs:index')
def editar_joc(request, id_joc):
    EditForm = modelform_factory(Joc, fields=('nom','preuE','preuG','imatge','descripcio'))
    unEdit = Joc()

    #comprovem que existeix l'oferta_disc
    if id_joc:
        unEdit = get_object_or_404(Joc, pk=id_joc)

    if request.method == 'POST':
        form = EditForm (request.POST,request.FILES, instance= unEdit)
        if form.is_valid():
           form.save()
           messages.info(request,"Joc canviat correctament")
           ctx={'joc': unEdit}
           return render(request,"jocs/joc.html",ctx)
    else:
        form= EditForm (instance = unEdit)

    for f in form.fields:
        form.fields[f].widget.attrs['class'] = 'formulari'

    form.fields['nom'].widget.attrs['placeholder']="Nom"
    form.fields['descripcio'].widget.attrs['placeholder']="Descripcio"
    form.fields['preuE'].widget.attrs['placeholder']="PreuE"
    form.fields['preuG'].widget.attrs['placeholder']="PreuG"

    return render (request, 'jocs/editar_joc.html', {'form': form} )

@login_required (login_url='jocs:index')
def eliminar_joc(request,id_joc=None):

    if request.method == 'POST':
        joc = get_object_or_404(Joc, pk=id_joc);
        if (id_joc):
            joc.delete()
            return redirect('usuaris:menu_usuari')
    else:
        return render(request, 'jocs/eliminar_joc.html', {'Joc': Joc.objects.get(pk=id_joc)})

from django.db.models import Q

def search(request):
    query = request.GET.get('q', '')
    if query:
        qset = (
            Q(nom__icontains=query)
        )
        results = Joc.objects.filter(qset).distinct()
    else:
        results = []
    return render( request, "jocs/productes.html",
                                { "llista_jocs": results,
                                   "query": query }
                               )

from django.core.urlresolvers import reverse
from django.http import *
from django.contrib import messages
from django.core.management import call_command
import datetime
import sys

@login_required (login_url='jocs:index')
def fer_backups(request, id_backup):
    if (request.user.usuari.admin):
        objectiu = ''
        if id_backup == '1':
            objectiu = 'comandes'
        if id_backup == '2':
            objectiu = 'usuaris'
        if id_backup == '3':
            objectiu = 'jocs'
        sysout = sys.stdout
        nomFitxer = "backups/media/bdd-Backup" + str(datetime.datetime.now()).replace(" ","").replace(":","-")+".xml"
        sys.stdout = open (nomFitxer, 'w')
        call_command('dumpdata',objectiu,indent=2,format='xml')
        sys.stdout = sysout
        return HttpResponseRedirect(reverse('jocs:index'))
    else:
        return HttpResponseRedirect(reverse('jocs:productes'))


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

import streamlit as st
from kiara import Kiara
from kiara.data import Value
from kiara.data.registry import DataRegistry
from kiara.workflow.kiara_workflow import KiaraWorkflow
from streamlit.delta_generator import DeltaGenerator

if typing.TYPE_CHECKING:
    pass

IMPORT_OPTION = "-- import file --"

# mypy: ignore-errors

class KiaraComponentMixin(object):
    @classmethod
    def create_components_class(
        cls, name: str, *mixins: typing.Iterable[typing.Type["KiaraComponentMixin"]]
    ):

        cls = type(name, tuple(mixins), {})
        return cls

    def __init__(self, temp_dir: str, **kwargs):

        self._temp_dir: str = temp_dir
        self._kiara: typing.Optional[Kiara] = None

    @property
    def temp_dir(self):
        return self._temp_dir

    @property
    def kiara(self) -> Kiara:

        if self._kiara is None:
            raise Exception("Kiara object not set (yet).")
        return self._kiara

    @property
    def data_store(self) -> DataRegistry:
        return self.kiara.data_store

    @property
    def data_registry(self) -> DataRegistry:
        return self.kiara.data_registry

class KiaraBaseWidgetsMixin(KiaraComponentMixin):
    def value_data(self, value_id: str, container: DeltaGenerator = st):

        value: Value = self.data_store.get_value_obj(value_id, raise_exception=True)
        value_data = value.get_value_data()
        if value.type_name == "table":
            container.dataframe(value_data.to_pandas())
        else:
            container.write(value_data)

class KiaraWorkflowWidgetsMixin(KiaraComponentMixin):
    def workflow_status(self, workflow_alias: str, container: DeltaGenerator = st):

        workflow: KiaraWorkflow = self.get_workflow(workflow_alias)

        state = workflow.get_current_state()
        for step_id, status in state.step_states.items():
            container.markdown(f" - *{step_id}*: {status.name}")

    # def create_workflow_inputs_container(self, workflow_alias: str, container: DeltaGenerator=st):
    #
    #     workflow = self.get_workflow(workflow_alias=workflow_alias)
    #     self.create_input_fields(value_set=workflow.inputs, container=container)
    #
    # def create_steps_details(self, workflow_alias: str, container: DeltaGenerator=st):
    #
    #     workflow = self.get_workflow(workflow_alias=workflow_alias)
    #     for step_id, desc in workflow.steps.steps.items():
    #
    #         exp = container.expander(f"Step: {step_id}")
    #         exp.write(desc.step.module.module_instance_doc)
    #         inputs = workflow.pipeline.get_step_inputs(step_id)
    #         outputs = workflow.pipeline.get_step_outputs(step_id)
    #         exp.write("inputs")
    #         self.create_output_fields(inputs, container=exp)
    #         exp.write("outputs")
    #         self.create_output_fields(outputs, container=exp)
    #
    # def create_workflow_outputs_container(self, workflow_alias: str, container: DeltaGenerator=st):
    #
    #     workflow = self.get_workflow(workflow_alias)
    #     self.create_output_fields(workflow.outputs, container=container)

# class Other(object):
#     def create_data_selection(self, value_type: str, container: DeltaGenerator = str):
#         def transform(value_id: str):
#             if value_id == IMPORT_OPTION:
#                 return None
#             return self.data_store.get_value_obj(value_id)
#
#         import_value = container.checkbox(f"Import new {value_type}")
#         if not import_value:
#             all_files = self.data_store.find_all_values_of_type("file")
#             aliases = set()
#             for f in all_files.values():
#                 aliases.update(f.alias_names)
#
#             selected_data = container.selectbox(
#                 f"Select '{value_type}' dataset", sorted(aliases)
#             )
#
#             if selected_data:
#                 value_md = self.data_store.get_value_info(selected_data)
#                 _md = value_md.metadata.get(value_md.value_type, {}).get(
#                     "metadata_item", {}
#                 )
#                 md_str = "| key | value |\n| --- | --- |\n"
#                 for k, v in _md.items():
#                     md_str = md_str + f"| {k} | {v} |\n"
#                 exp = container.expander("Metadata")
#                 exp.markdown(md_str)
#                 select_button = container.button("Select")
#                 if select_button:
#                     new_data = selected_data
#                     return new_data, transform
#
#             return None
#
#         else:
#             with container.container():
#
#                 file_type = None
#                 multiple = False
#
#                 container.write("Import into kiara data-store")
#                 uploaded_files = st.file_uploader(
#                     "Add files", type=file_type, accept_multiple_files=multiple
#                 )
#                 value = ""
#                 if uploaded_files and not multiple:
#                     value = uploaded_files.name
#                 alias = container.text_input("Alias", value=value)
#                 import_button = container.button("Import")
#
#             if import_button:
#                 if not uploaded_files:
#                     container.warning("No files selected")
#                     return None
#
#                 if not alias:
#                     container.warning("No alias provided")
#                     return None
#
#                 value_id = self.onboard_file(uploaded_files, aliases=[alias])
#                 container.info(f"Value '{alias}' (value_id: {value_id}) imported.")
#
#     def create_input_field(
#         self, field_name: str, value: Value, container: DeltaGenerator = str
#     ):
#
#         func_name = f"create_input_field_{value.type_name}"
#         if not hasattr(self, func_name):
#             raise Exception(f"Value type '{value.type_name}' not supported for input.")
#
#         container.write(value.value_schema.doc)
#         func = getattr(self, func_name)
#         default = value.value_schema.default
#         if default in [SpecialValue.NO_VALUE, SpecialValue.NOT_SET]:
#             default = None
#         result = func(
#             field_name=field_name, value=value, default=default, container=container
#         )
#         if isinstance(result, tuple):
#             if len(result) == 1:
#                 new_data = result[0]
#                 callback = None
#             elif len(result) == 2:
#                 new_data = result[0]
#                 callback = result[1]
#             else:
#                 raise Exception(
#                     f"Invalid return value for method '{func_name}. This is a bug."
#                 )
#         else:
#             new_data = result
#             callback = None
#
#         if callback:
#             new_data = callback(new_data)
#
#         if isinstance(new_data, Value):
#             new_data = new_data.get_value_data()
#         try:
#             value.set_value_data(new_data)
#         except Exception as e:
#             print(e)
#
#     def create_input_fields(self, value_set: ValueSet, container: DeltaGenerator = st):
#
#         for idx, (field_name, value) in enumerate(value_set.items()):
#             self.create_input_field(
#                 field_name=field_name, value=value, container=container
#             )
#
#     def create_input_field_boolean(
#         self,
#         field_name: str,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         new_data = container.checkbox(field_name, value=default)
#         return new_data
#
#     def create_input_field_string(
#         self,
#         field_name: str,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         if default is None:
#             default = ""
#         new_data = container.text_input(field_name, value=default)
#         return new_data
#
#     def create_input_field_list(
#         self,
#         field_name: str,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         if default is None:
#             default = []
#         new_data = container.text_area(field_name, value="\n".join(default))
#
#         def transform(text: str):
#             return text.split("\n")
#
#         return new_data, transform
#
#     def create_input_field_file(
#         self,
#         field_name,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         selection, transform = self.create_data_selection(
#             value_type="file", container=container
#         )
#
#         if not selection:
#             return None
#
#         return selection, transform
#
#     def create_output_fields(self, value_set: ValueSet, container: DeltaGenerator = st):
#
#         # columns = container.columns(len(value_set))
#         for idx, (field_name, value) in enumerate(value_set.items()):
#             self.create_output_field(
#                 field_name=field_name, value=value, container=container
#             )
#
#     def create_output_field(
#         self, field_name: str, value: Value, container: DeltaGenerator = st
#     ):
#
#         func_name = f"create_output_field_{value.type_name}"
#         if not hasattr(self, func_name):
#             raise Exception(f"Value type '{value.type_name}' not supported for output.")
#
#         container.write(value.value_schema.doc)
#         func = getattr(self, func_name)
#         if not value.item_is_valid():
#             value = None
#         func(field_name=field_name, value=value, container=container)
#
#     def create_output_field_table(
#         self,
#         field_name: str,
#         value: typing.Optional[Value],
#         container: DeltaGenerator = st,
#     ):
#
#         if value is None:
#             table: pa.Table = pa.Table.from_pydict({})
#         else:
#             table = value.get_value_data()
#         container.dataframe(table.to_pandas())
#
#     def create_output_field_string(
#         self,
#         field_name: str,
#         value: typing.Optional[Value],
#         container: DeltaGenerator = st,
#     ):
#
#         if value is None:
#             text = ""
#         else:
#             text = value.get_value_data()
#         container.write(text)
#
#     def create_output_field_list(
#         self, field_name, value: typing.Optional[Value], container: DeltaGenerator = st
#     ):
#
#         if value is None:
#             list_value = []
#         else:
#             list_value = value.get_value_data()
#
#         container.write(list_value)
#
#     def create_output_field_dict(
#         self, field_name, value: typing.Optional[Value], container: DeltaGenerator = st
#     ):
#
#         if value is None:
#             dict_value = {}
#         else:
#             dict_value = value.get_value_data()
#
#         container.write(dict_value)
#
#     def create_output_field_file(
#         self, field_name, value: typing.Optional[Value], container: DeltaGenerator = st
#     ):
#
#         if value is None:
#             file_value = {}
#         else:
#             file_value = value.get_value_data().dict()
#
#         container.write(file_value)


import telebot
from telebot import types
import os
import codecs
import requests
from functools import wraps
from jinja2 import Template
from datetime import date
from geopy.geocoders import Nominatim
import pycountry
import logging

token = os.getenv('API_BOT_TOKEN')
bot = telebot.TeleBot(token)

commands = {'start': 'Start using chatbot',
            'statistics': 'COVID-19 statistics in the world for today',
             'country': 'COVID-19 statistics in specified country',
            'help': 'Some useful info about chatbot',
            'contacts': 'Developers contacts'}

user_steps = {}
known_users = []

def get_user_step(uid):
    if uid in user_steps:
        return user_steps[uid]
    else:
        known_users.append(uid)
        user_steps[uid] = 0
        return user_steps[uid]

def send_action(action):
    def decorator(func):
        @wraps(func)
        def command_func(message, *args, **kwargs):
            bot.send_chat_action(message.chat.id, action)
            return func(message, *args, **kwargs)
        return command_func
    return decorator

@bot.message_handler(commands=['start'])
@send_action('typing')
def start_command_handler(message):

    logging.info("/start command from user {0} ({1} {2})"
                 .format(message.chat.username,
                         message.chat.first_name, message.chat.last_name))

    cid = message.chat.id
    markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
    btn_geo = types.KeyboardButton(text='send location', request_location=True)
    markup.add(btn_geo)
    bot.send_message(cid, 'Hi, {0}! Please, choose command from the list'
                     .format(message.chat.username),
                     reply_markup=markup)
    help_command_handler(message)

@bot.message_handler(commands=['country'])
@send_action('typing')
def country_command_handler(message):

    logging.info("/country command from user {0} ({1} {2})"
                 .format(message.chat.username,
                         message.chat.first_name, message.chat.last_name))

    cid = message.chat.id

    send = bot.send_message(cid, 'Please, enter country name.'.format(message.chat.username))
    bot.register_next_step_handler(send, get_country_name)

def get_country_name(message):
    cid = message.chat.id
    country_name = message.text.strip()

    statistics = get_info_by_country_name(country_name)

    if statistics is None:
        with codecs.open('template/not_found.html', 'r', encoding='UTF-8') as file:
            template = Template(file.read())
        bot.send_message(cid, template.render(), parse_mode='HTML')
        return

    reply = get_statistics_reply(statistics)
    bot.send_message(cid, reply, parse_mode='HTML')

def get_info_by_location(latitude, longitude):
    geolocator = Nominatim(user_agent="telegram-bot")
    location = geolocator.reverse((latitude, longitude))
    country_code = location.raw['address']['country_code']
    country = pycountry.countries.get(alpha_2=country_code).name

    return get_info_by_country_name(country)

def get_info_by_country_name(country_name):
    response = get_covid_statistics()
    for elem in response['Countries']:
        if elem['Country'].lower() == country_name.lower():
            logging.info("Request for statistics in {0}".format(country_name))
            return elem
    return None

@bot.message_handler(content_types=['location'])
@send_action('typing')
def geo_command_handler(message):
    cid = message.chat.id
    country_info = get_info_by_location(message.location.latitude, message.location.longitude)
    country_name = country_info['Country']

    logging.info("User {0} ({1} {2}) sent location: {3}"
                 .format(message.chat.username,
                         message.chat.first_name, message.chat.last_name,
                         country_name))

    reply = get_statistics_reply(country_info)
    bot.send_message(cid, reply, parse_mode='HTML')

@bot.message_handler(commands=['statistics'])
@send_action('typing')
def geo_command_handler(message):

    logging.info("/statistics command from user {0} ({1} {2})"
                 .format(message.chat.username,
                         message.chat.first_name, message.chat.last_name))

    cid = message.chat.id

    response = get_covid_statistics();

    with codecs.open('template/statistics.html', 'r', encoding='UTF-8') as file:
        template = Template(file.read())
        reply = template.render(date=date.today(),
                                new_confirmed=response['Global']['NewConfirmed'],
                                total_confirmed=response['Global']['TotalConfirmed'],
                                new_deaths=response['Global']['NewDeaths'],
                                total_deaths=response['Global']['TotalDeaths'],
                                new_recovered=response['Global']['NewRecovered'],
                                total_recovered=response['Global']['TotalRecovered'])

    bot.send_message(cid, reply, parse_mode='HTML')

@bot.message_handler(func=lambda message: message.text.lower() == 'hi')
@send_action('typing')
def greeting_command_handler(message):
    cid = message.chat.id
    with codecs.open('template/greeting.html', 'r', encoding='UTF-8') as file:
        template = Template(file.read())
        bot.send_message(cid, template.render(user_name=message.chat.username))

@bot.message_handler(commands=['contacts'])
@send_action('typing')
def contacts_command_handler(message):

    logging.info("/contacts command from user {0} ({1} {2})"
                 .format(message.chat.username,
                         message.chat.first_name, message.chat.last_name))

    cid = message.chat.id
    with codecs.open('template/contacts.html', 'r', encoding='UTF-8') as file:
        template = Template(file.read())
        bot.send_message(cid, template.render(user_name=message.chat.username), parse_mode='HTML')

@bot.message_handler(commands=['help'])
@send_action('typing')
def help_command_handler(message):

    logging.info("/help command from user {0} ({1} {2})"
                 .format(message.chat.username,
                         message.chat.first_name, message.chat.last_name))

    cid = message.chat.id
    help_text = 'The following commands are available:\n'
    for command in commands:
        help_text += '/' + command + ': '
        help_text += commands[command] + '\n'

    help_text += "\nIf you are using a smartphone you can also send location to get statistics in your country.\n"
    bot.send_message(cid, help_text)

@bot.message_handler(content_types=['text'])
@send_action('typing')
def unknown_command_handler(message):

    logging.info("Message from user {0} ({1} {2}): {3}"
                 .format(message.chat.username,
                         message.chat.first_name, message.chat.last_name,
                         message.text))

    cid = message.chat.id
    with codecs.open('template/unknown_command.html', 'r', encoding='UTF-8') as file:
        template = Template(file.read())
        bot.send_message(cid, template.render(text_command=message.text), parse_mode='HTML')

def get_statistics_reply(statistics):
    with codecs.open('template/country_statistics.html', 'r', encoding='UTF-8') as file:
        template = Template(file.read())
        reply = template.render(date=date.today(),
                                country=statistics['Country'],
                                new_confirmed=statistics['NewConfirmed'],
                                total_confirmed=statistics['TotalConfirmed'],
                                new_deaths=statistics['NewDeaths'],
                                total_deaths=statistics['TotalDeaths'],
                                new_recovered=statistics['NewRecovered'],
                                total_recovered=statistics['TotalRecovered'])
    return reply

def get_covid_statistics():
    url = "https://api.covid19api.com/summary"
    response = requests.request("GET", url).json()
    return response

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    bot.polling(none_stop=True, interval=0)


import numpy as np
import pandas as pd
from utils import utils

def opt_hu(hu_list, filenumber, filename, k, modeltype,
            activation_fun, loss_fun, optimer,
            lr, batch_size, max_num_epochs ,
            schedule, earlystop, pat,
            distr = "gamma"):

  x, x_test, x_all, y, y_test, dataset = utils.read_data(filename, filenumber, k)

  batch_train_losses = []
  batch_valid_losses = []
  batch_train_mses = []
  batch_valid_mses = []
  print("in opt_hu" + distr)

  if distr == "normal":
      predictions_loc = []
      predictions_scale = []

  if distr == "gamma":
      predictions_con = []
      predictions_rate = []

  for hu in hu_list:
    model = modeltype.DDR_MLP(
      num_hidden_layers = len(hu),
      num_hidden_units = hu,
      activation_fun = activation_fun,
      input_dim = k
    )
    print(hu)
    model, mfit_history = utils.run_training(model = model,
                                      x=x,
                                      y=y,
                                      loss_fun=loss_fun,
                                      num_epochs=max_num_epochs,
                                      batch_size=batch_size,
                                      lr=lr,
                                      optim=optimer,
                                      schedule = schedule,
                                      earlystop = earlystop,
                                      pat = pat)

    #append metrics to result arrays
    batch_train_losses.append(mfit_history.history['loss'])
    batch_valid_losses.append(mfit_history.history['val_loss'])
    batch_train_mses.append(mfit_history.history['mean_squared_error'])
    batch_valid_mses.append(mfit_history.history['val_mean_squared_error'])

    if distr == "normal":
      locs = np.array(model(x_all).loc)
      scales = np.array(model(x_all).scale)
      predictions_loc.append(locs)
      predictions_scale.append(scales)

    if distr == "gamma":
      cons = np.array(model(x_all).concentration)
      rates = np.array(model(x_all).rate)
      predictions_con.append(cons)
      predictions_rate.append(rates)

  min_ind, min_losses = utils.find_val_min(batch_valid_losses)

  #if hu_key is None:
  spec_filename = filename + "_" + str(filenumber)
  hu_key = utils.makehukey(spec_filename, hu_list, min_ind, min_losses)
  #hu_key.to_csv("results/" + "hu_key_" + filename + ".csv")

  if distr == "normal":
    dataset['pred_mean'] = predictions_loc[min_ind]
    dataset['pred_std'] = predictions_scale[min_ind]

  if distr == "gamma":
    dataset['pred_con'] = predictions_con[min_ind]
    dataset['pred_rate'] = predictions_rate[min_ind]
    dataset['pred_scale'] = (1/predictions_rate[min_ind])

  dataset.to_csv("results/"+ spec_filename +".csv")

  if distr == "normal":
      return batch_train_losses, batch_valid_losses, batch_train_mses, batch_valid_mses, predictions_loc, predictions_scale, hu_key

  if distr == "gamma":
      return batch_train_losses, batch_valid_losses, batch_train_mses, batch_valid_mses, predictions_con, predictions_rate, hu_key

def fitsimdat(num_sets, max_num_hidden_layers,
            max_hidden_units, rdseed,
            filename, num_files, k, modeltype,
            activation_fun, loss_fun, optimer,
            lr, batch_size, max_num_epochs,
            schedule, earlystop, pat,
            distr = "gamma", save = True, startkj = 0):

  hu_list = utils.rdsearch(num_sets, rdseed, max_num_hidden_layers, max_hidden_units)
  hu_key_all = []

  for kj in range(startkj, (startkj+num_files)):
    kj += 1
    print("doing " + str(kj) + "th dataset")

    print(modeltype)
    print("in fitsimdat:" + distr)

    if distr == "normal":
        batch_train_losses, batch_valid_losses, batch_train_mses, batch_valid_mses, predictions_loc, predictions_scale, hu_key = opt_hu(
            hu_list = hu_list, filenumber = kj, filename = filename, k = k, modeltype = modeltype,
            activation_fun = activation_fun, loss_fun = loss_fun, optimer = optimer,
            lr = lr, batch_size = batch_size, max_num_epochs = max_num_epochs,
            schedule = schedule, earlystop = earlystop, pat = pat, distr = distr)

    if distr == "gamma":
        batch_train_losses, batch_valid_losses, batch_train_mses, batch_valid_mses, predictions_con, predictions_rate, hu_key = opt_hu(
            hu_list = hu_list, filenumber = kj, filename = filename, k = k, modeltype = modeltype,
            activation_fun = activation_fun, loss_fun = loss_fun, optimer = optimer,
            lr = lr, batch_size = batch_size, max_num_epochs = max_num_epochs,
            schedule = schedule, earlystop = earlystop, pat = pat, distr = distr)

    hu_key_all.append(hu_key)

    if save:
      valid_losses = pd.DataFrame(batch_valid_losses).transpose()
      valid_mse = pd.DataFrame(batch_valid_mses).transpose()
      train_losses = pd.DataFrame(batch_train_losses).transpose()
      train_mse = pd.DataFrame(batch_train_mses).transpose()
      valid_losses.to_csv("results/trainmetrics/" + "valid_losses_" + filename + "_" + str(kj) + ".csv")
      valid_mse.to_csv("results/trainmetrics/" + "valid_mses_" + filename + "_" + str(kj) + ".csv")
      train_losses.to_csv("results/trainmetrics/" + "train_losses_" + filename + "_" + str(kj) + ".csv")
      train_mse.to_csv("results/trainmetrics/" + "train_mses_" + filename + "_" + str(kj) + ".csv")

      if distr == "normal":
          print("in fitsimdat2:" + distr)
          preds_loc = pd.DataFrame(np.squeeze(predictions_loc)).transpose()
          preds_scale = pd.DataFrame(np.squeeze(predictions_scale)).transpose()
          preds_loc.to_csv("results/trainmetrics/" + "preds_loc_" + filename + "_" + str(kj) + ".csv")
          preds_scale.to_csv("results/trainmetrics/" + "preds_scale_" + filename + "_" + str(kj) + ".csv")

      if distr == "gamma":
          preds_con = pd.DataFrame(np.squeeze(predictions_con)).transpose()
          preds_rate = pd.DataFrame(np.squeeze(predictions_rate)).transpose()
          preds_con.to_csv("results/trainmetrics/" + "preds_con_" + filename + "_" + str(kj) + ".csv")
          preds_rate.to_csv("results/trainmetrics/" + "preds_rate_" + filename + "_" + str(kj) + ".csv")

  hu_key = pd.concat(hu_key_all)
  hu_key.to_csv("results/" + "hu_key_" + filename + ".csv")

  return hu_key


from __future__ import absolute_import

from collections import defaultdict
from flask_restful.reqparse import RequestParser
from itertools import groupby
from sqlalchemy.orm import contains_eager, joinedload, subqueryload_all
from typing import List
from uuid import UUID

from changes.api.base import APIView
from changes.api.serializer.models.testcase import TestCaseWithOriginCrumbler
from changes.config import db
from changes.constants import Result, Status
from changes.lib import build_type
from changes.models.build import Build, BuildPriority
from changes.models.buildseen import BuildSeen
from changes.models.event import Event
from changes.models.failurereason import FailureReason
from changes.models.job import Job
from changes.models.jobstep import JobStep
from changes.models.source import Source
from changes.models.test import TestCase
from changes.models.user import User

from changes.utils.originfinder import find_failure_origins

def find_changed_tests(current_build, previous_build, limit=25):
    current_job_ids = [j.id.hex for j in current_build.jobs]
    previous_job_ids = [j.id.hex for j in previous_build.jobs]

    if not (current_job_ids and previous_job_ids):
        return []

    current_job_clause = ', '.join(
        ':c_job_id_%s' % i for i in range(len(current_job_ids))
    )
    previous_job_clause = ', '.join(
        ':p_job_id_%s' % i for i in range(len(previous_job_ids))
    )

    params = {}
    for idx, job_id in enumerate(current_job_ids):
        params['c_job_id_%s' % idx] = job_id
    for idx, job_id in enumerate(previous_job_ids):
        params['p_job_id_%s' % idx] = job_id

    # find all tests that have appeared in one job but not the other
    # we have to build this query up manually as sqlalchemy doesnt support
    # the FULL OUTER JOIN clause
    query = """
        SELECT c.id AS c_id,
               p.id AS p_id
        FROM (
            SELECT label_sha, id
            FROM test
            WHERE job_id IN (%(current_job_clause)s)
        ) as c
        FULL OUTER JOIN (
            SELECT label_sha, id
            FROM test
            WHERE job_id IN (%(previous_job_clause)s)
        ) as p
        ON c.label_sha = p.label_sha
        WHERE (c.id IS NULL OR p.id IS NULL)
    """ % {
        'current_job_clause': current_job_clause,
        'previous_job_clause': previous_job_clause
    }

    total = db.session.query(
        'count'
    ).from_statement(
        'SELECT COUNT(*) FROM (%s) as a' % (query,)
    ).params(**params).scalar()

    if not total:
        return {
            'total': 0,
            'changes': [],
        }

    results = db.session.query(
        'c_id', 'p_id'
    ).from_statement(
        '%s LIMIT %d' % (query, limit)
    ).params(**params)

    all_test_ids = set()
    for c_id, p_id in results:
        if c_id:
            all_test_ids.add(c_id)
        else:
            all_test_ids.add(p_id)

    test_map = dict(
        (t.id, t) for t in TestCase.query.filter(
            TestCase.id.in_(all_test_ids),
        ).options(
            joinedload('job', innerjoin=True),
        )
    )

    diff = []
    for c_id, p_id in results:
        if p_id:
            diff.append(('-', test_map[UUID(p_id)]))
        else:
            diff.append(('+', test_map[UUID(c_id)]))

    return {
        'total': total,
        'changes': sorted(diff, key=lambda x: (x[1].package, x[1].name)),
    }

def get_failure_reasons(build):
    from changes.buildfailures import registry

    rows = FailureReason.query.join(
        JobStep, JobStep.id == FailureReason.step_id,
    ).filter(
        FailureReason.build_id == build.id,
        JobStep.replacement_id.is_(None),
    )

    failure_reasons = []
    for row in rows:
        failure_reasons.append({
            'id': row.reason,
            'reason': registry[row.reason].get_html_label(build),
            'step_id': row.step_id,
            'job_id': row.job_id,
            'data': dict(row.data or {}),
        })

    return failure_reasons

def get_parents_last_builds(build):
    # type: (Build) -> List[Build]
    # A patch have only one parent, while a revision can have more.
    if build.source.patch:
        parents = [build.source.patch.parent_revision_sha]
    elif build.source.revision:
        parents = build.source.revision.parents

    if parents:
        parent_builds = list(Build.query.filter(
            Build.project == build.project,
            Build.status == Status.finished,
            Build.id != build.id,
        ).join(
            Source, Build.source_id == Source.id,
        ).options(
            contains_eager('source').joinedload('revision'),
        ).filter(
            Source.revision_sha.in_(parents),
            *build_type.get_any_commit_build_filters()
        ).order_by(Build.date_created.desc()))
        if parent_builds:
            # This returns a list with the last build of each revision.
            return [
                list(builds)[0]
                for sha, builds in groupby(
                    parent_builds,
                    lambda rev: rev.source.revision_sha
                )
            ]
    return []

class BuildDetailsAPIView(APIView):
    post_parser = RequestParser()
    post_parser.add_argument('priority', choices=BuildPriority._member_names_)

    def get(self, build_id):
        build = Build.query.options(
            joinedload('project', innerjoin=True),
            joinedload('author'),
            joinedload('source').joinedload('revision'),
            subqueryload_all('stats'),
        ).get(build_id)
        if build is None:
            return '', 404

        try:
            most_recent_run = Build.query.filter(
                Build.project == build.project,
                Build.date_created < build.date_created,
                Build.status == Status.finished,
                Build.id != build.id,
            ).join(
                Source, Build.source_id == Source.id,
            ).filter(
                *build_type.get_any_commit_build_filters()
            ).options(
                contains_eager('source').joinedload('revision'),
                joinedload('author'),
            ).order_by(Build.date_created.desc())[0]
        except IndexError:
            most_recent_run = None

        jobs = list(Job.query.filter(
            Job.build_id == build.id,
        ))

        # identify failures
        if not jobs:
            # If we have no jobs, the query to find failures becomes very expensive due to `in_([])` being
            # handled poorly, but since we know the result, we can just set it.
            test_failures = []
            num_test_failures = 0
        else:
            test_failures = TestCase.query.options(
                joinedload('job', innerjoin=True),
            ).filter(
                TestCase.job_id.in_([j.id for j in jobs]),
                TestCase.result == Result.failed,
            ).order_by(TestCase.name.asc())
            num_test_failures = test_failures.count()
            test_failures = test_failures[:25]

        failures_by_job = defaultdict(list)
        for failure in test_failures:
            failures_by_job[failure.job].append(failure)

        failure_origins = find_failure_origins(
            build, test_failures)
        for test_failure in test_failures:
            test_failure.origin = failure_origins.get(test_failure)

        # identify added/removed tests
        if most_recent_run and build.status == Status.finished:
            changed_tests = find_changed_tests(build, most_recent_run)
        else:
            changed_tests = []

        seen_by = list(User.query.join(
            BuildSeen, BuildSeen.user_id == User.id,
        ).filter(
            BuildSeen.build_id == build.id,
        ))

        extended_serializers = {
            TestCase: TestCaseWithOriginCrumbler(),
        }

        event_list = list(Event.query.filter(
            Event.item_id == build.id,
        ).order_by(Event.date_created.desc()))

        context = self.serialize(build)
        context.update({
            'jobs': jobs,
            'seenBy': seen_by,
            'events': event_list,
            'failures': get_failure_reasons(build),
            'testFailures': {
                'total': num_test_failures,
                'tests': self.serialize(test_failures, extended_serializers),
            },
            'testChanges': self.serialize(changed_tests, extended_serializers),
            'parents': self.serialize(get_parents_last_builds(build)),
        })

        return self.respond(context)

    def post(self, build_id):
        build = Build.query.options(
            joinedload('project', innerjoin=True),
            joinedload('author'),
            joinedload('source').joinedload('revision'),
        ).get(build_id)
        if build is None:
            return '', 404

        args = self.post_parser.parse_args()
        if args.priority is not None:
            build.priority = BuildPriority[args.priority]

        db.session.add(build)

        context = self.serialize(build)

        return self.respond(context, serialize=False)


import boto3
import requests
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError

from stravabot.api import ApiRequest, api_endpoint, bad_request
from stravabot.clients.strava import InvalidStravaTokenError
from stravabot.config import JWT_SECRET_KEY, KV_STORE_TABLE
from stravabot.db import KeyValueStore
from stravabot.messages import context, mrkdwn, response
from stravabot.models import User, UserAccessToken
from stravabot.services.response_url import ResponseUrlService
from stravabot.services.strava import StravaAthleteCredentials, StravaService
from stravabot.services.token import TokenService
from stravabot.services.user import UserService

dynamodb = boto3.resource("dynamodb")
store = KeyValueStore(dynamodb.Table(KV_STORE_TABLE))
tokens = TokenService(JWT_SECRET_KEY)
users = UserService(store)
strava = StravaService(users)
response_urls = ResponseUrlService(store, tokens)

def _create_user(athlete_credentials: StravaAthleteCredentials, slack_id: str) -> User:
    return User(
        strava_id=athlete_credentials.id,
        slack_id=slack_id,
        strava_access_token=UserAccessToken(
            token=athlete_credentials.access_token,
            refresh_token=athlete_credentials.refresh_token,
            expires_at=athlete_credentials.expires_at,
        ),
    )

@api_endpoint
def handler(request: ApiRequest) -> dict:
    data = request.json()
    if "token" not in data or "code" not in data:
        return bad_request()

    try:
        token = tokens.decode(data["token"])
    except ExpiredSignatureError:
        return bad_request(
            {
                "message": "Token expired",
            }
        )
    except InvalidTokenError:
        return bad_request()

    try:
        credentials = strava.get_athlete_credentials(data["code"])
    except InvalidStravaTokenError:
        return bad_request()

    users.put(_create_user(credentials, token.slack_user_id))
    response_url = response_urls.get(token, max_attempts=3)
    if response_url is not None:
        requests.post(
            response_url,
            json=response(
                context(mrkdwn("Connected to Strava")),
                replace_original=True,
            ),
        )

    return {"statusCode": 200}