# -*- coding: utf-8 -*-
"""
Created on Wed Dec  1 18:21:57 2021

@author: david.cheung1
"""
import pandas as pd
from io import StringIO
import glob
import math
from date import date
import logging
from tkinter import Tk
from tkinter.filedialog import askopenfilename
from datetime import datetime
import os.path

# function #################################################################################################################################################
def convert_dotout_or_excel_to_df(source_fileName: str , grid: int, header_pollutant: str) -> pd.DataFrame:
    if '.out' in source_fileName:
        f = open(f'{directory}/{grid}/{source_fileName}', 'r')
        data = f.read()[2:]
        df = pd.read_csv(StringIO(data))
        df.reset_index(inplace=True)
        df = df[list(df.columns[4:df.shape[1]-1])] # drop unwanted columns
        df['date'] = date_index.loc[:,('date')].astype('int64')
        # df['date'] = date_index['date'].astype('int64')
        df.set_index('date', inplace = True)

        # get header from reference excel
        for header_file in glob.glob(f'{directory}/{grid}/{grid}_{header_pollutant}*xlsx'):
            continue
        df1 = pd.read_excel(header_file)
        df =  df.set_axis(list(df1)[1:], axis=1, inplace=False)

    elif '.xlsx' in source_fileName:
        df = pd.read_excel(f'{directory}/{grid}/{source_fileName}')
        df = df[list(df.columns[1:])]
        df['date'] = date_index.loc[:,('date')].astype('int64')
        # df['date'] = date_index['date'].astype('int64')
        df.set_index('date', inplace = True)
    return(df)

def get_unique_pollutant_in_a_grid(grid: int) -> pd.array:
    totalPollutant = pd.unique(input1Table['AQO_Pollutant'][input1Table.Grid == grid])
    return totalPollutant

def get_background_CONC(pollutant:str, PATH_filename:str, Grid:int) -> pd.DataFrame:
    background_CONC = pd.read_csv(f'{directory}/{Grid}/{PATH_filename}', delim_whitespace=True)
    background_CONC = background_CONC.drop([0,1])
    background_CONC = background_CONC[background_CONC.columns[4:]]
    background_CONC = background_CONC.astype(str).astype(float)
    background_CONC.reset_index(inplace = True, drop = True)
    background_CONC['NOx'] = background_CONC['NO2'] + background_CONC['NO']
    background_CONC['date'] = date_index['date'].astype('int64')
    background_CONC.set_index('date', inplace = True)

    resultdf = background_CONC[f'{pollutant}'].to_frame()
    return resultdf

def jenkin_calculation(CONC: float) -> list:
    OX = float(inputPara['Value'][inputPara.Parameter == 'OX'])
    JK = float(inputPara['Value'][inputPara.Parameter == 'j/k'])
    NO2 = ((CONC + OX + JK) - math.sqrt((CONC + OX + JK)**2 - 4*CONC*OX))/2
    return NO2

def OLM_calculation(pollu_val_df:pd.DataFrame, NO_df:pd.DataFrame) -> pd.DataFrame:
    PATH_filename = pd.unique(pollu_val_df["Revised_PATH_Level1"])[0]
    Grid = pd.unique(pollu_val_df["Grid"])[0]
    pollutant = "O3"
    PATH_background_CONC_df = get_background_CONC(pollutant, PATH_filename, Grid).apply(lambda x: x*(46/48))
    PATH_background_CONC_df = PATH_background_CONC_df.rename(columns={'O3':'PATH_03'})
    NO_df = pd.concat([NO_df, PATH_background_CONC_df], axis=1)

    # case: lv1 + lv2 + lv3
    if str(pd.unique(pollu_val_df["ASR_Height_for_PATH_Level3"])[0]) != 'nan':
        PATH2_height = pd.unique(pollu_val_df["ASR_Height_for_PATH_Level2"])[0]
        PATH2_filename = pd.unique(pollu_val_df["PATH_Level2"])[0]
        PATH2_background_CONC_df = get_background_CONC(pollutant, PATH2_filename, Grid).apply(lambda x: x*(46/48))
        PATH2_background_CONC_df = PATH2_background_CONC_df.rename(columns={'O3':'PATH2_03'})
        NO_df = pd.concat([NO_df, PATH2_background_CONC_df], axis=1)

        PATH3_height = pd.unique(pollu_val_df["ASR_Height_for_PATH_Level3"])[0]
        PATH3_filename = pd.unique(pollu_val_df["PATH_Level_3"])[0]
        PATH3_background_CONC_df = get_background_CONC(pollutant, PATH3_filename, Grid).apply(lambda x: x*(46/48))
        PATH3_background_CONC_df = PATH3_background_CONC_df.rename(columns={'O3':'PATH3_03'})
        NO_df = pd.concat([NO_df, PATH3_background_CONC_df], axis=1)
        # logging.info('OLM calculation()  case2: lv1 + lv2 + lv3')
        for columns in NO_df:
            # sum up with lv1 PATH
            if float(columns.split('_')[-1]) < PATH2_height:
                NO_df[columns] = NO_df.apply(lambda row: min(row[columns], row["PATH_03"]), axis = 1)

            # sum up with lv2 PATH
            elif PATH2_height <= float(columns.split('_')[-1]) and float(columns.split('_')[-1]) < PATH3_height:
                NO_df[columns] = NO_df.apply(lambda row: min(row[columns], row["PATH2_03"]), axis = 1)

            # sum up with lv3 PATH
            elif PATH3_height <= float(columns.split('_')[-1]):
                NO_df[columns] = NO_df.apply(lambda row: min(row[columns], row["PATH3_03"]), axis = 1)

        NO_df = NO_df.drop(columns = ['PATH_03','PATH2_03','PATH3_03'])

    # case: lv1 + lv2
    elif str(pd.unique(pollu_val_df["ASR_Height_for_PATH_Level2"])[0]) != 'nan':
        PATH2_height = pd.unique(pollu_val_df["ASR_Height_for_PATH_Level2"])[0]
        PATH2_filename = pd.unique(pollu_val_df["PATH_Level2"])[0]
        PATH2_background_CONC_df = get_background_CONC(pollutant, PATH2_filename, Grid).apply(lambda x: x*(46/48))
        PATH2_background_CONC_df = PATH2_background_CONC_df.rename(columns={'O3': 'PATH2_03'})
        NO_df = pd.concat([NO_df, PATH2_background_CONC_df], axis=1)
        # logging.info('OLM calculation() case2: lv1 + lv2')
        for columns in NO_df:
            # sum up with lv1 PATH
            if float(columns.split('_')[-1]) < PATH2_height:
                NO_df[columns] = NO_df.apply(lambda row: min(row[columns], row["PATH_03"]), axis = 1)

            # sum up with lv2 PATH
            else:
                NO_df[columns] = NO_df.apply(lambda row: min(row[columns], row["PATH2_03"]), axis = 1)

        NO_df = NO_df.drop(columns = ['PATH_03','PATH2_03'])

    # case: lv1 only
    else:
        for columns in NO_df:
            NO_df[columns] = NO_df.apply(lambda row: min(row[columns], row["PATH_03"]), axis = 1)

        NO_df = NO_df.drop(columns = ['PATH_03'])

    return NO_df

def classify_pollutant_from_input1Table(pollu_val: str, jenkin: str) -> str:
    if pollu_val == 'NO2':
        if jenkin == 'Y':
            pollutant = 'NOx'
        else:
            pollutant = 'NO2'
    elif pollu_val == 'RSP':
        pollutant = 'RSP'
    elif pollu_val == 'FSP':
        pollutant = 'FSP'

    return pollutant

def classify_NOx_NO(OLM_df: pd.DataFrame)->pd.DataFrame:
    final_df = pd.DataFrame()
    NO_df = pd.DataFrame()
    NO2_df = pd.DataFrame()
    for i in OLM_df.index:
        source_fileName = str(OLM_df['Filename'].loc[i])
        grid = int(OLM_df['Grid'].loc[i])
        header_pollutant = str(OLM_df['AQO_Pollutant'].loc[i])
        ratio = float(OLM_df['NO/NO2_ratio'].loc[i])
        temp_df = convert_dotout_or_excel_to_df(source_fileName, grid, header_pollutant)
        # filter NOx, NO, NO2 in Source_Pollutant column
        if  str(OLM_df['Source_Pollutant'].loc[i]) == 'NOx':

            # get NO from NOx first
            df1 = temp_df.applymap(lambda x: x*ratio)
            if NO_df.shape[0] < 1:
                NO_df = df1
            else:
                NO_df = NO_df + df1
            # get NO2 from NOx
            df1 = temp_df.applymap(lambda x: x*(1 - ratio))
            if NO2_df.shape[0] < 1:
                NO2_df = df1
            else:
                NO2_df = NO2_df + df1

        elif str(OLM_df['Source_Pollutant'].loc[i]) == 'NO':
            if NO_df.shape[0] < 1:
                NO_df = temp_df
            else:
                NO_df = NO_df + temp_df

        else:

            if NO2_df.shape[0] < 1:
                NO2_df = temp_df
            else:
                NO2_df = NO2_df + temp_df

    if NO_df.shape[0] > 1:
        NO_df = OLM_calculation(OLM_df, NO_df)
        if final_df.shape[0] > 1:
            if NO2_df.shape[0] > 1:
                final_df = final_df + NO_df + NO2_df
            else:
                final_df = final_df + NO_df
        else:
            if NO2_df.shape[0] > 1:
                final_df = NO_df + NO2_df
            else:
                final_df = NO_df
    else:
        if final_df.shape[0] > 1:
            final_df = final_df + NO2_df
        else:
            final_df = NO2_df

    return final_df

def PATH_PATH2_PATH3(pollu_val_df: pd.DataFrame, process_df: pd.DataFrame, pollutant: str) -> pd.DataFrame:
    Grid = pd.unique(pollu_val_df["Grid"])[0]

    PATH_filename = pd.unique(pollu_val_df["Revised_PATH_Level1"])[0]
    PATH_background_CONC_df = get_background_CONC(pollutant, PATH_filename, Grid)
    PATH2_height = pd.unique(pollu_val_df["ASR_Height_for_PATH_Level2"])[0]
    PATH2_filename = pd.unique(pollu_val_df["PATH_Level2"])[0]
    PATH2_background_CONC_df = get_background_CONC(pollutant, PATH2_filename, Grid)
    PATH3_height = pd.unique(pollu_val_df["ASR_Height_for_PATH_Level3"])[0]
    PATH3_filename = pd.unique(pollu_val_df["PATH_Level_3"])[0]
    PATH3_background_CONC_df = get_background_CONC(pollutant, PATH3_filename, Grid)
    # logging.info('case: PATH + PATH2 + PATH3')
    for columns in process_df:
        # sum up with lv1 PATH
        if float(columns.split('_')[-1]) < PATH2_height:
            process_df[columns] = process_df[columns] + PATH_background_CONC_df[pollutant]

        # sum up with lv2 PATH
        elif PATH2_height <= float(columns.split('_')[-1]) and float(columns.split('_')[-1]) < PATH3_height:
            process_df[columns] = process_df[columns] + PATH2_background_CONC_df[pollutant]

        # sum up with lv3 PATH
        elif PATH3_height <= float(columns.split('_')[-1]):
            process_df[columns] = process_df[columns] + PATH3_background_CONC_df[pollutant]

    return process_df

def PATH_PATH2(pollu_val_df: pd.DataFrame, process_df: pd.DataFrame, pollutant: str) -> pd.DataFrame:
    Grid = pd.unique(pollu_val_df["Grid"])[0]

    PATH_filename = pd.unique(pollu_val_df["Revised_PATH_Level1"])[0]
    PATH_background_CONC_df = get_background_CONC(pollutant, PATH_filename, Grid)
    PATH2_height = pd.unique(pollu_val_df["ASR_Height_for_PATH_Level2"])[0]
    PATH2_filename = pd.unique(pollu_val_df["PATH_Level2"])[0]
    PATH2_background_CONC_df = get_background_CONC(pollutant, PATH2_filename, Grid)
    # logging.info('case: PATH + PATH2')
    for columns in process_df:
        # sum up with lv1 PATH
        if float(columns.split('_')[-1]) < PATH2_height:
            process_df[columns] = process_df[columns] + PATH_background_CONC_df[pollutant]

        # sum up with lv2 PATH
        else:
            process_df[columns] = process_df[columns] + PATH2_background_CONC_df[pollutant]

    return process_df

