#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @当前项目名 : python demo
# 接口实际值处理（返回编译过的实际值）

from assertpy import assert_that
from privately_owned.Port_Compile import OtherInterfaces_compile,workOrder_compile,\
    equipmentSchedule,StatisticsOfRepairQuantity,ListOfComplaints
from appletConnector import initialize,TheRepairOrderInterface,assets_management,rests, addKind,SystemAppController
from appletConnector import UserAppController
from privately_owned.method import transform_dataType
from privately_owned.Task_handling_button import IndependentMethod
from privately_owned.dicti_data_dispose import dictionaries
from utils.privately_owned.timeDisposal import TimeFormat

############接口实际处理（返回实际值）###################################

class repairs_workOrder:
    """报修工单模块实际值"""

    def __init__(self, JSESSIONID, post_Parameter):
        """
        :param JSESSIONID:
        :param post_Parameter: 接口要传入的post参数
        """
        self.JSESSIONID = JSESSIONID
        self.post_Parameter = post_Parameter
        self.compile_actualValue = None

    def applet_EventModules(self,state_name,userinfo):
        """
        小程序事件模块实际值
        :return:
        """
        url=None
        post_Parameter={};finish_date2=None;list_workOrder_strState=[];list_workOrder=None
        for key, value in self.post_Parameter.items():
            post_Parameter[key]=value
        # 去掉开始日期和结束日期的时间
        begin_date=post_Parameter["开始日期"]
        if begin_date:
            begin_date=begin_date[:10]
        finish_date1 = post_Parameter["结束日期"]
        if finish_date1:
            finish_date2 = finish_date1[:10]
        post_Parameter["开始日期"]=begin_date
        post_Parameter["结束日期"] = finish_date2
        list_workOrder_initial=None
        #获取待响应/预约中/待处理/处理中/已处理/已挂起列表数据接口的数据,小程序事件，返回工单列表
        if state_name == "外协_待响应" or state_name == "外协_预约中" or state_name == "外协_待处理" or state_name == "外协_处理中" or state_name == "外协_已处理" or state_name == "外协_已挂起":
            list_workOrder_initial,req_text,url = TheRepairOrderInterface(self.JSESSIONID, post_Parameter).chooseListData()
        #获取外协_已关单列表数据接口的数据,小程序事件，返回工单列表
        elif state_name == "外协_已关单":
            list_workOrder_initial,req_text,url = TheRepairOrderInterface(self.JSESSIONID,post_Parameter).closedTicketListData()
        #获取全部工单、紧急事件、驻场事件（包含已关单数据）列表数据接口的数据,小程序事件，返回工单列表
        elif state_name == "全部工单":
            post_Parameter["是否完成的工单"] = None
            list_workOrder_initial,url = TheRepairOrderInterface(self.JSESSIONID,post_Parameter).allListData()
        list_workOrder_intState = workOrder_compile(self.JSESSIONID, list_workOrder_initial).compile_homePage(userinfo )
        # 把工单整数类型的工单状态编译成状态名称
        for workOrder in list_workOrder_intState:
            int_state=workOrder["工单状态"]
            state_name = dictionaries(self.JSESSIONID, int_state).ADictionaryTable()  # 整数的工单状态转化成str工单名称
            workOrder["工单状态"]=state_name
            list_workOrder_strState.append( workOrder)
        # 截取工单更新日期和创建日期的日期
        list_dataKey = ["工单创建日期", "工单更新日期"]
        list_workOrder = TimeFormat(list_workOrder_strState, list_dataKey).CaptureTheAate("%Y-%m-%d")
        return list_workOrder,url

class ReportStatistics_class :
    """报修统计模块数据对比测试实际值"""

    def __init__(self, dicti_parameterPacket):
        """
        :param dicti_parameterPacket: 接口要传入的post参数
        """
        self.dicti_parameterPacket = dicti_parameterPacket

    def inquire_ReportStatistics(self, module):
        """
        报修统计页面（报修数据统计、故障类型统计）
        :return:
        """
        deviceList=None;list_office=None;begin_date=None;finish_date=None;deviceList=None;url=None;list_workOrder_compile=None;test_module=None
        new_workOrder_compile=[]
        list_office=self.dicti_parameterPacket["所选单位ID"];begin_date=self.dicti_parameterPacket["开始日期"];finish_date=self.dicti_parameterPacket["结束日期"]
        JSESSIONID = self.dicti_parameterPacket["登录用户JSESSIONID"]
        if module == "报修数量":
            deviceList,url = rests(JSESSIONID).numCountData(list_office, begin_date, finish_date)
            test_module="客户端-首页-报修统计（除普通用户外）-报修数量统计；服务端-报修统计-报修数量统计；"
            # deviceList=[{'cuser': {'office': {'id': 'e155a7d8e34f4e339d5207ab33e2add4', 'name': '生物城第一高级中学分校', 'hasChildren': False, 'type': '2', 'parentId': '0'},
            #                        'loginFlag': '1', 'roleNames': '', 'admin': False}, 'officeCountNum': '208', 'handleTaskFlag': False, 'histroryFlag': False}]
        elif module == "故障数量":
            deviceList,url = rests(JSESSIONID).faultCountData(list_office, begin_date, finish_date)
            test_module = "客户端-首页-报修统计（除普通用户外）-故障类型统计；服务端-报修统计-故障类型统计；"
            # deviceList =[{'prbTp': {'id': '3c1fa83ea73e46aa8b0745ea6e424f0c', 'prbTpNm': '教学功能室设备'}, 'prbTpTypeNum': '52', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': '0756e6cf572a4ecf82074b84fb298182', 'prbTpNm': '电脑故障'}, 'prbTpTypeNum': '33', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': 'fc5478163a6749f78300dbc6801d99ed', 'prbTpNm': '摄像头'}, 'prbTpTypeNum': '33', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': 'c5c08f65faf049778e391588565d5ad4', 'prbTpNm': '电子教学设备'}, 'prbTpTypeNum': '27', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': '7370317620c443cfbe717945ec59771c', 'prbTpNm': '其他设备'}, 'prbTpTypeNum': '14', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': 'e0f6567f1d9c4db3b114fd54f89523a4', 'prbTpNm': '网络设备'}, 'prbTpTypeNum': '14', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': '802a6a7a1dbb4bc389cb46f1b54980e1', 'prbTpNm': '办公设备'}, 'prbTpTypeNum': '14', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': 'bc860ff03eb54441954b1a794e835a8c', 'prbTpNm': '监控设备'}, 'prbTpTypeNum': '9', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': '5851adfeb3fd469aac7c60ec17545061', 'prbTpNm': '广播设备'}, 'prbTpTypeNum': '6', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0},
            #              {'prbTp': {'id': 'f65b0b91ae074eecb330dabb994653dd', 'prbTpNm': '打印设备'}, 'prbTpTypeNum': '6', 'handleTaskFlag': False, 'histroryFlag': False, 'customSort': 0}]
            # 编译接口返回的数据
        list_workOrder_compile = StatisticsOfRepairQuantity(JSESSIONID, deviceList).ReportStatistics(module)
        for workOrder_compile in list_workOrder_compile: # 把字符串的工单数转化成整数
            workOrder_number=int(workOrder_compile["工单数"])
            workOrder_compile["工单数"]=workOrder_number
            new_workOrder_compile.append(workOrder_compile)
        return  new_workOrder_compile,url, test_module

class AssetsOfEquipment_actualValue:
    """资产设备模块实际值"""

    def __init__(self,dicti_parameterPacket):
        """
        :param JSESSIONID:
        :param post_Parameter: 接口要传入的post参数
        """
        self.dicti_parameterPacket = dicti_parameterPacket
        self.compile_actualValue=None

    def equipmentSchedule(self):
        """
        设备清单页面实际值
        :return:
        """
        deviceList = None;url = None;list_workOrder_compile = None;str_officeID=None
        str_officeID= self.dicti_parameterPacket["所选单位ID"]
        devicename = self.dicti_parameterPacket["设备名称"]
        batchNo = self.dicti_parameterPacket["批次"]
        JSESSIONID = self.dicti_parameterPacket["登录用户JSESSIONID"]
        post_Parameter = {"单位ID": str_officeID, "设备名称": devicename, "批次": batchNo}
        """获取接口数据"""
        deviceList,url = assets_management(JSESSIONID,post_Parameter).equipListData()
        """编译接口数据"""
        list_workOrder_compile = equipmentSchedule(JSESSIONID, deviceList).compile_equipmentSchedule()
        # list_workOrder_compile=[{'设备名称': '硬盘dddddddddddddddddddddddddd', '跟新时间': '2019-08-09 10:32:12', '创建时间': '2019-08-01 13:52:21',
        #                          '批次': '202008014560024', '设备品牌': '戴尔1', '设备状态': '1', '位置信息': 'e70aeecc0eab411dbc20214b98ee3807',
        #                          '设备类型ID': '090ccfed6c0e49c9a097dba47ab069b7', '设备ID': 'd8b86fbe8f3840a389c7671e6228eaea', '设备编号': '878637654536355840.jpg'}]
        return list_workOrder_compile,url

