from functools import partial
from random import randint

import torch
import numpy

from models.point_completion import OccupancyModel
from train import MODEL_FILENAME, SHAPENET_CLASS_DIR
from utils.constants import DEVICE, POINTCLOUD_N
from utils.data_loader import generate_data_loader

def generate_grid(ncuts, xl, xr, yl, yr, zl, zr):
    # The unit cube centered at 0
    # Subdivided into a grid of 32^3 "voxels"
    x = numpy.linspace(xl, xr, ncuts)
    y = numpy.linspace(yl, yr, ncuts)
    z = numpy.linspace(zl, zr, ncuts)
    xg, yg, zg = numpy.meshgrid(x, y, z)
    x = torch.tensor(xg)
    y = torch.tensor(yg)
    z = torch.tensor(zg)
    # Convert to a grid of 3 dimensional coordinate
    tgrid = torch.stack([x, y, z], dim=3).permute(1, 0, 2, 3)
    # A cube is made up the 8 vertices
    # Convert to a list where every 8 coords denote a cube
    gridpts = torch.zeros(8*(ncuts-1)*(ncuts-1)*(ncuts-1), 3)

    '''
    Vertex Order for marching cubes is
    (0,0,0):(1,0,0):(1,1,0):(0,1,0):(0,0,1):(1,0,1):(1,1,1):(0,1,1)
    '''
    gpt = 0
    for i in range(ncuts-1):
        for j in range(ncuts-1):
            for k in range(ncuts-1):
                gridpts[gpt] = tgrid[i][j][k]
                gridpts[gpt+1] = tgrid[i+1][j][k]
                gridpts[gpt+2] = tgrid[i+1][j+1][k]
                gridpts[gpt+3] = tgrid[i][j+1][k]
                gridpts[gpt+4] = tgrid[i][j][k+1]
                gridpts[gpt+5] = tgrid[i+1][j][k+1]
                gridpts[gpt+6] = tgrid[i+1][j+1][k+1]
                gridpts[gpt+7] = tgrid[i][j+1][k+1]
                gpt = gpt + 8

    return gridpts

def generate_adaptive_grid(ncuts, xl, xh, yl, yh, zl, zh, limit, mesh_funct, onCuda):
    if not limit:
        return None
    g = generate_grid(ncuts, xl, xh, yl, yh, zl, zh)
    ag = g.view(-1, 3)

    final_grid = []
    # divide list of coordinates into cubes
    for i in range(0, int(ag.size()[0]), 8):
        # marking one active if occupancies differ on the vertices
        active = False
        for k in range(0, 8):
            coord = ag[i + k]
            if onCuda:
                coord = coord.cuda()
            active ^= mesh_funct(coord)
        if (active):
            # near left coordinate is v0
            nl = ag[i]
            # top right coordinate is v6
            tr = ag[i + 6]

            # subdivide this cube into 8 subvoxels
            g = generate_adaptive_grid(3, nl[0], tr[0], nl[1], tr[1], nl[2], tr[2], limit - 1, mesh_funct, onCuda)
            # replace this grid where the cube was
            if g is not None:
                final_grid.append(g)
            # or keep this cube
            else:
                final_grid.append(ag[i: i + 8])
        else:
            final_grid.append(ag[i:i + 8])
    for i in range(len(final_grid)):
        final_grid[i] = final_grid[i].view(-1, 3)
    final_grid = torch.cat(final_grid)

    return final_grid

def over_model_threshold(model, sample_pointcloud, pts):
    pts = pts.view(-1, 1, 3, 1).permute(0, 2, 1, 3)
    x = model(pts, sample_pointcloud)
    x = x.squeeze(-1)
    x = torch.sigmoid(x)
    return (x[0] > 0.6).item()

def write_point_cloud_to_xyz(pointcloud, filename):
    with open(filename, 'w') as fh:
        fh.write(f"{pointcloud[0].shape[0]}\n")
        for points in pointcloud[0]:
            fh.write(f"{points[0].item()} {points[1].item()} {points[2].item()}\n")

if __name__ == "__main__":
    model = OccupancyModel()
    model.load_state_dict(torch.load(MODEL_FILENAME, map_location=DEVICE))
    model.cuda()
    model.eval()

    test_loader = generate_data_loader(SHAPENET_CLASS_DIR, 'test.lst', batch_size=1)

    for batch_idx, data in enumerate(test_loader):
        pts, occupancies, sample_pointcloud, org_pointcloud = data

        write_point_cloud_to_xyz(org_pointcloud, './data/original_point_cloud_2.xyz')
        write_point_cloud_to_xyz(sample_pointcloud, './data/sample_point_cloud_2.xyz')

        torch.save(sample_pointcloud, './data/sample_pointcloud.pt')
        sample_pointcloud = sample_pointcloud.view(-1, POINTCLOUD_N, 3, 1).permute(0, 2, 1, 3).cuda()

        # f = partial(over_model_threshold, model, sample_pointcloud)
        # print('generating adaptive grid')
        # g = generate_adaptive_grid(32, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 3, f, True)
        # adaptive_grid_fn = 'phone_ag_32_3.txt'
        # print(f'saving adaptive grid to {generate_adaptive_grid}')
        # numpy.savetxt(generate_adaptive_grid, g.detach().numpy())

        g = generate_grid(32, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5)

        # uncomment to serialize grid to disk
        # non_adaptive_grid_fn = 'phone_g_32_3.txt'
        # print(f'saving adaptive grid to {non_adaptive_grid_fn}')
        # numpy.savetxt(non_adaptive_grid_fn, g.detach().numpy())

        occ = []
        with torch.no_grad():
            for p in g:
                c = p.view(-1, 1, 3, 1).permute(0, 2, 1, 3).cuda()
                pred = model(c, sample_pointcloud)
                c.cpu()
                occ.append(pred.cpu())
        print('saving results')
        numpy.savetxt('./data/phone_g_preds_32_3.txt', occ)

        pred = torch.tensor(numpy.loadtxt('./data/phone_g_preds_32_3.txt'), dtype=torch.float)
        pts = torch.tensor(numpy.loadtxt('./data/phone_g_32_3.txt'), dtype=torch.float)
        mask = pred > 0.6
        pointCloud = pts[mask]
        numpy.savetxt('./data/phone_32_3_ptcloud.xyz', pointCloud.detach().numpy())
        break


import itertools

from gavo import base
from gavo import rscdef
from gavo import svcs
from gavo import utils
from gavo.registry.model import VS

_VOTABLE_TO_SIMPLE_TYPE_MAP = {
	"char": "char",
	"bytea": "char",
	"unicodeChar": "char",
	"short": "integer",
	"int": "integer",
	"long": "integer",
	"float": "real",
	"double": "real",
}

def simpleDataTypeFactory(dbType):
	type, length, xtype = base.sqltypeToVOTable(dbType)
	if length=='1':
		length = None
	return VS.dataType(arraysize=length)[
		_VOTABLE_TO_SIMPLE_TYPE_MAP.get(type, "char")]

def voTableDataTypeFactory(dbType):
	type, length, xtype = base.sqltypeToVOTable(dbType)
	return VS.voTableDataType(arraysize=length)[type]

def getSchemaForRD(rd):
	"""returns a VS.schema instance for an rd.

	No tables are added.  You need to pick and choose them yourself.
	"""
	return VS.schema[
		VS.name[rd.schema.lower()],
		VS.title[base.getMetaText(rd, "title")],
		VS.description[base.getMetaText(rd, "description")],
	]

def getForeignKeyForForeignKey(fk, namesInSet):
	"""returns a VS.foreignKey for a rscdef.ForeignKey.

	If the target table's name is not in nameInSet, the foreign key
	is not created.
	"""
# XXX TODO: we don't need to expand any more as soon as we've done away with
# the table attribute of foreignKey
	targetName = fk.parent.expand(fk.destTableName).lower()
	if targetName not in namesInSet:
		return None

	return VS.foreignKey[
		VS.targetTable[targetName], [
			VS.fkColumn[
				VS.fromColumn[fromColName.lower()],
				VS.targetColumn[toColName.lower()]]
			for fromColName,toColName in zip(fk.source, fk.dest)]]

def getTableColumnFromColumn(column, typeFactory):
	"""returns a VS.column instance for an rscdef.Column instance.

	typeElement is a factory for types that has to accept an internal (SQL)
	type as child and generate whatever is necessary from that.

	This module contains simpleDataTypeFactory, voTableDataTypeFactory,
	and should soon contain tapTypeFactory.
	"""
	if isinstance(column.name, utils.QuotedName):
		colName = str(column.name)
	else:
		colName = column.name.lower()

	flags = []
	if column.isIndexed():
		flags.append("indexed")
	if column.isPrimary():
		flags.append("primary")
	elif not column.required:
		flags.append("nullable")

	return VS.column[
		VS.name[colName],
		VS.description[column.description],
		VS.unit[column.unit],
		VS.ucd[column.ucd],
		VS.utype[column.utype],
		typeFactory(column.type),
		[VS.flag[f] for f in flags]]

def getEffectiveTableName(tableDef):
	"""returns the "effective name" of tableDef.

	This is mainly for fudging the names of output tables since,
	by default, they're ugly (and meaningless on top of that).
	"""
	if isinstance(tableDef, svcs.OutputTableDef):
		return "output"
	else:
		return tableDef.getQName().lower()

def getTableForTableDef(tableDef, namesInSet):
	"""returns a VS.table instance for a rscdef.TableDef.

	namesInSet is a set of lowercased qualified table names; we need this
	to figure out which foreign keys to create.
	"""
	name = getEffectiveTableName(tableDef)

	# Fake type=output on the basis of the table name.  We'll have
	# to do something sensible here if this "type" thing ever becomes
	# more meaningful.
	type = None
	if name=="output":
		type = "output"

	res = VS.table(type=type)[
		VS.name[name],
		VS.title[base.getMetaText(tableDef, "title", propagate=False)],
		VS.description[base.getMetaText(tableDef, "description", propagate=True)],
		VS.utype[base.getMetaText(tableDef, "utype")], [
			getTableColumnFromColumn(col, voTableDataTypeFactory)
				for col in tableDef], [
			getForeignKeyForForeignKey(fk, namesInSet)
				for fk in tableDef.foreignKeys]]
	return res

def getTablesetForSchemaCollection(schemas, rootElement=VS.tableset):
	"""returns a vs:tableset element from a sequence of (rd, tables) pairs.

	In each pair, rd is used to define a VODataService schema, and tables is
	a sequence of TableDefs that define the tables within that schema.
	"""
	# we don't want to report foreign keys into tables not part of the
	# service's tableset (this is for consistency with TAP_SCHEMA,
	# mainly).  Hence, we collect the table names given.
	namesInSet = set(getEffectiveTableName(td).lower()
		for td in itertools.chain(*(tables for rd, tables in schemas)))

	res = rootElement()
	for rd, tables in schemas:
		res[VS.schema[
			VS.name[rd.schema],
			VS.title[base.getMetaText(rd, "title")],
			VS.description[base.getMetaText(rd, "description")],
			VS.utype[base.getMetaText(rd, "utype", None)],
			[getTableForTableDef(td, namesInSet)
				for td in tables]]]
	return res