def jenkin_and_other_pollutant(pollu_val_df: pd.DataFrame) -> pd.DataFrame:
    AQO_Pollutant = str(pd.unique(pollu_val_df['AQO_Pollutant'])[0])
    # 1. fliter input dataframe to NO2 + jenkin if there is Jenkin
    if AQO_Pollutant == 'NO2':
        jenkin = "Y"
        pollu_val_df = pollu_val_df[(pollu_val_df.Jenkin_Method != "O")]
    else:
        jenkin = 'N'

    #  2. combine all the raw data file together as process_df
    pollutant = classify_pollutant_from_input1Table(AQO_Pollutant, jenkin)
    process_df = pd.DataFrame()
    for i in pollu_val_df.index:
        source_fileName = str(pollu_val_df['Filename'].loc[i])
        grid = int(pollu_val_df['Grid'].loc[i])
        header_pollutant = str(pollu_val_df['AQO_Pollutant'].loc[i])
        # logging.info(f'f(x)_jenkin_and_other_pollutant part 2: import data from {source_fileName}')
        if process_df.shape[0] < 1:
            process_df = convert_dotout_or_excel_to_df(source_fileName, grid, header_pollutant)

        else:
            process_df = process_df + convert_dotout_or_excel_to_df(source_fileName, grid, header_pollutant)

    # 3. get background concentration from PATH file + add background concentreation
    PATH_filename = pd.unique(pollu_val_df["Revised_PATH_Level1"])[0]
    Grid = pd.unique(pollu_val_df["Grid"])[0]
    PATH_background_CONC_df = get_background_CONC(pollutant, PATH_filename, Grid)

    # case: lv1 + lv2 + lv3
    if str(pd.unique(pollu_val_df["ASR_Height_for_PATH_Level3"])[0]) != 'nan':
        process_df = PATH_PATH2_PATH3(pollu_val_df, process_df, pollutant)
    # case: lv1 + lv2
    elif str(pd.unique(pollu_val_df["ASR_Height_for_PATH_Level2"])[0]) != 'nan':
        process_df = PATH_PATH2(pollu_val_df, process_df, pollutant)
    # case: lv1 only
    else:
        for columns in process_df:
            process_df[columns] = process_df[columns] + PATH_background_CONC_df[pollutant]

    # 4. apply Jenkin calculation if there is Jenkin
    if jenkin == 'Y':
        # logging.info('f(x)_jenkin_and_other_pollutant part 4: apply Jenkin calculation')
        process_df = process_df.applymap(lambda x : jenkin_calculation(x))

    return process_df

def OLM(pollu_val_df: pd.DataFrame) -> pd.DataFrame:
    # 0. create OLM df
    OLM_df = pollu_val_df[(pollu_val_df.AQO_Pollutant == 'NO2') & (pollu_val_df.Jenkin_Method != 'J')]
    OLM_df.reset_index(inplace = True,drop=True)
    # 1. classify into NO OLM, OLM1 only, OLM2 only, OLM3 only into 4 dataframe
    # NO OLM
    OLM0_df = OLM_df[(OLM_df.OLM1 != 'Y') & (OLM_df.OLM2 != 'Y') & (OLM_df.OLM3 != 'Y')]
    OLM0_df.reset_index(inplace = True,drop=True)
    # OLM1 only
    OLM1_df = OLM_df[(OLM_df.OLM1 == 'Y')]
    OLM1_df.reset_index(inplace = True,drop=True)
    # OLM2 only
    OLM2_df = OLM_df[(OLM_df.OLM2 == 'Y')]
    OLM2_df.reset_index(inplace = True,drop=True)
    # OLM3 only
    OLM3_df = OLM_df[(OLM_df.OLM3 == 'Y')]
    OLM3_df.reset_index(inplace = True,drop=True)

    # 2. append OLM df to dfs if OLM df has value
    lists = [OLM0_df,OLM1_df,OLM2_df,OLM3_df]
    dfs = []
    for df in lists:
        if df.shape[0] > 1:
            dfs.append(df)

    # 3. import raw data from source file in each dataframe
    result_df = pd.DataFrame()
    for df in dfs:
        if result_df.shape[0] < 1:
            result_df = classify_NOx_NO(df)
        else:
            result_df = result_df + classify_NOx_NO(df)
    # 4. sum up PATH background concentration
    PATH_filename = pd.unique(pollu_val_df["Revised_PATH_Level1"])[0]
    Grid = pd.unique(OLM_df["Grid"])[0]
    pollutant = "NO2"
    PATH_background_CONC_df = get_background_CONC(pollutant, PATH_filename, Grid)

    # case: lv1 + lv2 + lv3
    if str(pd.unique(OLM_df["ASR_Height_for_PATH_Level3"])[0]) != 'nan':
        result_df = PATH_PATH2_PATH3(OLM_df, result_df, pollutant)

    # case: lv1 + lv2
    elif str(pd.unique(OLM_df["ASR_Height_for_PATH_Level2"])[0]) != 'nan':
        result_df = PATH_PATH2(OLM_df, result_df, pollutant)
    # case: lv1 only
    else:
        for columns in result_df:
            result_df[columns] = result_df[columns] + PATH_background_CONC_df[pollutant]

    return result_df

def check_output_file_exist(export_filename:str) -> str:
    if os.path.isfile(f'{export_filename}'):
        mode = "a"
    else:
        mode = "w"

    return mode

def check_result_df(result_df:pd.DataFrame):
    if result_df.shape[0] < 1:
        logging.error(f'Group {i}, no result df reture in OLM part')

def export_result_df_to_excel(result_df:pd.DataFrame, export_filename:str, group_id:int, group_pollutant:str):
    check_result_df(result_df)
    mode = check_output_file_exist(export_filename)
    # export to output.xlsx
    with pd.ExcelWriter(f'{export_filename}',mode = mode) as writer:
                result_df.to_excel(writer, sheet_name=f'{group_id}_{group_pollutant}')

if __name__ == '__main__':
    # logging #################################################################################################################################################
    logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s', level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S')
    logging.info("Script start")

    # variable #################################################################################################################################################
    Tk().withdraw()
    logging.info("Please select Cumulative_Input excel in file dialog.")
    filename = askopenfilename()
    inputfile = filename
    directory = inputfile.rsplit('/',1)[0]
    date_index = pd.read_csv(StringIO(date))
    now = datetime.now()
    dt_string = now.strftime("%d%m%Y_%H%M")
    export_filename = f'{directory}/Output_{dt_string}.xlsx'

    input1Table = pd.read_excel(inputfile)
    input1Table.columns = input1Table.iloc[4]
    input1Table = input1Table.iloc[5:,0:18]
    input1Table.reset_index(inplace = True, drop = True)
    input1Table = input1Table.dropna(how='all')
    input1Table.columns = [c.replace(' ', '_') for c in input1Table.columns]

    inputPara = pd.read_excel(inputfile)
    inputPara = inputPara.iloc[5:,19:21]
    inputPara.reset_index(inplace = True, drop = True)
    inputPara = inputPara.rename(columns={'Unnamed: 19': 'Parameter', 'Unnamed: 20': 'Value'})

    totalId = pd.unique(input1Table['id'])

    # main script #################################################################################################################################################
    for i in totalId:
        pollu_val_df = input1Table[input1Table.id == i]

        # Step 1: based on group id (id column) to filter the input1Table into pollu_val_df
        # Step 2: input {pollu_val_df} to OLM() or jenkin_and_other_pollutant(), output would be result_df
        # Step 3: check the output {result_df} and export it to Output_(current_date)_(current_time).xlsx
        if "A" in pd.unique(pollu_val_df['Jenkin_Method']):
            # OLM + Jenkin
            logging.info(f'Group {i}, OLM + Jenkin')
            logging.info(f'Group {i}, OLM part start.')
            result_df = OLM(pollu_val_df)
            export_result_df_to_excel(result_df, export_filename, i, "NO2_OLM")
            logging.info(f'Group {i}, OLM part is done.')

            logging.info(f'Group {i}, Jenkin part start.')
            Jenkin_df = pollu_val_df[(pollu_val_df.AQO_Pollutant == 'NO2') & (pollu_val_df.Jenkin_Method != 'O')]
            result_df = jenkin_and_other_pollutant(Jenkin_df)
            export_result_df_to_excel(result_df, export_filename, i, "NO2_Jenkin")
            logging.info(f'Group {i}, Jenkin part is done.')

        else:
            # only OLM
            if "O" in pd.unique(pollu_val_df['Jenkin_Method']):
                logging.info(f'Group {i}, only OLM.')
                logging.info(f'Group {i}, OLM part start.')
                pollu_val_df = input1Table[(input1Table.AQO_Pollutant == 'NO2') & (input1Table.Jenkin_Method == 'O')]
                result_df = OLM(pollu_val_df)
                export_result_df_to_excel(result_df, export_filename, i, "NO2_OLM")
                logging.info(f'Group {i}, OLM part is done.')
            # only Jenkin
            elif "J" in pd.unique(pollu_val_df['Jenkin_Method']):
                logging.info(f'Group {i}, only Jenkin.')
                logging.info(f'Group {i}, Jenkin part start.')
                pollu_val_df = input1Table[(input1Table.AQO_Pollutant == 'NO2') & (input1Table.Jenkin_Method == 'J')]
                result_df = jenkin_and_other_pollutant(pollu_val_df)
                export_result_df_to_excel(result_df, export_filename, i, "NO2_Jenkin")
                logging.info(f'Group {i}, Jenkin part is done.')
            # other pollutant
            else:
                pollu_val = pd.unique(pollu_val_df['AQO_Pollutant'])[0]
                logging.info(f'Group {i}, other pollutant: {pollu_val}.')
                logging.info(f'Group {i}, {pollu_val} start calculation.')
                result_df = jenkin_and_other_pollutant(pollu_val_df)
                export_result_df_to_excel(result_df, export_filename, i, pollu_val)
                logging.info(f'Group {i}, {pollu_val} calculation is done.')

    logging.info("Script End")
    logging.info(f'Output file is in: {export_filename}')


from enum import Enum, auto
import re
from typing import List, Optional, Any, Tuple, Dict
import xml.etree.ElementTree as XML

from errors import ErrorCodes, handle_error

escapes=re.compile(r"\\[0-9]{3}")

class InstructionKey(Enum):
  MOVE = auto()#

  CREATEFRAME = auto()#
  PUSHFRAME = auto()#
  POPFRAME = auto()#

  DEFVAR = auto()#
  CALL = auto()#
  RETURN = auto()#
  PUSHS = auto()#
  POPS = auto()#

  ADD = auto()#
  SUB = auto()#
  MUL = auto()#
  DIV = auto()#
  IDIV = auto()#

  LT = auto()#
  GT = auto()#
  EQ = auto()#

  AND = auto()#
  OR = auto()#
  NOT = auto()#

  INT2CHAR = auto()#
  STRI2INT = auto()#
  INT2FLOAT = auto()#
  FLOAT2INT = auto()#

  READ = auto()#
  WRITE = auto()#
  CONCAT = auto()#
  STRLEN = auto()#
  GETCHAR = auto()#
  SETCHAR = auto()#
  TYPE = auto()#
  JUMP = auto()#

  JUMPIFEQ = auto()#
  JUMPIFNEQ = auto()#

  EXIT = auto()#
  LABEL = auto()#

  DPRINT = auto()#
  BREAK = auto()

  # Stack operations
  CLEARS = auto()#

  ADDS = auto()#
  SUBS = auto()#
  MULS = auto()#
  DIVS = auto()#
  IDIVS = auto()#

  LTS = auto()#
  GTS = auto()#
  EQS = auto()#

  ANDS = auto()#
  ORS = auto()#
  NOTS = auto()#

  INT2CHARS = auto()#
  STRI2INTS = auto()#
  INT2FLOATS = auto()#
  FLOAT2INTS = auto()#

  JUMPIFEQS = auto()#
  JUMPIFNEQS = auto()#