class  ComplaintsModule:
    """投诉模块实际值"""

    def __init__(self,dicti_parameterPacket):
        """
        :param dicti_parameterPacket:参数包
        """
        self.dicti_parameterPacket = dicti_parameterPacket
        self.compile_actualValue=None

    def add_ComplaintsModule(self):
        """
        新增投诉接口
        :return:
        """
        loginName = self.dicti_parameterPacket["登录名"] ; roleName = self.dicti_parameterPacket["用户权限"]
        JSESSIONID =self.dicti_parameterPacket["登录用户JSESSIONID"] ;complaint_Title =self.dicti_parameterPacket["投诉标题"]
        complaint_phone = self.dicti_parameterPacket["用户联系电话"] ;complaint_content = self.dicti_parameterPacket["投诉内容"]
        post_Parameter={"投诉标题":complaint_Title,"投诉人电话":complaint_phone,"投诉内容":complaint_content}
        # 调用新增投诉接口
        InterfaceReturnValue,url = addKind(JSESSIONID).add_manualOperation_complain(post_Parameter)
        # 断言返回值
        assert_that(InterfaceReturnValue).described_as('新增投诉失败').is_equal_to("投诉成功，已通知服务台处理")
        print("\033[0;37;40m登录用户：%r，用户权限：%r,新增投诉成功,已通知服务台处理"%(loginName,roleName))
        return url

    def amend_ComplaintsModule(self,procedure):
        """
        投诉模块数据修改
        :param procedure:
        :return:
        """
        JSESSIONID=self.dicti_parameterPacket["登录用户JSESSIONID"]; post_Parameter=None
        if procedure == "服务台受理投诉，指派被投诉人：运维工程师（四组）" or procedure == "服务台受理投诉，指派被投诉人：运维组长（四组）":
            post_Parameter = {"投诉标题": self.dicti_parameterPacket["投诉标题"], "投诉人电话": self.dicti_parameterPacket["投诉人电话"],"投诉内容": self.dicti_parameterPacket["投诉内容"],
                              "投诉级别": self.dicti_parameterPacket["投诉级别"],"处理方案": self.dicti_parameterPacket["处理方案"],
                              "投诉单ID": self.dicti_parameterPacket["投诉单ID"],"被投诉人ID": self.dicti_parameterPacket["被投诉人ID"],
                              "处理结果":None,"操作": self.dicti_parameterPacket["操作"]}
        elif procedure == "运维工程师填写处理结果" or procedure == "运维组长填写处理结果" or procedure == "运维工程师修改处理结果" or procedure == "运维组长修改处理结果":
            post_Parameter =  {"投诉单ID": self.dicti_parameterPacket["投诉单ID"],"处理结果":self.dicti_parameterPacket["处理结果"],"操作": self.dicti_parameterPacket["操作"]}
        elif procedure == "服务台再次受理投诉，指派被投诉人：运维工程师（四组）" or procedure == "服务台再次受理投诉，指派被投诉人：运维组长（四组）":
            post_Parameter =  {"投诉单ID": self.dicti_parameterPacket["投诉单ID"],"被投诉人ID": self.dicti_parameterPacket["被投诉人ID"],"处理方案": self.dicti_parameterPacket["处理方案"],
                              "操作": self.dicti_parameterPacket["操作"]}
        elif procedure == "普通用户确认处理结果：未解决" or procedure == "用户管理员确认处理结果：未解决":
            post_Parameter =  {"投诉单ID": self.dicti_parameterPacket["投诉单ID"],"操作": self.dicti_parameterPacket["操作"]}
        elif procedure == "普通用户再次确认处理结果：已解决" or procedure == "用户管理员确认处理结果：已解决":
            post_Parameter =  {"投诉单ID": self.dicti_parameterPacket["投诉单ID"],"操作": self.dicti_parameterPacket["操作"]}
        # 修改投诉信息数据接口
        InterfaceReturnValue,url = addKind(JSESSIONID).add_manualOperation_updatesuggest(post_Parameter)
        if procedure =="服务台受理投诉，指派被投诉人：运维工程师（四组）" or procedure =="服务台受理投诉，指派被投诉人：运维组长（四组）" or procedure =="服务台再次受理投诉，指派被投诉人：运维工程师（四组）":
            assert_that(InterfaceReturnValue).described_as('服务台受理投诉，并且填写处理意见不成功').is_equal_to("填写处理意见成功，已通知工程师")
        elif procedure =="运维工程师修改处理结果" or procedure =="运维工程师填写处理结果" or procedure =="运维组长填写处理结果":
            assert_that(InterfaceReturnValue).described_as('运维工程师（运维组长），填写处理结果不成功').is_equal_to("填写处理结果成功，已通知客户确认")
        return url

    def  inquire_complaint_page(self):
        """
        投诉页面数据查询接口，返回编译过的数据
        :return:
        """
        JSESSIONID=self.dicti_parameterPacket["登录用户JSESSIONID"] ; monthNum=self.dicti_parameterPacket["日期参数"]
        titleAndcontent = self.dicti_parameterPacket["筛选条件内容或者标题"]
        post_Parameter ={"日期范围":monthNum,"筛选条件内容或者标题":titleAndcontent}
        # 调用投诉清单接口
        list_ListOfComplaints,url = rests(JSESSIONID).Complaint_list_page(post_Parameter)
        ##############################################################################################################
        """编译从接口投诉清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        list_workOrder_compile = ListOfComplaints(list_ListOfComplaints).compile_TheComplaintpage()
        return list_workOrder_compile,url

class WorkOrderProcess_actualValue:
    """工单流程，调接口获取返回值，并编译返回值"""

    def __init__(self, FilterParameters,post_Parameter=None):
        """
        :param JSESSIONID:
        :param post_Parameter: 接口要传入的post参数
        """
        self.FilterParameters=FilterParameters
        self.post_Parameter = post_Parameter
        self.compile_actualValue = None

    def WorkOrderList_actualValue_console(self,connector):
        """
        工单清单页面数据对比实际值控制台
        :return:
        """
        list_actualValue=None; post_Parameter=None; url=None
        if connector=="小程序首页工单":
            list_actualValue, post_Parameter, url = WorkOrderProcess_actualValue(self.FilterParameters).TheRepairSquare_noOffTicketListData()  # 小程序首页工单
        elif connector=="内部代办理工单":
            officeID = self.FilterParameters["所选单位ID"]
            list_actualValue, post_Parameter, url = WorkOrderProcess_actualValue(self.FilterParameters).TheRepairSquare_InsideRepairListData(True,officeID) # 内部代办理工单
        elif connector=="用户管理员区域管理员外协报修列表数据":
            officeID = self.FilterParameters["所选单位ID"]
            list_actualValue, post_Parameter, url = WorkOrderProcess_actualValue(self.FilterParameters).TheRepairSquare_ExternalRepairListData(officeID) # 用户管理员区域管理员外协报修列表数据
        elif connector=="外部用户-我的报修":
            list_actualValue, post_Parameter, url = WorkOrderProcess_actualValue(self.FilterParameters).TheRepairSquare_page( ) # 外部用户-我的报修
        elif connector=="全部工单、紧急事件、驻场事件（包含已关单数据）":
            list_actualValue, post_Parameter, url = WorkOrderProcess_actualValue(self.FilterParameters).TheRepairSquare_allListData( ) # 全部工单、紧急事件、驻场事件（包含已关单数据）
        elif connector == "外协未关单工单列表页面":
            list_actualValue, post_Parameter, url = WorkOrderProcess_actualValue(self.FilterParameters).TheRepairSquare_chooseListData()  # 外协未关单工单列表页面
        elif connector == "已关单列表数据":
            list_actualValue, post_Parameter, url = WorkOrderProcess_actualValue(self.FilterParameters).TheRepairSquare_closedTicketListData()  # 已关单列表数据
        return list_actualValue, post_Parameter, url

    def add_workOrder(self,procedure):
        """
       一键报修接口，并编译返回值
       :return:
       """
        InterfaceReturnValue=None
        JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        post_Parameter={"工单标题":self.FilterParameters["工单标题"], "故障类型ID":self.FilterParameters["故障类型ID"],"工单报修描述":self.FilterParameters["工单报修描述"],
                        "预约日期":self.FilterParameters["预约日期"], "预约时间段":self.FilterParameters["预约时间段"],"资产设备id":self.FilterParameters["资产设备id"],
                        "工单服务类型":self.FilterParameters["工单服务类型"]}
        # 调用新增工单接口
        if procedure == "普通用户-一键报修":
            InterfaceReturnValue = initialize(JSESSIONID).AKeyRepairService(post_Parameter)
        elif procedure == "服务台-PC端-报修工单":
            pass
        # 断言返回值
        assert_that(InterfaceReturnValue).described_as('2/新增工单失败').is_equal_to("提交成功，请等待信息中心管理员进行处理！")
        print("")

    def amend_sjTicketOperating_sjTicketOperating(self,Subordinate_procedure):
        """
         操作按钮获取表单流程，做除了一件报修以外的所有操作，都要先调一下
       接单/改派/改派审核/到达现场/挂起/挂起审核/解挂/完成工单/评价接口
        :param Subordinate_procedure: 工单操作步骤名称
        :param loginName:
        :param roleName:
        :return:
        """
        InterfaceReturnValue=None; positional="操作成功"; JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        # 获取接单/改派/改派审核/到达现场/挂起/挂起审核/解挂/完成工单/评价接口post参数
        sjTicketOperating_post={"工单ID":self.FilterParameters["工单ID"],"工单编号":self.FilterParameters["工单编号"],"工单报修人ID":self.FilterParameters["工单报修人ID"],"工单状态":self.FilterParameters["工单状态"],
                                "工单改派人ID":self.FilterParameters["工单改派人ID"],"工单处理人ID":self.FilterParameters["工单处理人ID"],"流程实例id":self.FilterParameters["流程实例id"],"报修人电话":self.FilterParameters["报修人电话"],
                                "预约开始时间":self.FilterParameters["预约开始时间"],"预约结束时间":self.FilterParameters["预约结束时间"],"确认开始服务时间":self.FilterParameters["确认开始服务时间"],"确认结束服务时间":self.FilterParameters["确认结束服务时间"],
                                "工单范围":self.FilterParameters["工单范围"],"任务名称":self.FilterParameters["任务名称"],"任务定义Key":self.FilterParameters["任务定义Key"],"意见状态":self.FilterParameters["意见状态"],
                                "工单服务类型":self.FilterParameters["工单服务类型"],"任务意见":self.FilterParameters["任务意见"],"事件解决方案":self.FilterParameters["事件解决方案"],"预约时间段":self.FilterParameters["预约时间段"],
                                "内部处理结果":self.FilterParameters["内部处理结果"],"评级":self.FilterParameters["评级"],"用户评价":self.FilterParameters["用户评价"],"挂起下拉框理由":self.FilterParameters["挂起下拉框理由"],
                                "挂起状态字段":self.FilterParameters["挂起状态字段"],"改派人群组ID":self.FilterParameters["改派人群组ID"]}
        # 调用关于工作流的接口接口
        sjTicketFlow_post ={"任务id":self.FilterParameters["任务id"],"任务名称":self.FilterParameters["任务名称"],"任务定义Key":self.FilterParameters["任务定义Key"],"流程实例id":self.FilterParameters["流程实例id"],
                            "流程定义id":self.FilterParameters["流程定义id"],"任务状态":self.FilterParameters["任务状态"],"处理类型":self.FilterParameters["处理类型"]}
        # 当运维组长改派待响应状态下的工单时，系统会获取改派人的位置信息
        if  Subordinate_procedure =="组长(四组)-待响应-改派-工程师(四组)" or Subordinate_procedure =="服务台(一号)-已挂起-改派-工程师(四组)" or Subordinate_procedure =="服务台-已挂起-改派-五组-运维工程师":
            changeTicketPosition_post={"工单ID":self.FilterParameters["工单ID"],"工单改派人ID":self.FilterParameters["工单改派人ID"]}
            positional,req_text = SystemAppController(JSESSIONID, changeTicketPosition_post).changeTicketPosition()
        # 调用“操作按钮获取表单流程”接口
        operating = TheRepairOrderInterface(JSESSIONID, sjTicketFlow_post).sjTicketFlow()
        if operating=="操作成功" and positional=="操作成功":
            # 调用接单/改派/改派审核/到达现场/挂起/挂起审核/解挂/完成工单/评价接口
            InterfaceReturnValue = TheRepairOrderInterface(JSESSIONID, sjTicketOperating_post).sjTicketOperating()
        else:
            print("操作按钮获取表单流程接口：",operating);print("改派更新位置接口：", operating)
        # 断言返回值
        assert_that(InterfaceReturnValue).described_as("“%r”操作，调用sjTicketOperating接口操作失败"%procedure).is_equal_to("操作成功")
        print("\033[1;34;40m操作按钮获取表单流程，操作成功；\033[0m\033[4;35;40m登录用户：%r，用户权限：%r" % (loginName, roleName))
        print("")

    def  TheRepairSquare_page(self):
        """
        报修广场数据查询接口,调用小程序--客户端--报修广场--我的报修接口，返回编译过的数据
        :return:
        """
        JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        startDate = self.FilterParameters["开始日期"];endingDate = self.FilterParameters["结束日期"]
        post_Parameter = {"开始日期": startDate, "结束日期": endingDate}
        # 调用小程序--客户端--报修广场--我的报修接口
        list_ListWorkOrder,url = TheRepairOrderInterface(JSESSIONID,post_Parameter).MyRepairListData()
        ##############################################################################################################
        """编译从接口投诉清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        list_workOrder = workOrder_compile(list_ListWorkOrder).WorkOrderProcess_MyRepairListData(self.FilterParameters)
        return list_workOrder,post_Parameter,url

    def TheRepairSquare_InsideRepairListData(self,effect=True,location_office=None):
        """
        报修广场--内部--数据查询接口，返回编译过的数据
        :return:
        """
        list_workOrder=None;JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        startDate = self.FilterParameters["开始日期"]
        if type(startDate)==type(["1"]):
            startDate=startDate[0]
        endingDate = self.FilterParameters["结束日期"]
        if type(endingDate)==type(["1"]):
            endingDate=endingDate[0]
        post_Parameter = {"开始日期": startDate, "结束日期": endingDate,"所在单位":location_office}
        # 调用小程序--客户端--报修广场--内部
        list_ListWorkOrder,req_text,url = TheRepairOrderInterface(JSESSIONID, post_Parameter).InsideRepairListData()
        ##############################################################################################################
        """编译从接口投诉清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        # "1":数据对比用户；
        if effect:
            list_workOrder = workOrder_compile(list_ListWorkOrder).WorkOrderProcess_InsideRepairListData(self.FilterParameters)
        # "1":获取部分post请求数据
        else:
            list_workOrder = OtherInterfaces_compile(list_ListWorkOrder).WorkOrderProcess_Post(self.FilterParameters,req_text)
        return list_workOrder,post_Parameter,url

    def TheRepairSquare_ExternalRepairListData(self,office_id=None):
        """
        报修广场--外协--数据查询接口，返回编译过的数据
        :return:
        """
        list_workOrder = None
        JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        startDate = self.FilterParameters["开始日期"]
        if type(startDate) == type(["1"]):
            startDate = startDate[0]
        endingDate = self.FilterParameters["结束日期"]
        if type(endingDate) == type(["1"]):
            endingDate = endingDate[0]
        post_Parameter = {"开始日期": startDate, "结束日期": endingDate, "所在单位": office_id}
        # 调用小程序--客户端--报修广场--外协接口
        list_ListWorkOrder,url = TheRepairOrderInterface(JSESSIONID,  post_Parameter).ExternalRepairListData()
        ##############################################################################################################
        """编译从接口投诉清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        list_workOrder = workOrder_compile(list_ListWorkOrder).WorkOrderProcess_ExternalRepairListData(self.FilterParameters)
        return list_workOrder,post_Parameter,url

    def TheRepairSquare_noOffTicketListData(self):
        """
        小程序--首页--工单
        :return:
        """
        JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        list_workOrder_port=None;list_workOrder=None
        roleName = self.FilterParameters["用户权限"]
        if  roleName == "普通用户" or roleName == "用户管理员" or roleName == "区域管理员":
            post_Parameter={"工单范围":None,"月份":"7"}
        else:
            post_Parameter = {"工单范围":"0","月份":"6"}
        # 调用小程序--首页--工单接口
        list_workOrder_port,url = TheRepairOrderInterface(JSESSIONID, post_Parameter).noOffTicketListData()
        ##############################################################################################################
        """编译从接口工单清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        list_workOrder = workOrder_compile( list_workOrder_port).compile_homePage(self.FilterParameters) # 编译调用小程序--首页--工单接口
        return list_workOrder,post_Parameter,url

    def TheRepairSquare_allListData(self,effect=True):
        """
        小程序--客户端-报修广场-已完成和全部；小程序--服务端-事件-全部工单列表实际值；小程序--服务端--首页--紧急报修和驻场服务实际值
        :return:
        """
        post_Parameter={};list_workOrder=None;list_ListWorkOrder=None;list_workOrder_intState=None;list_workOrder_strState=[]
        selected_office=None;selected_module=None;startDate=None;endingDate=None
        print("self.FilterParameters:",self.FilterParameters)
        startDate = self.FilterParameters["开始日期"];endingDate = self.FilterParameters["结束日期"]; JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        selected_module=self.FilterParameters["所属模块"];selected_office=self.FilterParameters["所选单位"]
        if selected_office=="空":
            selected_office=None
        if selected_module == "客户端-报修广场-已完成":
            post_Parameter={"工单类型":None,"开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围":None,"是否完成的工单":"true","工单服务类型":None}
        elif selected_module == "客户端-报修广场-全部":
            post_Parameter = {"工单类型": None, "开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围":None,"是否完成的工单":None,"工单服务类型":None}
        elif selected_module =="首页-紧急报修-未完成" :
            post_Parameter = {"工单类型": None, "开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围":None,"是否完成的工单":"false","工单服务类型":"1"}
        elif  selected_module =="首页-紧急报修-已完成" :
            post_Parameter = {"工单类型": None, "开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围":None,"是否完成的工单":"true","工单服务类型":"1"}
        elif  selected_module =="首页-紧急报修-全部" :
            post_Parameter = {"工单类型": None, "开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围":None,"是否完成的工单":None,"工单服务类型":"1"}
        elif selected_module == "首页-驻场服务-未完成" :
            post_Parameter = {"工单类型": None, "开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围":None,"是否完成的工单":"false","工单服务类型":"2"}
        elif  selected_module == "首页-驻场服务-已完成" :
            post_Parameter = {"工单类型": None, "开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围": None,"是否完成的工单":"true", "工单服务类型":"2"}
        elif selected_module == "首页-驻场服务-全部":
            post_Parameter = {"工单类型": None,"开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围": None,"是否完成的工单":None,"工单服务类型": "2"}
        elif selected_module == "服务端-事件-全部工单":
            post_Parameter = {"工单类型": None, "开始日期":startDate,"结束日期":endingDate,"所选单位":selected_office,"工单范围":None,"是否完成的工单":None,"工单服务类型":None}
        print("post_Parameter:",post_Parameter)
        # 调用接口
        list_ListWorkOrder,req_text,url  = TheRepairOrderInterface(JSESSIONID, post_Parameter).allListData()
        """编译从接口投诉清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        # "1":数据对比用户；
        if effect:
            list_workOrder = workOrder_compile(list_ListWorkOrder).WorkOrderProcess_allListData(self.FilterParameters)
        # "1":获取部分post请求数据
        else:
            list_workOrder = OtherInterfaces_compile(list_ListWorkOrder).WorkOrderProcess_Post(self.FilterParameters,req_text)
        return list_workOrder,post_Parameter,url

    def TheRepairSquare_chooseListData(self,effect=True):
        """
        小程序--服务端--事件（待响应；预约中；待处理；处理中；已处理；已关单；已挂起）
        :return:
        """
        req_text=None;list_workOrder_strState=[];post_Parameter = {};list_workOrder=None;list_ListWorkOrder=None
        JSESSIONID = self.FilterParameters["登录用户JSESSIONID"];startDate = self.FilterParameters["开始日期"];endingDate = self.FilterParameters["结束日期"]
        selected_module = self.FilterParameters["所属模块"]
        if selected_module == "服务端--事件--待响应":
            post_Parameter = {"工单状态":"2","开始日期":startDate,"结束日期":endingDate,"所在单位":None,"查看范围":None}
        elif selected_module == "服务端--事件--预约中":
            post_Parameter = {"工单状态":"3","开始日期":startDate,"结束日期":endingDate,"所在单位":None,"查看范围":None}
        elif selected_module == "服务端--事件--待处理":
            post_Parameter = {"工单状态": "4", "开始日期": startDate, "结束日期": endingDate, "所在单位": None, "查看范围": None}
        elif selected_module == "服务端--事件--处理中":
            post_Parameter = {"工单状态":"5","开始日期":startDate,"结束日期":endingDate,"所在单位":None,"查看范围":None}
        elif selected_module == "服务端--事件--已处理":
            post_Parameter = {"工单状态":"7","开始日期":startDate,"结束日期":endingDate,"所在单位":None,"查看范围":None}
        elif selected_module == "服务端--事件--已挂起":
            post_Parameter = {"工单状态": "6", "开始日期": startDate, "结束日期": endingDate, "所在单位": None, "查看范围": None}
        # 调用小程序--服务端--事件--待响应；预约中；待处理；处理中；已处理；已挂起
        list_ListWorkOrder,req_text,url = TheRepairOrderInterface(JSESSIONID,  post_Parameter).chooseListData()
        ##############################################################################################################
        """编译从接口投诉清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        if effect:
            list_workOrder_intState = workOrder_compile(list_ListWorkOrder).compile_homePage(self.FilterParameters)
            # 把工单整数类型的工单状态编译成状态名称
            for workOrder in list_workOrder_intState:
                int_state = workOrder["工单状态"]
                state_name = dictionaries(JSESSIONID, int_state).ADictionaryTable()  # 整数的工单状态转化成str工单名称
                workOrder["工单状态"] = state_name
                list_workOrder_strState.append(workOrder)
            # 截取工单更新日期和创建日期的日期
            list_dataKey = ["工单创建日期", "工单更新日期"]
            list_workOrder = TimeFormat(list_workOrder_strState, list_dataKey).CaptureTheAate("%Y-%m-%d")
        else:
            list_workOrder = OtherInterfaces_compile(list_ListWorkOrder).WorkOrderProcess_Post(self.FilterParameters,req_text)
        return list_workOrder,post_Parameter,url

    def TheRepairSquare_closedTicketListData(self):
        """
        已关单列表数据
        :param effect:
        :return:
        """
        req_text = None;post_Parameter = {};list_workOrder = None;list_ListWorkOrder = None;list_workOrder_strState=[]
        JSESSIONID = self.FilterParameters["登录用户JSESSIONID"];startDate = self.FilterParameters["开始日期"]
        endingDate = self.FilterParameters["结束日期"];selected_module = self.FilterParameters["所属模块"]
        post_Parameter = {"工单状态": "2", "开始日期": startDate, "结束日期": endingDate, "所在单位": None, "查看范围": None}
        # 调用小程序--服务端--事件--已关单
        list_ListWorkOrder, req_text, url = TheRepairOrderInterface(JSESSIONID, post_Parameter).closedTicketListData()
        list_workOrder_intState = workOrder_compile(list_ListWorkOrder).WorkOrderProcess_closedTicketListData(self.FilterParameters)
        # 把工单整数类型的工单状态编译成状态名称
        for workOrder in list_workOrder_intState:
            int_state = workOrder["工单状态"]
            state_name = dictionaries(JSESSIONID, int_state).ADictionaryTable()  # 整数的工单状态转化成str工单名称
            workOrder["工单状态"] = state_name
            list_workOrder_strState.append(workOrder)
        # 截取工单更新日期和创建日期的日期
        list_dataKey = ["工单创建日期", "工单更新日期"]
        list_workOrder = TimeFormat(list_workOrder_strState, list_dataKey).CaptureTheAate("%Y-%m-%d")
        return list_workOrder,post_Parameter,url

    def TheRepairSquare_sjTicketServe_details(self,post_Parameter):
        """
        工单详情
        :return:
        """
        new_workOrder_details=[]
        JSESSIONID = self.FilterParameters["登录用户JSESSIONID"]
        # 调用小程序--详情页面
        workOrder_details,url = TheRepairOrderInterface(JSESSIONID, post_Parameter).sjTicketServe_details()
        # 因为只有一条数据，所有加转化成列表
        new_workOrder_details.append(workOrder_details)
        """编译从接口工单清单返回的数据"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
        compile_workOrder = workOrder_compile(new_workOrder_details).connector_one(self.FilterParameters) # 编译调用小程序--首页--工单接口
        return compile_workOrder ,post_Parameter,url