def getTablesetForService(resource, rootElement=VS.tableset):
	"""returns a VS.tableset for a service or a published data resource.

	This is for VOSI queries and the generation of registry records.
	Where it actually works on services, it uses the service's getTableset
	method to find out the service's table set; if it's passed a TableDef
	of a DataDescriptor, it will turn these into tablesets.

	Sorry about the name.
	"""
	if isinstance(resource, rscdef.TableDef):
		tables = [resource]

	elif isinstance(resource, rscdef.DataDescriptor):
		tables = list(resource.iterTableDefs())

	else:
		tables = resource.getTableSet()

	if not tables:
		return rootElement[
			VS.schema[
				VS.name["default"]]]

	# it's possible that multiple RDs define the same schema (don't do
	# that, it's going to cause all kinds of pain).  To avoid
	# generating bad tablesets in that case, we have the separate
	# account of schema names; the schema meta is random when
	# more than one RD exists for the schema.
	bySchema, rdForSchema = {}, {}
	for t in tables:
		bySchema.setdefault(t.rd.schema, []).append(t)
		rdForSchema[t.rd.schema] = t.rd

	schemas = []
	for schemaName, tables in sorted(bySchema.iteritems()):
		schemas.append((rdForSchema[schemaName], tables))

	return getTablesetForSchemaCollection(schemas, rootElement)


n = int(input())
s = input()
abcList = [[] for i in range(n)]
for i in range(n):
    moji = s[i]
    abcList[ord(moji) - ord("a")].append(i)
print(abcList)
q = int(input())
for i in range(q):
    q, il, cr = map(int, input().split())
    if q == 1:
        i = il
        c = cr
        left = 0
        right = len(abcList)
        while left < right:
            mid = (left + right) // 2
            if abcList[mid] == -1:
                mid -= 1
            if left == mid:
                pass


"""
Helpers for sending emails.
"""
import functools
import os

import sendgrid
from sendgrid.helpers import mail

_SENDGRID_API_ENV = 'SENDGRID_API_KEY'

@functools.lru_cache()
def _sg() -> sendgrid.SendGridAPIClient:
    """Returns a cached SendGridAPIClient."""
    return sendgrid.SendGridAPIClient(api_key=os.environ.get(_SENDGRID_API_ENV))

def send_email(
        from_email: str, to_email: str, subject: str, content: str) -> None:
    """Sends an email."""
    from_email = mail.Email(from_email)
    to_email = mail.To(to_email)
    subject = subject
    content = mail.Content("text/html", content)
    the_mail = mail.Mail(from_email, to_email, subject, content)
    response = _sg().client.mail.send.post(request_body=the_mail.get())
    assert response.status_code == 202


import os
import numpy as np
from typing import List, Dict, Tuple, Union, Optional
import random
from gensim.models import Word2Vec
import pickle
import openpyxl
import re
from copy import deepcopy
from collections import namedtuple
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.font_manager as fm

ChKrEntity = namedtuple('entity', 'chinese ch_idx type korean kr_idx')

kings_total = ['k01_Taejo', 'k02_Jeongjong', 'k03_Taejong', 'k04_Sejong', 'k05_Munjong', 'k06_Danjong',
               'k07_Sejo', 'k08_Yejong', 'k09_Seongjong', 'k10_Yeonsangun', 'k11_Jungjong', 'k12_Injong',
               'k13_Myungjong', 'k14_Seonjo', 'k14_Seonjo_sujeong', 'k15_Gwanghaegun_jeongcho',
               'k15_Gwanghaegun_jungcho', 'k16_Injo', 'k17_Hyojong', 'k18_Hyeonjong', 'k18_Hyeonjong_gaesu',
               'k19_Sukjong', 'k19_Sukjong_bogwoljeongo', 'k20_Gyeongjong', 'k20_Gyeongjong_sujeong',
               'k21_Yeongjo', 'k22_Jeongjo', 'k23_Sunjo', 'k24_Heonjong', 'k25_Cheoljong']

HOME_PATH = os.path.expanduser('~')
SILOK_PATH = os.path.join(HOME_PATH, 'chosun-utf8')

PAD = 'PAD'
UNK = 'UNK'
GO = 'GO'
EOS = 'EOS'
EOS_ID = 3
# SPECIAL_WORDS = [PAD, UNK, GO, EOS]

CONFIG_TXT = 'config.txt'
CONFIG_PICKLE = 'config.p'
LOG_DIR = 'Logs'
PARAMS_DIR = 'Params'
PARAMS = 'params'
TRAIN_LOG = 'Train_log.txt'

not_ch = re.compile(r'[^\u2E80-\u2EFF\u3400-\u4DBF\u4E00-\u9FBF\uF900-\uFAFF]')
space = re.compile(r'\s{2,}')

# ###########################################################################
# ################## For NER ################################################
# ###########################################################################
T_NAME = '이름'
T_BOOK = '서명'
T_YEAR = '연호'
T_LOC = '지명'

TYPES = [T_NAME, T_LOC, T_BOOK, T_YEAR]

NAME_REGEX = re.compile(r'12*')
LOC_REGEX = re.compile(r'34*')
BOOK_REGEX = re.compile(r'56*')
YEAR_REGEX = re.compile(r'78*')

TYPES_REGEX = [NAME_REGEX, LOC_REGEX, BOOK_REGEX, YEAR_REGEX]

OUTSIDE = 'OUTSIDE'
B_NAME = 'B_NAME'
I_NAME = 'I_NAME'
B_LOC = 'B_LOC'
I_LOC = 'I_LOC'
B_BOOK = 'B_BOOK'
I_BOOK = 'I_BOOK'
B_YEAR = 'B_YEAR'
I_YEAR = 'I_YEAR'
BIO2IDX = {OUTSIDE: 0,
           B_NAME: 1, I_NAME: 2,
           B_LOC: 3, I_LOC: 4,
           B_BOOK: 5, I_BOOK: 6,
           B_YEAR: 7, I_YEAR: 8}

TYPE2IDX = {T_NAME: (BIO2IDX[B_NAME], BIO2IDX[I_NAME]),
            T_LOC: (BIO2IDX[B_LOC], BIO2IDX[I_LOC]),
            T_BOOK: (BIO2IDX[B_BOOK], BIO2IDX[I_BOOK]),
            T_YEAR: (BIO2IDX[B_YEAR], BIO2IDX[I_YEAR])}

CODE2KING = {'waa': (1, 'k01_Taejo'),
             'wba': (2, 'k02_Jeongjong'),
             'wca': (3, 'k03_Taejong'),
             'wda': (4, 'k04_Sejong'),
             'wea': (5, 'k05_Munjong'),
             'wfa': (6, 'k06_Danjong'),
             'wga': (7, 'k07_Sejo'),
             'wha': (8, 'k08_Yejong'),
             'wia': (9, 'k09_Seongjong'),
             'wja': (10, 'k10_Yeonsangun'),
             'wka': (11, 'k11_Jungjong'),
             'wla': (12, 'k12_Injong'),
             'wma': (13, 'k13_Myungjong'),
             'wna': (14, 'k14_Seonjo'),
             'wnb': (14, 'k14_Seonjo_sujeong'),
             'woa': (15, 'k15_Gwanghaegun_jungcho'),
             'wob': (15, 'k15_Gwanghaegun_jeongcho'),
             'wpa': (16, 'k16_Injo'),
             'wqa': (17, 'k17_Hyojong'),
             'wra': (18, 'k18_Hyeonjong'),
             'wrb': (18, 'k18_Hyeonjong_gaesu'),
             'wsa': (19, 'k19_Sukjong'),
             'wsb': (19, 'k19_Sukjong_bogwoljeongo'),
             'wta': (20, 'k20_Gyeongjong'),
             'wtb': (20, 'k20_Gyeongjong_sujeong'),
             'wua': (21, 'k21_Yeongjo'),
             'wva': (22, 'k22_Jeongjo'),
             'wwa': (23, 'k23_Sunjo'),
             'wxa': (24, 'k24_Heonjong'),
             'wya': (25, 'k25_Cheoljong')}
# ###########################################################################
# ################## For NER ################################################
# ###########################################################################

class PairData:
    def __init__(self,
                 ch_sent: str,
                 ch_tok: List[str],
                 kr_sent: str,
                 kr_tok: List[str]):
        self.ch_sent = ch_sent
        self.ch_tok = ch_tok
        self.ch_seq_len = len(self.ch_tok)
        self.kr_sent = kr_sent
        self.kr_tok = kr_tok
        self.kr_seq_len = len(self.kr_tok)

    def print(self):
        s = """
            Chinese
                sentence: %s
                token: %s
                sequence length: %s
            Korean
                sentence: %s
                token: %s
                sequence length: %s
            \n\r""" % (self.ch_sent, self.ch_tok, self.ch_seq_len,
                       self.kr_sent, self.kr_tok, self.kr_seq_len)
        return s

class DataSet:
    """
    Encoder Input: Sequence of Chinese Character Tokens
    Decoder Input: Sequence of Korean Tokens
    """
    def __init__(self,
                 enc_max_len: int,
                 dec_max_len: int,
                 ch_word2id: Dict,
                 kr_word2id: Dict):
        self.enc_max_len = enc_max_len
        # include GO or EOS token
        self.dec_max_len = dec_max_len

        self.ch_word2id = ch_word2id
        self.kr_word2id = kr_word2id

        self._sequential_indices = 0

        self.num_data = None
        self.full_indices = None
        self.enc_tokens = []
        self.enc_inputs = None
        self.enc_seq_len = None

        self.dec_tokens = []
        self.dec_inputs = None
        self.dec_targets = None
        self.dec_seq_len = None

    def make(self,
             pairs: List[PairData],
             train_phase: bool):

        new_pairs = list()
        for p in pairs:
            # GO or EOS token will be appended to Korean sequence
            if 1 <= p.ch_seq_len <= self.enc_max_len and 1 <= p.kr_seq_len <= self.dec_max_len - 1:
                new_pairs.append(p)
        del pairs

        self.num_data = len(new_pairs)
        self.full_indices = list(range(self.num_data))
        self.enc_inputs = np.zeros([self.num_data, self.enc_max_len], dtype=np.uint32)
        self.enc_seq_len = np.zeros([self.num_data], dtype=np.uint32)

        self.dec_inputs = np.zeros([self.num_data, self.dec_max_len], dtype=np.uint32)
        self.dec_targets = np.zeros([self.num_data, self.dec_max_len], dtype=np.uint32)
        self.dec_seq_len = np.zeros([self.num_data], dtype=np.uint32)

        for i, p in enumerate(new_pairs):
            # ch_ids = list(map(lambda x: self.ch_word2id.get(x, self.ch_word2id[UNK]), p.ch_tok))
            ch_ids = seq2ids(p.ch_tok, self.ch_word2id)
            self.enc_inputs[i, :p.ch_seq_len] = ch_ids
            self.enc_seq_len[i] = p.ch_seq_len

            # kr_ids = list(map(lambda x: self.kr_word2id.get(x, self.kr_word2id[UNK]), p.kr_tok))
            kr_ids = seq2ids(p.kr_tok, self.kr_word2id)
            self.dec_inputs[i, :p.kr_seq_len+1] = [self.kr_word2id[GO]] + kr_ids
            self.dec_targets[i, :p.kr_seq_len+1] = kr_ids + [self.kr_word2id[EOS]]
            self.dec_seq_len[i] = p.kr_seq_len + 1

            if not train_phase:
                self.enc_tokens.append(p.ch_tok)
                self.dec_tokens.append(p.kr_tok)

    def get_train_batch(self, batch_size):
        indices = random.sample(self.full_indices, batch_size)
        out = (self.enc_inputs[indices, :],
               self.enc_seq_len[indices],
               self.dec_inputs[indices, :],
               self.dec_targets[indices, :],
               self.dec_seq_len[indices])
        return out

    @property
    def sequential_indices(self):
        return self._sequential_indices

    @sequential_indices.setter
    def sequential_indices(self, idx=0):
        self._sequential_indices = idx

    def get_eval_batch(self, batch_size):
        s = self.sequential_indices
        e = self.sequential_indices + batch_size
        # If remain data is not enough, < batch size, drop remain data, finish sequential batch
        out = (self.enc_tokens[s:e],
               self.enc_inputs[s:e, :],
               self.enc_seq_len[s:e],
               self.dec_tokens[s:e])
        self.sequential_indices += batch_size
        return out

    def get_check_batch(self, batch_size):
        s = self.sequential_indices
        e = self.sequential_indices + batch_size
        out = (self.enc_tokens[s:e],
               self.enc_inputs[s:e, :],
               self.enc_seq_len[s:e],
               self.dec_tokens[s:e],
               self.dec_inputs[s:e, :],
               self.dec_targets[s:e, :],
               self.dec_seq_len[s:e],)
        self.sequential_indices += batch_size
        return out