STRING_TO_INSTRUCTION = {
  "MOVE": InstructionKey.MOVE,
  "CREATEFRAME": InstructionKey.CREATEFRAME,
  "PUSHFRAME": InstructionKey.PUSHFRAME,
  "POPFRAME": InstructionKey.POPFRAME,
  "DEFVAR": InstructionKey.DEFVAR,
  "CALL": InstructionKey.CALL,
  "RETURN": InstructionKey.RETURN,
  "PUSHS": InstructionKey.PUSHS,
  "POPS": InstructionKey.POPS,
  "ADD": InstructionKey.ADD,
  "SUB": InstructionKey.SUB,
  "MUL": InstructionKey.MUL,
  "DIV": InstructionKey.DIV,
  "IDIV": InstructionKey.IDIV,
  "LT": InstructionKey.LT,
  "GT": InstructionKey.GT,
  "EQ": InstructionKey.EQ,
  "AND": InstructionKey.AND,
  "OR": InstructionKey.OR,
  "NOT": InstructionKey.NOT,
  "INT2CHAR": InstructionKey.INT2CHAR,
  "STRI2INT": InstructionKey.STRI2INT,
  "INT2FLOAT": InstructionKey.INT2FLOAT,
  "FLOAT2INT": InstructionKey.FLOAT2INT,
  "READ": InstructionKey.READ,
  "WRITE": InstructionKey.WRITE,
  "CONCAT": InstructionKey.CONCAT,
  "STRLEN": InstructionKey.STRLEN,
  "GETCHAR": InstructionKey.GETCHAR,
  "SETCHAR": InstructionKey.SETCHAR,
  "TYPE": InstructionKey.TYPE,
  "LABEL": InstructionKey.LABEL,
  "JUMP": InstructionKey.JUMP,
  "JUMPIFEQ": InstructionKey.JUMPIFEQ,
  "EXIT": InstructionKey.EXIT,
  "DPRINT": InstructionKey.DPRINT,
  "BREAK": InstructionKey.BREAK,

  # Stack operations
  "CLEARS": InstructionKey.CLEARS,

  "ADDS": InstructionKey.ADDS,
  "SUBS": InstructionKey.SUBS,
  "MULS": InstructionKey.MULS,
  "DIVS": InstructionKey.DIVS,
  "IDIVS": InstructionKey.IDIVS,

  "LTS": InstructionKey.LTS,
  "GTS": InstructionKey.GTS,
  "EQS": InstructionKey.EQS,

  "ANDS": InstructionKey.ANDS,
  "ORS": InstructionKey.ORS,
  "NOTS": InstructionKey.NOTS,

  "INT2CHARS": InstructionKey.INT2CHARS,
  "STRI2INTS": InstructionKey.STRI2INTS,
  "INT2FLOATS": InstructionKey.INT2FLOATS,
  "FLOAT2INTS": InstructionKey.FLOAT2INTS,

  "JUMPIFEQS": InstructionKey.JUMPIFEQS,
  "JUMPIFNEQS": InstructionKey.JUMPIFNEQS
}

class ArgumentTypeKey(Enum):
  TYPE = auto()
  LABEL = auto()
  VAR = auto()
  INT = auto()
  FLOAT = auto()
  BOOL = auto()
  STRING = auto()
  NIL = auto()

STRING_TO_ARGUMENT_TYPE = {
  "type": ArgumentTypeKey.TYPE,
  "label": ArgumentTypeKey.LABEL,
  "var": ArgumentTypeKey.VAR,
  "int": ArgumentTypeKey.INT,
  "float": ArgumentTypeKey.FLOAT,
  "bool": ArgumentTypeKey.BOOL,
  "string": ArgumentTypeKey.STRING,
  "nil": ArgumentTypeKey.NIL
}

class FrameTypeKey(Enum):
  GLOBAL = auto()
  LOCAL = auto()
  TEMPORARY = auto()

STRING_TO_FRAME_TYPE = {
  "GF": FrameTypeKey.GLOBAL,
  "LF": FrameTypeKey.LOCAL,
  "TF": FrameTypeKey.TEMPORARY
}

def dec2char(matchobj):
  dec = matchobj.group(0)
  dec = int(dec[1:])
  return chr(dec)

class Argument:
  def __init__(self, t:ArgumentTypeKey, value:str, idx:int):
    self.idx = idx
    self.type = t
    if value is None:
      value = ""

    if self.type == ArgumentTypeKey.NIL and value == "nil":
      self.value = None
    elif self.type == ArgumentTypeKey.INT:
      try:
        self.value = int(value)
      except:
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"Failed to convert value '{value}' to int")
    elif self.type == ArgumentTypeKey.FLOAT:
      try:
        self.value = float(value)
      except:
        try:
          self.value = float.fromhex(value)
        except:
          handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"Failed to convert value '{value}' to float")
    elif self.type == ArgumentTypeKey.BOOL and (value == "true" or value == "false"):
      if value == "true":
        self.value = True
      else:
        self.value = False
    elif self.type == ArgumentTypeKey.STRING:
      self.value = escapes.sub(dec2char, value)
    elif self.type == ArgumentTypeKey.LABEL:
      self.value = value
    elif self.type == ArgumentTypeKey.TYPE:
      if value not in ("float", "int", "bool", "string", "nil"):
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"Argument type can't have value '{value}'")
      self.value = STRING_TO_ARGUMENT_TYPE[value]
    elif self.type == ArgumentTypeKey.VAR and len(value) != 0:
      amp_pos = value.find("@")
      if amp_pos == -1:
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"Can't parse string '{value}' as variable type")

      if value[:amp_pos] not in STRING_TO_FRAME_TYPE.keys():
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"Value '{value[:amp_pos]}' is not valid identificator of frame")

      frame_type = STRING_TO_FRAME_TYPE[value[:amp_pos]]

      variable_name = value[amp_pos + 1:]
      if not variable_name:
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"String '{value}' missing variable name for parsing as variable")

      self.value = (frame_type, variable_name)
    else:
      handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"Type '{self.type}' and value '{value}' is not valid combination of values")

  def __repr__(self):
    return f"Argument(Type: {self.type}, Value: '{self.value}')"

class Instruction:
  def __init__(self, instruction: InstructionKey, order:int, arguments: Optional[List[Argument]] = None):
    self.order = order
    self.instruction = instruction
    self.arguments = arguments if arguments else []

  @classmethod
  def from_element(cls, element: XML.Element):
    if "opcode" not in element.keys() or "order" not in element.keys():
      handle_error(ErrorCodes.XML_BAD_STRUCTURE, "Missing 'opcode' or 'order' instruction attribute")

    instruction_name = element.attrib["opcode"].upper()
    if instruction_name not in STRING_TO_INSTRUCTION.keys():
      handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"'{instruction_name}' is not valid instruction")

    argument_name_list = [arg.tag for arg in element]
    if argument_name_list.count("arg1") > 1 or argument_name_list.count("arg2") > 1 or argument_name_list.count("arg3") > 1:
      handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"'{instruction_name}' have multiple arguments with same name")

    order = element.attrib["order"]
    if not order.isdecimal():
      handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"'{instruction_name}' have invalid order attribute")

    arguments = []
    used_argument_indexes = []
    for argument in element:
      if argument.tag not in ("arg1", "arg2", "arg3"):
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"'{argument.tag}' in instruction '{instruction_name}' is not valid argument of instruction")

      if "type" not in argument.keys():
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"'{argument.tag}' in instruction '{instruction_name}' don't have type attribute")

      type_string = argument.attrib["type"]
      if type_string not in STRING_TO_ARGUMENT_TYPE:
        handle_error(ErrorCodes.INTERN, f"'{type_string}' is not valid type")

      idx = int(argument.tag[3:])
      if idx in used_argument_indexes:
        handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"'{argument.tag}' in instruction '{instruction_name}' is already present")

      used_argument_indexes.append(idx)
      arguments.append(Argument(STRING_TO_ARGUMENT_TYPE[type_string], argument.text, idx))

    # Check if there are no arg3 without arg2 or arg1 or arg2 without arg1
    if (3 in used_argument_indexes and (2 not in used_argument_indexes or 1 not in used_argument_indexes)) or \
      (2 in used_argument_indexes and 1 not in used_argument_indexes):
      handle_error(ErrorCodes.XML_BAD_STRUCTURE, f"'{instruction_name}' have invalid argument indexes")

    arguments.sort(key=lambda x: x.idx)
    return cls(STRING_TO_INSTRUCTION[instruction_name], int(order), arguments)

  def __repr__(self):
    arguments_string = (", ".join([str(arg) for arg in self.arguments])) if self.arguments else ""
    return f"Instruction({self.order}, {self.instruction}, [{arguments_string}])"

class VariableTypeKey(Enum):
  INT = auto()
  FLOAT = auto()
  BOOL = auto()
  STRING = auto()
  NIL = auto()

ArgumentTypeToVariableType = {
  ArgumentTypeKey.INT: VariableTypeKey.INT,
  ArgumentTypeKey.FLOAT: VariableTypeKey.FLOAT,
  ArgumentTypeKey.BOOL: VariableTypeKey.BOOL,
  ArgumentTypeKey.STRING: VariableTypeKey.STRING,
  ArgumentTypeKey.NIL: VariableTypeKey.NIL
}

class Variable:
  def __init__(self, label:str):
    self.__label = label

    self.__type:Optional[VariableTypeKey] = None
    self.__value = None

  def is_initialized(self):
    return self.__type is not None

  def set_value(self, value):
    if isinstance(value, bool):
      self.__type = VariableTypeKey.BOOL
    elif isinstance(value, int):
      self.__type = VariableTypeKey.INT
    elif isinstance(value, float):
      self.__type = VariableTypeKey.FLOAT
    elif isinstance(value, str):
      self.__type = VariableTypeKey.STRING
    elif value is None:
      self.__type = VariableTypeKey.NIL
    else:
      handle_error(ErrorCodes.INTERN, f"Invalid datatype '{type(value)}' passed to variable")
    self.__value = value

  def get_label(self):
    return self.__label

  def get_value(self) -> Tuple[VariableTypeKey, Any]:
    return self.__type, self.__value

  def __repr__(self):
    return f"[{self.__label}:{self.__type}='{self.__value}']"

class Frame:
  def __init__(self, frame_type: FrameTypeKey):
    self.type = frame_type # only for debug

    self.variable_storage:Dict[str, Variable] = {}

  def __get_by_name(self, label:str):
    if not self.__variable_exist(label): return None
    return self.variable_storage.get(label)

  def __variable_exist(self, label:str) -> bool:
    if label in self.variable_storage.keys(): return True
    return False

  def create_variable(self, label:str):
    if self.__variable_exist(label):
      handle_error(ErrorCodes.SEMANTIC_ERROR, f"Variable with name '{label}' already exists in frame of type '{self.type}'")
    self.variable_storage[label] = Variable(label)

  def set_value(self, label:str, value):
    variable = self.__get_by_name(label)
    if variable is None:
      handle_error(ErrorCodes.VARIABLE_DONT_EXIST, f"Variable with name '{label}' doesn't exists in frame of type '{self.type}'")

    variable.set_value(value)

  def get_value(self, label:str) -> Tuple[VariableTypeKey, Any]:
    variable = self.__get_by_name(label)
    if variable is None:
      handle_error(ErrorCodes.VARIABLE_DONT_EXIST, f"Variable with name '{label}' doesn't exists in frame of type '{self.type}'")

    return variable.get_value()

  def get_number_of_initialized_variables(self):
    cnt = 0
    for var in self.variable_storage.values():
      if var.is_initialized():
        cnt += 1

    return cnt

  def __repr__(self):
    variables = "\n\t".join([str(var) for var in self.variable_storage])
    return f"Frame({self.type}:\n\t{variables})"


import sys
import copy
import time

import pandas as pd
import numpy as np
import matplotlib.pylab as plt

from helpers.file_system import write_to_json, write_to_feather
from parameter.mcmc.helpers import compute_acf
from parameter.mcmc.helpers import compute_iact
from parameter.mcmc.helpers import compute_sjd

from palettable.colorbrewer.qualitative import Dark2_8