class OtherInterfaces_actualValue:
    """其他接口实际值"""

    def __init__(self, JSESSIONID, FilterParameters=None,post_Parameter=None):
        """
        :param JSESSIONID:
        :param post_Parameter: 接口要传入的post参数
        """
        self.JSESSIONID = JSESSIONID
        self.FilterParameters=FilterParameters
        self.post_Parameter = post_Parameter
        self.compile_actualValue = None

    def findGroupList_actualValue(self):
        """
        查询所有群组(服务台改派用)
        :return:
        """
        # 调用接口获取接口返回值
        list_actualValue,url = UserAppController(self.JSESSIONID, None).findGroupList()
        # 编译接口返回值
        list_workOrder = OtherInterfaces_compile(self.JSESSIONID, list_actualValue).findGroupList_compile()
        # list_workOrder=[{'群组ID': '1c60c437542f44c8f8aa83a7c6a08dff9', '群组名称': '机动组5'}]
        return list_workOrder,url

    def findUserListByGroup_actualValue(self,group_id):
        """
        工单操作改派选人
        :return:
        """
        post_Parameter={"群组ID":group_id}
        # 调用接口获取接口返回值
        list_actualValue, url = UserAppController(self.JSESSIONID, None).findUserListByGroup(post_Parameter)
        # 编译接口返回值
        list_workOrder = OtherInterfaces_compile(self.JSESSIONID, list_actualValue).findUserListByGroup_compile()
        # list_workOrder=[{'用户ID': '5c2e57e50d904563b78acc6091970a67', '用户名称': '运维人员四'}, {'用户ID': 'fa20e86b843b4a53936d714afb967a7b', '用户名称': '运维组长'}]
        return list_workOrder, url