class ParaData:
    """
    XML file paragraph data
    """
    def __init__(self,
                 chinese: str,
                 level5_id: str,
                 y: np.ndarray,
                 seq_len: int,
                 entities: List[Tuple[str, int, str]]):
        self.chinese = chinese
        self.level5_id = level5_id
        self.y = y
        self.seq_len = seq_len
        self.entities = entities

    def print(self):
        s = """
            Chinese:    %s
            level5_id:  %s
            Y:          %s
            seq_len:    %s
            entities:   %s
            restore-e:  %s
            \r""" % (self.chinese,
                     self.level5_id,
                     list(self.y),
                     self.seq_len,
                     self.entities,
                     pred2ne(self.chinese, self.y))
        return s

class DataSetNER:
    """
    Input: Chinese Character
    Output: Begin, Inside, Outside
    """
    def __init__(self,
                 max_seq_len: int,
                 char2id: Dict):

        self.max_seq_len = max_seq_len
        self.char2id = char2id

        self._sequential_indices = 0

        self.num_data = None
        self.full_indices = None

        self.ch_toks = []
        self.x = None
        self.y = None
        self.seq_len = None

    def make(self,
             paras: List[ParaData],
             train_phase: bool):

        new_paras = []
        for p in paras:
            # GO or EOS token will be appended to Korean sequence
            if 1 <= p.seq_len <= self.max_seq_len:
                new_paras.append(p)
        del paras

        self.num_data = len(new_paras)
        self.full_indices = list(range(self.num_data))
        self.x = np.zeros([self.num_data, self.max_seq_len], dtype=np.uint16)
        self.y = np.zeros([self.num_data, self.max_seq_len], dtype=np.uint16)
        self.seq_len = np.zeros([self.num_data], dtype=np.uint16)

        for i, p in enumerate(new_paras):
            ch_ids = seq2ids(list(p.chinese), self.char2id)

            if not (len(ch_ids) == len(p.y) == p.seq_len):
                raise ValueError('Sequence Length Not Equal x: %d,  y: %d,  seq_len: %d' %
                                 (len(ch_ids), len(p.y), p.seq_len))

            self.x[i, :p.seq_len] = ch_ids
            self.y[i, :p.seq_len] = p.y
            self.seq_len[i] = p.seq_len

            if not train_phase:
                self.ch_toks.append(list(p.chinese))
            print('\rMake Dataset... %d/%d' % (i, self.num_data), end='')
        print()
        return

    def get_train_batch(self, batch_size):
        """
        :param batch_size: batch size
        :return: x, y, seq_len
        """
        indices = random.sample(self.full_indices, batch_size)
        x = self.x[indices, :]
        y = self.y[indices, :]
        seq_len = self.seq_len[indices]
        return x, y, seq_len

    @property
    def sequential_indices(self):
        return self._sequential_indices

    @sequential_indices.setter
    def sequential_indices(self, idx=0):
        self._sequential_indices = idx

    def get_eval_batch(self, batch_size):
        s = self.sequential_indices
        e = self.sequential_indices + batch_size
        # If remain data is not enough, < batch size, drop remain data, finish sequential batch
        ch_toks = self.ch_toks[s:e]
        x = self.x[s:e, :]
        y = self.y[s:e, :]
        seq_len = self.seq_len[s:e]
        self.sequential_indices += batch_size
        return ch_toks, x, y, seq_len

def clean_up_ch(ch: str):
    """
    Remove all character which is not Chinese.
    """
    return not_ch.sub('', ch)

def pickle_store(obj, path):
    f = open(path, 'wb')
    pickle.dump(obj, f)
    f.close()
    return

def pickle_load(path):
    f = open(path, 'rb')
    a = pickle.load(f)
    f.close()
    return a

def read_xlsx(xlsx_path, column: List):
    wb = openpyxl.load_workbook(xlsx_path)
    ws = wb.active
    data = []
    if len(column) == 1:
        for r in ws.rows:
            data.append(r[column[0]].value)
    else:
        for r in ws.rows:
            rr = []
            for c in column:
                rr.append(r[c].value)
            data.append(tuple(rr))
    wb.close()
    return data

def read_pickles(folder: str):
    files = os.listdir(folder)
    d = []
    for f in files:
        if f.split('.')[-1] == 'p':
            d = d + pickle_load(os.path.join(folder, f))
    return d

def print_write(s, file, mode=None):
    if isinstance(file, str):
        if mode is None:
            mode = 'a'
        f = open(file, mode)
        print(s, end='')
        f.write(s)
        f.close()
    else:
        print(s, end='')
        file.write(s)

def dict_swap(my_dic: Dict):
    return {v: k for k, v in my_dic.items()}

def uni2dec(c):
    encoded = list(c.encode('unicode-escape'))[2:]
    if not encoded:
        return 0
    h = ''
    for c in encoded:
        h += chr(c)
    return int(h, 16)

def unicode_classify(c):
    dec = uni2dec(c)
    if (int('4E00', 16) <= dec <= int('9FFF', 16) or
            int('3400', 16) <= dec <= int('4DBF', 16) or
            int('F900', 16) <= dec <= int('FAFF', 16)):
        return 0    # Chinese
    elif int('AC00', 16) <= dec <= int('D7AF', 16):
        return 1    # Korean
    else:
        return 2    # else

def text_readlines(file_path):
    f = open(file_path, 'r', encoding='utf-8')
    t = f.readlines()
    f.close()
    return t

def text_read(file_path):
    f = open(file_path, 'r', encoding='utf-8')
    t = f.read()
    f.close()
    return t

def read_dic(path, start_line):
    f = open(path, 'r', encoding='utf-8')
    lines = f.readlines()[start_line:]
    f.close()
    dic = dict()
    for i, l in enumerate(lines):
        try:
            s = l.split()
            dic[s[0]] = s[1]
        except IndexError:
            print(i)
            print(lines[i])
            print(lines[i - 1])
            raise IndexError
    return dic

def read_lexicon(path, start_line):
    f = open(path, 'r', encoding='utf-8')
    lines = f.readlines()[start_line:]
    f.close()
    o = list()
    for i, l in enumerate(lines):
        try:
            s = l.split()
            o.append((s[0], s[1]))
        except IndexError:
            print(i)
            print(lines[i])
            print(lines[i-1])
            raise IndexError
    return o

def chinese_regularize(line, dic):
    """
    Change all chinese character unified
    :param line: Chinese or Korean that has chinese character sentence
    :param dic: compatibility -> unified chinese character dictionary
    :return: unified chinese sentence
    """
    # line_out = ''
    # for c in line:
    #     try:
    #         line_out = line_out + dic[c]
    #     except KeyError:
    #         line_out = line_out + c
    # return line_out
    return ''.join(list(map(lambda x: dic.get(x, x), line)))

def remove_redundant_line(lines: List[str], check=0):
    new_lines = []
    for line in lines:
        f = False
        for c in line:
            if unicode_classify(c) == check:    # 0 hanja, 1 hangeul
                f = True
                break
        if f:
            new_lines.append(line)
    return new_lines

def remove_single_entity(ne_list):
    new = []
    for n in ne_list:
        if isinstance(n, tuple):
            if len(n[0]) > 1:
                new.append(n)
        else:
            if len(n) > 1:
                new.append(n)
    return new

def get_txt_paths(basic_path: str, kings: List[str]):
    txts = []
    for king in kings:
        king_path = os.path.join(basic_path, king)
        books = os.listdir(king_path)
        for book in books:
            book_path = os.path.join(king_path, book)
            texts = os.listdir(book_path)
            for text in texts:
                text_path = os.path.join(book_path, text)
                txts.append(text_path)
    return txts

def seq2ids(seq: List[str], d: Dict) -> List[int]:
    ids = list(map(lambda x: d.get(x, d[UNK]), seq))
    return ids

def ids2seq(ids: Union[np.ndarray, List[int]], d: Dict, clip_token: Optional[str] = None):
    seq = list(map(lambda x: d[x], ids))
    if clip_token is not None:
        try:
            return seq[:seq.index(clip_token)]
        except ValueError:
            return seq
    else:
        return seq

def load_word2vec(model: Union[Word2Vec, str],
                  special_words: List[str]) -> Tuple[Dict, np.ndarray, int]:
    """
    :param model: gensim word2vec model
    :param special_words: List of special word such as Pad, Unknown, Go and EOS token
    :return: word dictionary, embedding vectors, embedding size
    """
    if isinstance(model, str):
        model = Word2Vec.load(model)

    size = model.wv.vectors.shape[1]

    special_vectors = list()
    m = np.mean(model.wv.vectors)
    s = np.std(model.wv.vectors)
    for word in special_words:
        if word == PAD:
            special_vectors.append(np.zeros((1, size)))
        else:
            special_vectors.append(np.random.normal(size=(1, size), loc=m, scale=s))

    special_vectors = np.concatenate(special_vectors, axis=0)
    assert special_vectors.shape[0] == len(special_words)

    word2idx = {c: i for i, c in enumerate(special_words + model.wv.index2word)}
    vectors = np.concatenate((special_vectors, model.wv.vectors), axis=0)

    return word2idx, vectors, size

def pred2ne(sent: str, pred: Union[np.ndarray, List, Tuple]):
    if len(sent) != len(pred):
        raise ValueError('sentence length(%d) and prediction length(%d) is not equal'
                         % (len(sent), len(pred)))

    seq_len = sent.find(PAD)
    if seq_len < 0:
        seq_len = len(sent)
    sent = sent[:seq_len]
    pred = pred[:seq_len]
    pred_seq = ''.join(map(lambda x: str(x), pred))

    entities = []

    for r, t in zip(TYPES_REGEX, TYPES):
        for m in r.finditer(pred_seq):
            start, end = m.span()
            entities.append((sent[start:end], start, t))

    entities.sort(key=lambda x: x[1])
    return entities

def entity_form(target: List[List[Tuple[str, int, str]]],
                prediction: List[List[Tuple[str, int, str]]]) -> Tuple[float, float, float]:
    assert len(target) == len(prediction)
    n_sentence = len(target)
    true_ne = deepcopy(target)
    pred_ne = deepcopy(prediction)

    tp_ne = []
    fp_ne = []
    fn_ne = []

    for i in range(n_sentence):
        p = set(pred_ne[i])
        t = set(true_ne[i])

        tp_ne.append(p & t)
        fp_ne.append(p - t)
        fn_ne.append(t - p)

    true_positive = 0
    false_positive = 0
    false_negative = 0
    for i in range(n_sentence):
        true_positive += len(tp_ne[i])
        false_positive += len(fp_ne[i])
        false_negative += len(fn_ne[i])

    return score(true_positive, false_positive, false_negative)