def print_progress_report(mcmc, proposed_state, state_history, lag=1000):
    """Prints the progress report to screen."""

    i = mcmc.current_iter
    iters_between_reports = mcmc.settings['no_iters_between_progress_reports']

    if (i + 1) % iters_between_reports is not 0:
        return None

    mean_time_per_iter = (time.time() - mcmc.start_time) / i
    est_time_remaining = mean_time_per_iter * (mcmc.settings['no_iters'] - i)

    avg_params = np.zeros(mcmc.no_params_to_estimate)
    for j in range(i):
        avg_params += state_history[j]['params'] / (i + 1)

    avg_accept_rate = 0.0
    if i > (lag + 1):
        for j in range(i - lag + 1, i):
            avg_accept_rate += state_history[j]['accepted'] / float(lag)
    else:
        for j in range(i):
            avg_accept_rate += state_history[j]['accepted'] / (i + 1)

    print("###################################################################")
    print(" Iteration: " + str(i + 1) + " of : "
        + str(mcmc.settings['no_iters']) + " completed.")
    print(" Time per iteration: {:.3f}s and estimated time remaining: {:.3f}s.".format(mean_time_per_iter, est_time_remaining))
    print("")
    print(" Current state of the Markov chain:")
    print( ["%.4f" % v for v in state_history[i-1]['params']])
    print("")
    print(" Proposed next state of the Markov chain:")
    print( ["%.4f" % v for v in proposed_state['params']])
    print("")
    print(" Current posterior mean estimate: ")
    print( ["%.4f" % v for v in avg_params])
    print("")
    print(" Current acceptance rate (over last 1,000 iterations):")
    print(" %.4f" % avg_accept_rate)
    print("")
    print(" Current IACT values (over last 1,000 iterations):")
    print( ["%.2f" % v for v in compute_iact(mcmc, state_history, lag=lag)])
    if mcmc.alg_type is 'qmh':
        if (i > mcmc.settings['memory_length']):
            avg_samples_hessian = 0.0
            avg_hessian_estimated = 0.0
            avg_hessians_corrected = 0.0
            for j in range(i):
                if state_history[j]['hessian_samples'] > 0:
                    avg_samples_hessian += state_history[j]['hessian_samples'] / i
                    avg_hessian_estimated += state_history[j]['hessian_estimated'] * 1.0 / i
                    avg_hessians_corrected += state_history[j]['hessian_corrected'] * 1.0 / i
            print("")
            print(" Mean number of samples for Hessian estimate:")
            print(" {:.4f}".format(avg_samples_hessian))
            print("")
            print(" Rate of successful QN proposal computations:")
            print(" {:.4f}".format(avg_hessian_estimated))
            print("")
            print(" Rate of Hessian correction:")
            print(" {:.4f}".format(avg_hessians_corrected))
    if 'adapted_step_size' in proposed_state:
        print("")
        print(" Current adapted step size (with target accept prob: {}):".format(mcmc.settings['adapt_step_size_target']))
        print(" {:.4f}".format(proposed_state['adapted_step_size']))
    print("")
    print("###################################################################")
    print("")

def print_greeting(mcmc, estimator):
    """Prints the greeting when starting a run to screen."""

    print("")
    print("###################################################################")
    print("Starting MH algorithm...")
    print("")
    print("Sampling from the parameter posterior using: " + mcmc.name)
    print("in the model: " + mcmc.model.name)
    print("")
    if mcmc.using_gradients:
        print("Likelihood and gradients estimated using:")
        print(estimator.name)
        if mcmc.hessians_computed_by:
            print("Hessian is estimated using: " + mcmc.hessians_computed_by)
    else:
        print("Likelihood estimated using:")
        print(estimator.name)
    print("")
    if 'hessian' in mcmc.settings:
        step_size = mcmc.settings['step_size_hessian']
        eff_step_size = np.sqrt(np.diag(mcmc.settings['hessian'])) * step_size
        print("The proposal has effective random step sizes: ")
        i = 0
        for param in mcmc.model.params_to_estimate:
            print("{}: {:.3f}".format(param, eff_step_size[i]))
            i += 1
        print("")
    print("Running MH for {} iterations.".format(mcmc.settings['no_iters']))
    print("")
    print("The rest of the settings are as follows: ")
    for key in mcmc.settings:
        print("{}: {}".format(key, mcmc.settings[key]))
    print("")
    print("###################################################################")

def plot(mcmc, max_acf_lag = 500):
    """ Plots results to the screen after a run of an MCMC algorithm. """
    no_iters = mcmc.settings['no_iters']
    no_burnin_iters = mcmc.settings['no_burnin_iters']
    effective_iters = no_iters - no_burnin_iters
    no_params = mcmc.model.no_params_to_estimate
    param_names = mcmc.model.params_to_estimate
    no_bins = int(np.sqrt(effective_iters))

    accept_rate = params = np.zeros(effective_iters)
    params = np.zeros((effective_iters, no_params))
    prop_params = np.zeros((effective_iters, no_params))
    nat_gradient = np.zeros((effective_iters, no_params))
    no_nat_gradients = True

    for i in range(effective_iters):
        j = i + no_burnin_iters
        accept_rate[i] = mcmc.state_history[j]['accepted']
        params[i, :] = mcmc.state_history[j]['params']
        prop_params[i, :] = mcmc.state_history[j]['params_prop']
        if 'nat_gradient' in mcmc.state_history[j]:
            nat_gradient[i, :] = mcmc.state_history[j]['nat_gradient']
            no_nat_gradients = False
        else:
            no_nat_gradients = True

    accept_rate = np.cumsum(accept_rate) / np.arange(1, effective_iters+1)

    plt.figure(1)
    plt.plot(accept_rate)
    plt.ylabel("Running mean acceptance rate")
    plt.xlabel("iter")

    plt.figure(2)
    for i in range(no_params):
        col = Dark2_8.mpl_colors[i % 8]

        plt.subplot(no_params, 5, 5 * i + 1)
        plt.hist(params[:, i], bins=no_bins, color = col)
        plt.ylabel("Marginal posterior probability of " + str(param_names[i]))
        plt.xlabel("iter")

        plt.subplot(no_params, 5, 5 * i + 2)
        plt.plot(params[:, i], color = col)
        plt.ylabel("Parameter trace of " + str(param_names[i]))
        plt.xlabel("iter")

        plt.subplot(no_params, 5, 5 * i + 3)
        acf = compute_acf(params[:, i], max_lag=max_acf_lag)
        plt.plot(np.arange(max_acf_lag), acf, color = col)
        plt.ylabel("ACF of " + str(param_names[i]))
        plt.xlabel("iter")

        plt.subplot(no_params, 5, 5 * i + 4)
        plt.plot(prop_params[:, i], color = col)
        plt.ylabel("Proposed trace of " + str(param_names[i]))
        plt.xlabel("iter")

        plt.subplot(no_params, 5, 5 * i + 5)
        if not no_nat_gradients:
            plt.plot(nat_gradient[:, i], color = col)
            plt.ylabel("natural gradient of " + str(param_names[i]))
            plt.xlabel("iter")
    plt.show()

def compile_benchmark_results(mcmc, sim_name=None):
    """Helper for compiling the benchmark results from a run of
       the algorithm in mh_quasi_newton_benchmark.py before saving to file."""

    no_iters = mcmc.settings['no_iters']
    no_burnin_iters = mcmc.settings['no_burnin_iters']
    no_effective_iters = no_iters - no_burnin_iters
    idx = range(no_burnin_iters, no_iters)
    current_time = time.strftime("%c")

    if not 'error_sr1_fro' in mcmc.state_history[no_iters-1]:
        return None

    benchmarkout = {}
    benchmarkout.update({'simulation_name': sim_name})
    benchmarkout.update({'simulation_time': current_time})
    benchmarkout.update({'time_per_iteration': mcmc.time_per_iter})

    df = pd.DataFrame(mcmc.state_history)
    field_names = ['error_bfgs_fro', 'error_ls_fro', 'error_sr1_fro']

    for field in field_names:
        if not field in mcmc.state_history[no_iters-1]:
            print("Skipping saving " + field + " to file.")
            continue

        if type(df[no_iters-1][field]) is float or type(df[no_iters-1][field]) is np.float64:
            tmp = np.zeros((no_effective_iters, 1))
        else:
            tmp = np.zeros((no_effective_iters, len(df[no_iters-1][field])))

        for i in range(no_effective_iters):
            foo = df[i + no_burnin_iters][field]

            if type(foo) is not np.ndarray:
                if np.isnan(foo): foo = 0.0
                if np.isposinf(foo): foo = 10000000.0
                if np.isneginf(foo): foo = -10000000.0

            if type(foo) is np.ndarray:
                idx = np.where(np.isnan(foo))
                foo[idx] = 0.0
                idx = np.where(np.isposinf(foo))
                foo[idx] = 10000000.0
                idx = np.where(np.isneginf(foo))
                foo[idx] = -10000000.0

            tmp[i, :] = foo

        benchmarkout.update({field: tmp})

    return benchmarkout

def compile_results(mcmc, sim_name=None):
    """Helper for compiling the results from a run before saving to file."""
    no_iters = mcmc.settings['no_iters']
    no_burnin_iters = mcmc.settings['no_burnin_iters']
    no_effective_iters = no_iters - no_burnin_iters
    idx = range(no_burnin_iters, no_iters)
    current_time = time.strftime("%c")

    mcmcout = {}
    mcmcout.update({'simulation_name': sim_name})
    mcmcout.update({'simulation_time': current_time})
    mcmcout.update({'time_per_iteration': mcmc.time_per_iter})

    df = pd.DataFrame(mcmc.state_history)
    field_names = ['params', 'params_prop', 'nat_gradient', 'accepted', 'state_trajectory']

    for field in field_names:
        if not field in mcmc.state_history[0]:
            print("Skipping saving " + field + " to file.")
            continue

        if type(df[0][field]) is float or type(df[0][field]) is np.float64:
            tmp = np.zeros((no_effective_iters, 1))
        else:
            tmp = np.zeros((no_effective_iters, len(df[0][field])))

        for i in range(no_effective_iters):
            foo = df[i + no_burnin_iters][field]

            if type(foo) is not np.ndarray:
                if np.isnan(foo): foo = 0.0
                if np.isposinf(foo): foo = 10000000.0
                if np.isneginf(foo): foo = -10000000.0

            if type(foo) is np.ndarray:
                idx = np.where(np.isnan(foo))
                foo[idx] = 0.0
                idx = np.where(np.isposinf(foo))
                foo[idx] = 10000000.0
                idx = np.where(np.isneginf(foo))
                foo[idx] = -10000000.0

            tmp[i, :] = foo

        mcmcout.update({field: tmp})

    if hasattr(mcmc, 'adapted_step_sizes'):
        mcmcout.update({'adapted_step_sizes': mcmc.adapted_step_sizes})

    if hasattr(mcmc, 'no_hessians_corrected'):
        mcmcout.update({'no_hessians_corrected': mcmc.no_hessians_corrected})

    data = {}
    data.update({'observations': mcmc.model.obs})
    if mcmc.model.states is None:
        data.update({'states': mcmc.model.states})
    data.update({'simulation_name': sim_name})
    data.update({'simulation_time': current_time})

    settings = copy.deepcopy(mcmc.settings)
    recasted_settings = {}
    for key in settings:
        recasted_settings.update({key: str(settings[key])})
    recasted_settings.update({'sampler_name': mcmc.name})
    recasted_settings.update({'simulation_name': sim_name})
    recasted_settings.update({'simulation_time': current_time})

    return mcmcout, data, recasted_settings, df

def save_to_file(mcmc, file_path, sim_name=None, sim_desc=None):
    """Helper for saving results to file."""
    mcout, data, settings, mcoutdf = compile_results(mcmc, sim_name=sim_name)

    if sim_desc:
        desc = {'description': sim_desc,
                'time': settings['simulation_time']
            }
        write_to_json(desc, file_path, sim_name, 'description.txt')

    try:
        write_to_json(mcout, file_path, sim_name, 'mcmc_output.json')
    except:
        print("Error exporting JSON. Probably due to NaN or Inf. Use feather instead.")
    #write_to_feather(mcoutdf, file_path, sim_name, 'mcmc_output.feather')
    write_to_json(data, file_path, sim_name, 'data.json')
    write_to_json(settings, file_path, sim_name, 'settings.json')

    benchmark = compile_benchmark_results(mcmc, sim_name=sim_name)

    if not type(benchmark) is type(None):
        write_to_json(benchmark, file_path, sim_name, 'benchmark.json')