"""Added the provider_user_id to the flask_dance_oauth table

Revision ID: 9e57c4ed8a45
Revises: 1ab080a61204
Create Date: 2019-01-05 00:38:30.274975

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '9e57c4ed8a45'
down_revision = '1ab080a61204'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('flask_dance_oauth', sa.Column('provider_user_id', sa.String(length=256), nullable=True))
    op.create_unique_constraint(op.f('uq_flask_dance_oauth_provider_user_id'), 'flask_dance_oauth', ['provider_user_id'])
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint(op.f('uq_flask_dance_oauth_provider_user_id'), 'flask_dance_oauth', type_='unique')
    op.drop_column('flask_dance_oauth', 'provider_user_id')
    # ### end Alembic commands ###


from pyrr import Vector3, vector, vector3, matrix44
from math import sin, cos, radians

class Camera:
    def __init__(self):
        # posicion inicial de la camara
        self.camera_pos = Vector3([0.0, 4.0, 3.0])

        # establecer las direcciones de la camara, en que coordenadas se encuentra el frente, arriba y a la derecha
        self.camera_front = Vector3([0.0, 0.0, -1.0])
        self.camera_up = Vector3([0.0, 1.0, 0.0])
        self.camera_right = Vector3([1.0, 0.0, 0.0])

        # sensibilidad del mouse para el movimiento de la camara
        self.mouse_sensitivity = 0.25
        self.jaw = -90
        self.pitch = 0

    # actualizacion de la vista para la camara actual
    def get_view_matrix(self):
        return matrix44.create_look_at(self.camera_pos, self.camera_pos + self.camera_front, self.camera_up)

    # capturar y procesar el movimiento del mouse
    def process_mouse_movement(self, xoffset, yoffset, constrain_pitch=True):
        # calculamos el movimiento de xoffset y yoffset multiplicado por el movimiento del mouse denotado por su sensitividad
        xoffset *= self.mouse_sensitivity
        yoffset *= self.mouse_sensitivity

        # calculamos el movimiento horizontal y vertical de la camara
        self.jaw += xoffset
        self.pitch += yoffset

        # limitar la rotacion de la camara a solo 45° vertical y horizontalmente
        if constrain_pitch:
            if self.pitch > 45:
                self.pitch = 45
            if self.pitch < -45:
                self.pitch = -45

        self.update_camera_vectors()

    # movimiento de la camara
    def update_camera_vectors(self):
        # vector 3 local para almacenar el movimiento de la camara
        front = Vector3([0.0, 0.0, 0.0])

        # se calcula la nueva ubicacion de la camara haciendo uso de trigonometria
        front.x = cos(radians(self.jaw)) * cos(radians(self.pitch))
        front.y = sin(radians(self.pitch))
        front.z = sin(radians(self.jaw)) * cos(radians(self.pitch))

        # actualizar la nueva ubicacion de la camara
        self.camera_front = vector.normalise(front)
        self.camera_right = vector.normalise(vector3.cross(self.camera_front, Vector3([0.0, 1.0, 0.0])))
        self.camera_up = vector.normalise(vector3.cross(self.camera_right, self.camera_front))

    # movimiento WASD para la camara
    def process_keyboard(self, direction, velocity):
        if direction == "FORWARD":
            self.camera_pos += self.camera_front * velocity

        if direction == "BACKWARD":
            self.camera_pos -= self.camera_front * velocity

        if direction == "LEFT":
            self.camera_pos -= self.camera_right * velocity

        if direction == "RIGHT":
            self.camera_pos += self.camera_right * velocity


# from django_filters import rest_framework as filters

# from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import generics, permissions, mixins, status
from rest_framework.exceptions import ValidationError
from rest_framework.filters import SearchFilter
from rest_framework.response import Response

from .models import Post, Upvote, Comment
from .serializers import (
    PostSerializer,
    UpvoteSerializer,
    CommentSerializer,
)
from .services import PaginationPosts
from .permissions import (
    AuthorRightsPermission,
    AuthorRightsPermissionPost,
    CommentAuthorRightsPermission,
)

class PostList(generics.ListCreateAPIView):
    """
    Endpoint for creating and viewing posts

    permission_classes - list custom permissions for user who interacts with posts
    pagination_class - custom pagination class
    filter_backends - list of filter classes
    search_fields - based on this list of fields, filtering will be applied
    """

    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, AuthorRightsPermission]
    pagination_class = PaginationPosts
    filter_backends = [SearchFilter]
    search_fields = ["title", "author__username", "comment__content"]

    """ set author of post to currently logged in user """

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

class PostRetrieveDestroy(generics.RetrieveDestroyAPIView):
    """
    Endpoint for retrieving and deleting posts
    """

    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [
        permissions.IsAuthenticatedOrReadOnly,
        AuthorRightsPermissionPost,
    ]

    """
    delete particular post that belongs to logged in user,
    preventing user from deleting other users' posts
    """

    def delete(self, request, *args, **kwargs):
        post = Post.objects.filter(pk=self.kwargs["pk"], author=self.request.user)
        if post.exists():
            return self.destroy(request, *args, **kwargs)
        else:
            raise ValidationError("This is not your post!")

class UpvoteCreate(generics.CreateAPIView, mixins.DestroyModelMixin):
    """
    Endpoint for upvoting and deleting upvote from posts
    """

    serializer_class = UpvoteSerializer
    permission_classes = [permissions.IsAuthenticated, AuthorRightsPermission]

    """ get the upvote, which was made by logged in user to a particular post, if exists """

    def get_queryset(self):
        user = self.request.user
        post = Post.objects.get(pk=self.kwargs["pk"])
        return Upvote.objects.filter(upvoter=user, post=post)

    """ create an upvote, if not upvoted already, otherwise throw an exception """

    def perform_create(self, serializer):
        if self.get_queryset().exists():
            raise ValidationError("You already upvoted that post")
        serializer.save(
            upvoter=self.request.user, post=Post.objects.get(pk=self.kwargs["pk"])
        )

    """ delete upvote, if upvoted already, otherwise throw an exception """

    def delete(self, request, *args, **kwargs):
        if self.get_queryset().exists():
            self.get_queryset().delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            raise ValidationError(
                "For deleting upvote you should first upvote the post..."
            )

class CommentCreate(generics.ListCreateAPIView, mixins.DestroyModelMixin):
    """
    Endpoint for creating a comment to particular post
    """

    serializer_class = CommentSerializer
    permission_classes = [permissions.IsAuthenticated, AuthorRightsPermission]

    """ get the comments, which was made by logged in user to a particular post, if exists """

    def get_queryset(self):
        user = self.request.user
        post = Post.objects.get(pk=self.kwargs["pk"])
        return Comment.objects.filter(comment_author=user, commented_on=post)

    """ create a comment to a particular post by logged in user """

    def perform_create(self, serializer):
        serializer.save(
            comment_author=self.request.user,
            commented_on=Post.objects.get(pk=self.kwargs["pk"]),
        )

class CommentRetrieveDestroy(generics.RetrieveDestroyAPIView):
    """
    Endpoint for retrieving and deleting comments
    """

    queryset = Comment.objects.all()
    serializer_class = CommentSerializer
    permission_classes = [
        permissions.IsAuthenticatedOrReadOnly,
        CommentAuthorRightsPermission,
    ]

    """ allow user to delete only his own comments,
        preventing from deleting other users' comments
    """

    def delete(self, request, *args, **kwargs):
        comment = Comment.objects.filter(
            pk=self.kwargs["pk"], comment_author=self.request.user
        )
        if comment.exists():
            return self.destroy(request, *args, **kwargs)
        else:
            raise ValidationError(
                "You are not allowed to delete the other users' comments!"
            )


import copy
import torch
import spacy
import numpy as np
import pandas as pd
from src.utils import read_file, split_ids

nlp = spacy.load("en_core_sci_md")

class ClassificationDataset(torch.utils.data.Dataset):
    """Holder object for the following items:
    @param input_ids... see HF documention.
    @param attention_mask... see HF documentation.
    @param questions are the questions to generate.
    @param question_attention_mask are the attention_masks for the questions
    to generate.
    @param ids is a list of strings that correspond to the ids of the questions
    @param triggers is a separate list of triggers."""

    def __init__(self, input_ids, attention_mask, questions, question_attn_mask, ids, triggers=None):
        self.input_ids = input_ids
        self.attention_mask = attention_mask
        self.questions = questions
        self.question_attn_mask = question_attn_mask
        self.ids = ids
        self.triggers = triggers

    def __getitem__(self, idx):
        item = {
            "input_ids": self.input_ids[idx],
            "attention_mask": self.attention_mask[idx],
            "labels": self.questions[idx],
            "decoder_attention_mask": self.question_attn_mask[idx],
            "id": self.ids[idx],
        }

        return item

    def __len__(self):
        return len(self.input_ids)

class BARTDataLoader:
    """Data loader class for BART model.
    @param data_loc is the file location of the dataframe.
    @param relations_text_loc is the folder location of the n2c2 discharge summaries.
    @param tokenizer is the Huggingface tokenizer.
    @param max_len is the maximum length of a sequence from the passage.
    @param max_q_len is the maximum question length.
    @param chunk_mode will determine how we split up discharge summaries.
    @param split_questions if true, will take a sequence of questions for the
    same trigger and split it up into multiple labels.
    @param trigger_aware if true, will append the trigger to the beginning of
    the inputs to the model.
    @param stride is the typical stride when examining LMs.
    @param val_split is the validation split percent
    @param test_split is the test split percent.
    @param seed is the seed to split the data with."""

    def __init__(
        self,
        data_loc: str,
        relations_text_loc: str,
        tokenizer,
        debug_mode: bool = False,
        max_len: int = 512,
        max_q_len: int = 184,
        max_trigger_len: int = 184,
        chunk_mode: str = "sentence-level",
        split_questions: bool = False,
        stride: int = 512,
        val_split: int = 0.10,
        test_split: int = 0.20,
        seed: int = 0,
    ):

        self.data_loc = data_loc
        self.relations_text_loc = relations_text_loc
        self.tokenizer = tokenizer
        self.debug_mode = debug_mode
        self.max_len = max_len
        self.max_q_len = max_q_len
        self.chunk_mode = chunk_mode
        self.split_questions = split_questions
        self.max_trigger_len = max_trigger_len
        self.stride = stride
        self.val_split = val_split
        self.test_split = test_split
        self.seed = seed

    def _split_data_into_sentences_more_context(self, all_tokenized_outputs):
        """Split the data into sentences and tokenize + pad it.
        @param all_tokenized_outputs is a list of dictionaries with the following input:
            @param input_ids is the input ids of the discharge summary.
            @param trigger_location is a list of 1s and 0s into @param input_ids.
            @param trigger_ids is a list of ids of the text for the trigger_ids.
            @param id is the discharge summary id.
            @param question is ids of the question asked (padded already).
            @param question_attn_mask is the attention mask of the @param question.
            @param sentence_offsets is the offset of the start of each sentence.

        @return a ClassificationDataset instance."""
        xs, questions, question_attn_mask, attn_mask, ids, triggers = [], [], [], [], [], []
        prompt = self.tokenizer.encode(
            " After reading the above EMR, what question do you have about ", add_special_tokens=False
        )
        end_prompt = self.tokenizer.encode("? Question: ", add_special_tokens=False)
        for idx, row in enumerate(all_tokenized_outputs):
            tg_st = row["trigger_location"].index(1)
            tg_end = tg_st + sum(row["trigger_location"])
            sent_onset = np.where(np.asarray(row["sentence_offsets"]) > tg_st)[0][0] - 1
            sent_end = np.where(np.asarray(row["sentence_offsets"]) > tg_end)[0][0]

            tk_onset = row["sentence_offsets"][sent_onset]
            tk_end = row["sentence_offsets"][sent_end]
            selected_sent = row["input_ids"][tk_onset:tk_end][: self.max_len]
            pad = (self.max_len + self.max_trigger_len + len(prompt) + len(end_prompt)) - (
                len(selected_sent) + len(row["trigger_ids"])
            )
            input_ = [self.tokenizer.bos_token_id] + selected_sent
            input_ += prompt + row["trigger_ids"][: self.max_trigger_len] + end_prompt + [self.tokenizer.eos_token_id]
            pad_input = input_ + [self.tokenizer.pad_token_id] * pad

            # Add input_ids, input attn mask, trigger locations, question_ids,
            # question attn map, and the article ID.
            xs.append(pad_input)
            attn_mask.append([1] * len(input_) + [0] * pad)
            questions.append(row["question"][: self.max_q_len])
            question_attn_mask.append(row["question_attn_mask"])
            ids.append(row["id"])
            triggers.append(row["trigger_str"])

        return ClassificationDataset(xs, attn_mask, questions, question_attn_mask, ids, triggers=triggers)

    def _split_data_into_strides(self, all_tokenized_outputs):
        """Split the data into @param stride sized chunks and tokenize + pad it.
        @param all_tokenized_outputs is a list of dictionaries with the following input:
            @param input_ids is the input ids of the discharge summary.
            @param trigger_location is a list of 1s and 0s into @param input_ids.
            @param trigger_ids is a list of ids of the text for the trigger_ids.
            @param id is the discharge summary id.
            @param question is ids of the question asked (padded already).
            @param question_attn_mask is the attention mask of the @param question.
            @param sentence_offsets is the offset of the start of each sentence.

        @return a ClassificationDataset instance."""
        # Now split up data to max_len + stride.
        xs, questions, question_attn_mask, attn_mask, ids, triggers = [], [], [], [], [], []
        prompt = self.tokenizer.encode(
            " After reading the above EMR, what question do you have about ", add_special_tokens=False
        )
        end_prompt = self.tokenizer.encode("? Question: ", add_special_tokens=False)
        for idx, row in enumerate(all_tokenized_outputs):
            for i in range(0, len(row["input_ids"]), self.stride):
                pad = (self.max_len + self.max_trigger_len + len(prompt) + len(end_prompt)) - (
                    len(row["input_ids"][i : i + self.max_len - 2]) + len(row["trigger_ids"])
                )
                input_ = [self.tokenizer.bos_token_id] + row["input_ids"][i : i + self.max_len - 2]
                input_ = input_ + prompt + row["trigger_ids"] + end_prompt + [self.tokenizer.eos_token_id]
                pad_input = input_ + [self.tokenizer.pad_token_id] * pad

                # If all the labels are 0, there are no questions here! Discard.
                trig = row["trigger_location"][i : i + len(input_)]
                if sum(trig) == 0:
                    continue

                # Add input_ids, input attn mask, trigger locations, question_ids,
                # question attn map, and the article ID.
                xs.append(pad_input)
                attn_mask.append([1] * len(input_) + [0] * pad)
                questions.append(row["question"])
                question_attn_mask.append(row["question_attn_mask"])
                ids.append(row["id"])
                triggers.append(row["trigger_str"])

        return ClassificationDataset(xs, attn_mask, questions, question_attn_mask, ids, triggers=triggers)

    def _split_data_into_no_inputs(self, all_tokenized_outputs):
        """Split the data into @param stride sized chunks and tokenize + pad it.
        @param all_tokenized_outputs is a list of dictionaries with the following input:
            @param input_ids is the input ids of the discharge summary.
            @param trigger_location is a list of 1s and 0s into @param input_ids.
            @param trigger_ids is a list of ids of the text for the trigger_ids.
            @param id is the discharge summary id.
            @param question is ids of the question asked (padded already).
            @param question_attn_mask is the attention mask of the @param question.
            @param sentence_offsets is the offset of the start of each sentence.

        @return a ClassificationDataset instance."""
        to_pad_length = max([len(x["trigger_ids"]) for x in all_tokenized_outputs])
        xs, questions, question_attn_mask, attn_mask, ids, triggers = [], [], [], [], [], []
        for idx, row in enumerate(all_tokenized_outputs):
            pad_tokens = to_pad_length - len(row["trigger_ids"])
            xs.append(row["trigger_ids"] + [self.tokenizer.pad_token_id] * pad_tokens)
            attn_mask.append([1] * len(row["trigger_ids"]) + [0] * pad_tokens)
            questions.append(row["question"])
            question_attn_mask.append(row["question_attn_mask"])
            ids.append(row["id"])
            triggers.append(row["trigger_str"])

        return ClassificationDataset(xs, attn_mask, questions, question_attn_mask, ids, triggers)

    def _tokenize_df(self, df, is_training):
        """Turn a dataframe into tokenized + padded inputs + labels.
        @param df is the dataframe to process.
        @param is_training is if the dataframe output is for training or evaluating."""
        all_tokenized_outputs = []
        for index, row in df.iterrows():
            text, remapper = read_file(row.id, self.relations_text_loc)
            tokenized_output = self.tokenizer(text, return_offsets_mapping=True, add_special_tokens=False)

            # Find the offset
            labels = [0] * len(tokenized_output.input_ids)
            new_st, new_end = remapper[row.start_index], remapper[row.end_index]
            tok_st = np.where(np.asarray(tokenized_output.offset_mapping) > new_st)[0][0]
            tok_end = np.where(np.asarray(tokenized_output.offset_mapping) > new_end)[0][0]
            for i in range(tok_st, tok_end + 1):
                labels[i] = 1

            # Add to our map
            tk_q = self.tokenizer(row.question, max_length=self.max_q_len, padding="max_length")
            tk_tr = self.tokenizer(
                row.reasoning, max_length=self.max_trigger_len, truncation=True, add_special_tokens=False
            )
            sentence_ch_offsets = [x.end_char for x in nlp(text).sents]
            sentence_tk_offsets = [
                np.where(np.asarray(tokenized_output.offset_mapping) > x)[0][0] for x in sentence_ch_offsets[:-1]
            ]
            sentence_tk_offsets.append(len(tokenized_output.input_ids) - 1)

            outputs_ = {
                "input_ids": tokenized_output.input_ids,
                "trigger_location": labels,
                "trigger_ids": tk_tr["input_ids"],
                "id": row.id,
                "question": tk_q["input_ids"],
                "question_attn_mask": tk_q["attention_mask"],
                "sentence_offsets": sentence_tk_offsets,
                "trigger_str": row.reasoning,
            }

            if self.split_questions and is_training:
                tk_qs = [
                    self.tokenizer(q + "?", max_length=self.max_q_len, padding="max_length")
                    for q in row.question.split("?")[:-1]
                ]
                for q in tk_qs:
                    c_outputs_ = copy.deepcopy(outputs_)
                    c_outputs_["question"] = q["input_ids"]
                    c_outputs_["question_attn_mask"] = q["attention_mask"]
                    all_tokenized_outputs.append(c_outputs_)
            else:
                all_tokenized_outputs.append(outputs_)

        if self.chunk_mode == "sentence-level":
            return self._split_data_into_sentences_more_context(all_tokenized_outputs)
        elif self.chunk_mode == "split-level":
            return self._split_data_into_strides(all_tokenized_outputs)
        else:
            return self._split_data_into_no_inputs(all_tokenized_outputs)

    def tokenize_generated_df(self, df):
        """Turn a dataframe into tokenized + padded inputs + labels. Use this function
        for when trying to get predictions on dataset with predicted triggers.
        @param df is the dataframe to process. This DF must have a column named
        `text`."""
        all_tokenized_outputs = []
        for index, row in df.iterrows():
            text = row["text"]

            tokenized_output = self.tokenizer(text, return_offsets_mapping=True, add_special_tokens=False)

            # Find the offset
            labels = [0] * len(tokenized_output.input_ids)
            new_st, new_end = row.st_ch, row.end_ch
            try:
                tok_st = np.where(np.asarray(tokenized_output.offset_mapping) > new_st)[0][0]
                tok_end = np.where(np.asarray(tokenized_output.offset_mapping) > new_end)[0][0]
            except:
                tok_end = len(tokenized_output.offset_mapping) - 1

            for i in range(tok_st, tok_end + 1):
                labels[i] = 1

            # Add to our map
            tk_tr = self.tokenizer(
                row.trigger, max_length=self.max_trigger_len, truncation=True, add_special_tokens=False
            )
            sentence_ch_offsets = [x.end_char for x in nlp(text).sents]
            sentence_tk_offsets = [
                np.where(np.asarray(tokenized_output.offset_mapping) > x)[0][0] for x in sentence_ch_offsets[:-1]
            ]
            sentence_tk_offsets.append(len(tokenized_output.input_ids) - 1)

            outputs_ = {
                "input_ids": tokenized_output.input_ids,
                "trigger_location": labels,
                "trigger_ids": tk_tr["input_ids"],
                "id": row.id,
                "question": [self.tokenizer.bos_token_id],
                "question_attn_mask": [1],
                "sentence_offsets": sentence_tk_offsets,
                "trigger_str": row.trigger,
            }

            all_tokenized_outputs.append(outputs_)

        if self.chunk_mode == "sentence-level":
            return self._split_data_into_sentences_more_context(all_tokenized_outputs)
        elif self.chunk_mode == "split-level":
            return self._split_data_into_strides(all_tokenized_outputs)
        else:
            return self._split_data_into_no_inputs(all_tokenized_outputs)

    def load_data(self) -> (ClassificationDataset, ClassificationDataset, ClassificationDataset):
        """Load the data and split it."""
        df = pd.read_csv(self.data_loc)
        ordered_ids = []
        seen = set()
        for id_ in list(df.id.values):
            if not (id_ in seen):
                seen.add(id_)
                ordered_ids.append(id_)

        tr_ids, val_ids, test_ids = split_ids(
            ordered_ids, seed=self.seed, val_split=self.val_split, test_split=self.test_split
        )

        # Create each df
        tr_df = df[df.id.isin(tr_ids)]
        vl_df = df[df.id.isin(val_ids)]
        te_df = df[df.id.isin(test_ids)]

        # If we are in debug mode, use a smaller percent of the data.
        if self.debug_mode:
            tr_df = tr_df[: int(len(tr_df) * 0.1)]
            vl_df = vl_df[: int(len(vl_df) * 0.1)]
            te_df = te_df[: int(len(te_df) * 0.1)]

        # Now tokenize each df
        tr_set = self._tokenize_df(tr_df, is_training=True)
        vl_set = self._tokenize_df(vl_df, is_training=False)
        te_set = self._tokenize_df(te_df, is_training=False)
        return tr_set, vl_set, te_set


import random
import numpy as np

import keras
from keras.models import Sequential
from keras.models import model_from_json
from keras.layers import Dense, SimpleRNN, GRU, LSTM
from keras.layers import Dropout

class kerasModels(object):

    def __init__(self, n_in, hidden_layer_size, n_out, hidden_layer_type, output_type='linear', dropout_rate=0.0, loss_function='mse', optimizer='adam'):
        """ This function initialises a neural network

        :param n_in: Dimensionality of input features
        :param hidden_layer_size: The layer size for each hidden layer
        :param n_out: Dimensionality of output features
        :param hidden_layer_type: the activation types of each hidden layers, e.g., TANH, LSTM, GRU, BLSTM
        :param output_type: the activation type of the output layer, by default is 'LINEAR', linear regression.
        :param dropout_rate: probability of dropout, a float number between 0 and 1.
        :type n_in: Integer
        :type hidden_layer_size: A list of integers
        :type n_out: Integrer
        """

        self.n_in  = int(n_in)
        self.n_out = int(n_out)

        self.n_layers = len(hidden_layer_size)

        self.hidden_layer_size = hidden_layer_size
        self.hidden_layer_type = hidden_layer_type

        assert len(self.hidden_layer_size) == len(self.hidden_layer_type)

        self.output_type   = output_type
        self.dropout_rate  = dropout_rate
        self.loss_function = loss_function
        self.optimizer     = optimizer

        # create model
        self.model = Sequential()

    def define_feedforward_model(self):
        seed = 12345
        np.random.seed(seed)

        # add hidden layers
        for i in range(self.n_layers):
            if i == 0:
                input_size = self.n_in
            else:
                input_size = self.hidden_layer_size[i - 1]

            self.model.add(Dense(
                    units=self.hidden_layer_size[i],
                    activation=self.hidden_layer_type[i],
                    kernel_initializer="normal",
                    input_dim=input_size))
            self.model.add(Dropout(self.dropout_rate))

        # add output layer
        self.final_layer = self.model.add(Dense(
            units=self.n_out,
            activation=self.output_type.lower(),
            kernel_initializer="normal",
            input_dim=self.hidden_layer_size[-1]))

        # Compile the model
        self.compile_model()

    def define_sequence_model(self):
        seed = 12345
        np.random.seed(seed)

        # add hidden layers
        for i in range(self.n_layers):
            if i == 0:
                input_size = self.n_in
            else:
                input_size = self.hidden_layer_size[i - 1]

            if self.hidden_layer_type[i]=='rnn':
                self.model.add(SimpleRNN(
                        units=self.hidden_layer_size[i],
                        input_shape=(None, input_size),
                        return_sequences=True))
            elif self.hidden_layer_type[i]=='gru':
                self.model.add(GRU(
                        units=self.hidden_layer_size[i],
                        input_shape=(None, input_size),
                        return_sequences=True))
            elif self.hidden_layer_type[i]=='lstm':
                self.model.add(LSTM(
                        units=self.hidden_layer_size[i],
                        input_shape=(None, input_size),
                        return_sequences=True))
            elif self.hidden_layer_type[i]=='blstm':
                self.model.add(LSTM(
                        units=self.hidden_layer_size[i],
                        input_shape=(None, input_size),
                        return_sequences=True,
                        go_backwards=True))
            else:
                self.model.add(Dense(
                        units=self.hidden_layer_size[i],
                        activation=self.hidden_layer_type[i],
                        kernel_initializer="normal",
                        input_shape=(None, input_size)))

        # add output layer
        self.final_layer = self.model.add(Dense(
            units=self.n_out,
            input_dim=self.hidden_layer_size[-1],
            kernel_initializer='normal',
            activation=self.output_type.lower()))

        # Compile the model
        self.compile_model()

    def define_stateful_model(self, batch_size=25, seq_length=200):
        seed = 12345
        np.random.seed(seed)

        # params
        batch_size = batch_size
        timesteps  = seq_length

        # add hidden layers
        for i in range(self.n_layers):
            if i == 0:
                input_size = self.n_in
            else:
                input_size = self.hidden_layer_size[i - 1]

            if hidden_layer_type[i]=='lstm':
                self.model.add(LSTM(
                        units=self.hidden_layer_size[i],
                        batch_input_shape=(batch_size, timesteps, input_size),
                        return_sequences=True,
                        stateful=True))   #go_backwards=True))
            elif self.hidden_layer_type[i]=='blstm':
                self.model.add(LSTM(
                        units=self.hidden_layer_size[i],
                        batch_input_shape=(batch_size, timesteps, input_size),
                        return_sequences=True,
                        stateful=True,
                        go_backwards=True))
            else:
                self.model.add(Dense(
                        units=self.hidden_layer_size[i],
                        activation=self.hidden_layer_type[i],
                        kernel_initializer="normal",
                        batch_input_shape=(batch_size, timesteps, input_size)))

        # add output layer
        self.final_layer = self.model.add(Dense(
            units=self.n_out,
            input_dim=self.hidden_layer_size[-1],
            kernel_initializer='normal',
            activation=self.output_type.lower()))

        # Compile the model
        self.compile_model()

    def compile_model(self):
        self.model.compile(loss=self.loss_function, optimizer=self.optimizer, metrics=['accuracy'])

    def save_model(self, json_model_file, h5_model_file):
        # serialize model to JSON
        model_json = self.model.to_json()
        with open(json_model_file, "w") as json_file:
            json_file.write(model_json)
        # serialize weights to HDF5
        self.model.save_weights(h5_model_file)
        print("Saved model to disk")

    def load_model(self, json_model_file, h5_model_file):
        #### load the model ####
        json_file = open(json_model_file, 'r')
        loaded_model_json = json_file.read()
        json_file.close()
        loaded_model = model_from_json(loaded_model_json)
        loaded_model.load_weights(h5_model_file)
        print("Loaded model from disk")

        #### compile the model ####
        self.model = loaded_model
        self.compile_model()


import sys
from pathlib import Path

import tiktoken
from dotenv import load_dotenv
from langchain import LLMChain, OpenAI, PromptTemplate
from langchain.chains.mapreduce import MapReduceChain
from langchain.chains.summarize import load_summarize_chain
from langchain.docstore.document import Document
from langchain.text_splitter import CharacterTextSplitter
from pqdm.threads import pqdm
from rich.console import Console

load_dotenv()
MODEL_NAME = "gpt-3.5-turbo-16k"
console = Console()
llm = OpenAI(model=MODEL_NAME, temperature=0)
console.print("Using model", llm.model_name, style="bold green")
text_splitter = CharacterTextSplitter()

def test_splitter(file: Path):
    content = file.read_text()
    texts = text_splitter.split_text(content)
    print(len(texts))

def main(file: Path):
    content = file.read_text()
    texts = text_splitter.split_text(content)
    docs = [Document(page_content=t) for t in texts]
    chain = load_summarize_chain(llm, chain_type="map_reduce")
    response = chain.run(docs)
    console.print(response, style="bold green")

def summary(file: Path):
    content = file.read_text()
    texts = text_splitter.split_text(content)
    texts = [content]
    template = PromptTemplate(
        input_variables=["text"],
        template="Summarize the following text and give me key points: \n{text}",
    )
    chain = LLMChain(llm=llm, prompt=template)
    responses = pqdm(texts, lambda t: chain.run(text=t), n_jobs=8)
    for response in responses:
        console.print(response, style="blue")
    Path("summary2c.md").write_text("\n".join(responses))
    # docs = [Document(page_content=t) for t in texts]

    # chain = load_summarize_chain(llm, chain_type="map_reduce")
    # response = chain.run(docs)

def get_document_length(file: Path):
    content = file.read_text()
    # texts = text_splitter.split_text(content)
    encoding = tiktoken.encoding_for_model(MODEL_NAME)
    tokens = encoding.encode(content)
    print("Tokens:", len(tokens))

if __name__ == "__main__":
    # main(Path(sys.argv[1]))
    # test_splitter(Path(sys.argv[1]))
    get_document_length(Path(sys.argv[1]))
    summary(Path(sys.argv[1]))


import sys
import pygame as pg

from gamestates import CoinTossScreen, ShootOut, DustSettling, PlayerSelect, Instructions, TitleScreen
from state_engine import Game

def run_game():
    print('initializing game')
    pg.init()
    screen = pg.display.set_mode((1024, 576))
    states = {
        "TITLESCREEN": TitleScreen(),
        "PLAYERSELECT": PlayerSelect(),
        "INSTRUCTIONS": Instructions(),
        "COINTOSS": CoinTossScreen(),
        "SHOOTOUT": ShootOut(),
        "DUSTSETTLING": DustSettling()
    }
    game = Game(screen, states, "TITLESCREEN")
    print('running game')
    game.run()
    pg.quit()
    sys.exit()

if __name__ == "__main__":
    run_game()


import time
from river import compose, ensemble, linear_model, metrics, neighbors, reco, facto,drift
from river import neural_net as nn
from river import optim, preprocessing, tree, datasets
from EvOAutoML import regression, pipelinehelper
from EvOAutoML.config import AUTOML_REGRESSION_PIPELINE, REGRESSION_PARAM_GRID
import itertools
from river import feature_extraction, stats, utils
import calendar
import numbers
import string
import math
import six
import numpy as np

COMBINATION_STRATEGY_MAJORITY_VOTING = 'Majority Voting Strategy'
COMBINATION_STRATEGY_WEIGHTED_AVERAGE = 'Weighted Average Strategy'
COMBINATION_STRATEGY_BEST_MODEL = 'Best Model Strategy'
COMBINATION_STRATEGY_BEST_MODELS_AVERAGED = 'Best Models Weighted Average Strategy'

MODEL_SEED = 42

def get_hour(x):
    x['hour'] = x['moment'].hour
    return x

def get_month(x):
    return {
        calendar.month_name[month]: month == x['month'].month
        for month in range(1, 13)
    }

def get_month_distances(x):
    return {
        calendar.month_name[month]: math.exp(-(x['month'].month - month) ** 2)
        for month in range(1, 13)
    }

def get_ordinal_date(x):
    return {'ordinal_date': x['month'].toordinal()}

def get_date_features(x):
    weekday = x['date'].weekday()
    return {'weekday': weekday, 'is_weekend': weekday in (5, 6)}

def millis(start_time):
    """
    Calculates the time spent in an interval
    Parameters in milliseconds.
    ----------
    name : start_time
      The initial time tick
    """
    elapsed = time.time_ns()-start_time
    return elapsed/1000000

# {'vendor_id': '2', 'pickup_datetime': datetime.datetime(2016, 1, 1, 0, 0, 17),
# 'passenger_count': 5, 'pickup_longitude': -73.98174285888672, 'pickup_latitude': 40.71915817260742,
# 'dropoff_longitude': -73.93882751464845, 'dropoff_latitude': 40.82918167114258, 'store_and_fwd_flag': 'N'}
def parse_Taxis(tr):
    tr["distance"] = (
        HaversineDistance(
            tr["pickup_latitude"], tr["pickup_longitude"],
            tr["dropoff_latitude"], tr["dropoff_longitude"]
        )
    )
    tr["log_distance"] = np.log(tr['distance'])
    # tr["log_duration"] = np.log(tr['trip_duration'])
    tr['pickup_day_of_week'] = tr["pickup_datetime"].dt.week
    # day_name().astype('category')
    tr['pickup_month_of_year'] = tr["pickup_datetime"].dt.month_name().astype('category')
    tr['pickup_hour_of_day'] = tr["pickup_datetime"].dt.hour.astype('category')

    # Consider adding orders for categorical data to get the plots in nice way
    # tr['pickup_day_of_week'] = tr['pickup_day_of_week'].cat.set_categories(['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'], ordered=True)
    # tr['pickup_month_of_year'] = tr['pickup_month_of_year'].cat.set_categories(['January','February','March','April','May','June','July','August','September','October','November','December'], ordered=True)
    # tr['pickup_hour_of_day'] = tr['pickup_hour_of_day'].cat.set_categories(np.arange(0,24), ordered=True)

    return tr

def HaversineDistance(lat1,lon1,lat2,lon2):
	"""
	Returns the distance between two lat-long cordinates in km
	"""
	REarth = 6371
	lat = np.abs(np.array(lat1)-np.array(lat2))*np.pi/180
	lon = np.abs(np.array(lon1)-np.array(lon2))*np.pi/180
	lat1 = np.array(lat1)*np.pi/180
	lat2 = np.array(lat2)*np.pi/180
	a = np.sin(lat/2)*np.sin(lat/2)+np.cos(lat1)*np.cos(lat2)*np.sin(lon/2)*np.sin(lon/2)
	d = 2*np.arctan2(np.sqrt(a),np.sqrt(1-a))
	d = REarth*d
	return d

def parse_MovieLens100k(x):
    # return {'user':int(x['user']), 'item':int(x['item'])}
    return {'user': 2.0}

def parse_Mv(x):
    # brown
    x3 = 0
    if x['x3'] == 'green':
        x3 = 1
    elif x['x3'] == 'red':
        x3 = 2

    x7 = 0
    if x['x7'] == 'yes':
        x7 = 1

    x8 = 0
    if x['x8'] == 'large':
        x8 = 1

    return {'x1': x['x1'], 'x2': x['x2'], 'x3': x3, 'x4': x['x4'], 'x5': x['x5'],
            'x6': x['x6'], 'x7': x7, 'x8': x8, 'x9': x['x9'], 'x10': x['x10']}

def get_preprocessing_pipeline(dataset_name):
    model_pipeline = compose.Pipeline()
    if dataset_name == datasets.Bikes().__class__.__name__:
        extract_features = compose.Select('clouds', 'humidity',
                                          'pressure', 'temperature', 'wind')
        extract_features += (
            get_hour |
            feature_extraction.TargetAgg(
                by=['station', 'hour'], how=stats.Mean())
        )

        model_pipeline |= extract_features
    elif dataset_name == datasets.AirlinePassengers().__class__.__name__:
        extract_features = compose.TransformerUnion(
            get_ordinal_date, get_month_distances)
        model_pipeline |= extract_features

    elif dataset_name == datasets.Restaurants().__class__.__name__:
        to_discard = ['store_id', 'date', 'genre_name',
                      'area_name', 'latitude', 'longitude']
        model = get_date_features
        for n in [7, 14, 21]:
            model += feature_extraction.TargetAgg(
                by='store_id', how=stats.RollingMean(n))
        model |= compose.Discard(*to_discard)
        model_pipeline |= model

    elif dataset_name == datasets.synth.Mv().__class__.__name__:
        model_pipeline = compose.FuncTransformer(parse_Mv)

    elif dataset_name == datasets.Taxis().__class__.__name__:
        model_pipeline = compose.FuncTransformer(parse_Taxis)

    elif dataset_name == datasets.MovieLens100K().__class__.__name__:
        to_discard = ['title', 'occupation', 'genres', 'gender', 'zip_code']
        model_pipeline = compose.Discard(*to_discard)

        model_pipeline = compose.Select('user', 'item')
        model_pipeline += (
            compose.Select('genres') | compose.FuncTransformer(split_genres)
        )
        model_pipeline+= (
            compose.Select('age') | compose.FuncTransformer(bin_age)
        )
        # model_pipeline = preprocessing.PredClipper(
        #     regressor=model_pipeline,
        #     y_min=0,
        #     y_max=5
        # )
        print(model_pipeline)
    return model_pipeline

def split_genres(x):
    genres = x['genres'].split(', ')
    return {f'genre_{genre}': 1 / len(genres) for genre in genres}

def bin_age(x):
    if x['age'] <= 18:
        return {'age_0-18': 1}
    elif x['age'] <= 32:
        return {'age_19-32': 1}
    elif x['age'] < 55:
        return {'age_33-54': 1}
    else:
        return {'age_55-100': 1}

def get_LinearRegression(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = linear_model.LinearRegression(
        intercept_lr=0,
        optimizer=optim.SGD(0.001)
    )
    model |= scale | learn
    return model

def get_KNN_Model(n_neighbors, dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()
    learn = neighbors.KNNRegressor(
        window_size=672, n_neighbors=n_neighbors)
    model |= scale | learn
    return model

def get_Adaptive_random_forest(n_models, dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()
    learn = ensemble.AdaptiveRandomForestRegressor(n_models=n_models,
                                                   seed=MODEL_SEED,
                                                   metric=metrics.RMSE(),
                                                   binary_split=True,
                                                   max_depth=5
                                                   )
    model |= scale | learn
    return model

def get_EWA_regressor(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    optimizers = [
        optim.SGD(0.01),
        optim.RMSProp(),
        optim.AdaGrad()
    ]

    learn = ensemble.EWARegressor([
        linear_model.LinearRegression(
            optimizer=o, intercept_lr=.1)
        for o in optimizers
    ],
        learning_rate=0.005
    )

    model |= scale | learn
    return model

def get_BAGG(n_models, dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = ensemble.BaggingRegressor(
        model=linear_model.LinearRegression(intercept_lr=0.1),
        n_models=n_models,
        seed=MODEL_SEED
    )
    model |= scale | learn
    return model

def get_SRPRegressor(n_models, dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()
    base_model = tree.HoeffdingTreeRegressor(grace_period=50)
    learn = ensemble.SRPRegressor(
        model=base_model,
        training_method="patches",
        n_models=n_models,
        seed=MODEL_SEED,
        drift_detector=drift.ADWIN()
    )
    model |= scale | learn
    return model

def get_SGTRegressor(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = tree.SGTRegressor(
        delta=0.01,
        lambda_value=0.01,
        grace_period=20,
        feature_quantizer=tree.splitter.DynamicQuantizer(std_prop=0.1)
    )
    model |= scale | learn
    return model

def get_LogisticRegression(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = linear_model.LogisticRegression(
        optimizer=optim.SGD(.1))
    model |= scale | learn
    return model

def get_PARRegression(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = linear_model.PARegressor(
        C=0.01,
        mode=2,
        eps=0.1,
        learn_intercept=False
    )
    model |= scale | learn
    return model

# https://riverml.xyz/0.7.0/api/neural-net/MLPRegressor/
def get_MLPRegression(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = nn.MLPRegressor(
        # two hidden layers with 10 and 10 neurons, respectively.
        hidden_dims=(10, 10),
        activations=(
            nn.activations.Identity,
            nn.activations.Identity,
            nn.activations.Identity,
        ),
        optimizer=optim.SGD(1e-4),
        seed=MODEL_SEED
    )
    model |= scale | learn
    return model

def get_HATR(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = tree.HoeffdingAdaptiveTreeRegressor(
        grace_period=100,
        leaf_prediction='adaptive',
        model_selector_decay=0.5,
        max_depth=5,
        splitter=tree.splitter.TEBSTSplitter(),
        seed=MODEL_SEED
    )
    model |= scale | learn
    return model

def get_HTR(dataset_name):
    model = get_preprocessing_pipeline(dataset_name)
    scale = preprocessing.StandardScaler()

    learn = tree.HoeffdingTreeRegressor(
        grace_period=100,
        leaf_prediction='adaptive',
        model_selector_decay=0.5,
        max_depth=5,
        splitter=tree.splitter.TEBSTSplitter()
    )
    model |= scale | learn
    return model

def get_EVOAutoML():
    model_pipeline = compose.Pipeline(
        ('Scaler', pipelinehelper.PipelineHelperTransformer([
            ('StandardScaler', preprocessing.StandardScaler()),
            # ('MinMaxScaler', preprocessing.MinMaxScaler()),
            # ('MinAbsScaler', preprocessing.MaxAbsScaler()),
            # ('OneHotEnconder', preprocessing.OneHotEncoder())
        ])),
        ('Regressor', pipelinehelper.PipelineHelperRegressor([
            ('HT', tree.HoeffdingTreeRegressor()),
            ('KNN', neighbors.KNNRegressor()),
            ('HATR', tree.HoeffdingAdaptiveTreeRegressor()),
            ('PAR', linear_model.PARegressor()),
            ('LR', linear_model.LinearRegression())
        ]))
    )
    EvOAutoML_model = regression.EvolutionaryBaggingRegressor(
        model=model_pipeline,
        param_grid={
            'Scaler': model_pipeline.steps['Scaler'].generate({}),
            # 'Regressor': AUTOML_REGRESSION_PIPELINE.steps['Regressor'].generate({
            'Regressor': model_pipeline.steps['Regressor'].generate({
                'HT__binary_split': [True, False],
                'HT__max_depth': [10, 30, 60, 100],
                'HT__grace_period': [10, 100, 200],
                'HT__max_size': [5, 10],
                'HT__leaf_prediction': ['adaptive', 'mean'],

                'KNN__n_neighbors': [1, 5, 20],
                'KNN__window_size': [100, 500, 1000],
                'KNN__p': [1, 2, 5],

                'HATR__max_size': [5, 10],
                'HATR__grace_period': [10, 100, 200],
                'HATR__leaf_prediction': ['adaptive', 'mean'],
                'HATR__model_selector_decay': [0.1, 0.5],

                'PAR__mode': [1, 2],

                'LR__l2': [.0, .01, .001],
            })
        },
        seed=42
    )
    return EvOAutoML_model


import torch.nn as nn
from torchvision.ops import nms
import numpy as np
import torch
from PIL import Image

def bbox_iou(box1, box2):
    b1_x1, b1_y1, b1_x2, b1_y2 = box1[:, 0], box1[:, 1], box1[:, 2], box1[:, 3]
    b2_x1, b2_y1, b2_x2, b2_y2 = box2[:, 0], box2[:, 1], box2[:, 2], box2[:, 3]
    inter_rect_x1 = torch.max(b1_x1, b2_x1)
    inter_rect_y1 = torch.max(b1_y1, b2_y1)
    inter_rect_x2 = torch.min(b1_x2, b2_x2)
    inter_rect_y2 = torch.min(b1_y2, b2_y2)
    inter_area = torch.clamp(inter_rect_x2 - inter_rect_x1 + 1, min=0) * \
                 torch.clamp(inter_rect_y2 - inter_rect_y1 + 1, min=0)
    b1_area = (b1_x2 - b1_x1 + 1) * (b1_y2 - b1_y1 + 1)
    b2_area = (b2_x2 - b2_x1 + 1) * (b2_y2 - b2_y1 + 1)
    iou = inter_area / (b1_area + b2_area - inter_area + 1e-16)
    return iou

class DecodeBox(nn.Module):
    def __init__(self, anchors, num_classes, img_size):
        super(DecodeBox, self).__init__()
        self.anchors = anchors
        self.num_anchors = len(anchors)
        self.num_classes = num_classes
        self.bbox_attrs = 5 + num_classes
        self.img_size = img_size

    def forward(self, input):
        batch_size = input.size(0)
        input_height = input.size(2)
        input_width = input.size(3)
        stride_h = self.img_size[1] / input_height
        stride_w = self.img_size[0] / input_width
        scaled_anchors = [(anchor_width / stride_w, anchor_height / stride_h) for anchor_width, anchor_height in self.anchors]

        prediction = input.view(batch_size, self.num_anchors,
                                self.bbox_attrs, input_height, input_width).permute(0, 1, 3, 4, 2).contiguous()
        x = torch.sigmoid(prediction[..., 0])
        y = torch.sigmoid(prediction[..., 1])
        w = prediction[..., 2]
        h = prediction[..., 3]
        conf = torch.sigmoid(prediction[..., 4])
        pred_cls = torch.sigmoid(prediction[..., 5:])
        FloatTensor = torch.cuda.FloatTensor if x.is_cuda else torch.FloatTensor
        LongTensor = torch.cuda.LongTensor if x.is_cuda else torch.LongTensor
        grid_x = torch.linspace(0, input_width - 1, input_width).repeat(input_height, 1).repeat(
            batch_size * self.num_anchors, 1, 1).view(x.shape).type(FloatTensor)
        grid_y = torch.linspace(0, input_height - 1, input_height).repeat(input_width, 1).t().repeat(
            batch_size * self.num_anchors, 1, 1).view(y.shape).type(FloatTensor)
        anchor_w = FloatTensor(scaled_anchors).index_select(1, LongTensor([0]))
        anchor_h = FloatTensor(scaled_anchors).index_select(1, LongTensor([1]))
        anchor_w = anchor_w.repeat(batch_size, 1).repeat(1, 1, input_height * input_width).view(w.shape)
        anchor_h = anchor_h.repeat(batch_size, 1).repeat(1, 1, input_height * input_width).view(h.shape)
        pred_boxes = FloatTensor(prediction[..., :4].shape)
        pred_boxes[..., 0] = x.data + grid_x
        pred_boxes[..., 1] = y.data + grid_y
        pred_boxes[..., 2] = torch.exp(w.data) * anchor_w
        pred_boxes[..., 3] = torch.exp(h.data) * anchor_h
        scale = torch.Tensor([stride_w, stride_h] * 2).type(FloatTensor)
        output = torch.cat((pred_boxes.view(batch_size, -1, 4) * scale,
                            conf.view(batch_size, -1, 1), pred_cls.view(batch_size, -1, self.num_classes)), -1)
        return output.data

def letterbox(image, size):
    iw, ih = image.size
    w, h = size
    scale = min(w/iw, h/ih)
    nw = int(iw*scale)
    nh = int(ih*scale)
    image = image.resize((nw,nh), Image.BICUBIC)
    new_image = Image.new('RGB', size, (128,128,128))
    new_image.paste(image, ((w-nw)//2, (h-nh)//2))
    return new_image

def NMS(prediction,class_num,conf_thres=0.8,nms_thres=0.2):
    #   转换坐标形式:(x,y,w,h)>(x1,y1,x2,y2)
    box_temp=prediction.new(prediction.shape)
    box_temp[:,:,0]=prediction[:,:,0]-prediction[:,:,2]/2
    box_temp[:,:,1]=prediction[:,:,1]-prediction[:,:,3]/2
    box_temp[:,:,2]=prediction[:,:,0]+prediction[:,:,2]/2
    box_temp[:,:,3]=prediction[:,:,1]+prediction[:,:,3]/2
    prediction[:,:,:4]=box_temp[:,:,:4]

    #   output 存放nms输出
    output = [None for _ in range(len(prediction))]
    #   prediction:(batch_size,2535,7)
    #   7:4+1+2
    #   pred:2535*7
    for index,pred in enumerate(prediction):
        #   cls_conf:最大类别得分 cls_pred:最大类别索引
        cls_conf,cls_pred=torch.max(pred[:,5:7],dim=1,keepdim=True)
        score=pred[:,4]*cls_conf[:,0]
        size_a=pred.shape[0]
        pred=pred[(score>conf_thres).squeeze()]
        size_b=pred.shape[0]
        # print("根据置信度得分删除{}个预测框，还剩{}个预测框".format(size_a-size_b,size_b))

        cls_conf=cls_conf[(score>conf_thres).squeeze()]
        cls_pred=cls_pred[(score>conf_thres).squeeze()]

        if not pred.size(0):
            continue
        #   detection:4+obj_conf+最大类得分+最大类
        detection=torch.cat((pred[:,:5],cls_conf.float(),cls_pred.float()),dim=1)
        # print(detection)
        # print("*****"*15)
        #unique_label包含所有类别
        unique_label=detection[:,-1].cpu().unique()
        #对两个类分别进行NMS算法
        for cls in unique_label:
            is_cls=detection[:,-1]==cls
            # print("当前检测类{}".format(cls))
            #当前类存入detection_class
            detection_class=detection[is_cls]
            # print(detection_class)

            boxes=detection_class[:,:4]             #预测框坐标
            score=detection_class[:,4]*detection_class[:,5]

            # keep保存NMS过滤后的预测框索引
            keep=nms(boxes=boxes,scores=score,iou_threshold=nms_thres)
            # print(keep)
            # print("*****" * 15)
            max_detection=detection_class[keep]
            # print("*****" * 15)
            # print(max_detection)
            output[index] = max_detection if output[index] is None else torch.cat(
                (output[index], max_detection))
    return output

def remove_gray(top, left, bottom, right, input_shape, image_shape):
    new_shape = image_shape*np.min(input_shape/image_shape)
    offset = (input_shape-new_shape)/2./input_shape
    scale = input_shape/new_shape
    box_yx = np.concatenate(((top+bottom)/2,(left+right)/2),axis=-1)/input_shape
    box_hw = np.concatenate((bottom-top,right-left),axis=-1)/input_shape
    box_yx = (box_yx - offset) * scale
    box_hw *= scale
    box_mins = box_yx - (box_hw / 2.)
    box_maxes = box_yx + (box_hw / 2.)
    boxes =  np.concatenate([
        box_mins[:, 0:1],
        box_mins[:, 1:2],
        box_maxes[:, 0:1],
        box_maxes[:, 1:2]
    ],axis=-1)
    boxes *= np.concatenate([image_shape, image_shape],axis=-1)
    return boxes


from datetime import datetime, timedelta, timezone

# X-RAY ------
from aws_xray_sdk.core import xray_recorder

from lib.db import db

class UserActivities:
  def run(user_handle):
    #try:
      # X-RAY ------
      # Start a segment
      #segment = xray_recorder.begin_segment('user_activities')

    print("UserActivities.run")
    model = {
      'errors': None,
      'data': None
    }

    if user_handle == None or len(user_handle) < 1:
      model['errors'] = ['blank_user_handle']
    else:
      print("else")
      sql = db.template('users','show')
      results = db.query_object_json(sql,{'handle':user_handle})
      print("results: ", results)
      model['data'] = results

      # X-RAY ------
      # Start a subsegment
      #subsegment = xray_recorder.begin_subsegment('mock-data')
      #dict = {
      #  "now": now.isoformat(),
      #  "results-size": len(model['data'])
      #}
      #segment.put_metadata('key', dict, 'namespace')
    #finally:
    return model


from typing import List

from constants import OUT_OF_VOCABULARY_DELIM, LEFT_PAD_SYMBOL, RIGHT_PAD_SYMBOL

def tokenize(tweet: str, span: int, extended_func: bool = False,
             left_pad_symbol: str = LEFT_PAD_SYMBOL, right_pad_symbol: str = RIGHT_PAD_SYMBOL) -> List[str]:
    """
    Tokenize tweets given a length for the tokens.

    :param left_pad_symbol: Padding symbol for the tweet start
    :param right_pad_symbol: Padding symbol for the tweet end
    :param span: Execution range. Ex: Unigram = 1 character; Bigram = 2 characters; Trigram = 3 characters
    :param tweet: Tweet input string
    :param extended_func: If True, apply extended functionality for BYOM
    :return: List of tokens
    """
    if extended_func:
        tweet = left_pad_symbol * (span - 1) + tweet + right_pad_symbol * (span - 1)
    tweet_len = len(tweet)
    return [tweet[c:c + span] for c in range(tweet_len) if (c + span) <= tweet_len and
            OUT_OF_VOCABULARY_DELIM not in tweet[c:c + span]]


# -*- coding: utf-8 -*-
"""
Created on Fri Jun  3 19:17:33 2016