def surface_form(target: List[List[Tuple[str, int, str]]],
                 prediction: List[List[Tuple[str, int, str]]]) -> Tuple[float, float, float]:
    assert len(target) == len(prediction)
    n_sentence = len(target)
    true_ne = []
    pred_ne = []

    for i in range(n_sentence):
        for ne in target[i]:
            true_ne.append(ne[0])
        for ne in prediction[i]:
            pred_ne.append(ne[0])

    t = set(true_ne)
    p = set(pred_ne)

    tp_ne = p & t
    fp_ne = p - t
    fn_ne = t - p

    true_positive = len(tp_ne)
    false_positive = len(fp_ne)
    false_negative = len(fn_ne)

    return score(true_positive, false_positive, false_negative)

def harmonic_mean(a, b):
    return (2*a*b)/(a+b)

def score(tp: int, fp: int, fn: int) -> Tuple[float, float, float]:
    try:
        precision = tp / (tp + fp)
    except ZeroDivisionError:
        precision = 0

    try:
        recall = tp / (tp + fn)
    except ZeroDivisionError:
        recall = 0

    try:
        f1 = harmonic_mean(precision, recall)
    except ZeroDivisionError:
        f1 = 0

    return f1, precision, recall

def search_entity_by_dictionary(line, ne_list):
    # ne_list = [('綾城監', '이름'), ('尹熙鼎', '이름'), ('文尙男', '이름'), ('聖賚', '이름')]
    entities = []
    temp = line
    for ne, c in ne_list:
        flag = False
        s = 0
        while True:
            ne_idx = temp.find(ne, s)
            if ne_idx < 0:
                break
            else:
                flag = True
                s = ne_idx + len(ne)
                entities.append((ne, ne_idx, c))
        if flag:
            temp = temp.replace(ne, '-'*(len(ne)))
    return entities

def entity_lookup(attention_map, chinese_entities, kr_tokens):
    # attention_map [decoder length, encoder length]
    # entities = [('徐便己', 36, '이름'), ('胡璟', 43, '이름'),
    # ('龍州', 52, '지명'), ('李勇', 66, '이름'), ('《綱目》', 43, '서명')]
    entities = []
    for entity_tuple in chinese_entities:
        entity = entity_tuple[0]
        ch_idx = entity_tuple[1]
        entity_type = entity_tuple[2]

        if entity_type == '서명':
            entity = entity.strip('《》')
            ch_idx = ch_idx+1

        a = attention_map[:, ch_idx:ch_idx+len(entity)]
        s = np.sum(a, axis=1)
        e = ChKrEntity(chinese=entity,
                       ch_idx=ch_idx,
                       type=entity_type,
                       korean=kr_tokens[np.argmax(s)],
                       kr_idx=np.argmax(s))
        entities.append(e)
        # entities.append((kr_tokens[np.argmax(s)], np.argmax(s)))
    return entities

def entity_replace(hypothesis: List[str], entities: List[ChKrEntity], entity_dic: Dict):
    hyp_new = hypothesis[:]
    for entity in entities:
        try:
            kr = entity_dic[entity.chinese]
            hyp_new[entity.kr_idx] = kr
        except KeyError:
            pass
    return hyp_new

def matplotlib_fonts():
    font_list = [(f.name, f.fname) for f in fm.fontManager.ttflist if 'Nanum' in f.name]

    # path = '/usr/share/fonts/truetype/nanum/NanumMyeongjo.ttf'

    # font_name = fm.FontProperties(fname=path).get_name()
    print(font_list)
    # print(font_name)

    print([(f.name, f.fname) for f in fm.fontManager.ttflist])

    print(fm.FontProperties(fname='/usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc'))

def plot_attention(attention_map, input_tags=None, output_tags=None, title='attention_map'):
    """
    :param attention_map: 2-Dimensional matrix [output_len, input_len]
    :param input_tags: input token sequence
    :param output_tags: output token sequence
        if input_tags & output_tags aren't given, tick labels are number.
    :param title: figure title
    :return: None
    """
    output_len, input_len = attention_map.shape
    # print(attention_map.shape)
    # Plot the attention_map
    # plt.clf()
    f = plt.figure()
    ax = f.add_subplot(1, 1, 1)
    ax.set_title(title)
    # Add image
    i = ax.matshow(attention_map, interpolation='nearest', cmap='Blues')

    # print(ax)
    # Add colorbar
    # cbaxes = f.add_axes([0.2, 0, 0.6, 0.03])
    # cbar = f.colorbar(i, cax=cbaxes, orientation='vertical')
    # cbar.ax.set_xlabel('Alpha value (Probability output of the "softmax")', labelpad=2)

    font = fm.FontProperties(fname='/usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc')

    # Add labels
    ax.set_yticks(range(output_len))
    if output_tags is None:
        ax.set_yticklabels(list(range(output_len)))
    else:
        ax.set_yticklabels(output_tags[:output_len], fontproperties=font, fontsize='large')

    ax.set_xticks(range(input_len))
    if input_tags is None:
        ax.set_xticklabels(list(range(input_len)))
    else:
        ax.set_xticklabels(input_tags[:input_len], fontproperties=font, fontsize='large')

    ax.set_xlabel('Input Sequence')
    ax.set_ylabel('Output Sequence')

    # add grid and legend
    ax.grid()
    # plt.show()
    return


from odoo import api, fields, models

class AccountPaymentTerm(models.Model):
    _inherit = 'account.payment.term'

    deposit_percentage = fields.Float(string='Deposit Percentage',
                                      help='Require Percentage deposit when paying on the front end.')
    deposit_flat = fields.Float(string='Deposit Flat',
                                      help='Require Flat deposit when paying on the front end.')

class PaymentTransaction(models.Model):
    _inherit = 'payment.transaction'

    def _post_process_after_done(self):
        now = fields.Datetime.now()
        res = super(PaymentTransaction, self)._post_process_after_done()

        # Post Process Payments made on the front of the website, reconciling to Deposit.
        for transaction in self.filtered(lambda t: t.payment_id
                                                   and t.sale_order_ids
                                                   and sum(t.sale_order_ids.mapped('amount_total_deposit'))
                                                   and not t.invoice_ids and (now - t.date).seconds < 1200):
            if not transaction.sale_order_ids.mapped('invoice_ids'):
                # don't process ones that we might still be able to process later...
                transaction.write({'is_processed': False})
            else:
                # we have a payment and could attempt to reconcile to an invoice
                # Leave the payment in 'is_processed': True
                transaction.sale_order_ids._auto_deposit_payment_match()
        return res


import torch
import torchvision
import torch.nn as nn
from typing import Optional, Callable, Type, Union
from torchvision.models.resnet import Bottleneck, conv3x3, conv1x1

class BasicBlock(torchvision.models.resnet.BasicBlock):
    expansion: int = 1

    def __init__(
        self,
        inplanes: int,
        planes: int,
        stride: int = 1,
        downsample: Optional[nn.Module] = None,
        groups: int = 1,
        base_width: int = 64,
        dilation: int = 1,
        norm_layer: str=None,
    ) -> None:
        super(torchvision.models.resnet.BasicBlock, self).__init__()
        if norm_layer == "bn":
            self.bn1 = nn.BatchNorm2d(planes)
            self.bn2 = nn.BatchNorm2d(planes)
        else:
            self.bn1 = nn.GroupNorm(groups, planes)
            self.bn2 = nn.GroupNorm(groups, planes)
        if base_width != 64:
            raise ValueError("BasicBlock only supports base_width=64")
        if dilation > 1:
            raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
        # Both self.conv1 and self.downsample layers downsample the input when stride != 1
        self.conv1 = conv3x3(inplanes, planes, stride)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = conv3x3(planes, planes)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

class ResNet(torchvision.models.resnet.ResNet):
    """ResNet generalization for CIFAR thingies."""

    def __init__(self, block, layers, num_classes=10, zero_init_residual=False,
                 groups=1, base_width=64, replace_stride_with_dilation=None,
                 norm_layer=None, strides=[1, 2, 2, 2], pool='avg'):
        """Initialize as usual. Layers and strides are scriptable."""
        super(torchvision.models.ResNet, self).__init__()  # nn.Module

        self.dilation = 1
        if replace_stride_with_dilation is None:
            # each element in the tuple indicates if we should replace
            # the 2x2 stride with a dilated convolution instead
            replace_stride_with_dilation = [False, False, False, False]
        if len(replace_stride_with_dilation) != 4:
            raise ValueError("replace_stride_with_dilation should be None "
                             "or a 4-element tuple, got {}".format(replace_stride_with_dilation))
        self._norm_layer = norm_layer if norm_layer is not None else "bn"
        self.groups = groups

        self.inplanes = base_width
        if self._norm_layer == "bn":
                self.bn1 = nn.BatchNorm2d(self.inplanes)
        else:
            self.bn1 = nn.GroupNorm(self.groups, self.inplanes)

        self.base_width = 64  # Do this to circumvent BasicBlock errors. The value is not actually used.
        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=3, stride=1, padding=1, bias=False)
        self.relu = nn.ReLU(inplace=True)

        self.layers = nn.ModuleList()
        width = self.inplanes
        for idx, layer in enumerate(layers):
            self.layers.append(self._make_layer(block, width, layer, stride=strides[idx], dilate=replace_stride_with_dilation[idx]))
            width *= 2

        self.pool = nn.AdaptiveAvgPool2d((1, 1)) if pool == 'avg' else nn.AdaptiveMaxPool2d((1, 1))
        self.fc_in_features = width // 2 * block.expansion
        self.fc_out_features = num_classes
        self.fc = nn.Linear(self.fc_in_features, self.fc_out_features)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

        # Zero-initialize the last BN in each residual branch,
        # so that the residual branch starts with zeros, and each residual block behaves like an identity.
        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
        if zero_init_residual:
            for m in self.modules():
                if isinstance(m, torchvision.models.resnet.Bottleneck):
                    nn.init.constant_(m.bn3.weight, 0)
                elif isinstance(m, BasicBlock):
                    nn.init.constant_(m.bn2.weight, 0)

    def _make_layer(
        self,
        block: Type[Union[BasicBlock, Bottleneck]],
        planes: int,
        blocks: int,
        stride: int = 1,
        dilate: bool = False,
    ) -> nn.Sequential:
        norm_layer = self._norm_layer
        downsample = None
        previous_dilation = self.dilation
        if dilate:
            self.dilation *= stride
            stride = 1
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                conv1x1(self.inplanes, planes * block.expansion, stride),
                nn.BatchNorm2d(planes * block.expansion) if self._norm_layer == "bn" else nn.GroupNorm(self.groups, planes * block.expansion),
            )

        layers = []
        layers.append(
            block(
                self.inplanes, planes, stride, downsample, self.groups, self.base_width, previous_dilation, norm_layer
            )
        )
        self.inplanes = planes * block.expansion
        for _ in range(1, blocks):
            layers.append(
                block(
                    self.inplanes,
                    planes,
                    groups=self.groups,
                    base_width=self.base_width,
                    dilation=self.dilation,
                    norm_layer=norm_layer,
                )
            )

        return nn.Sequential(*layers)

    def _forward_impl(self, x):
        # See note [TorchScript super()]
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)

        for layer in self.layers:
            x = layer(x)

        x = self.pool(x)
        x = torch.flatten(x, 1)
        x = self.fc(x)

        return x

    def set_output_layer(self, fc_layer:nn.Module):
        self.fc = fc_layer