# 抓诗词

import requests
import re
import json
from bs4 import BeautifulSoup
from pymongo import MongoClient

client = MongoClient('localhost',27017)
mydb = client['mydb']
poems = mydb['poems']

# 获取诗词类别url
def category(url,headers):
	categories_url = []
	r = requests.get(url, headers=headers)
	soup = BeautifulSoup(r.text, 'lxml')
	categories = soup.select('div.main3 > div.right > div.sons > div.cont')
	for item in categories:
		link = item.select('a') # 获取a 标签
		for i in link:
			c_url = i.get('href') # 获取链接
			categories_url.append('https://www.gushiwen.org'+c_url) # 类别 url
	return categories_url

# 获取页面内容
def get_one_page(url, headers):
	poems_box = []
	r = requests.get(url,headers)
	soup = BeautifulSoup(r.text, 'lxml')
	poems = soup.select('div.left > div.sons')[0].select('.cont')

	# 正则切割内容
	for item in poems:
		poem = item.select('a')[0].get_text()
		title = re.findall(r'《.*?》', item.select('a')[1].get_text())[0]
		author = re.findall(r'(.*?)《', item.select('a')[1].get_text())[0]
		data = {
			'poem' : poem,
			'title' : title,
			'author': author
		}
		poems_box.append(data)
	return (poems_box)

if __name__ == '__main__':
	url = 'https://www.gushiwen.org/shiju/'
	headers = {
	'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
	'accept-encoding': 'gzip, deflate, br',
	'accept-language': 'zh-CN,zh;q=0.9,la;q=0.8',
	'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
	}

	for url in category(url,headers):
		for i in get_one_page(url,headers):
			poems.insert(i)


import torch.nn as nn
import torch
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from torch.utils.data import TensorDataset, DataLoader

def get_perceptron_weights(X_train, y_train, num_epochs=20):
    n_dims = X_train.shape[1]

    X_train = torch.tensor(X_train.values).float()
    y_train = torch.tensor(y_train).long()

    train_set = TensorDataset(X_train, y_train)

    train_loader = DataLoader(train_set, batch_size=32, shuffle=True)

    model = nn.Sequential(nn.Linear(n_dims, 2), nn.Softmax(dim=1))
    # define the loss function
    loss_fn = nn.CrossEntropyLoss()
    # define the optimizer
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    # put the model in training mode
    model.train()

    for epoch in range(num_epochs):
        for X_train, Y_train in train_loader:
                # compute the model output
                Y_pred = model(X_train)
                # calculate loss
                loss = loss_fn(Y_pred, Y_train)
                # reset the gradients
                optimizer.zero_grad()
                # backpropagation
                loss.backward()
                # update model weights
                optimizer.step()

    return abs(model[0].weight.data[1].numpy())


import json
import requests
from bs4 import BeautifulSoup

#создаём "промежуточный" суп для получения пагинации
url = 'https://parsinger.ru/html/index3_page_1.html'
response = requests.get(url)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'lxml')

pages = soup.find('div', class_='pagen').find_all('a') #получаем число страниц

res_json = [] #создаём результирующий json

#цикл чтобы пробежаться по страницам
for i in range(len(pages)):
    print(f'Страница {i+1} из {len(pages)}')
    #снова делаю суп, с учётом пагинации
    url = f'https://parsinger.ru/html/index3_page_{i+1}.html'
    response = requests.get(url)
    response.encoding = 'utf-8'
    soup = BeautifulSoup(response.text, 'lxml')

    #получаем список имён, список списков описаний, список цен
    names = [x.text for x in soup.find_all('a', class_='name_item')]
    descriptions = [x.text.strip().split('\n') for x in soup.find_all('div', class_='description')]
    prices = [x.text for x in soup.find_all('p', class_='price')]

    #упаковываем всё в json, присваиваем нужнм именам нужные значения
    for name, description, price in zip(names, descriptions, prices):
        res_json.append({
            'name': name.strip(),
            'brand': [x.split(':')[1].strip() for x in description][0],
            'type': [x.split(':')[1].strip() for x in description][1],
            'connect': [x.split(':')[1].strip() for x in description][2],
            'game': [x.split(':')[1].strip() for x in description][3],
            'prce': price
        })

#создаём json-файл
with open('res.json', 'w', encoding='utf-8') as file:
    json.dump(res_json, file, indent=4, ensure_ascii=False)

print('Ответ в виде json записан!')


from django.db import models
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile", blank=True, null=True)
    photo = models.ImageField(upload_to='media/', blank=True, null=True)

    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            Profile(user=instance).save()

class ImageNFT(models.Model):
    imagenft = models.ImageField(upload_to='media/', blank=True, null=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="profile_user", null=True)


#!/usr/bin/env python3

import argparse
import os
from pprint import pprint
import sys

from script_utils import print_error, print_section, print_tx_address

from clove.utils.search import get_network_by_symbol

sys.path.append(os.path.dirname(os.path.realpath(__file__)))

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description="Generate and publish atomic swap initial transaction.")
    parser.add_argument('-n', '--network', help='Network for creating transaction in', type=str, required=True)
    parser.add_argument('-s', '--sender', help='Sender address', type=str, required=True)
    parser.add_argument('-r', '--recipient', help='Recipient address', type=str, required=True)
    parser.add_argument('-a', '--amount', help='Transaction amount', type=float, required=True)
    parser.add_argument('-p', '--private-key', help='Private key', type=str, required=True)
    args = parser.parse_args()

    network = get_network_by_symbol(args.network)

    print_section('Creating transaction for', args.network)
    print_section('Sender address:\t', args.sender)
    print_section('Recipient address:\t', args.recipient)
    print_section('Transaction amount:\t', args.amount)

    wallet = network.get_wallet(private_key=args.private_key)
    utxo = network.get_utxo(args.sender, args.amount)
    if not utxo:
        print_error('UTXO not found')
        exit(1)

    print_section(f'Found {len(utxo)} UTXO\'s')
    pprint(utxo)
    transaction = network.atomic_swap(args.sender, args.recipient, args.amount, utxo)

    print_section('Adding fee and signing')
    transaction.add_fee_and_sign(wallet)

    print_section('Transaction ready to be published')
    details = transaction.show_details()
    pprint(details)

    publish = input('Do you want to publish this transaction (y/n): ')
    if publish != 'y':
        print_section('Bye!')
        exit()

    print_section('Publishing transaction')
    if not transaction.publish():
        print_error('Something went wrong, transaction was NOT published.')
        exit(1)
    print_section('Transaction published!')
    print_tx_address(args.network, details["transaction_address"])


import os
import unittest

from jsonasobj import as_json

from biolinkml.generators.pythongen import PythonGenerator
from tests.test_issues.environment import env
from tests.utils.python_comparator import compare_python, compile_python
from tests.utils.test_environment import TestEnvironmentTestCase

class Issue113TestCase(TestEnvironmentTestCase):
    env = env

    def test_issue_113(self):
        """ Make sure that types are generated as part of the output """
        env.generate_single_file('issue_113.py',
                                 lambda: PythonGenerator(env.input_path('issue_113.yaml')).serialize(),
                                 comparator=lambda exp, act: compare_python(exp, act, 'issue_113.py'),
                                 value_is_returned=True)
        module = compile_python(env.expected_path('issue_113.py'))
        example = module.TestClass(test_attribute_2="foo")
        assert hasattr(example, "test_attribute_2")
        assert hasattr(example, "test_attribute_1")
        example.wiible = "foo"
        example.test_attribute_1 = "foo"
        example.test_attribute_2 = "foo"

        env.generate_single_file('issue_113.json',
                                 lambda: PythonGenerator(env.input_path('issue_113.yaml')).serialize(),
                                 comparator=lambda exp, act: compare_python(exp, act, 'issue_113.py'),
                                 value_is_returned=True)

        def output_generator(dirname) -> None:
            with open(os.path.join(dirname, 'issue_113.json'), 'w') as f:
                f.write(as_json(example))

        env.generate_directory('issue_113', lambda dirname: output_generator(dirname))

if __name__ == '__main__':
    unittest.main()


import re

fname = "regex.txt"
fhandle = open(fname)
x = 0
list = list()
for line in fhandle:
    y = re.findall('[0-9]+',line)
    int(y)
    x = x + y
    if len(y) > 1:
        list.append(y)
print(x)


import os
import os.path as osp
import platform
import shutil
import time
import warnings
import torchvision.transforms as T

import torch

import mmcv
from mmcv.runner.base_runner import BaseRunner
from mmcv.runner.epoch_based_runner import EpochBasedRunner
from mmcv.runner.builder import RUNNERS
from mmcv.runner.checkpoint import save_checkpoint
from mmcv.runner.utils import get_host_info
from PIL import Image, ImageFont, ImageDraw
import numpy as np

MEAN=np.asarray([0.485, 0.456, 0.406])
STD=np.asarray([0.229, 0.224, 0.225])

def save_log_images(set_n, folder, epoch):
    '''
    Args:
        set_n: set_1 or set_2. Including
        [images_lower1, images_lower1_proj, ori_lower1, student_loss1[index_lower1], teacher_loss1[index_lower1],
        images_higher1, images_higher2_proj, ori_higher1, student_loss1[index_higher1], teacher_loss1[index_higher1]]
        folder: folder used to save images
    Returns:
    '''
    saved_folder = os.path.join(folder, "saved_images", "epoch_%d"%(epoch))
    os.makedirs(saved_folder, exist_ok=True)
    lower_info = set_n[0:5]
    higher_info = set_n[5:]

    num_low = lower_info[0].size(0)
    num_high = higher_info[0].size(0)
    saved_folder_low = os.path.join(saved_folder, "low_images")
    saved_folder_high = os.path.join(saved_folder, "high_images")
    os.makedirs(saved_folder_low, exist_ok=True)
    os.makedirs(saved_folder_high, exist_ok=True)
    font  = ImageFont.load_default()
    transform = T.Compose([T.Normalize((-1 * MEAN/STD), (1.0/STD)), T.ToPILImage()])

    for i in range(num_low):
        grid = lower_info[2].size(2)
        height = lower_info[1].size(2) # get the height of small image
        save_image = Image.new('RGB', (3 * lower_info[2].size(2), lower_info[2].size(3)), (250, 250, 250))
        image_lower = transform(lower_info[0][i])
        image_lower_proj = transform(lower_info[1][i])
        ori_lower = transform(lower_info[2][i])
        save_image.paste(ori_lower, (0,0))
        save_image.paste(image_lower, (grid + 1, 0))
        save_image.paste(image_lower_proj, (grid * 2, 0))
        caption = " Student: %f \n Teacher: %f\n"%(lower_info[3][i], lower_info[4][i])
        draw = ImageDraw.Draw(save_image)
        draw.text((grid + 3, height + 2), caption, font=font, fill="black")
        save_image.save(os.path.join(saved_folder_low, "image_set%d_%d.png"%(i, torch.cuda.current_device())))
        save_image.close()

    for i in range(num_high):
        grid = higher_info[2].size(2)
        height = higher_info[1].size(2) # get the height of the small images
        save_imageh = Image.new('RGB', (3 * higher_info[2].size(2), higher_info[2].size(3)), (250, 250, 250))
        image_higher = transform(higher_info[0][i])
        image_higher_proj = transform(higher_info[1][i])
        ori_higher = transform(higher_info[2][i])
        save_imageh.paste(ori_higher, (0, 0))
        save_imageh.paste(image_higher, (grid, 0))
        save_imageh.paste(image_higher_proj, (grid * 2, 0))
        caption = " Student: %f \n Teacher: %f\n" % (higher_info[3][i], higher_info[4][i])
        draw = ImageDraw.Draw(save_imageh)
        draw.text((grid + 3, height + 2), caption, font=font, fill="black")
        save_imageh.save(os.path.join(saved_folder_high, "image_set%d_%d.png"%(i, torch.cuda.current_device())))
        save_imageh.close()