@author: xf05id1
"""

from epics import PV
import time

ttl1 = PV('XF:05IDD-ES:1{EVR:1-Out:FP1}Src:Scale-SP')
BT1p = PV('XF:05IDD-VA:1{BT:1-CCG:1}P-I')

def movefs():
#    ttl1.put(4)
#    time.sleep(2)
#    ttl1.put(3)
     shut_fast.high_cmd()
     time.sleep(2)
     shut_fast.low_cmd()

open_wait = 1 #min
close_wait = 5 #min
setp = 5E-6

num_cycle = 24*12*3

for i in range(num_cycle+1):
    print('open fast shutter')
    movefs()
    while(BT1p.get() < setp):
        print('pressure: '+str(BT1p.get()))
        print('wait '+str(open_wait)+' min')
        time.sleep(open_wait*60)
    print('pressure: '+str(BT1p.get()))
    print('close fast shutter')
    movefs()
    print('wait '+str(close_wait)+' min')
    time.sleep(close_wait*60)


import math_tool
import json
from handle_cd_method import trim_comma_in_paras, trim_method

def cal_single_rel(bug_report_vector, augmented_method_vector):
    return math_tool.cosine_similarity(bug_report_vector, augmented_method_vector)

def load_augmentation_methods(path):
    with open(path, 'r') as f:
        dic = json.loads(f.read())
    return dic

def cal_rel(brv, dic):
    result_dic = dict()
    for key in dic:
        rel_value = cal_single_rel(brv, dic[key])
        result_dic[key] = rel_value

    ranked_dic = _rank_dic(result_dic)
    return ranked_dic

def _rank_dic(dic):
    sorted_dic = sorted(dic.items(), key = lambda x: x[1], reverse = True)
    return sorted_dic

# read "link_buggyMethods/xxx" file and return a dictionary
def load_link_dic(path):
    dic = {}
    f = open(path, 'r')
    lines = f.readlines()
    for line in lines:
        line = line.strip()
        if len(line) > 0:
            parts = line.split('\t')
            br_id = parts[0]
            pm_lists_str = parts[1].rstrip()
            pm_lists = pm_lists_str.split('外')
            for pm_list in pm_lists:
                pm_parts = pm_list.split('内')
                if len(pm_parts) < 2:
                    print(pm_parts, "in this sentence can not find PATH / METHOD_NAME !")
                    continue
                path = '/' + '/'.join((pm_parts[0].split('/'))[2:])
                method = pm_parts[1]

                path_method = path + '#' + trim_method(trim_comma_in_paras(method))

                if br_id not in dic:
                    dic.setdefault(br_id, []).append(path_method)
                else:
                    dic[br_id].append(path_method)
    return dic

# for item in ['Closure']: #'Time', 'Mockito', 'Lang', 'Math'
#     dic = load_link_dic("/Users/lienming/Downloads/final_defects4j/linked-bugMethods/" + item + "_bugId_buggyMethodsName")
# for ms in dic['Time_3']:
#     print(ms)

# print(load_link_dic("/Users/lienming/Downloads/final_defects4j/linked-bugMethods/Time_bugId_buggyMethodsName")['Time_25'])


# venv\scripts\activate
# $env:FLASK_APP = "app"
# $env:FLASK_DEBUG = 1
# python -m flask run
#
# http://flask-bootstrap.azurewebsites.net/

import datetime

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.dates import DayLocator, DateFormatter
from io import BytesIO

import random

from flask import Flask, render_template, Response, request, redirect, url_for, json
from urllib.request import Request, urlopen
from flask_paginate import Pagination, get_page_parameter

app = Flask(__name__)
users = []

@app.route("/")
def home():
    return render_template('jumbotron.html')

@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

@app.route('/email', methods=['POST'])
def email():
    return render_template('email.html', email=request.form.get('email_address'))

@app.route("/json/local")
def json_local():
    with open('data/users.json') as f:
        local_users = json.load(f)
    return render_template('json_local.html', users=local_users)

@app.route("/json/remote")
def json_remote():
    url = "https://api.github.com"
    response = urlopen(url)
    github_urls = json.loads(response.read())
    return render_template('json_remote.html', urls=github_urls)

@app.route('/json/users', methods=['GET'])
def json_users():

    global users

    if len(users) == 0:
        with open('data/users.json') as f:
            users = json.load(f)

    return render_template('json_users.html', users=users)

@app.route('/json/users/add', methods=['POST'])
def json_add():

    global users

    users.append({"name": request.form.get('name')})
    return redirect(url_for('json_users'))

# Random Duck API

duck_url = "https://random-d.uk/api/v2/"

# paginate, filter and sort

@app.route("/duck")
def duck():

    global duck_url

    query = duck_url + "random"
    req = Request(query, headers={'User-Agent': 'Mozilla/5.0'})
    res = urlopen(req)
    duck_json = json.loads(res.read())

    return render_template('duck/duck.html', duck=duck_json)

@app.route("/ducks")
def ducks():

    global duck_url
    # "image_count": 282,
    # "images": []

    search = False
    q = request.args.get('q')
    if q:
        search = True

    page = request.args.get(get_page_parameter(), type=int, default=1)

    query = duck_url + "list"
    req = Request(query, headers={'User-Agent': 'Mozilla/5.0'})
    res = urlopen(req)
    ducks_json = json.loads(res.read())

    pagination = Pagination(page=page, total=ducks_json['image_count'], search=search, record_name='ducks')

    return render_template('duck/ducks.html', ducks=ducks_json['images'], url=duck_url, pagination=pagination)

# FHRS API

fhrs_url = "http://api.ratings.food.gov.uk"

@app.route("/countries")
def countries():

    global fhrs_url

    # page = 1
    # page_size = 10

    # Create the URL string to query the FHRS API
    # In this case, http://api.ratings.food.gov.uk/Countries/basic
    # I found the API query failed without adding, headers = {'x-api-version': 2}
    # You may want to limit the number of results you bring back from the API
    # For example, query = fhrs_url + '/Countries/basic/{}/{}'.format(page, page_size)

    query = fhrs_url + '/Countries/basic'
    headers = {'x-api-version': 2}

    req = Request(query, headers=headers)
    res = urlopen(req)
    fhrs_json = json.loads(res.read())

    return render_template('countries.html', data=fhrs_json)

# Graph

@app.route("/graph")
def graph():
    str_date = datetime.datetime.now()
    return render_template('graph.html', date=str_date)

@app.route('/plot.png')
def plot_png():
    fig = create_figure()
    output = BytesIO()
    FigureCanvas(fig).print_png(output)
    return Response(output.getvalue(), mimetype='image/png')

def create_figure():

    dataset = "./data/NY-City-Central-Park-Historical-Temperature-Data.csv"
    # dataframe
    df = pd.read_csv(dataset)
    # Convert the date column, 18690101, to a Python datetime
    df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')
    # Locate a range of dates
    start_date = '07-01-2020'
    end_date = '08-01-2020'
    mask = (df['date'] > start_date) & (df['date'] <= end_date)
    df = df.loc[mask]
    # Convert the min, max columns from Fahredheit to Celsius
    # (32°F − 32) × 5/9 = 0°C
    df['min'] = (df['min']-32) * 5/9
    df['max'] = (df['max']-32) * 5/9
    # Create the Figure
    fig = Figure()
    ax = fig.subplots()
    ax.plot(df['date'], df['max'])
    #defines the tick location
    ax.xaxis.set_major_locator(DayLocator())
    #defines the label format
    ax.xaxis.set_major_formatter(DateFormatter("%d-%m"))
    ax.tick_params(axis="x", labelrotation= 90)

    return fig


from rozlink import app, db
from flask import request, redirect, abort
from flask_login import login_required, logout_user, current_user
from rozlink.utils.bot import create_unique_token
import telebot
from rozlink.telegram_bot import bot

@app.route('/tgauth')
@login_required
def tgauth():
    current_user.telegram_token = create_unique_token()
    db.session.add(current_user)
    try:
        db.session.commit()
    except Exception as e:
        print(e)
    print(f"{current_user.login}: {current_user.telegram_token}")
    return redirect("https://telegram.me/{}?start={}".format(app.config["TELEGRAM_BOT_NAME"], current_user.telegram_token))

@app.route(app.config["WEBHOOK_URL_PATH"], methods=['POST'])
def webhook():
    if request.headers.get('content-type') == 'application/json':
        json_string = request.get_data().decode('utf-8')
        update = telebot.types.Update.de_json(json_string)
        bot.process_new_updates([update])
        return ''
    else:
        abort(403)