if __name__ == "__main__":
    from torchsummary import summary
        # This function creates a fully connected layer to stack on top of the feature extractor
    def make_fc_layer(in_feats:int, out_feats:int, hidden_feats:list ) -> nn.Module:
        if len(hidden_feats) == 0:
            return nn.Sequential(
                nn.BatchNorm1d(in_feats),
                nn.Linear(in_feats, out_feats)
            )
        else:
            layers = []
            layers.append(nn.BatchNorm1d(in_feats))
            layers.append(nn.Linear(in_feats, hidden_feats[0]))
            for i in range(0, len(hidden_feats)-1):
                layers.append(nn.BatchNorm1d(hidden_feats[i]))
                layers.append(nn.Linear(hidden_feats[i], hidden_feats[i+1]))
            layers.append(nn.BatchNorm1d(hidden_feats[-1]))
            layers.append(nn.Linear(hidden_feats[-1], out_feats))
            return nn.Sequential(*layers)

    net = ResNet(BasicBlock, [3, 3, 3], num_classes=10, groups=2, norm_layer="gn")
    net.set_output_layer(make_fc_layer(net.fc_in_features, 100, [256, 512, 256]))
    summary(net, (3, 32, 32))


from flask_restful import Resource, reqparse
from werkzeug.datastructures import FileStorage
from werkzeug.utils import secure_filename
from pytorch_helper.resnet34 import load_model, predict
from pytorch_helper.constants import SF_CARS, INDIA_CARS, INDCARS_PARAM, SFCARS_PARAM
import os

class Predict(Resource):
    ALLOWED_EXTENTIONS = {'jpeg', 'jpg', 'png'}

    def __allowedfile(self, filename):
        return '.' in filename and filename.rsplit('.', 1)[1].lower() in Predict.ALLOWED_EXTENTIONS

    def post(self):
        parse = reqparse.RequestParser()
        parse.add_argument('image', type=FileStorage, location='files', required=True)
        parse.add_argument('model', required=True, choices=(SFCARS_PARAM, INDCARS_PARAM),
                           help=f"Model should be '{SFCARS_PARAM}' or '{INDCARS_PARAM}'")
        args = parse.parse_args()
        image_file = args['image']
        model_name = args['model']
        print(image_file.filename)
        if image_file and self.__allowedfile(image_file.filename):
            try:
                filename = secure_filename(image_file.filename)
                loc = os.path.join('uploads', filename)
                image_file.save(loc)
                if model_name.strip() == SFCARS_PARAM:
                    model = load_model(SF_CARS, chkpt_model=SFCARS_PARAM)
                    res, total_cars = predict(model=model, fileloc=loc, chkpt_model=SFCARS_PARAM)
                elif model_name.strip() == INDCARS_PARAM:
                    model = load_model(INDIA_CARS, chkpt_model=INDCARS_PARAM)
                    res, total_cars = predict(model=model, fileloc=loc, chkpt_model=INDCARS_PARAM)
                else:
                    os.remove(loc)
                    return {"message": {'error': "Invalid Model Name", 'status': 404}}, 404
                os.remove(loc)
                return {'predictions': res, 'total_cars': total_cars, 'status': 200}, 200
            except Exception as e:
                return {"message": {'error': f"Internal Server Error {str(e)}", 'status': 500}}, 500

        else:
            return {"message": {'error': "Invalid Filename", 'status': 404}}, 404


# -*- coding: utf-8 -*-
"""
Created on Tue Apr 25 17:56:08 2023

@author: shada
"""

import torch
import torch.nn as nn

class MLP(nn.Module):
    def __init__(self, state_dim, action_dim):
        super(MLP, self).__init__()
        self.fc1 = nn.Linear(state_dim, 64)
        self.fc2 = nn.Linear(64, 48)
        self.fc3 = nn.Linear(48, 24)
        self.fc4 = nn.Linear(24, action_dim)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = torch.relu(self.fc3(x))
        x = self.fc4(x)
        return x


"""
Combine ESR Leavers data sets into a single file.
Steps:
1. Find files in Trust_data/ESR_Leavers
2. Calculate the Termination Year-Month
3. Group by Year-Month, Ward and Leaving Reason and calculate leavers frequency
4. Drop all columns except Organisation, Termination Month, Leaving Reason, Frequency.
5. Save to file Leavers_Monthly_Frequencies.csv
"""
import pandas as pd
import numpy as np

from .utilities import check_file_names, ScriptFactory
from .config import EXTRACT_PATH, ALLOCATE_WARD_COLUMN

FILE_NAME = "ESR_Leavers"

def monthly_frequency(data):
    """
    Reduce a data set to a frequency table.
    Parameters
    ----------
    data: pandas.DataFrame
        ESR Leavers data set.
    Returns
    -------
    pandas.DataFrame
    """
    grps = data.groupby([ALLOCATE_WARD_COLUMN, "Termination Month", "Leaving Reason", "Staff Group"])
    result = pd.DataFrame(
        [np.concatenate((i, j.shape))[:-1] for i, j in grps]
    )
    result.columns = ["Organisation", "Termination Month", "Leaving Reason", "Staff Group", "Count"]
    return result

tasks = {
    "Load data": dict(path="Trust_data", name="ESR_Leavers"),
    "To datetime": dict(columns=["Termination Date"]),
    "Manipulate column": dict(
        new_column="Termination Month",
        old_column="Termination Date",
        function=lambda x: "{}-{}".format(x.year, x.month)
    ),
    "Apply function": dict(function=monthly_frequency),
    "To file": dict(extract_path=EXTRACT_PATH, file_name="Leavers_Monthly_Frequencies")
}

if __name__ == '__main__':

    routine = ScriptFactory(EXTRACT_PATH, "ESR_Leavers", tasks)
    check_file_names("ESR_Leavers")
    routine.process_script()


class Washer():
    def wash(self):
        print('洗衣服')

haier1 = Washer()

# 添加属性  对象名.属性名 = 值
haier1.width = 400
haier1.height = 500

# 获取属性 对象名.属性名
print(f'洗衣机的宽度是{haier1.width}')
print(f'洗衣机的高度是{haier1.height}')

01-Python核心编程/代码/07-面向对象/01-面向对象基础/hm_04_类外面添加和获取对象属性.py

hm_04_类外面添加和获取对象属性.py


import logging
import pytest
import copy

from math import ceil
from ..cim_tests import FieldTestHelper
from ..utilities.log_helper import format_search_query_log
from ..utilities.log_helper import get_table_output

MAX_TIME_DIFFERENCE = 45
LOGGER = logging.getLogger("pytest-splunk-addon")

class IndexTimeTestTemplate(object):
    """
    Test templates to test the index time fields of an App
    """

    logger = logging.getLogger("pytest-splunk-addon-tests")

    @pytest.mark.first
    @pytest.mark.splunk_indextime
    def test_indextime_key_fields(
        self,
        splunk_search_util,
        splunk_ingest_data,
        splunk_setup,
        splunk_indextime_key_fields,
        record_property,
        caplog,
    ):
        """
        This test case checks that a key_field has the expected values.
        The key fields are as follows:

            * src
            * src_port
            * dest
            * dest_port
            * dvc
            * host
            * user
            * url

        Args:
            splunk_search_util (SearchUtil): Object that helps to search on Splunk.
            splunk_ingest_data (fixture): To ingest data into splunk.
            splunk_indextime_key_fields (fixture): Test for key fields
            record_property (fixture): Document facts of test cases.
            caplog (fixture): fixture to capture logs.
        """

        index_list = (
            "(index="
            + " OR index=".join(splunk_search_util.search_index.split(","))
            + ")"
        )

        assert splunk_indextime_key_fields.get(
            "identifier"
        ) or splunk_indextime_key_fields.get(
            "hosts"
        ), "Host or identifier fields cannot be determined from the config file.."

        if splunk_indextime_key_fields.get("identifier"):
            extra_filter = splunk_indextime_key_fields.get("identifier")
        else:
            extra_filter = (
                'host IN ("'
                + '","'.join(set(splunk_indextime_key_fields.get("hosts")))
                + '")'
            )
        fields_to_check = copy.deepcopy(
            splunk_indextime_key_fields["tokenized_event"].key_fields
        )

        query = "sourcetype={} {} | table {}".format(
            splunk_indextime_key_fields.get("sourcetype"),
            extra_filter,
            ",".join(fields_to_check),
        )

        search = "search {} {}".format(index_list, query)
        record_property("Query", search)
        LOGGER.debug("Base search for indextime key field test: {}".format(search))
        results = splunk_search_util.getFieldValuesList(
            search,
            interval=splunk_search_util.search_interval,
            retries=splunk_search_util.search_retry,
        )
        results = list(results)
        LOGGER.debug("Results:{}".format(results))

        if not results:
            assert False, (
                f"\nNo Events found for query." f"{format_search_query_log(search)}"
            )
        result_fields = dict()
        for result in results:
            for key, val in result.items():
                try:
                    result_fields[key].append(val)
                except KeyError:
                    result_fields[key] = [val]

        # This logic helps in comparing Results when the token is
        # only replaced once but the value is assigned to n events
        # Example syslog: all the headers are only tokenized once hence
        #   key_fields = {'host': ['dummy_host']}
        #   result_dict = {'host': ['dummy_host']*n}
        result_fields = {key: set(value) for key, value in result_fields.items()}
        fields_to_check = {key: set(value) for key, value in fields_to_check.items()}
        if not result_fields == fields_to_check:
            value_list, missing_keys = [], []
            for each_field in fields_to_check.keys():
                if each_field in result_fields.keys():
                    if not fields_to_check.get(each_field) == result_fields.get(
                        each_field
                    ):
                        value_list.append(
                            [
                                each_field,
                                fields_to_check[each_field],
                                result_fields.get(each_field),
                            ]
                        )
                else:
                    missing_keys.append([each_field, fields_to_check[each_field]])
            final_str = ""
            if value_list:
                result_str = get_table_output(
                    headers=["Key_field", "Expected_values", "Actual_values"],
                    value_list=[
                        [
                            each_value[0],
                            str(each_value[1]),
                            str(each_value[2]),
                        ]
                        for each_value in value_list
                    ],
                )
                final_str += f"Some values for the following key fields are missing\n\n{result_str}"

            if missing_keys:
                missing_keys_result_str = get_table_output(
                    headers=["Key_field", "Expected_values"],
                    value_list=[
                        [
                            each_key[0],
                            str(each_key[1]),
                        ]
                        for each_key in missing_keys
                    ],
                )
                final_str += f"\n\nSome key fields are not found in search results\n\n{missing_keys_result_str}"
            LOGGER.info(final_str)

            assert (
                int(len(value_list)) == 0 and int(len(missing_keys)) == 0
            ), f"\nSearch query: {search}{final_str}\n"

    @pytest.mark.first
    @pytest.mark.splunk_indextime
    def test_indextime_time(
        self,
        splunk_search_util,
        splunk_ingest_data,
        splunk_setup,
        splunk_indextime_time,
        record_property,
        caplog,
    ):
        """
        This test case checks that _time value in the events has the expected values.

        Args:
            splunk_search_util (SearchUtil): Object that helps to search on Splunk.
            splunk_ingest_data (fixture): To ingest data into splunk.
            splunk_indextime_time (fixture): Test for _time field
            record_property (fixture): Document facts of test cases.
            caplog (fixture): fixture to capture logs.
        """
        index_list = (
            "(index="
            + " OR index=".join(splunk_search_util.search_index.split(","))
            + ")"
        )

        assert splunk_indextime_time.get("identifier") or splunk_indextime_time.get(
            "hosts"
        ), "Host or identifier fields cannot be determined from the config file.."
        assert splunk_indextime_time[
            "tokenized_event"
        ].time_values, "_time field cannot be determined from the config file."

        if splunk_indextime_time.get("identifier"):
            extra_filter = splunk_indextime_time.get("identifier")
        else:
            extra_filter = (
                'host IN ("'
                + '","'.join(set(splunk_indextime_time.get("hosts")))
                + '")'
            )

        if splunk_indextime_time["tokenized_event"].time_values:
            extra_filter += " | eval e_time=_time"

        query = "sourcetype={} {} | table {}".format(
            splunk_indextime_time.get("sourcetype"),
            extra_filter,
            "e_time",
        )

        search = "search {} {}".format(index_list, query)

        record_property("Query", search)
        LOGGER.debug("Base search for indextime time field test: {}".format(search))
        results = splunk_search_util.getFieldValuesList(
            search,
            interval=splunk_search_util.search_interval,
            retries=splunk_search_util.search_retry,
        )
        results = list(results)
        LOGGER.debug("Results:{}".format(results))
        if not results:
            assert False, (
                f"\nNo Events found for query." f"{format_search_query_log(search)}"
            )
        result_fields = {
            key: [ceil(float(item[key])) for item in results]
            for key in results[0].keys()
        }

        key_time = [
            ceil(t) for t in splunk_indextime_time["tokenized_event"].time_values
        ]
        result_fields["e_time"].sort()
        key_time.sort()

        record_property("time_values", key_time)
        record_property("result_time", result_fields)

        assert all(
            timestamp in result_fields["e_time"] for timestamp in key_time
        ), "Actual time {} :: Time in result {}".format(
            key_time, result_fields["e_time"]
        )

    @pytest.mark.first
    @pytest.mark.splunk_indextime
    def test_indextime_line_breaker(
        self,
        splunk_search_util,
        splunk_ingest_data,
        splunk_setup,
        splunk_indextime_line_breaker,
        record_property,
        caplog,
    ):
        """
        This test case checks that number of events is as expected.

        Args:
            splunk_search_util (SearchUtil): Object that helps to search on Splunk.
            splunk_ingest_data (fixture): To ingest data into splunk.
            splunk_indextime_line_breaker (fixture): Test for event count
            record_property (fixture): Document facts of test cases.
            caplog (fixture): fixture to capture logs.
        """
        expected_events_count = int(
            splunk_indextime_line_breaker["expected_event_count"]
        )
        index_list = (
            "(index="
            + " OR index=".join(splunk_search_util.search_index.split(","))
            + ")"
        )
        host = '("' + '","'.join(splunk_indextime_line_breaker.get("host")) + '")'
        query = "search {} sourcetype={} host IN {} | stats count".format(
            index_list, splunk_indextime_line_breaker.get("sourcetype"), host
        )
        record_property("Query", query)

        LOGGER.debug("Base search for indextime key field test: {}".format(query))
        results = list(
            splunk_search_util.getFieldValuesList(
                query,
                interval=splunk_search_util.search_interval,
                retries=splunk_search_util.search_retry,
            )
        )
        count_from_results = int(results[0].get("count"))
        LOGGER.debug("Resulting count:{}".format(count_from_results))
        assert count_from_results == expected_events_count, (
            f"{format_search_query_log(query)}"
            f"\nExpected count: {expected_events_count} Actual Count: {count_from_results}"
        )