@RUNNERS.register_module()
class KDBasedRunnerSaveImages(BaseRunner):
    """KD-based Runner.

    This runner train models epoch by epoch. For each epoch, the runner feed in the teacher model.
    """
    def __init__(self,
                 model,
                 t_model,
                 batch_processor=None,
                 optimizer=None,
                 work_dir=None,
                 logger=None,
                 meta=None,
                 max_iters=None,
                 max_epochs=None
                 ):
        super(KDBasedRunnerSaveImages, self).__init__(
                                            model,
                                            batch_processor,
                                            optimizer,
                                            work_dir,
                                            logger,
                                            meta,
                                            max_iters,
                                            max_epochs)
        self.t_model = t_model

    def run_iter(self, data_batch, train_mode, **kwargs):
        if self.batch_processor is not None:
            outputs = self.batch_processor(
                self.model, data_batch, train_mode=train_mode, **kwargs)
        elif train_mode:
            outputs, set_1, set_2 = self.model.train_step(data_batch, self.optimizer, self.t_model, self.save_images,
                                            **kwargs)
            if self.save_images:
                save_log_images(set_1, self.work_dir, self.epoch)
                set_1, set_2 = None, None
        else:
            outputs = self.model.val_step(data_batch, self.optimizer, **kwargs)
        if not isinstance(outputs, dict):
            raise TypeError('"batch_processor()" or "model.train_step()"'
                            'and "model.val_step()" must return a dict')
        if 'log_vars' in outputs:
            self.log_buffer.update(outputs['log_vars'], outputs['num_samples'])
        self.outputs = outputs

    def train(self, data_loader, **kwargs):
        self.model.train()
        self.mode = 'train'
        self.data_loader = data_loader
        self._max_iters = self._max_epochs * len(self.data_loader)
        self.call_hook('before_train_epoch')
        time.sleep(2)  # Prevent possible deadlock during epoch transition
        self.save_images = torch.tensor([False]).cuda()
        for i, data_batch in enumerate(self.data_loader):
            self._inner_iter = i
            self.call_hook('before_train_iter')
            if self.epoch % 10 == 0:
                if i == 0:
                    self.save_images = torch.tensor([True]).cuda()
                else:
                    self.save_images = torch.tensor([False]).cuda()
            else:
                self.save_images = torch.tensor([False]).cuda()
            self.run_iter(data_batch, train_mode=True, **kwargs)
            self.call_hook('after_train_iter')
            self._iter += 1

        self.call_hook('after_train_epoch')
        self._epoch += 1

    @torch.no_grad()
    def val(self, data_loader, **kwargs):
        self.model.eval()
        self.mode = 'val'
        self.data_loader = data_loader
        self.call_hook('before_val_epoch')
        time.sleep(2)  # Prevent possible deadlock during epoch transition
        for i, data_batch in enumerate(self.data_loader):
            self._inner_iter = i
            self.call_hook('before_val_iter')
            self.run_iter(data_batch, train_mode=False)
            self.call_hook('after_val_iter')

        self.call_hook('after_val_epoch')

    def run(self, data_loaders, workflow, max_epochs=None, **kwargs):
        """Start running.

        Args:
            data_loaders (list[:obj:`DataLoader`]): Dataloaders for training
                and validation.
            workflow (list[tuple]): A list of (phase, epochs) to specify the
                running order and epochs. E.g, [('train', 2), ('val', 1)] means
                running 2 epochs for training and 1 epoch for validation,
                iteratively.
        """
        assert isinstance(data_loaders, list)
        assert mmcv.is_list_of(workflow, tuple)
        assert len(data_loaders) == len(workflow)
        if max_epochs is not None:
            warnings.warn(
                'setting max_epochs in run is deprecated, '
                'please set max_epochs in runner_config', DeprecationWarning)
            self._max_epochs = max_epochs

        assert self._max_epochs is not None, (
            'max_epochs must be specified during instantiation')

        for i, flow in enumerate(workflow):
            mode, epochs = flow
            if mode == 'train':
                self._max_iters = self._max_epochs * len(data_loaders[i])
                break

        work_dir = self.work_dir if self.work_dir is not None else 'NONE'
        self.logger.info('Start running, host: %s, work_dir: %s',
                         get_host_info(), work_dir)
        self.logger.info('Hooks will be executed in the following order:\n%s',
                         self.get_hook_info())
        self.logger.info('workflow: %s, max: %d epochs', workflow,
                         self._max_epochs)
        self.call_hook('before_run')

        while self.epoch < self._max_epochs:
            for i, flow in enumerate(workflow):
                mode, epochs = flow
                if isinstance(mode, str):  # self.train()
                    if not hasattr(self, mode):
                        raise ValueError(
                            f'runner has no method named "{mode}" to run an '
                            'epoch')
                    epoch_runner = getattr(self, mode)
                else:
                    raise TypeError(
                        'mode in workflow must be a str, but got {}'.format(
                            type(mode)))

                for _ in range(epochs):
                    if mode == 'train' and self.epoch >= self._max_epochs:
                        break
                    epoch_runner(data_loaders[i], **kwargs)

        time.sleep(1)  # wait for some hooks like loggers to finish
        self.call_hook('after_run')

    def save_checkpoint(self,
                        out_dir,
                        filename_tmpl='epoch_{}.pth',
                        save_optimizer=True,
                        meta=None,
                        create_symlink=True):
        """Save the checkpoint.

        Args:
            out_dir (str): The directory that checkpoints are saved.
            filename_tmpl (str, optional): The checkpoint filename template,
                which contains a placeholder for the epoch number.
                Defaults to 'epoch_{}.pth'.
            save_optimizer (bool, optional): Whether to save the optimizer to
                the checkpoint. Defaults to True.
            meta (dict, optional): The meta information to be saved in the
                checkpoint. Defaults to None.
            create_symlink (bool, optional): Whether to create a symlink
                "latest.pth" to point to the latest checkpoint.
                Defaults to True.
        """
        if meta is None:
            meta = {}
        elif not isinstance(meta, dict):
            raise TypeError(
                f'meta should be a dict or None, but got {type(meta)}')
        if self.meta is not None:
            meta.update(self.meta)
            # Note: meta.update(self.meta) should be done before
            # meta.update(epoch=self.epoch + 1, iter=self.iter) otherwise
            # there will be problems with resumed checkpoints.
            # More details in https://github.com/open-mmlab/mmcv/pull/1108
        meta.update(epoch=self.epoch + 1, iter=self.iter)

        filename = filename_tmpl.format(self.epoch + 1)
        filepath = osp.join(out_dir, filename)
        optimizer = self.optimizer if save_optimizer else None
        save_checkpoint(self.model, filepath, optimizer=optimizer, meta=meta)
        # in some environments, `os.symlink` is not supported, you may need to
        # set `create_symlink` to False
        if create_symlink:
            dst_file = osp.join(out_dir, 'latest.pth')
            if platform.system() != 'Windows':
                mmcv.symlink(filename, dst_file)
            else:
                shutil.copy(filepath, dst_file)


from django.http import Http404
from django.conf import settings
from django.core.cache import cache
from rest_framework import  permissions
from api.secure.models import role, project_user_role, role_permission
from api.project.models import project

class api_permission(permissions.BasePermission):
    '''
    A implement class that match site client permission to socpes.
    '''
    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.

        All we need to do here is that:
        We need get a set of permission for current user, if it's super user, just
        return True.

        For PRIVATE project, only project members can view (GET method), instead of
        Anonymous, so we should check if current user is a team member before next
        step.

        All permissions will cached by role name.
        """

        # super user has all permissions.
        if request.user.is_superuser:
            return True

        project_is_private = False
        perm_parm_dict = {'owner_username':'', 'project_name':''}
        perm_parm_dict.update(request.parser_context['kwargs'])

        owner_username = perm_parm_dict['owner_username']
        project_name = perm_parm_dict['project_name']
        perm_list = []

        all_perms = cache.get(settings.PERMISSIONS_CACHED_KEY)
        if not all_perms:
            all_role = role.objects.all()
            all_perms = {}
            for r in all_role:
                p_list = []
                rp_ins_list = role_permission.objects.filter(role=r)
                for rp in rp_ins_list:
                    p_dict = {}
                    p_dict['codename'] = rp.permission.endpoint.codename
                    p_dict['GPPD'] = rp.permission.GPPD
                    p_list.append(p_dict)
                all_perms[r.name] = p_list
            # default expire time is 1 day, which confied in settings.py
            cache.set(settings.PERMISSIONS_CACHED_KEY, all_perms)

        if project_name and owner_username:
            proj_ins = self.__get_project_instance(owner_username, project_name)
            project_is_private = self.__check_project_private(proj_ins)
            # check if project is PRIVATE
            if project_is_private and not self.__is_team_member(proj_ins, request.user):
                # check if current user is team member.
                return False

            pur_ins_list = project_user_role.objects.filter(project=proj_ins, user=request.user)
            for pur in pur_ins_list:
                perm_list.extend(all_perms[pur.role.name])
            # all users has anonymous' permission
            perm_list.extend(all_perms[settings.ANONYMOUS_ROLE_NAME])

        if not len(perm_list):
            perm_list = all_perms[settings.ANONYMOUS_ROLE_NAME]

        # get view namespace
        view_namespace = self.__get_fullname(view)
        GPPD = settings.GPPD[request.method.upper()]
        return self.__has_permission_on_view(GPPD, view_namespace, perm_list)

    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True

    def __has_permission_on_view(self, method, view_namespace, permission_list):
        '''
        Return `True` is at list one row was found, `False` otherwise.
        '''
        #raise BaseException(method, view_namespace)
        for p in permission_list:
            if p['codename'] == view_namespace and p['GPPD'] == method:
                return True

        return False

    def __get_fullname(self, o):
        '''
        Return full namespace of object.
        '''
        return o.__module__ + "." + o.__class__.__name__

    def __get_project_instance(self, owner_username, project_name):
        '''
        Get project instance.
        '''
        proj_ins = None
        try:
            proj_ins = project.objects.get_by_natural_key(owner_username, project_name)
        except: raise Http404
        else:
            return proj_ins

    def __check_project_private(self, project_instance):
        '''
        Check if project is private.

        If one of or both arguments not provide, raise HTTP 404 error.
        '''
        return project_instance.is_private

    def __is_team_member(self, project_instance,  username):
        '''
        Check if a user is one of team member of the givn project.
        '''
        username_list = project_instance.objects.get_team_members_username()

        if isinstance(username_list, (tuple, list)):
            return username_list.count(username)
        else:
            raise False

        return True

    def __is_owner(self, project_instance, username):
        '''
        Check if a user is the owner of the givn project.
        '''
        if project_instance.user.username == username:
            return True
        else:
            return False


from DataType import FVar, TVar, AmpVar, PhVar, OVar
import Functions
import os

FVar_list = []
TVar_list = []
AmpVar_list = []
PhVar_list = []
OVar_list = []

OutputFileName = "Unknown.zyt"
Title = "Unknown"

def ToConfigFile():

    os.chdir(os.path.dirname(__file__))
    CurrentDir = (os.getcwd()) + "\\"
    print(CurrentDir)

    OutputFileName.replace(' ','')

    OutputFile = open(CurrentDir + OutputFileName, 'w+')

    if len(FVar_list) == 0:
        FVar_list.append(FVar("None", 0, 0, 0, 0, 0))

    if len(TVar_list) == 0:
        TVar_list.append(TVar("None", 0, 0, 0, 0, 0))

    if len(AmpVar_list) == 0:
        AmpVar_list.append(AmpVar("None", 0, 0, 0, 0, 0))

    if len(PhVar_list) == 0:
        PhVar_list.append(PhVar("None", 0, 0, 0, 0, 0))

    if len(OVar_list) == 0:
        OVar_list.append(OVar("None", 0, 0, 0, 0, 0))

    print(Title, file = OutputFile)
    print(len(FVar_list), file = OutputFile)
    for i in range(0, len(FVar_list)):
        print(FVar_list[i].name, FVar_list[i].lb, FVar_list[i].ub, FVar_list[i].var, FVar_list[i].llb, FVar_list[i].uub, file = OutputFile)

    print(len(TVar_list), file = OutputFile)
    for i in range(0, len(TVar_list)):
        print(TVar_list[i].name, TVar_list[i].lb, TVar_list[i].ub, TVar_list[i].var, TVar_list[i].llb, TVar_list[i].uub, file = OutputFile)

    print(len(AmpVar_list), file = OutputFile)
    for i in range(0, len(AmpVar_list)):
        print(AmpVar_list[i].name, AmpVar_list[i].lb, AmpVar_list[i].ub, AmpVar_list[i].var, AmpVar_list[i].llb, AmpVar_list[i].uub, file = OutputFile)

    print(len(PhVar_list), file = OutputFile)
    for i in range(0, len(PhVar_list)):
        print(PhVar_list[i].name, PhVar_list[i].lb, PhVar_list[i].ub, PhVar_list[i].var, PhVar_list[i].llb, PhVar_list[i].uub, file = OutputFile)

    print(len(OVar_list), file = OutputFile)
    for i in range(0, len(OVar_list)):
        print(OVar_list[i].name, OVar_list[i].lb, OVar_list[i].ub, OVar_list[i].var, OVar_list[i].llb, OVar_list[i].uub, file = OutputFile)

    ##print ('--END--', sep = '', end = '', file = OutputFile)
    OutputFile.close()

## ---------------------Script Begin-----------------------------

FVar_list.append(FVar("f", 0, 100, 50, 0, 10000))
TVar_list.append(TVar("t1", 0, 40, 20, 0, 10000))
TVar_list.append(TVar("t2", 0, 60, 30, 0, 10000))
TVar_list.append(TVar("t3", 0, 80, 40, 0, 10000))
AmpVar_list.append(AmpVar("amp_ramsey", 0, 1, 1, 0, 1))
AmpVar_list.append(AmpVar("amp_detect", 0, 1, 1, 0, 1))
AmpVar_list.append(AmpVar("amp_pumping", 0, 1, 1, 0, 1))
PhVar_list.append(PhVar("phvar", 0, 2, 0, 0, 4))

## -----------------------Script End-----------------------------

Title = "Ramsey"
OutputFileName = "Ramsey.zyt" ##The spaces in the OutputFile will be diminished
ToConfigFile()

##DO NOT DELETE THE FOLLOWING SHARPS
##########


"""
Lists

 - Lists are mutable, ordered data structure type.
 - range(start, stop, stepover)