from itertools import tee
import numpy as np
import math

def distance_between_points(a, b):
    """
    Calculates the Euclidean distance between two points
    :param a: first point
    :param b: second point
    :return: Euclidean distance between a and b
    """
    return np.linalg.norm(np.array(b) - np.array(a))

def pairwise(iterable):
    """
    Returns an iterator over all pairs of elements in iterable
    :param iterable: iterable to iterate over
    :return: s -> (s0, s1), (s1, s2), (s2, s3), ...
    """
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

def es_points_along_line(start, end, r):
    """
    Equally spaced points along a line defined by start, end, and r
    :param start: start point
    :param end: end point
    :param r: maximum distance between points
    :return: list of equally spaced points along the line, separated by distance r
    """
    d = distance_between_points(start, end)
    n_points = int(np.ceil(d / r))
    if n_points > 1:
        step = d / (n_points - 1)
        for i in range(n_points):
            next_point = steer(start, end, step * i)
            yield next_point

def steer(start, end, d):
    """
    Return a point in the direction of end, that is distance away from start
    :param start: start point
    :param end: end point
    :param d: distance away from start
    :return: point in the direction of end, that is distance away from start
    """
    start, end = np.array(start), np.array(end)
    v = end - start
    u = v / (np.sqrt(np.sum(v ** 2)))
    steered_point = start + u * d
    return tuple(steered_point)

def check_node_in_ellipse(node, x_ellipse, y_ellipse, a, b, angle):
    """
    Check if node is within ellipse
    :param node: node to check
    :param x_ellipse: ellipse x coordinate
    :param y_ellipse: ellipse y coordinate
    :param a: ellipse a parameter
    :param b: ellipse b parameter
    :param angle: ellipse angle in radians
    :return: boolean, True if node is within ellipse, False otherwise
    """
    return (((((math.cos(angle)*(node[0] - x_ellipse) + math.sin(angle)*(node[1] - y_ellipse))**2)/(a**2)) + (((math.sin(angle)*(node[0] - x_ellipse) - math.cos(angle)*(node[1] - y_ellipse))**2)/(b**2))) <= 1)


#!/usr/bin/env python3

# Created by Tong Gong
# Created time November 2020
# This is a program to calculates the total cost for a given diameter pizza.

import constants

def main():
    # This is the funciton to calculate the total cost of pizza.

    # Input
    diameter = int(input("Enter the diameter of the pizza (inch)"))

    # Process
    without_hst = (constants.rent + constants.labor +
                   constants.materials * diameter)
    final = without_hst * constants.hst

    # Output
    print("")
    print("The prize is ${}".format(final))

if __name__ == "__main__":
    main()


from sqlalchemy import Table, Column, String, Integer

from utils.datetime import naive_now
from .base import metadata, TimeStamp

SubscriptionItemsTable = Table(
    "subscription_items",
    metadata,
    Column("id", String(32), primary_key=True),
    Column("created_at", TimeStamp(), index=True, default=naive_now),
    Column("deleted_at", TimeStamp()),
    Column("sub_id", String(32)),
    Column("price_id", String(32)),
    Column("quantity", Integer),
)


from django.shortcuts import render
from cap import caplib
import json
import xmlsec
import os
from lxml import etree

capMsg = caplib.Alert()

def alert(request):
    return render(request, 'alert.html')

def map(request):
    capMsg.sender = request.POST['source'] if request.POST.has_key('source') else ''
    capMsg.status = request.POST['messageStatus'] if request.POST.has_key('messageStatus') else ''
    capMsg.msg_type = request.POST['messageType'] if request.POST.has_key('messageType') else ''
    capMsg.scope = request.POST['scope'] if request.POST.has_key('scope') else ''

    if (capMsg._scope == 'Restricted'):
        capMsg.restriction = request.POST['restrictedText'] if request.POST.has_key('restrictedText') else ''
    elif(capMsg._scope == 'Private'):
        capMsg.address = request.POST['address'] if request.POST.has_key('address') else ''

    return render(request, 'map.html')

def info(request):
    return render(request, 'info.html')

def finish(request):

    infoBlock = caplib.Info()
    area = caplib.Area()

    # info
    infoBlock._urgency = request.POST['urgency'] if request.POST.has_key('urgency') else ''
    infoBlock._severity = request.POST['severity'] if request.POST.has_key('severity') else ''
    infoBlock._certainty = request.POST['certainty'] if request.POST.has_key('certainty') else ''
    infoBlock._category = request.POST['category'] if request.POST.has_key('category') else ''
    infoBlock._response_type = request.POST['responseType'] if request.POST.has_key('responseType') else ''
    infoBlock._language = request.POST['language'] if request.POST.has_key('language') else ''
    infoBlock._event = request.POST['event'] if request.POST.has_key('event') else ''
    infoBlock._sender_name = request.POST['senderName'] if request.POST.has_key('senderName') else ''
    infoBlock._headline = request.POST['headline'] if request.POST.has_key('headline') else ''
    infoBlock._description = request.POST['description'] if request.POST.has_key('description') else ''
    infoBlock._instruction = request.POST['instruction'] if request.POST.has_key('instruction') else ''
    infoBlock._web = request.POST['web'] if request.POST.has_key('web') else ''
    infoBlock._contact = request.POST['contact'] if request.POST.has_key('contact') else ''
    # infoBlock._event_code = request.POST['eventCode']

    #area
    area._area_description = request.POST['areaDesc'] if request.POST.has_key('areaDesc') else ''

    circles = request.POST['circleAreas'] if request.POST.has_key('circleAreas') else '{}'
    circlesDataList = json.loads(circles) #if request.POST.has_key('source') else ''
    area.add_multiple_circles(circlesDataList)

    polygons = request.POST['polygonAreas'] if request.POST.has_key('polygonAreas') else '{}'
    polygonData = json.loads(polygons)
    area.add_multiple_polygons(polygonData)

    #Nest objects
    infoBlock.add_area(area.to_xml_tree())

    capMsg.add_info(infoBlock.to_xml_tree())

    #Apply a digital signature

    # #Get the private key and the certificate
    # datadir = os.path.abspath('./test/data/x509Files')
    # private_key = os.path.join(datadir, 'test.pem')
    # public_certificate = os.path.join(datadir, 'test.cert')

    #Add the signature and print
    # signed_cap_msg = xmlsec.sign(capMsg.to_xml_tree(),
    #                          key_spec=private_key,
    #                          cert_spec=public_certificate)
    #
    # print etree.tostring(signed_cap_msg, pretty_print=True)
    #
    # # Verify and print
    # print xmlsec.verify(signed_cap_msg, public_certificate)

    try:
        result = capMsg.to_xml_string()
        # result = signed_cap_msg.to_xml_string()
    except AssertionError as ex:
        result = ex.message

    return render(request, 'finish.html', {'result': result})

def cap(request):
    return render(request, 'cap.html')


# Native imports
import logging
import logging.config
from os import getenv
from os.path import exists
from yaml import safe_load

# Imports
from main import create_app

# Authorship Information
__author__ = "Islam Elkadi"
__copyright__ = "Copyright 2021, Thea Manager"
__credits__ = ["Islam Elkadi"]
__license__ = "N/A"
__version__ = "1.0.0"
__maintainer__ = "Islam Elkadi"
__email__ = "islam@theamanager.com"
__status__ = "Prototype"

# ---------------------------------------------------------------
#                           Configure Logging
# ---------------------------------------------------------------

def setup_logging(
    default_path="log_config.yaml", default_level=logging.INFO, env_key="LOG_CFG"
):
    """
    Setup logging configuration

    Parameters
    ----------

        default_path: str [required]
            file path to read logging configurations from

        default_level: required
            default logging level

        env_key: str [required]
            environment key for logging configuration
    """
    path = default_path
    value = getenv(env_key, None)

    if value:
        path = value

    if exists(path):
        with open(path, "rt") as f:
            configuration = safe_load(f.read())
        logging.config.dictConfig(configuration)
    else:
        logging.basicConfig(level=default_level)

# App object
application = create_app()

# Entry point
if __name__ == "__main__":
    setup_logging()
    application.run(host="0.0.0.0", port=5000, debug=True)


"""Silence Finder."""
from dataclasses import dataclass, field
from pathlib import Path
import re

from rich import print

from ..helpers import ffprogress
from .SegmentData import SegmentData

@dataclass
class SilenceFinder:
    """Finds silence in a file and generates a list of SegmentData's representing the non-silence portions."""
    input_path: Path
    start_time: float = 0.0
    end_time: float = 0.0
    silence_duration: float = 1.0
    silence_threshold: int = -35
    _ffoutput: list = field(init=False, repr=False)

    def find(self):
        self._run_silencedetect()
        times = self._get_segment_times()
        if not times:
            return list()

        # Generate SegmentData list
        retval = list()
        for i, (start_time, end_time) in enumerate(times):
            retval.append(SegmentData(
                id=i,
                start_time=start_time,
                end_time=end_time,
            ))
        return retval

    def _run_silencedetect(self):
        """Run the silencedetect filter from ffmpeg and return the output lines."""
        # Run ffmpeg's silencedetect filter
        cmd = ["ffmpeg", "-i", self.input_path]
        if self.start_time:
            cmd.extend(["-ss", str(self.start_time)])
        if self.end_time:
            cmd.extend(["-to", str(self.end_time)])
        cmd.extend([
            "-filter_complex",
            f"[0]silencedetect=d={self.silence_duration}:n={self.silence_threshold}dB[s0]",
            "-map", "[s0]",
            "-f", "null",
            "-"
        ])
        ff = ffprogress.run(cmd, "Detecting Silence")

        # Check to see if ffmpeg exited abnormally
        if ff is None:
            print("[bold red]Error:[/] Could not determine segment times.")
            exit(1)
        self._ffoutput = ff.output.splitlines()

    def _get_segment_times(self):
        """Compute non-silence segment start and end times."""
        silence_start_re = re.compile(r' silence_start: (?P<start>[0-9]+(\.?[0-9]*))$')
        silence_end_re = re.compile(r' silence_end: (?P<end>[0-9]+(\.?[0-9]*)) ')
        total_duration_re = re.compile(
            r'size=[^ ]+ time=(?P<hours>[0-9]{2}):(?P<minutes>[0-9]{2}):(?P<seconds>[0-9\.]{5}) bitrate=')
        # Segments start when silence ends, and segments end when silence starts.
        segment_starts = []
        segment_ends = []
        start_time = self.start_time or 0
        end_time = 10000000.0
        for line in self._ffoutput:
            # Check for silence start
            silence_start_match = silence_start_re.search(line)
            if silence_start_match:
                segment_ends.append(float(silence_start_match.group('start')))
                if len(segment_starts) == 0:
                    # Started with non-silence.
                    segment_starts.append(start_time)
                continue

            # Check for silence end
            silence_end_match = silence_end_re.search(line)
            if silence_end_match:
                segment_starts.append(float(silence_end_match.group('end')))
            total_duration_match = total_duration_re.search(line)

            # Check for duration
            if total_duration_match:
                hours = int(total_duration_match.group('hours'))
                minutes = int(total_duration_match.group('minutes'))
                seconds = float(total_duration_match.group('seconds'))
                end_time = hours * 3600 + minutes * 60 + seconds

        if len(segment_starts) == 0:
            # No silence found.
            return None

        if len(segment_starts) > len(segment_ends):
            # Finished with non-silence.
            segment_ends.append(end_time)

        output = list(zip(segment_starts, segment_ends))

        return output


from sqlalchemy import Integer, ForeignKey, String, Column, Date, Table, Boolean
from sqlalchemy.orm import relationship
from database import Base, db_session
from datetime import datetime
import ast
from flask_login import current_user
from abc import ABCMeta, abstractmethod
from flask import Flask, redirect, render_template, request, url_for, flash
from classes import common

class Course(Base):
    __tablename__ = 'course'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    offering = Column(String)
    uniusers = relationship("UniUser",
                            secondary="ucassociation",
                            backref="course")

    survey = relationship("Survey",
                       secondary="csassociation",
                       backref='course')

    def __init__(self, name=None, offeringid=None, survey=[]):
        self.name = name
        self.offering = offeringid
        self.survey = survey

    def __repr__(self):
        return '<CourseName %r>' % (self.name)

csassociation_table = Table('csassociation', Base.metadata,
                            Column('course_id', Integer,
                                   ForeignKey('course.id')),
                            Column('survey_id', Integer,
                                   ForeignKey('survey.id'))
                            )

ucassociation_table = Table('ucassociation', Base.metadata,
                            Column('uniuser_id', Integer,
                                   ForeignKey('uniuser.id')),
                            Column('course_id', Integer,
                                   ForeignKey('course.id'))
                            )


from django.db import models

# Create your models here.

CROP_CHOICES= (
    ('Barley', 'Barley'),
    ('Wheat', 'Wheat'),
    ('Maize', 'Maize'),
    ('Sugarcane', 'Sugarcane'),
    ('Rice','Rice'),
    )

LOCATION = (('AMRITSAR','Amritsar'),
             ('BARNALA','Barnala'),
             ('FARIDKOT','Faridkot'),
             ('FAZILKA','Fazilka'),
             ('FIROZEPUR','Firozepur'),
             ('GURDASPUR','Gurdaspur'),
             ('HOSHIARPUR','Hoshiarpur'),
             ('JALANDHAR','Jalandhar'),
             ('KAPURTHALA','Kapurthala'),
             ('LUDHIANA','Ludhiana'),
             ('MANSA','Mansa'),
             ('MOGA','Moga'),
             ('MUKTSAR','Muktsar'),
             ('NAWANSHAHR','Nawanshahr'),
             ('PATHANKOT','Pathankot'),
             ('PATIALA','Patiala'),
             ('RUPNAGAR','Rupnagar'),
             ('SANGRUR','Sangrur'),)

class SoilInput(models.Model):
	Ph = models.FloatField()
	Nitrogen = models.FloatField()
	Phosphorus = models.FloatField()
	Potassium  = models.FloatField()
	Temperature = models.FloatField()

class YieldInput(models.Model):
	Crop = models.CharField(max_length=6, choices=CROP_CHOICES, default='Barley')
	Location = models.CharField(max_length =19,choices=LOCATION,default='PATIALA')


from typing import List

from promformat.parser.PromQLParser import PromQLParser

class Expr:
    def __init__(self, ctx):
        self.ctx = ctx

class Literal(Expr):
    def __init__(self, ctx, value):
        super(Literal, self).__init__(ctx)
        self.value = value

class Number(Literal):
    pass

class String(Literal):
    pass

class ParensNode(Expr):
    def __init__(self, ctx, vector_operation):
        super(ParensNode, self).__init__(ctx)
        self.vector_operation = vector_operation

class UnaryOpNode(Expr):
    def __init__(self, ctx, operator, operand):
        super(UnaryOpNode, self).__init__(ctx)
        self.operator = operator
        self.operand = operand

class PowOpNode(Expr):
    def __init__(self, ctx, left, right, operator, grouping):
        super(PowOpNode, self).__init__(ctx)
        self.left = left
        self.right = right
        self.operator = operator
        self.grouping = grouping

class AddOpNode(Expr):
    def __init__(self, ctx, left, right, operator, grouping):
        super(AddOpNode, self).__init__(ctx)
        self.left = left
        self.right = right
        self.operator = operator
        self.grouping = grouping

class MultOpNode(Expr):
    def __init__(self, ctx, left, right, operator, grouping):
        super(MultOpNode, self).__init__(ctx)
        self.left = left
        self.right = right
        self.operator = operator
        self.grouping = grouping

class CompareOperationNode(Expr):
    def __init__(
        self,
        ctx,
        left,
        right,
        operator,
        grouping,
        bool_keyword,
    ):
        super(CompareOperationNode, self).__init__(ctx)
        self.left = left
        self.right = right
        self.operator = operator
        self.grouping = grouping
        self.bool_keyword = bool_keyword

class OnIgnoring:
    def __init__(self, operator, labels):
        self.operator = operator
        self.labels = labels

class GroupLeftRight:
    def __init__(self, operator, labels):
        self.operator = operator
        self.labels = labels

class Grouping:
    def __init__(self, on_ignoring, group_left_right):
        self.on_ignoring = on_ignoring
        self.group_left_right = group_left_right

class AndUnlessOperationNode(Expr):
    def __init__(self, ctx, left, right, operator, grouping):
        super(AndUnlessOperationNode, self).__init__(ctx)
        self.left = left
        self.right = right
        self.operator = operator
        self.grouping = grouping

class OrOperationNode(Expr):
    def __init__(self, ctx, left, right, operator, grouping):
        super(OrOperationNode, self).__init__(ctx)
        self.left = left
        self.right = right
        self.operator = operator
        self.grouping = grouping

class LabelNode(Expr):
    def __init__(self, ctx: PromQLParser.LabelMatcherContext):
        super(LabelNode, self).__init__(ctx)
        self.name = ctx.labelName().getText()
        self.operator = ctx.labelMatcherOperator().getText()
        self.value = ctx.STRING().getText()

class OffsetNode(Expr):
    def __init__(self, ctx, instant_selector, offset, duration):
        super(OffsetNode, self).__init__(ctx)
        self.instant_selector = instant_selector
        self.offset = offset
        self.duration = duration

class LabelNameNode(Expr):
    def __init__(self, ctx, name: str):
        super(LabelNameNode, self).__init__(ctx)
        self.name = name

class LabelMatcherNode(Expr):
    def __init__(self, ctx, labels: List[LabelNode]):
        super(LabelMatcherNode, self).__init__(ctx)
        self.labels = labels

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

class InstantSelectorNode(Expr):
    def __init__(
        self, ctx, metric_name: str, labels: List[LabelNode], left_brace, right_brace
    ):
        super(InstantSelectorNode, self).__init__(ctx)
        self.metric_name = metric_name
        self.labels = labels
        self.left_brace = left_brace
        self.right_brace = right_brace

class SubqueryRangeNode(Expr):
    def __init__(self, ctx, subquery_range: str, offset):
        super(SubqueryRangeNode, self).__init__(ctx=ctx)
        self.subquery_range = subquery_range
        self.offset = offset

class SubqueryNode(Expr):
    def __init__(self, ctx, left, subquery_range):
        super(SubqueryNode, self).__init__(ctx)
        self.left = left
        self.subquery_range = subquery_range

class MatrixSelectorNode(Expr):
    def __init__(self, ctx, selector: InstantSelectorNode, time_range):
        super(MatrixSelectorNode, self).__init__(ctx)
        self.selector = selector
        self.time_range = time_range

class AggregationNode(Expr):
    def __init__(
        self,
        ctx,
        operator: str,
        group_operator: str,
        label_list,
        parameter_list,
        is_prefix,
    ):
        super(AggregationNode, self).__init__(ctx)
        self.operator = operator
        self.group_operator = group_operator
        self.label_list = label_list
        self.parameter_list = parameter_list
        self.is_prefix = is_prefix

class MetricNameNode(Expr):
    def __init__(self, ctx, metric_name):
        super(MetricNameNode, self).__init__(ctx)
        self.metric_name = metric_name