"""
# Creating a list using range()

one_ten = list(range(1, 11))
print(one_ten)

one_ten.insert(len(one_ten), 11)
print('\n')

# calculate the average of students average
# students_grades = list([91, 75, 88, 69])

def mean(grades):
     grades_total = sum(grades)
     grades_count = len(grades)
     result = grades_total / grades_count
     return result

"""
dir() keyword
 - dir lists all attributes of a data type
 - dir(list)

help(object.attribute)
 - help(returns an description/documentation of a datatype/attribute)
"""

# Now, calculate avg heights for students in a dict

grade_5_b = {
     'leen': 150,
     'ela': 153,
     'meral': 145,
     'ghazi': 135,
     'kamooleh': 159
}

def avg_height():
     """Average height calculator"""
     return sum(grade_5_b.values()) / len(grade_5_b)

new_set = {1, 2, 3, 5, 6}
new_set.add(4)
# sorted(new_set)

if __name__ == '__main__':

     student_grade = list(map(int, input('Enter students grades: ').split()))
     print(mean(student_grade))
     print('')

     print(avg_height())

     print(new_set)
     print(one_ten)


class connect:
    def __init__(self, access=None, secret=None):
        self.region='us-east-2'
        self.ac = access
        self.se = secret
        self.myaddress='52.14.29.127'
        self.key='dec15a'
        self.MAX_SPOT_BID='1.0'
        self.security_groups = ['default']

        import time
        import boto
        import boto.ec2
        from boto.ec2.blockdevicemapping import BlockDeviceType, BlockDeviceMapping
        self.ec2_conn = boto.ec2.connect_to_region(self.region, aws_access_key_id=self.ac, aws_secret_access_key=self.se)

        shell_script = """
        #!/bin/bash -ex
        yum install -y docker mysql git python-pip
        sudo amazon-linux-extras install -y docker
        pip install aws-ec2-assign-elastic-ip
        aws-ec2-assign-elastic-ip --access-key {}, --secret-key {}  --valid-ips {}
        service docker start
        docker run -d -p 8887:8888 -v /tmp:/tmp shantanuo/notebook

        """
        self.my_user_data=shell_script.format(self.ac,self.se, self.myaddress).encode()

        self.dev_sda1 = BlockDeviceType()
        self.bdm = BlockDeviceMapping()
        self.dev_sda1.size = 500
        self.bdm['/dev/xvda'] = self.dev_sda1

    def startEc2Spot(self, ami, instance_type):
        aid = {'image_id': ami, 'instance_type': instance_type, 'user_data': self.my_user_data , 'key_name': self.key,
              'security_groups': self.security_groups, 'block_device_map' : self.bdm, 'price': self.MAX_SPOT_BID}
        daid=dict(aid)
        rid=self.ec2_conn.request_spot_instances(**daid)

        time.sleep(180)
        job_sir_id = rid[0].id # spot instance request = sir, job_ is the relevant aws item for this job
        reqs = self.ec2_conn.get_all_spot_instance_requests()
        for sir in reqs:
            if sir.id == job_sir_id:
                job_instance_id = sir.instance_id
                print ("job instance id: " + str(job_instance_id))

                if self.myaddress:
                    self.ec2_conn.associate_address(job_instance_id, self.myaddress)
                    print ('ssh -i ' + self.key+ '.pem ec2-user@'+self.myaddress)
                else:
                    address = self.ec2_conn.allocate_address()
                    self.ec2_conn.associate_address(job_instance_id, address.public_ip)
                    print ('ssh -i ' + self.key+ '.pem ec2-user@'+str(address.public_ip))

    def startEc2(self, ami, instance_type):
        aid = { 'image_id': ami, 'instance_type': instance_type, 'user_data': self.my_user_data ,'key_name': self.key,
                 'security_groups': self.security_groups, 'block_device_map' : self.bdm}
        daid=dict(aid)
        rid=self.ec2_conn.run_instances(**daid)

        time.sleep(120)
        iid=self.ec2_conn.get_all_instances(filters={'reservation-id': rid.id})[0].instances[0]
        if self.myaddress:
            self.ec2_conn.associate_address(iid.id, self.myaddress)
            print ('ssh -i ' + self.key+ '.pem ec2-user@'+self.myaddress)
        else:
            address = self.ec2_conn.allocate_address()
            self.ec2_conn.associate_address(iid.id, address.public_ip)
            print ('ssh -i ' + self.key+ '.pem ec2-user@'+str(address.public_ip))

    def showEc2(self):
        mylist=[]
        info=self.ec2_conn.get_only_instances()
        for reservation in info:
            mylist.append( (reservation , reservation.launch_time, reservation.instance_type,
                            reservation.image_id,reservation.state, reservation.ip_address))
        import pandas as pd
        col_name=['instance_id', 'launch_time', 'instance_type', 'image_id', 'state', 'ip_address']
        try:
            df = pd.DataFrame(mylist, columns=col_name)
            return df
        except ValueError:
            pass

    def deleteEc2(self,  instance_id_to_delete, mylist=None):
        mylist=[]
        mylist.append(instance_id_to_delete)
        print (mylist)
        self.ec2_conn.terminate_instances(instance_ids=mylist)

    def deleteAllEc2(self):
        mylistDel=[]
        info=self.ec2_conn.get_only_instances()
        for reservation in info:
            mylistDel.append(reservation.id)

        print ("this does not actually delete the ec2 instances. Run the following command on your own risk :)\n")
        print ("import boto")
        print ("ec2_conn = boto.connect_ec2(aws_access_key_id='%s', aws_secret_access_key='%s')" % (self.ac, self.se))
        print ("ec2_conn.terminate_instances(instance_ids=%s)" % (mylistDel))

    def showImages(self):
        mylist=[]
        i_list=self.ec2_conn.get_all_images(owners=['self'])
        for i in i_list:
            mylist.append((i.id, i.is_public, i.name, i.description,i.region))
        import pandas as pd
        col_name=['image_id', 'is_public', 'name', 'description', 'region']
        df = pd.DataFrame(mylist, columns=col_name)
        return df

    """