class FunctionNode:
    def __init__(self, ctx: PromQLParser.Function_Context, parameters):
        self.ctx = ctx
        self.parameters = parameters
        self.name = self.ctx.FUNCTION().getText()


from datetime import datetime
from flask import request, session, Blueprint, make_response, render_template, redirect
from .models import Hacker
from hacker_server import db

bp = Blueprint('hacker_main', __name__, url_prefix='/')

@bp.route('/', methods=["POST", "GET"])
def index():
    '''초기 접속 시 실행할 함수'''
    return redirect('/hacker_home')

@bp.route('/hacker_home', methods=["POST", "GET"])
def hacker_home():
    '''해커 홈'''
    hacker = Hacker.query.order_by(Hacker.create_date.desc())
    context = hacker.paginate(per_page=10)
    return render_template(
        'index.html',
        context=context,
    )

@bp.route('/xss/', methods=["POST", "GET"])
def xss():
    hacker = Hacker()
    hacker.create_date = datetime.now()
    hacker.title = request.args.get('title')
    hacker.content = request.args.get('content')
    db.session.add(hacker)
    db.session.commit()
    return redirect(request.referrer)


import time
import numpy

def threeSumCount(array):
    start_time = time.time()
    counter = 0
    length_range = range(len(array))
    for i in length_range:
        for j in length_range[i + 1:]:
            for z in length_range[j + 1:]:
                # print("Matching index %s %s %s with value %s %s %s will result to %s" % (i, j, z, array[i], array[j], array[z], array[i] + array[j] + array[z]))
                if array[i] + array[j] + array[z] == 0:
                    counter += 1
    print("BruteForce Time Taken --- %s seconds ---" % (time.time() - start_time))
    return counter


class Node:
    def __init__(self,data=None):
        self.data=data
        self.next=None

class LinkedList:
    def __init__(self):
        self.head=None

    # From the previous code
    def newnode(self,new):
        newnode=Node(new)
        if self.head is None:
            self.head=newnode
        else:
            p=self.head
            while p.next is not None:
                p=p.next
            p.next=newnode

    def display(self):
        if self.head is None:
            print("Empty linked list")
        else:
            p=self.head

            while p is not None:
                print(p.data)
                p=p.next

    def checkloop(self):
        if self.head is None:
            print("Empty linked list")
        else:
            p=q=self.head
            while p and q is not None:
                p=p.next
                if( q.next.next is not None):
                    q=q.next.next
                else:
                    print("No loop")
                    return False

                if (p==q):
                    print("loop exists")
                    return True

            return False

if __name__ == '__main__':
    link=LinkedList()
    a=Node(8)
    a.next=Node(5)
    a.next.next=Node(4)
    a.next.next.next=Node(7)
    a.next.next.next.next.next=Node(9)
    a.next.next.next.next.next.next=a.next.next
    link.head=a
    print(link.checkloop())


from typing import Optional, List
from lang.python.helper import TreeNode, print_tree

class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        # print_tree(root)
        return self.m2(root, targetSum)
        result = []
        self.m1(root, targetSum, [], result)
        return result

    def m1(self, root, target, path, result):
        if root is None:
            return
        p = path.copy()
        p.append(root.val)
        if root.left is None and root.right is None:
            if sum(p) == target:
                result.append(p)

        self.m1(root.left, target, p, result)
        self.m1(root.right, target, p, result)

    def m2(self, root, target):
        lst = []
        num_lst = []
        if root is None:
            return []

        result = []
        lst.append(root)
        num_lst.append([])
        while lst:
            cur = lst.pop(0)
            cur_num = num_lst.pop(0)
            cur_num.append(cur.val)

            if cur.left is None and cur.right is None:
                if sum(cur_num) == target:
                    result.append(cur_num)
            if cur.left:
                lst.append(cur.left)
                num_lst.append(cur_num[:])
            if cur.right:
                lst.append(cur.right)
                num_lst.append(cur_num[:])

        return result


from typing import List, Dict

from clang import cindex

from . import entity_base
from pybind11_weaver.utils import fn

import logging

from pybind11_weaver import gen_unit

_logger = logging.getLogger(__name__)

class MethodCoder:

    def __init__(self, cursor, scope_full_name, inject_docstring):
        self.inect_docstring = inject_docstring
        self.fn_name = cursor.spelling
        self.call_stmt = f"""BindMethod_{self.fn_name}(obj);"""
        self.def_template = f"""
virtual void BindMethod_{self.fn_name}(Pybind11T & obj){{{{
    {{body}}
}}}}
"""
        self.body = []
        self.append(cursor, scope_full_name)

    def get_def_stmt(self):
        return self.def_template.format(body="\n".join(self.body))

    def append(self, cursor, scope_full_name):
        def is_virtual(cursor):
            return cursor.is_virtual_method() or cursor.is_pure_virtual_method()

        def is_static(cursor):
            return cursor.is_static_method()

        # to support overload, we will cast member function to function pointer
        pointer = f"&{scope_full_name}::{cursor.spelling}"
        method_pointer_type = fn.get_fn_pointer_type(cursor)
        casted_pointer = f"static_cast<{method_pointer_type}>({pointer})"
        if is_static(cursor):
            self.body.append(
                f"obj.def_static(\"{cursor.spelling}\",{casted_pointer});")
        else:
            self.body.append(
                f"obj.def(\"{cursor.spelling}\",{casted_pointer});")
            if is_virtual(cursor):
                _logger.warning(
                    f"virtual method {cursor.spelling} is not fully supported yet, override in python is not allowed.")
        if self.inect_docstring:
            self.body[-1] = entity_base._inject_docstring(
                self.body[-1], cursor, "last_arg")

class ClassEntity(entity_base.Entity):

    def __init__(self, gu: gen_unit.GenUnit, cursor: cindex.Cursor):
        entity_base.Entity.__init__(self, gu, cursor)
        assert cursor.kind in [cindex.CursorKind.CLASS_DECL, cindex.CursorKind.STRUCT_DECL]
        self.extra_methods_codes = []

    def get_cpp_struct_name(self) -> str:
        return self.cursor.type.spelling.replace("::", "_")

    def init_default_pybind11_value(self, parent_scope_sym: str) -> str:
        code = f'{parent_scope_sym},"{self.name}"'
        if self.gu.io_config.gen_docstring:
            code = entity_base._inject_docstring(code, self.cursor, "append")
        return code

    def update_stmts(self, pybind11_obj_sym: str) -> List[str]:
        codes = []

        def is_pubic(cursor):
            return cursor.access_specifier == cindex.AccessSpecifier.PUBLIC and self.gu.is_visible(cursor)

        # generate constructor binding
        ctor_found = False
        for cursor in self.cursor.get_children():
            if cursor.kind == cindex.CursorKind.CONSTRUCTOR and is_pubic(cursor):
                ctor_found = True
                param_types = fn.fn_arg_type(cursor)
                codes.append(
                    f"{pybind11_obj_sym}.def(pybind11::init<{','.join(param_types)}>());")
        if not ctor_found:
            codes.append(f"{pybind11_obj_sym}.def(pybind11::init<>());")
        if self.gu.io_config.gen_docstring:
            for i, code in enumerate(codes):
                codes[i] = entity_base._inject_docstring(code, cursor, "last_arg")

        # generate method binding
        methods: Dict[str, MethodCoder] = dict()
        for cursor in self.cursor.get_children():
            if cursor.kind == cindex.CursorKind.CXX_METHOD and is_pubic(cursor):
                if not cursor.spelling in methods:
                    methods[cursor.spelling] = MethodCoder(cursor, self.qualified_name(),
                                                           self.gu.io_config.gen_docstring)
                else:
                    methods[cursor.spelling].append(cursor, self.qualified_name())

        codes.append(f"Pybind11WeaverBindAllMethods({pybind11_obj_sym});")
        call_method_bind = []
        method_bind_body = []
        for _, method in methods.items():
            call_method_bind.append(method.call_stmt)
            method_bind_body.append(method.get_def_stmt())
        new_line = "\n"
        bind_all = f"""
void Pybind11WeaverBindAllMethods(Pybind11T & obj){{
   {new_line.join(call_method_bind)}
}}

{new_line.join(method_bind_body)}
        """
        self.extra_methods_codes.append(bind_all)

        # generate field binding
        for cursor in self.cursor.get_children():
            if cursor.kind == cindex.CursorKind.FIELD_DECL and is_pubic(cursor):
                codes.append(
                    f"{pybind11_obj_sym}.def_readwrite(\"{cursor.spelling}\",&{self.qualified_name()}::{cursor.spelling});")
                if self.gu.io_config.gen_docstring:
                    codes[-1] = entity_base._inject_docstring(codes[-1], cursor, "last_arg")

        return codes

    def default_pybind11_type_str(self) -> str:
        type_full_name = self.cursor.type.spelling
        return f"pybind11::class_<{type_full_name}>"

    def extra_code(self) -> str:
        """Entity may inject extra code into the generated binding struct."""
        return "\n".join(self.extra_methods_codes)


line=open('day16.txt','r').read().strip()
offset=int(line[:7])
bas=[0,1,0,-1]
ll=len(line)*10000

print(ll,offset)
dim=100
dll=[[1]+[0]*(dim-1)]
for i in range(ll-offset+100):
    dl=[1]
    vl=dll[-1]
    if i%100000==0:
        print(i)
    for j in range(dim-1):
        dl.append((vl[j]+vl[j+1])%10)
    dll.append(dl)
print(len(dll),dll[99][99])

nl=list(map(int,line))
ln=len(line)
ss=''
for i in range(offset,offset+8):
    su=sum([nl[j%ln]*dll[j-i+99][99] for j in range(i,ll)])%10
    print(su)
    ss+=str(su)
print(ss)


from Cryptodome.PublicKey import RSA
from Cryptodome.Signature import PKCS1_v1_5
from Cryptodome.Hash import SHA256

import binascii

from util.hash_util import hash_block, sha256

class Verification:
    @staticmethod
    def valid_proof_of_work(prev_hash, outstanding_transactions, proof_of_work):
        guess = (
            str(prev_hash)
            + str([tx.to_ordered_dict() for tx in outstanding_transactions])
            + str(proof_of_work)
        ).encode()
        return sha256(guess)[0:2] == "00"

    @classmethod
    def verify_blockchain(cls, blockchain):
        for (index, block) in enumerate(blockchain):
            if index == 0:
                continue
            if block.prev_hash != hash_block(blockchain[index - 1]):
                print(
                    "Blockchain may have split. There is a block that is out of order"
                )
                return False
            if not cls.valid_proof_of_work(
                block.prev_hash, block.transactions[:-1], block.proof_of_work
            ):
                print("Proof of work not valid!")
                return False
        return True

    @staticmethod
    def verify_transaction(transaction, get_balance):
        if (transaction.sender) == "MINING":
            return True
        if transaction.sender == transaction.recepient:
            print("Transaction Failed: sender and recepient can't be the same.")
            return False
        sender_balance = get_balance(transaction.sender)
        if sender_balance < transaction.amount:
            print("Transaction Failed: insufficient funds.")
            return False
        public_key = RSA.importKey(binascii.unhexlify(transaction.sender))
        verifier = PKCS1_v1_5.new(public_key)
        h = SHA256.new(
            (
                str(transaction.sender)
                + str(transaction.recepient)
                + str(transaction.amount)
            ).encode("utf8")
        )
        return verifier.verify(h, binascii.unhexlify(transaction.signature))