#x = connect('xxx', 'xxx')
#x.startEc2Spot('ami-009d6802948d06e52', 'm3.large')
#x.showEc2()
#x.deleteAllEc2()
#x.showImages()
    """


import asyncio
import datetime
import hashlib
import logging
import os
from dataclasses import dataclass
from functools import partial
from typing import Dict, Callable, Optional, Awaitable

import bs4
import httpx
import sanic
from anyio import create_task_group
from sanic.request import Request
from sanic.response import text

logger = logging.getLogger("websub")

class HubNotFoundException(Exception):
    pass

@dataclass
class Subscription:
    hub: str
    topic: str
    hex_id: str

    handler: Callable[[bytes], Awaitable[None]]

    verified_at: Optional[datetime.datetime] = None
    lease: Optional[datetime.timedelta] = None

    cold: bool = True

    def __repr__(self) -> str:
        return f"<Subscription {self.topic} (0x{self.hex_id.upper()} {self.lease})>"

class WebSubClient:
    def __init__(self, https: bool, app: sanic.Sanic, server: str = None, _from: str = None):
        self.server = server
        self.https = https
        self.app = app
        self._from = f"{_from or 'default'} (pywebsub)"
        self.running = False
        self.subscriptions: Dict[str, Subscription] = {}
        self.seen_hashes = set()
        self.heartbeat_hashes = set()

    async def subscribe(self, hub: str, topic: str, handler: Callable[[bytes], Awaitable[None]]):
        s = Subscription(hub=hub,
                         topic=topic,
                         hex_id=os.urandom(16).hex(),
                         handler=handler)
        self.subscriptions[topic] = s
        if self.running:
            s.cold = False
            await self.make_request(s)

    async def unsubscribe(self, topic: str):
        sub = self.subscriptions.get(topic)
        if sub is None:
            logger.warning(f"Unsubscribe requested for {topic}, but subscription does not exist.")
        else:
            if self.running:
                await self.make_request(sub, "unsubscribe")
            del self.subscriptions[topic]

    async def discover(self, topic: str) -> str:
        try:
            resp = await httpx.get(topic, headers=self.headers)
        except httpx.exceptions.HTTPError as e:
            logger.exception(f"{topic} discovery request failed with exception:")
            raise HubNotFoundException(e)

        if resp.status_code not in range(200, 300):
            raise HubNotFoundException(f"{topic} discovery request failed, status is {resp.status_code}")
        else:
            logger.debug(f"{topic} discovery request succeeded")
            soup = bs4.BeautifulSoup(resp.content, "xml")
            link = soup.find("link", rel="hub")
            if link is None:
                raise HubNotFoundException(f"rel=hub link not present in {topic}")

            return link.attrs['href']

    async def discover_and_sub(self, topic: str, handler: Callable[[bytes], Awaitable[None]]):
        hub = await self.discover(topic)
        await self.subscribe(hub, topic, handler)

    async def make_request(self, sub: Subscription, mode: str = "subscribe"):
        callback_url = self.make_callback_url(sub.hex_id)
        logger.info(f"Subscribing to {sub.topic}, calling back to {callback_url}")

        values = {
              "hub.callback": callback_url,
              "hub.topic":    sub.topic,
              "hub.mode":     "subscribe"
        }

        try:
            resp = await httpx.post(sub.hub, data=values, headers=self.headers)
        except httpx.exceptions.HTTPError:
            logger.exception(f"{mode} request failed with exception, {sub} at {callback_url}:")
            return

        if resp.status_code != 202:
            logger.error(f"{mode} request failed, {sub} at {callback_url}, status is {resp.status_code}")
        else:
            logger.info(f"{mode} request succeeded, {sub} at {callback_url}")

    def make_callback_url(self, hex_id: str) -> str:
        return self.url_for('callback', hex_id=hex_id)

    def url_for(self, view_name: str, **kwargs):
        return self.app.url_for(f"websub.{view_name}", **kwargs,
                                _scheme='https' if self.https else 'http',
                                _external=True, _server=self.server)

    def get_sub_by_hex(self, hex_id: str) -> Optional[Subscription]:
        for s in self.subscriptions.values():
            if s.hex_id.lower() == hex_id.lower():
                return s

    async def broadcast(self, sub: Subscription, req: Request):
        body: bytes = req.body
        h: bytes = hashlib.md5(req.body).digest()
        if h not in self.seen_hashes:
            self.seen_hashes.add(h)
            await sub.handler(body)
        else:
            logger.info(f"Update for {sub} already handled, hash is {h.hex()}")

    @property
    def bp(self) -> sanic.Blueprint:
        bp = sanic.Blueprint("websub")

        @bp.route("/hb/<hex_id>")
        async def heartbeat(request: Request, hex_id: str) -> sanic.response.HTTPResponse:
            return text(hex_id, status=200 if hex_id in self.heartbeat_hashes else 404)

        @bp.route("/push-callback/<hex_id>", methods=["GET", "POST"])
        async def callback(request: Request, hex_id: str) -> sanic.response.HTTPResponse:
            topic = request.args.get("hub.topic")
            mode = request.args.get("hub.mode")

            if mode == "subscribe":
                sub = self.subscriptions.get(topic)
                if sub is None:
                    logger.warning(f"Unexpected subscription for {topic} on {hex_id}")
                    return text("Unexpected subscription", status=400)
                else:
                    lease_s = request.args.get('hub.lease_seconds')
                    if not lease_s:
                        logger.error(f"Lease is not resolved for sub {sub}: {lease_s!r}")
                        return text("No lease", status=400)
                    sub.verified_at = datetime.datetime.now()
                    sub.lease = datetime.timedelta(seconds=int(lease_s))
                    logger.info(f"Subscription verified for {sub}, lease is {sub.lease}")
                    if hex_id != sub.hex_id:
                        logger.warning(f"Subscription hex does not match path hex: {sub.hex_id} != {hex_id}")
                    return text(request.args.get("hub.challenge"))

            elif mode == "unsubscribe":
                sub = self.subscriptions.get(topic)
                if sub is None:
                    logger.warning(f"Unexpected unsubscribe for {topic} on {hex_id}")
                    return text("Unexpected unsubscribe", status=400)
                else:
                    logger.info(f"Unsubscribe confirmed for {topic} on {hex_id}")
                    if hex_id != sub.hex_id:
                        logger.warning(f"Subscription hex does not match path hex: {sub.hex_id} != {hex_id}")
                    return text(request.args.get("hub.challenge"))

            elif mode == "denied":
                logger.warning(f"Subscription denied for {topic}, reason was {request.args.get('hub.reason')}")
                return sanic.response.HTTPResponse()
                # TODO: Don't do anything for now, should probably mark the subscription.
            else:
                sub = self.get_sub_by_hex(hex_id)
                if sub is None:
                    logger.warning("Got unknown message for unknown subscription:")
                    logger.warning(f"{hex_id}: {request}")
                    return text("Unknown subscription", status=400)
                else:
                    logger.info(f"Update for {sub}")
                    await self.broadcast(sub, request)
                    return sanic.response.HTTPResponse()

        return bp

    @property
    def headers(self):
        return {
              "From": self._from
        }

    def install(self):
        bp = self.bp
        if bp.name not in self.app.blueprints:
            self.app.blueprint(self.bp)

    async def boot(self, *args, **kwargs):
        create_server = partial(self.app.create_server, *args, **kwargs, return_asyncio_server=True)

        async with create_task_group() as tg:
            await tg.spawn(create_server)
            await tg.spawn(self.start)

    async def start(self):
        self.running = True
        self.install()
        logger.debug("waiting 5 seconds before starting checking wait_till_heartbeat...")
        await asyncio.sleep(5)
        logger.debug("waiting till heartbeat...")
        await self.wait_till_heartbeat()
        logger.debug("starting subbed loop...")
        await self.ensure_subbed_loop()

    async def wait_till_heartbeat(self):
        class NotCorrect(Exception):
            pass

        while True:
            try_hex = os.urandom(6).hex()
            self.heartbeat_hashes.add(try_hex)
            try:
                r = await httpx.get(self.url_for("heartbeat", hex_id=try_hex))
                if r.status_code != 200:
                    raise NotCorrect()
            except httpx.exceptions.HTTPError:
                logger.debug("heartbeat failed with HTTPError, waiting 2 seconds...")
                await asyncio.sleep(2)
            except NotCorrect:
                logger.debug("heartbeat failed reaching current server, waiting 2 seconds...")
                await asyncio.sleep(2)
            else:
                return
            finally:
                self.heartbeat_hashes.remove(try_hex)

    async def ensure_subbed_loop(self):
        while True:
            try:
                await self.ensure_subbed()
            except Exception:
                logger.exception("ensure_subbed gave an exception")

            await asyncio.sleep(60)

    async def ensure_subbed(self):
        logger.debug("ensure_subbed called")
        in_one_hour = datetime.datetime.now() + datetime.timedelta(hours=1)
        for s in self.subscriptions.values():
            logger.debug(f"ensure_subbed: checking {s}")
            if not s.cold and (s.verified_at is None or s.lease is None):
                logger.debug(f"ensure_subbed: {s} not yet verified, skipping...")
                continue
            if s.cold or (s.verified_at + s.lease) < in_one_hour:
                s.cold = False
                await self.make_request(s)
            else:
                logger.debug(f"ensure_subbed: {s} does not need new lease, verified at {s.verified_at}")


import sys

open_dir = r"C:\Users\cmh02\OneDrive\바탕 화면\Algorithm\python_algorithm\탐색&시뮬레이션\08_곶감(모래시계)\in3.txt"
sys.stdin = open(open_dir, "rt")

n = int(input())

a = [list(map(int, input().split())) for _ in range(n)]

m = int(input())

b = [list(map(int, input().split())) for _ in range(m)]

# print(a)
# print(b)

for x in b:
    row, direction, cnt = x
    # 행 선택
    selected_row = a[row-1]

    # 왼쪽
    temp = [0] * n
    if direction == 0:
        # 원하는 만큼 회전...
        for i in range(n):
            x = selected_row[i]
            temp[i-cnt] = x
    else:
        # 오른쪽 회전
        for i in range(n):
            x = selected_row[i]

            rotate = i+cnt
            # 인덱스를 벗어나면...
            if rotate > n - 1:
                rotate = rotate - n
                temp[rotate] = x
            else:
                temp[rotate] = x

    a[row-1] = temp

# 모래시계 모양의 영역에 감 몇 개가 있는지
s = 0
e = n
sum1 = 0
for i in range(n):
    for j in range(s, e):
        sum1 += a[i][j]

    if i < n//2:
        s += 1
        e -= 1
    else:
        s -= 1
        e += 1

print(sum1)


import os
import sys
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
from PIL import Image

chrome_options = Options()
delay = 5 # seconds

def get_warranty_HTML(file):
  global driver
  chrome_options.add_argument("--headless")
  chrome_options.add_argument("--log-level=3")
  driver = webdriver.Chrome('C:/TEMP/chromedriver.exe', options=chrome_options)
  driver.get('https://support.hpe.com/hpsc/wc/public/find')
  if os.name == "posix":
    os.system ("clear")
  elif os.name == ("ce" or "nt" or "dos"):
    os.system ("cls")

  captchadef()

  count_lines = len(open(file).readlines())

  if count_lines < 10:
    check_n(count_lines, file, driver)

  elif count_lines <= 20:
    driver.find_element_by_xpath('//*[@id="wcFormDataItem"]/span/a').click()
    check_n(count_lines, file, driver)
  else:
    print('No more of 20 serials')
    quit()

def check_n(count_lines, file, driver):
  n = 0
  try:
    WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'serialNumber%s' %(n))))
    print ("Checking Serials, please wait...!")
  except TimeoutException:
    print ("Loading took too much time!")
  while n < count_lines:
    for line in open(file):
      driver.find_element_by_id('serialNumber%s' %(n)).send_keys(line.strip())
      n= n + 1

  try:
    driver.find_element_by_name('submitButton').click()
  except:
    print('Submit Button not found, exit...')
    quit()

  captchadef()

  try_number = 0
  while True:
    try:
      driver.find_element_by_xpath('//*[@id="nonIntroBlock"]/div')
      n = 0
      remo = 1
      while n < count_lines:
        try:
          product= 'productNumber'+ str(n)
          driver.find_element_by_id(product)
          for element in driver.find_elements_by_xpath('//*[@id="serialNumber%s"]' %(str(n))):
            print ('\n', element.get_attribute('value'))
          if try_number >= 2:
            remocheck = ('/html/body/div[1]/div/div[3]/div/table/tbody/tr/td[3]/table/tbody/tr[2]/td/div/form/table/tbody/tr[%s]/td[4]/a' %(str(remo)))
            print('\nRemoving bad serials with P/N')
            driver.find_element_by_xpath(remocheck).click()
            paso = 1
            break
          product_n = input('Need insert Product number for this serial: ')
          driver.find_element_by_id(product).clear()
          driver.find_element_by_id(product).send_keys(product_n)
        except:
          pass
        n = n + 1
        remo = remo + 2
      print('Trying...')
      driver.find_element_by_name('submitButton').click()
      try_number = try_number + 1
      paso = 1
    except:
      paso = 1
      break

  captchadef()

  if paso == 1:
    f = open("checked.txt","a")
    for line in open(file):
      print('Warranty checked for '+ line.strip())
      f.write('\nWarranty checked for '+ line.strip() +('\n'))
      print('-----------------------------------------------')
      f.write('----------------------------------------------- \n')
      for element in driver.find_elements_by_xpath('//*[@id="product_description_%s"]/h3/b' %(line.strip())):
        print (element.text)
        f.write(element.text +('\n'))
      for element in driver.find_elements_by_xpath('//*[@id="generate_table_%s"]/div' %(line.strip())):
        print (element.text)
        f.write(element.text +('\n'))
      for element in driver.find_elements_by_xpath('//*[@id="generate_table_%s"]/table/tbody' %(line.strip())):
        print (element.text)
        f.write(element.text)
        print('\n')
        f.write('\n')
    f.close()
    input('All SN checked press ENTER to finish.')
  driver.close()

def captchadef():
  global driver
  # Time to waiting is page is ready 'delay'
  try:
    WebDriverWait(driver, delay).until(EC.presence_of_element_located((By.ID, 'captchaChars')))
  except TimeoutException:
    print ("Loading took too much time or not captcha needed")
    return()
  try:
    z = 0
    if z > 1:
      print('Captcha fail, try again...')
    while driver.find_element_by_id('captchaChars'):
      element = driver.find_element_by_xpath('//*[@id="captchaImg"]')
      location = element.location
      size = element.size
      time.sleep(2)
      driver.save_screenshot('pageimage.png')
      # crop image
      x = location['x']
      y = location['y']
      width = location['x']+size['width']
      height = location['y']+size['height']
      im = Image.open('pageImage.png')
      im = im.crop((int(x), int(y), int(width), int(height)))
      im.save('captcha.png')
      img=Image.open('captcha.png')
      img.show()
      capt_re = input('Please insert captcha: ')
      driver.find_element_by_id('captchaChars').send_keys(capt_re)
      driver.find_element_by_id('captchaSubmitBtn').click()
      os.system('TASKKILL /F /IM Microsoft.Photos.exe 2>NUL') #for windows 10
  except:
    print('\nNo more captcha needed')
  return()

def main(argv):
  if len(argv) == os.path.isfile('*.txt'):
    print('\nChecking for %s ... \n' % (argv[1]))
    get_warranty_HTML(argv[1])
  else:
    while True:
      argv = input('Please insert your txt file (q): ')

      if os.path.isfile(argv):
        print('\nChecking for %s ... \n' % (argv))
        get_warranty_HTML(argv)
      if argv == 'q':
        quit()

if __name__ == "__main__":
    main(sys.argv)