import numpy as np
import tensorflow as tf
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import parameter_initialization as pi
import activation_func as af

NLAYER = 5
NUNIT = [100, 80, 60, 40, 10]
EPOCH = 10
LEARNING_RATE = 0.05
ACTIVATION_FUNC = {'Step': af.step, 'SimpleReturn': af.simplereturn, 'ReLU': af.ReLU, 'Approximated_ReLU': af.Approximated_ReLU, 'Parametric_ReLU': af.Parametric_ReLU, 'ELU': af.ELU, 'sigmoid': af.sigmoid, 'softsign': af.softsign, 'tanh': af.tanh, 'tanhplus': af.tanhplus, 'softsignplus': af.softsignplus}
USE_FUNC = 'ReLU'
PARAMETER_INIT = {'he': pi.he, 'randn': pi.randn, 'xavier': pi.xavier, 'normalized_initialization': pi.ni}
USE_INIT = 'he'
y_lim = (0, 7000)

x = np.random.randn(1000,100)
activations = {}
for i in range(NLAYER):
    if i != 0:
        x = activations[i - 1]

    w = pi.he(NUNIT[i], NUNIT[i+1])
    z = tf.cast(tf.matmul(x, w), tf.float32)
    a = ACTIVATION_FUNC[USE_FUNC](z)
    activations[i] = a

plt.figure(figsize=(18, 4))
for i, a in activations.items():
    plt.subplot(1, len(activations), i + 1)
    plt.title(str(i + 1) + "-layer")
    plt.hist(a.flatten(), 30, range=(0, 1))
    plt.ylim(y_lim)
plt.show()
plt.savefig('../image/' + USE_FUNC + '_' + USE_INIT + '_figure.png')


import io
import math
from pathlib import Path, PureWindowsPath
from struct import unpack

class PDB:
	def __init__(self, path):
		with open(path,"rb") as fh:
			pdb_data = fh.read()
		self.fp = io.BytesIO(pdb_data)

		self.magic = self.fp.read(32)
		self.block_size = unpack("<I",self.fp.read(4))[0]
		self.free_block_map = self.fp.read(4)
		self.num_blocks = unpack("<I",self.fp.read(4))[0]
		self.num_dir_bytes = unpack("<I",self.fp.read(4))[0]
		self.reserved = self.fp.read(4)
		self.block_map_addr = unpack("<I",self.fp.read(4))[0]

		self.streams = []
		self.section_offsets = []

		self.omap_from_src = {}
		self.omap_to_src = {}

		self._get_stream_info()

	def _get_stream_info(self):
		# Seek to the address of the stream index
		stream_index_addr = self.block_size * self.block_map_addr
		self.fp.seek(stream_index_addr)

		stream_directory = b""
		byte_count = 0

		# Compile data from each block referenced in the stream index into a single byte stream
		for i in range(0, math.ceil(self.num_dir_bytes / self.block_size)):
			offset = unpack("<I",self.fp.read(4))[0] * self.block_size
			pos = self.fp.tell()
			self.fp.seek(offset)
			to_read = self.block_size
			if byte_count + to_read > self.num_dir_bytes:
				to_read = self.num_dir_bytes - byte_count
			stream_directory += self.fp.read(to_read)
			byte_count += to_read
			self.fp.seek(pos)

		sp = io.BytesIO(stream_directory)
		num_streams = unpack("<I",sp.read(4))[0]

		# Get the size and block count for each stream
		for i in range(num_streams):
			sp.seek((i+1) * 4)
			curr_stream = {}
			curr_stream['size'] = unpack("<I",sp.read(4))[0]
			curr_stream['block_count'] = math.ceil(curr_stream['size'] / self.block_size)
			curr_stream['blocks'] = []
			self.streams.append(curr_stream)

		# Populate the blocks array for each stream
		for i in self.streams:
			if i['size'] == 0:
				continue
			for block in range(i['block_count']):
				i['blocks'].append(unpack("<I",sp.read(4))[0])

	def read_stream(self, index):
		stream_data = b""
		byte_count = 0
		for i in self.streams[index]['blocks']:
			offset = i * self.block_size
			self.fp.seek(offset)
			to_read = self.block_size
			if to_read + byte_count > self.streams[index]['size']:
				to_read = self.streams[index]['size'] - byte_count
			stream_data += self.fp.read(to_read)
			byte_count += to_read

		return stream_data

	def parse_dbi(self):
		self.DBI_Stream = DBIStream(self.read_stream(3))
		try:
			from_src, to_src = self.DBI_Stream.parse_omap()
			from_src_data = self.read_stream(from_src)
			fh = io.BytesIO(from_src_data)
			for i in range(0, int(len(from_src_data) / 8)):
				mapping = fh.read(8)
				src = mapping[:4]
				to = mapping[4:]
				src = int.from_bytes(src, "little")
				to = int.from_bytes(to, "little")
				self.omap_from_src[src] = to

			to_src_data = self.read_stream(to_src)
			fh = io.BytesIO(to_src_data)
			for i in range(0, int(len(to_src_data) / 8)):
				mapping = fh.read(8)
				to = mapping[:4]
				src = mapping[4:]
				src = int.from_bytes(src, "little")
				to = int.from_bytes(to, "little")
				self.omap_to_src[to] = src
		except:
			# PDB does not contain the OMAP structures, should probably add code to do things here
			pass

		self._parse_section_headers()
		self.func_list = self._parse_func_symbols()

	def _parse_section_headers(self):
		section_header_data = self.read_stream(self.DBI_Stream.section_header_index)
		sp = io.BytesIO(section_header_data)
		count = 1
		while True:
			name = sp.read(8)
			if name == b"":
				break
			name = name.split(b"\x00")[0].decode("utf-8")
			virt_size = unpack("<I", sp.read(4))[0]
			virt_address = unpack("<I", sp.read(4))[0]
			raw_data = unpack("<I", sp.read(4))[0]
			raw_data_p = unpack("<I", sp.read(4))[0]
			self.section_offsets.append(virt_address)
			sp.seek(sp.tell()+16)

	def _parse_func_symbols(self):
		self.functions_by_offset = {}
		sym_stream = self.read_stream(self.DBI_Stream.ss_index)
		sp = io.BytesIO(sym_stream)
		while True:
			sym_len = sp.read(2)
			if sym_len == b'':
				break
			sym_len = unpack("<H", sym_len)[0]
			symbol = io.BytesIO(sp.read(sym_len))
			new_symbol = {}
			sym_type = unpack("<H", symbol.read(2))[0]
			if sym_type != 4366:
				continue
			flags = unpack("<I", symbol.read(4))[0]
			if flags != 2:
				continue
			offset = unpack("<I", symbol.read(4))[0]
			section = unpack("<H", symbol.read(2))[0]
			name = symbol.read(sym_len - 12).split(b"\x00")[0].decode("utf-8")
			self.functions_by_offset[offset + self.section_offsets[section - 1]] = name

class DBIStream:
	def __init__(self, stream_data):
		self.stream = io.BytesIO(stream_data)
		self.version_sig = self.stream.read(4)
		self.version_header = unpack("<I",self.stream.read(4))[0]
		self.age = unpack("<I",self.stream.read(4))[0]
		self.gs_index = unpack("<H",self.stream.read(2))[0]
		self.build_number = unpack("<H",self.stream.read(2))[0]
		self.ps_index = unpack("<H",self.stream.read(2))[0]
		self.pdb_dll_version = unpack("<H",self.stream.read(2))[0]
		self.ss_index = unpack("<H",self.stream.read(2))[0]
		self.pdb_dll_rbld = unpack("<H",self.stream.read(2))[0]
		self.mod_info_size = unpack("<i",self.stream.read(4))[0]
		self.sec_cont_size = unpack("<i",self.stream.read(4))[0]
		self.sec_map_size = unpack("<i",self.stream.read(4))[0]
		self.src_info_size = unpack("<i",self.stream.read(4))[0]
		self.type_srv_map_size = unpack("<i",self.stream.read(4))[0]
		self.MFC_type_srv_index = unpack("<I",self.stream.read(4))[0]
		self.opt_dbg_header_size = unpack("<i",self.stream.read(4))[0]
		self.ec_sub_size = unpack("<i",self.stream.read(4))[0]
		self.flags = unpack("<H",self.stream.read(2))[0]
		self.machine = unpack("<H",self.stream.read(2))[0]
		self.padding = unpack("<I",self.stream.read(4))[0]

		self.omap_from_src = {}
		self.omap_to_src = {}

	def parse_omap(self):
		omap_to_src_offset = 64 + self.mod_info_size + self.sec_cont_size + self.sec_map_size + self.src_info_size + self.type_srv_map_size + self.ec_sub_size + 6
		self.stream.seek(omap_to_src_offset)
		omap_to_src_index = unpack("<H",self.stream.read(2))[0]
		omap_from_src_index = unpack("<H",self.stream.read(2))[0]
		self.section_header_index = unpack("<H",self.stream.read(2))[0]
		return (omap_from_src_index, omap_to_src_index)


n=[2,7,11,15]
target = 9

#initial solution

"""At first forloop it will start to print the index of element in n and second forloop it start print
index of second element and compare using if condition by add elemnt first and second is equal to
target it print its index as output"""

for i in range(len(n)):
    for j in range(i+1, len(n)):
        if n[i] + n[j] == target:
            print(i,j)

#improved solution
""" In a first forloop it prints the index position of a element in a list n.And in if condition target is sub
with every element in n if not in intially declared dictinory result it appends in results both element and its index
else it prints its indexposition of the result and n"""

result = {}
for i in range(len(n)):
    if target - n[i] not in result:
        result[n[i]] = i
    else:
        print(result[target - n[i]], i)


from flask import Flask, request, render_template, redirect, url_for
import json
import time
import random
import string
# Flask constructor
app = Flask(__name__, template_folder="Templates")

# A decorator used to tell the application
# which URL is associated function

result = {}

starttime = 0

@app.route('/')
def client():
    with open("time.json") as test:
        d = json.load(test)
    seconds = time.time()*1000 - d["time"]
    if d["time"] != 0 and seconds < 270000:
        with open("output.json") as test_file:
            data = json.load(test_file)
        return data
    if d["time"] != 0 and (seconds >= 270000 and seconds < 300000):
        return {"message": "NULL"}
    if seconds >= 300000:
        output = ''.join(random.choices(
            string.ascii_uppercase+string.digits, k=10))
        result = {"message": str(output)}
        with open("output.json", "w") as c:
            json.dump(result, c)
        t = time.time()*1000
        start = {"time": t}
        with open("time.json", "w") as c:
            json.dump(start, c)
        return result

if __name__ == '__main__':
    app.run()


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

from he_or_she.scraping.items import ArticleItem

class NYTimesSpider(scrapy.Spider):
    name = 'nytimes'
    allowed_domains = ['nytimes.com']
    start_urls = ['http://nytimes.com/']
    api_url = 'https://www.nytimes.com/svc/collections/v1/publish/'

    def start_requests(self):
        nytimes_authors_path = os.path.join(os.path.dirname(__file__), 'nytimes_authors.json')
        with open(nytimes_authors_path) as nytimes_authors_fp:
            nytimes_authors = json.load(nytimes_authors_fp)
            for author in nytimes_authors:
                if author['gender'] != 'unclear':
                    query_url = f"{author['url']}?sort=newest&page=0"
                    yield scrapy.Request(f"{self.api_url}{query_url}", meta={'author': author})

    def parse(self, response):
        response_json = json.loads(response.body_as_unicode())
        for page in range(response_json['members']['total_pages']):
            query_url = f"{response.meta['author']['url']}?sort=newest&page={page}"
            yield scrapy.Request(f"{self.api_url}{query_url}", self.parse_article_list, meta=response.meta)

    def parse_article_list(self, response):
        response_json = json.loads(response.body_as_unicode())
        for item in response_json['members']['items']:
            if len(item['authors']) == 1:
                yield ArticleItem(
                    headline=item['headline'],
                    summary=item['summary'],
                    author_gender=response.meta['author']['gender'],
                )


from typing import List
from arrow import Arrow
import arrow
from datetime import datetime
from sqlalchemy import create_engine
from sqlalchemy import select, update
from sqlalchemy.ext.automap import automap_base
import sqlalchemy
import numpy as np

from common.enums import TaskTypeEnum
from globalsurgespider.items import StationSurgeListItem
from models.models import StationRealDataSpecific, SpiderTaskInfo, StationStatus, StationRealDataIndex
from sqlalchemy import ForeignKey, Sequence, MetaData, Table
from sqlalchemy import Column, Date, Float, ForeignKey, Integer, text
from sqlalchemy.dialects.mysql import DATETIME, INTEGER, TINYINT, VARCHAR
from core.db import DbFactory
from decorators import timer_count
from conf.settings import TASK_OPTIONS, DB_TABLE_SPLIT_OPTIONS

class StationSurgeRealData:
    """
        海洋站潮位实况
        实现分表功能
    """

    def __init__(self, station_code: str, list_station_realdata: List[StationRealDataSpecific], tid: int):
        self.station_code = station_code
        self.list_station_realdata = list_station_realdata
        self.tid = tid
        self.session = DbFactory().Session
        pass

    @property
    def gmt_start(self) -> Arrow:
        """
            起始时间
        """

        # sorted_list = self.list_station_realdata.sort(_sort)
        sorted_list = sorted(self.list_station_realdata, key=lambda station: station['ts'])
        start_ts: Arrow = sorted_list[0]['ts']
        return arrow.get(start_ts)

    @property
    def gmt_end(self) -> Arrow:
        # 倒叙排列
        sorted_list = sorted(self.list_station_realdata, key=lambda station: station['ts'], reverse=True)
        end_ts: Arrow = sorted_list[0]['ts']
        return arrow.get(end_ts)

    def create_split_tab(self) -> bool:
        """
            创建分表
        """
        is_created = self._check_need_split_tab(to_create=True)
        return is_created
        pass

    def insert_realdata_list(self, to_coverage: bool = False,
                             realdata_list: List[StationSurgeListItem] = []) -> bool:
        """
            判断 当前需要插入的数据是否已经存在于 表中，若存在且 to_coverage = True 则进行覆盖
        :param to_coverage:
        :param realdata_list:
        :return:
        """
        # TODO:[*] 23-03-12 注意此处需要根据插入的数据进行判断，是否需要跨表插入
        # 注意此处为 scrapy.Item 不能直接通过 obj.xx 需要通过 obj.get('xx') 获取
        months_list: List[int] = [temp.get('dt').month for temp in realdata_list]

        def _filter_month(val_realdata, month: int) -> bool:
            return val_realdata.dt.month == month

        months_set = set(months_list)
        # eg {month:int,realdate:List}
        list_distmonth_realdata = []
        # {month:realdata_list}
        dict_distmonth_realdata: dict = {}
        # 若当前爬取的实况跨月，则需要按照不同的月份进行分表
        for temp_month in months_set:
            dict_distmonth_realdata[temp_month] = []
            for temp_realdata in realdata_list:
                if temp_realdata.get('dt').month == temp_month:
                    dict_distmonth_realdata[temp_month].append(temp_realdata)

        for temo_month, temp_realdata_list in dict_distmonth_realdata.items():
            # temp_realdata_dict
            # 取出第一个
            # - 23-04-26 注意 temp_realdata_list[0].get('dt') 是 datetime.datetime ，需要转为 arrow
            now_arrow: Arrow = arrow.get(temp_realdata_list[0].get('dt'))
            tab_name: str = self._get_split_tab_name(now_arrow)
            station_code: str = self.station_code
            if self._check_exist_tab(tab_name):
                pass
            else:
                # 若不存在指定的表，需要创建该表
                self._create_station_realdata_tab(tab_name, now_arrow)
            # 动态更新表名
            self._insert_realdata(tab_name, station_code, realdata_list, to_coverage=to_coverage)

        pass

    @timer_count(10)
    def _insert_realdata(self, tab_name: str, station_code: str, realdata_list: List[StationSurgeListItem],
                         to_coverage: bool = False):
        """
            若 to_coverage = True 则向表中覆盖已存在的数据
        :param realdata_list:
        :param to_coverage:
        :return:
        """
        # dist_stationcodes: set[str] = set([temp.station_code for temp in realdata_list])
        # for dist_station_code in dist_stationcodes:
        #     temp_stationcode_realdata = list(filter(lambda o: o['station_code'] == dist_station_code, realdata_list))
        # 按照 station_code | timestamp | gmt_dt 查询，若存在则批量更新
        # 动态修改当前的表名
        StationRealDataSpecific.__table__.name = tab_name
        # 根据 station_code | gmt_start < gmt_realitime < gmt_end 过滤结果
        # 对于要插入的集合进行遍历
        # -> S1: station_code | gmt_realtime | ts 存在 则 update
        # -> s2: station_code | gmt_realtime | ts 不存在 则 create
        # query = select(StationRealDataSpecific).where(StationRealDataSpecific.station_code == station_code).where(
        #     StationRealDataSpecific.gmt_realtime > self.gmt_start).where(
        #     StationRealDataSpecific.gmt_realtime < self.gmt_end)
        query = select(StationRealDataSpecific).where(StationRealDataSpecific.station_code == station_code)
        # 插入
        print(f'[-]inserting {station_code} realdata,count:{len(realdata_list)}~')

        for temp_realdata in realdata_list:
            # ERROR:
            #     raise AttributeError(f"Use item[{name!r}] to get field value")
            # AttributeError: Use item['surge'] to get field value
            # 判断是否存在
            temp_query = query.where(StationRealDataSpecific.gmt_realtime == temp_realdata['dt'])
            temp_now: datetime = datetime.utcnow()
            surge: float = temp_realdata['surge']
            if np.isnan(surge):
                continue
            try:
                temp_query = self.session.scalars(temp_query).fetchall()
                # TODO:[*] 23-03-03 注意此处的 surge 有可能为 nan 需要加入判断
                # surge:int=
                if len(temp_query) > 0:
                    # update
                    # 在执行如下 update 操作时出错
                    stmt = update(StationRealDataSpecific).where(
                        StationRealDataSpecific.station_code == station_code).where(
                        StationRealDataSpecific.gmt_realtime == temp_realdata['dt']).values(
                        surge=surge)
                    self.session.execute(stmt)\
                        # .execute_options(
                    # synchronize_session="evaluate")
                else:
                    obj_realdata = StationRealDataSpecific(station_code=station_code, surge=surge,
                                                           tid=self.tid,
                                                           gmt_realtime=temp_realdata['dt'],
                                                           ts=temp_realdata['ts'])
                    self.session.add(obj_realdata)
            except Exception as ex:
                # print('[!]func: _insert_realdata ERROR!')
                print(ex.args)

        self.session.commit()
        self.session.close()
        print(f'[-]insert:{station_code} realdata over!')
        # TODO:[-] 23-03-02 写入完当前爬取的 station 潮位后更新 tb:station_status
        # TODO:[*] 23-03-02 此处修改为根据 realdata_list 找到最近的实况时间

        station_status = StationStatusData(station_code)
        station_status.insert(TaskTypeEnum.SUCCESS, self.tid, self.gmt_end.datetime)
        print(f'[-]updated {station_code} status~')
        pass

    def _check_need_split_tab(self, dt: Arrow, to_create: bool = True) -> bool:
        """

            判断是否需要分表，若已存在表是否覆盖
        @param to_create: 是否覆盖
        @return:
        """
        tab_name: str = self._get_split_tab_name(dt)
        is_need = False
        if self._check_exist_tab(tab_name) is False or (self._check_exist_tab(tab_name) and to_create):
            is_need = self._create_station_realdata_tab(tab_name, dt)
        return is_need

    def _get_split_tab_name(self, dt: Arrow) -> str:
        """
            获取分表名称
            按照结束时间生成表名
            eg: gmt_start 2023-02-26 xxx_202302
        @param dt:当前时间
        @return: 分表名称 eg: station_realdata_specific_202302
        """
        tab_base_name: str = DB_TABLE_SPLIT_OPTIONS.get('station').get('tab_split_name')
        tab_dt_name: str = dt.format('YYYYMM')
        tab_name: str = f'{tab_base_name}_{tab_dt_name}'
        return tab_name

    def _check_exist_tab(self, tab_name: str) -> bool:
        """
            判断指定表是否存在
        @param tab_name:
        @return:
        """
        is_exist = False
        auto_base = automap_base()
        db_factory = DbFactory()
        session = db_factory.Session
        engine = db_factory.engine
        auto_base.prepare(engine, reflect=True)
        list_tabs = auto_base.classes
        if tab_name in list_tabs:
            is_exist = True
        return is_exist
        pass

    def _create_station_realdata_tab(self, tab_name: str, dt: arrow.Arrow) -> bool:
        """
            根据 tab_name 创建对应的潮位实况表
        @param tab_name:
        @return:
        """
        is_ok = False
        meta_data = MetaData()
        Table(tab_name, meta_data, Column('id', Integer, primary_key=True),
              Column('is_del', TINYINT(1), nullable=False, server_default=text("'0'"), default=0),
              Column('station_code', VARCHAR(200), nullable=False, index=True), Column('tid', Integer, nullable=False),
              Column('surge', Float, nullable=False),
              Column('ts', Integer, nullable=False),
              Column('gmt_realtime', DATETIME(fsp=6), default=datetime.utcnow, index=True),
              Column('gmt_create_time', DATETIME(fsp=6), default=datetime.utcnow),
              Column('gmt_modify_time', DATETIME(fsp=6), default=datetime.utcnow))
        db_factory = DbFactory()
        session = db_factory.Session
        engine = db_factory.engine
        with engine.connect() as conn:
            # result_proxy = conn.execute(sql_str)
            # result = result_proxy.fetchall()
            try:
                meta_data.create_all(engine)
                is_ok = True
            except Exception as ex:
                print(ex.args)
        # TODO:[-] 23-04-28 还需要插入表 station_realdata_index
        year: int = dt.format('yyyy')
        local_start: arrow.Arrow = arrow.Arrow(year=year, month=dt.format('MM'), day=1, hour=0, minute=0)
        local_end: arrow.Arrow = local_start.shift(month=1)
        gmt_start: arrow.Arrow = local_start.shift(hour=-8)
        gmt_end: arrow.Arrow = local_end.shift(hour=-8)
        tab_index: StationRealDataIndex = StationRealDataIndex(tab_name=tab_name, year=year,
                                                               gmt_start=gmt_start.datetime,
                                                               gmt_end=gmt_end.datetime)
        session.add(tab_index)
        session.commit()
        return is_ok

class SpiderTask:
    def __init__(self, now_utc: Arrow, count_stations: int, task_name: str):
        self.now_utc = now_utc
        self.count_stations = count_stations
        self.task_name = task_name
        self.session = DbFactory().Session
        pass

    def to_db(self) -> int:
        interval: int = TASK_OPTIONS.get('interval')
        task_info: SpiderTaskInfo = SpiderTaskInfo(timestamp=self.now_utc.timestamp(), task_name=self.task_name,
                                                   task_type=TaskTypeEnum.SUCCESS.value,
                                                   spider_count=self.count_stations, interval=interval)
        # with DbFactory().Session as session:
        task_id: int = -1
        try:
            self.session.add(task_info)
            self.session.commit()
        finally:
            task_id = task_info.id
            self.session.close()
        return task_id

class StationStatusData:
    def __init__(self, station_code: str):
        self.station_code = station_code
        self.session = DbFactory().Session

    def insert(self, status: TaskTypeEnum, tid: int, gmt_realtime: datetime):
        """
            插入 station_code 更新 gmt_update_dt | status
        :param status: 状态
        :param tid: tb: task_info id
        :param gmt_realtime: 最后的潮位实况时间
        :return:
        """
        # session = self.session
        now_utc: datetime = datetime.utcnow()
        # step1: 从 tb: station_status 中查找，若存在则update | 不存在则 create
        query = select(StationStatus).where(StationStatus.station_code == self.station_code)
        try:
            temp_first = self.session.scalars(query).fetchall()
            if len(temp_first) > 0:
                # update
                # AttributeError: 'CursorResult' object has no attribute 'execute_options'
                self.session.execute(
                    update(StationStatus).where(StationStatus.station_code == self.station_code).values(
                        status=status.value,
                        gmt_realtime=gmt_realtime, gmt_modify_time=now_utc))
            else:
                obj_status = StationStatus(station_code=self.station_code, tid=tid, status=status.value,
                                           gmt_realtime=gmt_realtime)
                self.session.add(obj_status)
            self.session.commit()
        except Exception as ex:
            print(f'status insert error!msg:{ex.args}')
        # self.session.close()


"""
Use a simple Discrete Variable Representation method to solve
one-dimensional potentials.

A good general introduction to DVR methods is
Light and Carrington, Adv. Chem. Phys. 114, 263 (2000)
"""

from matplotlib import pyplot as plt
import numpy as np
import scipy.sparse.linalg as sla
import scipy.special.orthogonal as ortho
# import bessel
import warnings

class DVR(object):
    def v(self, V):
        """
        Return the potential matrix with the given potential.
        Usage:
            v_matrix = self.v(V)

        @param[in] V potential function
        @returns v_matrix potential matrix
        """
        v_matrix = np.diag(V(self.x))
        return v_matrix

    def h(self, V):
        """Return the hamiltonian matrix with the given potential.
        Usage:
            H = self.h(V)

        @param[in] V potential function
        @returns H potential matrix
        """
        return self.t() + self.v(V)

    def dvr2fbr(DVR, T):
        """Transform a matrix from the discrete variable representation
        to the finite basis representation"""
        return np.dot(T, np.dot(DVR, np.transpose(T)))

    def fbr2dvr(FBR, T):
        """Transform a matrix from the finite basis representation to the
        discrete variable representation."""
        return np.dot(np.transpose(T), np.dot(FBR, T))

    def plot(self, V, E, U, **kwargs):
        doshow = kwargs.get('doshow', False)
        nplot = kwargs.get('nplot', 5)
        xmin = kwargs.get('xmin', self.x.min())
        xmax = kwargs.get('xmax', self.x.max())
        ymin = kwargs.get('ymin', np.ceil(V(self.x).min() - 1.))
        ymax = kwargs.get('ymax',
                          np.floor(max(U.max()+E.max()+1., V(self.x).max()+1.)))
        plt.plot(self.x, V(self.x))
        for i in range(nplot):
            if i == 0:
                plt.plot(self.x, abs(U[:, i])+E[i])
            else:
                plt.plot(self.x, U[:, i]+E[i])
        plt.axis(ymax=ymax, ymin=ymin)
        plt.axis(xmax=xmax, xmin=xmin)
        if doshow: plt.show()
        return

    def run(self, V, num_eigs = 5, **kwargs):
        h = self.h(V)
        # Get the eigenpairs
        # There are multiple options here.
        # If the user is asking for all of the eigenvalues,
        # then we need to use np.linalg.eigh()
        if num_eigs == h.shape[0]:
            E, U = np.linalg.eigh(h)
        # But if we don't need all eigenvalues, only the smallest ones,
        # then when the size of the H matrix becomes large enough, it is
        # better to use sla.eigsh() with a shift-invert method. Here we
        # have to have a good guess for the smallest eigenvalue so we
        # ask for eigenvalues closest to the minimum of the potential.
        else:
            E, U = sla.eigsh(h, k=num_eigs, which='LM',
                             sigma=V(self.x).min())

        xmin = kwargs.get('xmin', self.x.min())
        xmax = kwargs.get('xmax', self.x.max())
        ymin = kwargs.get('ymin', np.ceil(V(self.x).min() - 1.))
        ymax = kwargs.get('ymax',
                          np.floor(max(U.max()+E.max()+1., V(self.x).max()+1.)))
        precision = kwargs.get('precision', 8)

        # Print and plot stuff
        print('The first {n:d} energies are:'.format(n=num_eigs))
        print(np.array_str(E[:num_eigs], precision=precision))
        self.plot(V, E, U, nplot=num_eigs,
                  xmin=xmin, xmax=xmax,
                  ymin=ymin, ymax=ymax,
                  doshow=True)
        return

    def inf_square_well_test(self, precision=8):
        print('Testing 1-D DVR with an infinite square-well potential')
        vF = VFactory()
        V = vF.square_well(depth=1e30, width=10.)
        self.test_potential(V, num_eigs=5, precision=precision,
                            xmin=-10., xmax=10.,
                            ymin=-0.25, ymax=2.)
        e_exact = np.square(np.arange(1,6)) * np.pi**2. / 2. / 10.**2.
        print("Compare to the exact energies:")
        print(np.array_str(e_exact, precision=precision))
        print
        return

    def square_well_test(self, precision=8):
        #print'Testing 1-D DVR with a finite square-well potential'
        vF = VFactory()
        V = vF.square_well(depth=9./2., width=10.)
        self.test_potential(V, num_eigs=5, precision=precision,
                            xmin=-10., xmax=10.,
                            ymin=-0.25, ymax=2.)
        e_exact = 9./2. * np.array([0.009636, 0.038522, 0.086582,
                                    0.153683, 0.239608])
        print("Compare to these energies:")
        print(np.array_str(e_exact, precision=precision))
        #print "from: http://pilotscholars.up.edu/phy_facpubs/8\n"
        return

    def double_well_test(self, precision=8):
        print('Testing 1-D DVR with a double-well potential')
        vF = VFactory()
        V = vF.double_well()
        self.test_potential(V, num_eigs=5, precision=precision,
                            xmin=-3.5, xmax=3.5,
                            ymin=-0.5, ymax=4.)
        print
        return

    def sho_test(self, k=1., num_eigs=5, precision=8,
            xmin=-3.5, xmax=3.5, ymin=0., ymax=6.):
        print('Testing 1-D DVR with an SHO potential')
        vF = VFactory()
        V = vF.sho(k=k)
        self.run(V, num_eigs=num_eigs,
                            precision=precision,
                            xmin=xmin, xmax=xmax,
                            ymin=ymin, ymax=ymax)
        print
        return

    def morse_test(self, precision=8, xmin=0., xmax=32., ymin=-3., ymax=1.):
        print('Testing 1-D DVR with a Morse potential')
        vF = VFactory()
        V = vF.morse(D=3., a=0.5)
        self.test_potential(V, num_eigs=5, precision=precision,
                            xmin=xmin, xmax=xmax,
                            ymin=ymin, ymax=ymax)
        print
        return

    def sombrero_test(self, precision=8):
        print('Testing 1-D DVR with a sombrero potential')
        vF = VFactory()
        V = vF.sombrero(a=-5.)
        self.test_potential(V, num_eigs=5, precision=precision,
                            xmin=-5., xmax=5., ymax=5.)
        print
        return

    def woods_saxon_test(self, precision=8):
        print('Testing 1-D DVR with a Woods-Saxon potential')
        vF = VFactory()
        V = vF.woods_saxon(A=4)
        self.test_potential(V, num_eigs=5, precision=precision,
                            xmin=0., xmax=5.,
                            ymin=-50., ymax=0.)
        print
        return

    def test_all(self, precision=8):
        self.square_well_test(precision=precision)
        self.double_well_test(precision=precision)
        self.sho_test(precision=precision)
        self.morse_test(precision=precision)
        self.sombrero_test(precision=precision)
        self.woods_saxon_test(precision=precision)

class SincDVR(DVR):
    r"""Sinc function basis for non-periodic functions over an interval
    `x0 +- L/2` with `npts` points.
    Usage:
        d = sincDVR1D(npts, L, [x0])

    @param[in] npts number of points
    @param[in] L size of interval
    @param[in] x0 origin offset (default=0)
    @attribute a step size
    @attribute n vector of x-domain indices
    @attribute x discretized x-domain
    @attribute k_max cutoff frequency
    @method h return hamiltonian matrix
    @method f return DVR basis vectors
    """
    def __init__(self, npts, L, x0=0.):
        # L = float(L)
        self.npts = npts
        self.L = L
        self.x0 = x0
        self.a = L / npts
        self.n = np.arange(npts)
        self.x = self.x0 + self.n * self.a - self.L / 2. + self.a / 2.
        self.w = np.ones(npts, dtype=np.float64) * self.a
        self.k_max = np.pi/self.a

    def t(self, hc=1., mc2=1.):
        """Return the kinetic energy matrix.
        Usage:
            T = self.t()

        @returns T kinetic energy matrix
        """
        _m = self.n[:, np.newaxis]
        _n = self.n[np.newaxis, :]
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            T = 2. * (-1.)**(_m-_n) / (_m-_n)**2. / self.a**2.
        T[self.n, self.n] = np.pi**2. / 3. / self.a**2.
        T *= 0.5 * hc**2. / mc2   # (pc)^2 / (2 mc^2)
        return T

    def ip(self, hbar=1.):
        """Return the momentum matrix times i (imaginary number)
        i.e. ip = hbar frac{d}{dx}
        Usage:
            iP = self.p()

        @returns iP momentum matrix times i (imaginary number)
        """
        _m = self.n[:, np.newaxis]
        _n = self.n[np.newaxis, :]
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            iP = (-1.)**(_m-_n) / (_m-_n) / self.a
        iP[self.n, self.n] = 0.
        iP *= hbar
        return iP

    def f(self, x=None):
        """Return the DVR basis vectors"""
        if x is None:
            x_m = self.x[:, np.newaxis]
        else:
            x_m = np.asarray(x)[:, np.newaxis]
        x_n = self.x[np.newaxis, :]
        return np.sinc((x_m-x_n)/self.a)/np.sqrt(self.a)

class SincDVRPeriodic(SincDVR):
    r"""Sinc function basis for periodic functions over an interval
    `x0 +- L/2` with `N` points."""
    def __init__(self, *v, **kw):
        # Small shift here for consistent abscissa
        SincDVR.__init__(self, *v, **kw)
        self.x -= self.a/2.

    def t(self, hc=1., mc2=1.):
        """Return the kinetic energy matrix.
        Usage:
            T = self.t(V)

        @returns T kinetic energy matrix
        """
        _m = self.n[:, np.newaxis]
        _n = self.n[np.newaxis, :]
        _arg = np.pi*(_m-_n)/self.npts
        if (0 == self.npts % 2):
            T = 2.*(-1.)**(_m-_n)/np.sin(_arg)**2.
            T[self.n, self.n] = (self.npts**2. + 2.)/3.
        else:
            T = 2.*(-1.)**(_m-_n)*np.cos(_arg)/np.sin(_arg)**2.
            T[self.n, self.n] = (self.npts**2. - 1.)/3.
        T *= (np.pi/self.L)**2.
        T *= 0.5 * hc**2. / mc2   # (pc)^2 / (2 mc^2)
        return T

    def f(self, x=None):
        """Return the DVR basis vectors"""
        if x is None:
            x_m = self.x[:, np.newaxis]
        else:
            x_m = np.asarray(x)[:, np.newaxis]
        x_n = self.x[np.newaxis, :]
        f = np.sinc((x_m-x_n)/self.a)/np.sinc((x_m-x_n)/self.L)/np.sqrt(self.a)
        if (0 == self.npts % 2):
            f *= np.exp(-1j*np.pi*(x_m-x_n)/self.L)
        return f

class SineDVR(DVR):
    r"""Sine function basis for non-periodic functions over an interval
    `x_min ... x_max` with `npts` points.
    Usage:
        d = sincDVR1D(npts, xmin, xmax)

    @param[in] npts number of points
    @param[in] xmin "left" end of interval
    @param[in] xmax "right" end of interval
    @attribute a step size
    @attribute n vector of x-domain indices
    @attribute x discretized x-domain
    @attribute k_max cutoff frequency
    @attribute L size of x-domain
    @method h return hamiltonian matrix
    @method f return DVR basis vectors
    """
    def __init__(self, npts, xmin=-1., xmax=1.):
        self.npts = npts
        self.L = float(xmax) - float(xmin)
        self.a = self.L / float(npts + 1.)
        self.n = np.arange(1, npts + 1)
        self.x = float(xmin) + self.a * self.n
        self.k_max = None

    def t(self, hc=1., mc2=1.):
        """Return the kinetic energy matrix.
        Usage:
            T = self.t(V)

        @returns T kinetic energy matrix
        """
        _i = self.n[:, np.newaxis]
        _j = self.n[np.newaxis, :]
        m = self.npts + 1
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            T = ((-1.)**(_i-_j)
                * (1./np.square(np.sin(np.pi / (2. * m) * (_i-_j)))
                - 1./np.square(np.sin(np.pi / (2. * m) * (_i+_j)))))
        T[self.n - 1, self.n - 1] = 0.
        T += np.diag((2. * m**2. + 1.) / 3.
                     - 1./np.square(np.sin(np.pi * self.n / m)))
        T *= np.pi**2. / 2. / self.L**2. #prefactor common to all of T
        T *= 0.5 * hc**2. / mc2   # (pc)^2 / (2 mc^2)
        return T

#     def f(self, x=None):
#         """Return the DVR basis vectors"""
#         if x is None:
#             x_m = self.x[:, np.newaxis]
#         else:
#             x_m = np.asarray(x)[:, np.newaxis]
#         x_n = self.x[np.newaxis, :]
#         return np.sinc((x_m-x_n)/self.a)/np.sqrt(self.a)

class HermiteDVR(DVR):
    r"""Hermite function basis for non-periodic functions over an interval
    `-x_max ... x_max` with `npts` points.
    Usage:
        d = sincDVR1D(npts, xmax, [x0])

    @param[in] npts number of points
    @param[in] xmax "right" end of interval
    @param[in] x0 shifted center of interval
    @attribute a step size
    @attribute n vector of x-domain indices
    @attribute x discretized x-domain
    @attribute w quadrature weights
    @attribute k_max cutoff frequency
    @attribute L size of x-domain
    @method h return hamiltonian matrix
    @method f return DVR basis vectors
    """
    def __init__(self, npts, xmax=None, x0=0.):
        assert (npts < 269), \
            "Must make npts < 269 for numpy to find quadrature points."
        self.npts = npts
        self.x0 = float(x0)
        self.n = np.arange(npts)
        c = np.zeros(npts+1)
        c[-1] = 1.
        self.x = np.polynomial.hermite.hermroots(c)
        if xmax is None:
            self.gamma = 1.
        else:
            assert xmax is None, "Sorry, xmax is currently broken"
            self.gamma = self.x.max() / float(xmax)

        self.x = self.x0 + self.x / self.gamma
        self.w = np.exp(-np.square(self.x))
        self.L = self.x.max() - self.x.min()
        self.a = None
        self.k_max = None

    def t(self, hc=1., mc2=1.):
        """Return the kinetic energy matrix.
        Usage:
            T = self.t(V)

        @returns T kinetic energy matrix
        """
        _i = self.n[:, np.newaxis]
        _j = self.n[np.newaxis, :]
        _xi = self.x[:, np.newaxis]
        _xj = self.x[np.newaxis, :]

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            T = 2.*(-1.)**(_i-_j)/(_xi-_xj)**2.

        T[self.n, self.n] = 0.
        T += np.diag((2. * self.npts + 1.
                      - np.square(self.x)) / 3.)
        T *= self.gamma
        T *= 0.5 * hc**2. / mc2   # (pc)^2 / (2 mc^2)
        return T

#     def f(self, x=None):
#         """Return the DVR basis vectors"""
#         if x is None:
#             x_m = self.x[:, np.newaxis]
#         else:
#             x_m = np.asarray(x)[:, np.newaxis]
#         x_n = self.x[np.newaxis, :]
#         return np.sinc((x_m-x_n)/self.a)/np.sqrt(self.a)

class BesselDVR(DVR):
    r"""Bessel function basis for non-periodic functions over an interval
    `0 ... R` with `npts` points, `dim` dimensions, `lam` angular
    momentum number.
    Usage:
        d = sincDVR1D(npts, R, dim, lam)

    @param[in] npts number of points
    @param[in] R max radius
    @param[in] dim dimension of the Bessel representation
    @param[in] lam angular momentum quantum number
    @attribute n vector of domain indices
    @attribute z discretized domain
    @attribute nu
    @attribute K
    @attribute r
    @method h return hamiltonian matrix
    @method f return DVR basis vectors
    """
    def __init__(self, npts, R, dim, lam):
        assert type(dim) == int, "dim must be an integer."
        assert dim > 1, "dim must be 2 or more."
        self.npts = npts
        self.n = np.arange(npts)
        self.R = R
        self.dim = dim
        self.lam = lam
        self.__init_private()

    def __init_private(self):
        self.nu = self.lam + self.dim/2. - 1.
        self.z = bessel.j_root(nu=self.nu, N=self.npts)
        self.K = self.z[-1] / self.R
        self.x = self.z / self. K

    def t(self, hc=1., mc2=1.):
        """Return the kinetic energy matrix.
        Usage:
            T = self.t(V)

        @returns T kinetic energy matrix
        """
        n = self.npts
        nu = self.nu
        K = self.K

        _i = self.n[:, np.newaxis]
        _j = self.n[np.newaxis, :]
        _xi = self.z[:, np.newaxis]
        _xj = self.z[np.newaxis, :]
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            T = 8. * K**2. * (-1.)**(_i-_j) * _xi * _xj /(_xi**2. - _xj**2.)**2.
        T[self.n, self.n] = 0.
        T += np.diag(K**2. / 3. * (1. + 2. * (nu**2. - 1.) / self.z**2.))
        T *= 0.5 * hc**2. / mc2   # (pc)^2 / (2 mc^2)
        return T

class GaussianDVR(DVR):
    pass

class ChebDVR(DVR):
    pass

# Factory functions to build different potentials:
# A factory is a function that makes a function.
class VFactory(object):
    """Factory functions to build different potentials
    A factory is a function that returns other functions.
    """
    def square_well(self, depth = 1., width = 1.,
                    origin = 0., o_val = 0.):
        """Usage:
                V = square_well_factory(**kwargs)

        Returns a function of a single variable V(x),
        representing the square-well potential:

             (-A/2, V0)            (A/2, V0)
        ------------       +       ----------------
                   |               |
                   |               |
                   |               |
                   |               |
         (-A/2, 0) |-------+-------| (A/2, 0)
                         (0, 0)

        Keyword arguments:
        @param[in] depth    Depth of the potential well (default=1)
        @param[in] width    Width of the potential well (default=1)
        @param[in] origin   Location of the well's center (default=0)
        @param[in] o_val    Value of the potential at origin (default=0)
        @returns   V        The square well potential function V(x)
        """
        def V(x):
            interior_idx = np.abs(x - origin) < width / 2.
            V = np.ones_like(x) * (depth + o_val)
            V[interior_idx] = o_val
            return V
        return V

    def double_well(self, x1 = -2., x2 = -1., x3 = 1.,
                    x4 = 2., V1 = 1., V2 = 0.,
                    V3 = 1., V4 = 0., V5 = 1.):
        """Usage:
                V = double_square_well_factory(**kwargs)

        Returns a one-dimensional potential function that represents
        a double-square-well potential. The potential looks like

           (x1, V1)      (x2, V3)   (x3, V3)      (x4, V5)
        ----------            ---------            ----------
                 |            |       |            |
                 |            |       |            |
                 |            |       |            |
                 |            |       |            |
                 |____________|       |____________|
           (x1, V2)      (x2, V2)   (x3, V4)      (x4, V4)

        Keywork arguments
        @param[in] x1    x-coordinate x1 above (default=-2)
        @param[in] x2    x-coordinate x2 above (default=-1)
        @param[in] x3    x-coordinate x3 above (default=1)
        @param[in] x4    x-coordinate x4 above (default=2)
        @param[in] V1    constant V1 above (default=1)
        @param[in] V2    constant V2 above (default=0)
        @param[in] V3    constant V3 above (default=1)
        @param[in] V4    constant V4 above (default=0)
        @param[in] V5    constant V5 above (default=1)
        @returns   V     double square-well potential V(x)
        """
        assert (x1 < x2 < x3 < x4), \
            "x-coordinates do not satisfy x1 < x2 < x3 < x4"
        def V(x):
            l_well_idx = np.logical_and(x < x2, x > x1)
            r_well_idx = np.logical_and(x < x4, x > x3)
            middle_idx = np.logical_and(x >= x2, x <= x3)
            far_rt_idx = np.greater_equal(x, x4)
            V = np.ones_like(x) * V1
            V[l_well_idx] = V2
            V[middle_idx] = V3
            V[r_well_idx] = V4
            V[far_rt_idx] = V5
            return V
        return V

    def sho(self, k = 1., x0 = 0.):
        """Usage:
                V = harmosc_factory(**kwargs)

        Return a one-dimensional harmonic oscillator potential V(x)
        with wavenumber k. i.e. V(x) = 1/2 * k * (x - x0)^2

        Keyword arguments
        @param[in] k    wavenumber of the SHO potential (default=1)
        @param[in] x0   displacement from origin (default=0)
        @returns   V    1-D SHO potential V(x)
        """
        def V(x): return 0.5 * k * np.square(x - x0)
        return V

    def power(self, a = 1., p=1., x0 = 0.):
        """Usage:
                V = self.power(**kwargs)

        Return a potential V(x) = a * (x - x0)^p

        Keyword arguments
        @param[in] a    coefficient (default=1)
        @param[in] p    power to raise x (default=1)
        @param[in] x0   displacement from origin (default=0)
        @returns   V    1-D cubic potential V(x)
        """
        def V(x): return a * np.power(x - x0, p)
        return V

    def morse(self, D = 1., a = 1., x0 = 0.):
        """Usage:
                V = morse_factory(**kwargs)

        Return a one-dimensional Morse potential V(x)
        i.e. V(x) = D * (1 - exp(-a * (x - x0)))^2 - D

        Keyword arguments
        @param[in] D    dissociation depth
        @param[in] a    inverse "width" of the potential
        @param[in] x0   equilibrium bond distance
        @returns   V    Morse potential V(x)
        """
        def V(x):
            return D * np.power(1. - np.exp(-a * (x - x0)), 2.) - D
        return V

    def sombrero(self, a = -10., b = 1.):
        """Usage:
                V = sombrero_factory(**kwargs)

        Return a one-dimensional version of the sombrero potential
        i.e. V(x) = a * x^2 + b * x^4
        This function asserts a < 0 and b > 0

        Keyword arguments
        @param[in] a    coefficient of the x^2 term (default=-10)
        @param[in] b    coefficient of the x^4 term (default=1)
        @returns   V    1-D Mexican hat potential V(x)
        """
        assert (a < 0), "Coefficient a must be negative"
        assert (b > 0), "Coefficient b must be positive"
        def V(x):
            return a * np.square(x) + b * np.power(x, 4)
        return V

    def woods_saxon(self, V0 = 50., z = 0.5, r0 = 1.2, A = 16):
        """Usage:
                V = woods_saxon_factory(**kwargs)

        Return a Woods-Saxon potential
        i.e. V(r) = - V0 / (1. + exp((r - R) / z))
        where R = r0 * A^(1/3)

        Keyword arguments
        @param[in] V0   potential depth (default=50.)
        @param[in] z    surface thickness (default=0.5)
        @param[in] r0   rms nuclear radius (default=1.2)
        @param[in] A    mass number (default=16)
        @returns   V    Woods-Saxon potential V(r)
        """
        def V(r):
            x0 = r0 * np.power(A, 1. / 3.)
            return -V0 / (1. + np.exp((r - x0)/ z))
        return V

if __name__ == '__main__':
    dvr = SincDVR(npts=200, L=14)
    x = dvr.x

    def v(x):
        return x**2

    dvr.run(v, num_eigs=8)

    # dvr = HermiteDVR(npts=20)


# ============================ 1. Environment setup ============================
import os
import dgl
import time
import torch
import pickle
import numpy as np
import pandas as pd
import networkx as nx
import torch.nn as nn
from tqdm import tqdm
import torch.nn.functional as F
from dgl.data import DGLDataset
#torch.cuda.set_device(0)

# ========================= 2. Setting up the Dataset =========================

data_time = time.time()

file = open('../data/PolypharmacyDataset.obj', 'r')
dataset = pickle.load(file)

end = time.time()
hours, rem = divmod(end-data_time , 3600)
minutes, seconds = divmod(rem, 60)

print('\nPolypharmacyDataset Created!\n')
print('\ndataset is compiled! \ncompiling time = {:0>2}:{:0>2}:{:05.2f}'.format(int(hours),int(minutes),seconds))

# ========================= 3. Data loading and batch =========================

print('\nCreating train and test batches ...\n')

from dgl.dataloading import GraphDataLoader
from torch.utils.data.sampler import SubsetRandomSampler

num_examples = len(dataset)
num_train = int(num_examples * 0.8)

train_sampler = SubsetRandomSampler(torch.arange(num_train))
test_sampler = SubsetRandomSampler(torch.arange(num_train, num_examples))

train_dataloader = GraphDataLoader(
    dataset, sampler=train_sampler, batch_size=5, drop_last=False)
test_dataloader = GraphDataLoader(
    dataset, sampler=test_sampler, batch_size=5, drop_last=False)

print('\nTrain and test batches are created!\n')

# ========================= 4. GNN Model: Siamese GCN =========================

from dgl.nn import GraphConv

class GCN(nn.Module):
    def __init__(self, in_feats, h_feats, num_classes):
        super(GCN, self).__init__()
        self.conv1 = GraphConv(in_feats, h_feats)
        self.conv2 = GraphConv(h_feats,  num_classes)

    def forward(self, g, in_feat):
        h = self.conv1(g, in_feat)
        h = F.relu(h)
        h = self.conv2(g, h)
        g.ndata['h'] = h
        out = F.relu(dgl.mean_nodes(g, 'h'))
        #out = F.relu(dgl.max_nodes(g, 'h'))
        return out

# =============================== 5. Training =================================
train_time = time.time()

#print('\nCreating the SiameseGCN model ...\n')

# Create the model with given dimensions
model = GCN(dataset.dim_nfeats, 450, dataset.gclasses)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

print('\n======================== Trainig ========================\n')

for epoch in range(20):
    batch = 0
    for batched_graph, labels in train_dataloader:
        start_time = time.time()
        g1 = batched_graph[0]
        g2 = batched_graph[1]
        pred1 = model(g1, g1.ndata['PSE'].float())
        pred2 = model(g2, g2.ndata['PSE'].float())
        pred = F.relu((pred1+pred2)/2)
        loss = F.binary_cross_entropy(torch.sigmoid(pred).float(),labels.float())
        #loss = 1- F.cosine_similarity(torch.sigmoid(pred),labels).mean()
        #loss = F.triplet_margin_loss(labels,pred1,pred2)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        run_time = round(time.time() - start_time,3)
        print ('epoch%s, batch%s | loss = %s | time: %s s' % (epoch,batch,loss.tolist(),run_time))
        batch += 1

end = time.time()
hours, rem = divmod(end-train_time , 3600)
minutes, seconds = divmod(rem, 60)
print('\ntotal training time = {:0>2}:{:0>2}:{:05.2f}'.format(int(hours),int(minutes),seconds))

torch.save(model.state_dict(), 'state_dict_model.pt')
torch.save(model, 'entire_model.pt')
print('\nmodel is saved!\n')

print('\n======================== Testing ========================\n')

num_correct = 0
num_correct_0 = 0
num_incorrect = 0
num_tests = 0
for batched_graph, labels in test_dataloader:
    pred1 = model(batched_graph[0], batched_graph[0].ndata['PSE'].float())
    pred2 = model(batched_graph[1], batched_graph[1].ndata['PSE'].float())
    pred = F.relu((pred1+pred2)/2)
    for i in range(len(labels)):
        for j in range(len(labels[i])):
            num_tests += 1
            if labels[i][j] == 1 and pred[i][j] != 0:
                num_correct += 1
            elif labels[i][j] == 1 and pred[i][j] == 0:
                num_incorrect += 1
            elif labels[i][j] == 0 and pred[i][j] != 0:
                num_incorrect += 1
            elif labels[i][j] == 0 and pred[i][j] == 0:
                num_correct_0 += 1
                pass

    acc = ((num_correct+num_correct_0)*100)/(num_tests)
    acc2 = ((num_correct_0)*100)/(num_tests)
    prec = ((num_correct)*100)/(num_incorrect+num_correct)
    sim = ((F.cosine_similarity(pred.float(),labels.float())).mean().tolist())*100
    print('Accuracy: %s, %s | Precision: %s | Similarity: %s' %(round(acc,5),round(acc2,5),round(prec,5),round(sim,5)))


import os
import pickle
import re

import torch
import nni.retiarii.nn.pytorch as nn
from nni.retiarii.nn.pytorch import LayerChoice
from nni.retiarii.serializer import model_wrapper

from blocks import ShuffleNetBlock, ShuffleXceptionBlock

@model_wrapper
class ShuffleNetV2OneShot(nn.Module):
    block_keys = [
        'shufflenet_3x3',
        'shufflenet_5x5',
        'shufflenet_7x7',
        'xception_3x3',
    ]

    def __init__(self, input_size=224, first_conv_channels=16, last_conv_channels=1024,
                 n_classes=1000, affine=False):
        super().__init__()

        assert input_size % 32 == 0
        self.stage_blocks = [4, 4, 8, 4]
        self.stage_channels = [64, 160, 320, 640]
        self._input_size = input_size
        self._feature_map_size = input_size
        self._first_conv_channels = first_conv_channels
        self._last_conv_channels = last_conv_channels
        self._n_classes = n_classes
        self._affine = affine
        self._layerchoice_count = 0

        # building first layer
        self.first_conv = nn.Sequential(
            nn.Conv2d(3, first_conv_channels, 3, 2, 1, bias=False),
            nn.BatchNorm2d(first_conv_channels, affine=affine),
            nn.ReLU(inplace=True),
        )
        self._feature_map_size //= 2

        p_channels = first_conv_channels
        features = []
        for num_blocks, channels in zip(self.stage_blocks, self.stage_channels):
            features.extend(self._make_blocks(num_blocks, p_channels, channels))
            p_channels = channels
        self.features = nn.Sequential(*features)

        self.conv_last = nn.Sequential(
            nn.Conv2d(p_channels, last_conv_channels, 1, 1, 0, bias=False),
            nn.BatchNorm2d(last_conv_channels, affine=affine),
            nn.ReLU(inplace=True),
        )
        self.globalpool = nn.AvgPool2d(self._feature_map_size)
        self.dropout = nn.Dropout(0.1)
        self.classifier = nn.Sequential(
            nn.Linear(last_conv_channels, n_classes, bias=False),
        )

        self._initialize_weights()

    def _make_blocks(self, blocks, in_channels, channels):
        result = []
        for i in range(blocks):
            stride = 2 if i == 0 else 1
            inp = in_channels if i == 0 else channels
            oup = channels

            base_mid_channels = channels // 2
            mid_channels = int(base_mid_channels)  # prepare for scale
            self._layerchoice_count += 1
            choice_block = LayerChoice([
                ShuffleNetBlock(inp, oup, mid_channels=mid_channels, ksize=3, stride=stride, affine=self._affine),
                ShuffleNetBlock(inp, oup, mid_channels=mid_channels, ksize=5, stride=stride, affine=self._affine),
                ShuffleNetBlock(inp, oup, mid_channels=mid_channels, ksize=7, stride=stride, affine=self._affine),
                ShuffleXceptionBlock(inp, oup, mid_channels=mid_channels, stride=stride, affine=self._affine)
            ], label="LayerChoice" + str(self._layerchoice_count))
            result.append(choice_block)

            if stride == 2:
                self._feature_map_size //= 2
        return result

    def forward(self, x):
        bs = x.size(0)
        x = self.first_conv(x)
        x = self.features(x)
        x = self.conv_last(x)
        x = self.globalpool(x)

        x = self.dropout(x)
        x = x.contiguous().view(bs, -1)
        x = self.classifier(x)
        return x

    def _initialize_weights(self):
        for name, m in self.named_modules():
            if isinstance(m, nn.Conv2d):
                if 'first' in name:
                    torch.nn.init.normal_(m.weight, 0, 0.01)
                else:
                    torch.nn.init.normal_(m.weight, 0, 1.0 / m.weight.shape[1])
                if m.bias is not None:
                    torch.nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.BatchNorm2d):
                if m.weight is not None:
                    torch.nn.init.constant_(m.weight, 1)
                if m.bias is not None:
                    torch.nn.init.constant_(m.bias, 0.0001)
                torch.nn.init.constant_(m.running_mean, 0)
            elif isinstance(m, nn.BatchNorm1d):
                torch.nn.init.constant_(m.weight, 1)
                if m.bias is not None:
                    torch.nn.init.constant_(m.bias, 0.0001)
                torch.nn.init.constant_(m.running_mean, 0)
            elif isinstance(m, nn.Linear):
                torch.nn.init.normal_(m.weight, 0, 0.01)
                if m.bias is not None:
                    torch.nn.init.constant_(m.bias, 0)

def load_and_parse_state_dict(filepath="./data/checkpoint-150000.pth.tar"):
    checkpoint = torch.load(filepath, map_location=torch.device("cpu"))
    if "state_dict" in checkpoint:
        checkpoint = checkpoint["state_dict"]
    result = dict()
    for k, v in checkpoint.items():
        if k.startswith("module."):
            k = k[len("module."):]
        result[k] = v
    return result


import pygame
import aspose.words as aw

class Boardimg:

    def __init__(self, img):
        self.img = img
        self.img_file = pygame.image.load(img)
        self.x = 0
        self.y = 0
        self.img_size = self.img_file.get_size()
        self.rect = pygame.Rect(self.x, self.y, self.img_size[0], self.img_size[1])

    def set_img(self, img):
        self.img = img
        self.img_file = pygame.image.load(img)
        self.img_size = self.img_file.get_size()
        self.rect = pygame.Rect(self.x, self.y, self.img_size[0], self.img_size[1])

    def get_img(self):
        return self.img

    def covert_to_png(self):
        doc = aw.Document()
        builder = aw.DocumentBuilder(doc)
        shape = builder.insert_image(self.img)
        pageSetup = builder.page_setup
        pageSetup.page_width = shape.width
        pageSetup.page_height = shape.height
        pageSetup.top_margin = 0
        pageSetup.left_margin = 0
        pageSetup.bottom_margin = 0
        pageSetup.right_margin = 0
        doc.save("image.png")
        self.set_img("image.png")

a = Boardimg("image.svg")
a.covert_to_png()


from typing import List

from scipy.spatial import Voronoi
import torch

def get_centroid(pts):
    n = pts.size(0)
    return torch.sum(pts[:,0])/n , torch.sum(pts[:,1])/n

def get_waypoints(map : torch.Tensor, N : int, range : float):
    free_idx = torch.argwhere(map==0)
    waypoints = free_idx[torch.randint(free_idx.size()[0],(map.size(0),N))]

if __name__ == "__main__":
    import torchvision
    #from cocomas import maps
    map_file = "cocomas/maps/empty.png"
    map = torchvision.io.read_image(map_file, torchvision.io.ImageReadMode.GRAY)/255
    get_waypoints(map, 10, 5)


import collections
import itertools
import logging
import random
import string
import threading
import time
from typing import (
    Any,
    Callable,
    Dict,
    List,
    Mapping,
    Optional,
    Set,
    Tuple,
    Union,
)

import doorpi.actions
import doorpi.event

from . import log

LOGGER: doorpi.DoorPiLogger = logging.getLogger(__name__)  # type: ignore

ActionCallable = Callable[[str, Mapping[str, Any]], Any]
RegistrableAction = Union[str, "doorpi.actions.Action", ActionCallable]

def generate_id() -> str:
    """Generates a random event ID."""
    size = 6
    chars = "".join((string.ascii_uppercase, string.digits))
    return "".join(random.choice(chars) for _ in range(size))

class EventHandler:
    """The event handler and action dispatcher."""

    actions: Dict[str, List[ActionCallable]]
    events: Dict[str, Set[str]]
    extra_info: Dict[str, Any]
    sources: List[str]

    __active: bool

    def __init__(self) -> None:
        conf = doorpi.INSTANCE.config
        db_path = conf["eventlog"]
        self.log = log.EventLog(db_path)

        self.actions = collections.defaultdict(list)
        self.events = collections.defaultdict(set)
        self.extra_info = {"LastKey": "NotSetYet", "event": {}}
        self.sources = []
        self.__active = True

        # register eventbased actions from configfile
        for event, actions in conf.view("events").items():
            LOGGER.info("Registering configured actions for %s", event)
            for action in actions:
                LOGGER.debug("Registering action %s", repr(action))
                self.register_action(event, action)

        # register configured DTMF actions
        LOGGER.info("Registering DTMF actions")
        for seq, actions in conf.view("sipphone.dtmf").items():
            for action in actions:
                LOGGER.debug("Registering action %r for DTMF %r", action, seq)
                self.register_action(f"OnDTMF_{seq}", action)

    def destroy(self) -> None:
        """Shut down the event handler"""
        self.__active = False
        self.log.destroy()

    @property
    def event_history(self) -> Tuple[log.EventLogEntry, ...]:
        return self.log.get_event_log()

    @property
    def threads(self) -> List[threading.Thread]:
        """List event threads managed by the handler"""
        return [
            t
            for t in threading.enumerate()
            if t.name.startswith("DoorPi Event")
        ]

    @property
    def idle(self) -> bool:
        """Return whether the handler is currently idle"""
        return not self.threads

    def get_events_by_source(self, source: str) -> Set[str]:
        """Group all known events by the sources that can fire them"""
        return {ev for ev in self.events if source in self.events[ev]}

    def register_source(self, source: str) -> None:
        """Register a new event source"""
        if source not in self.sources:
            self.sources.append(source)
            LOGGER.debug("Added event source %s", source)

    def register_event(self, event: str, source: str) -> None:
        """Register an event to be fired from the named event source"""
        suppress_logs = _suppress_logs(event)
        if not suppress_logs:
            LOGGER.debug("Registering event %s with source %s", event, source)
        self.register_source(source)

        if source not in self.events[event]:
            self.events[event].add(source)
            if not suppress_logs:
                LOGGER.debug(
                    "Registered source %s for event %s", source, event
                )
        else:
            LOGGER.warning(
                "Multiple registrations for event %s from source %s",
                event,
                source,
            )

    def fire_event(
        self, event: str, source: str, *, extra: Dict[str, Any] = None
    ) -> None:
        """Fire an event asynchronously"""
        if not self.__active:
            return
        threading.Thread(
            target=self.fire_event_sync,
            args=(event, source),
            kwargs={"extra": extra},
            name=f"DoorPi Event {event} from {source}",
        ).start()

    def fire_event_sync(
        self, event: str, source: str, *, extra: Dict[str, Any] = None
    ) -> None:
        """Fire an event synchronously"""
        if not self.__active:
            return

        if extra is None:
            extra = {}
        suppress_logs = _suppress_logs(event)

        if source not in self.sources:
            LOGGER.warning(
                "Unknown event source %s, skipping %s", source, event
            )
            return
        if event not in self.events:
            LOGGER.warning(
                "Unknown event %s (from source %s), skipping", event, source
            )
            return
        if source not in self.events[event]:
            LOGGER.warning(
                "Source %s not registered for %s, skipping", source, event
            )
            return

        if event not in self.actions:
            if not suppress_logs:
                LOGGER.debug("No actions registered for %s, skipping", event)
            return

        event_id = generate_id()
        start_time = time.time()

        if not suppress_logs:
            self.log.log_event(event_id, source, event, start_time, extra)

        extra.update(
            {
                "last_fired": str(start_time),
                "source": source,
                "event_id": event_id,
            }
        )

        # copy over info from last event run
        last_info = self.extra_info.get(event, {})
        for key in ["last_finished", "last_duration"]:
            extra[key] = last_info.get(key, None)
        self.extra_info[event] = extra

        if not suppress_logs:
            LOGGER.debug(
                "[%s] Executing %d action(s) for %s",
                event_id,
                len(self.actions[event]),
                event,
            )

        oneshot_actions = []
        for action in self.actions[event]:
            try:
                if not suppress_logs:
                    LOGGER.debug("[%s] Executing %s", event_id, action)
                action(event_id, extra)
                if not suppress_logs:
                    self.log.log_action(event_id, str(action), start_time)
            except doorpi.event.AbortEventExecution:
                LOGGER.info("[%s] Aborting event execution early")
            except Exception:  # pylint: disable=broad-except
                try:
                    LOGGER.exception(
                        '[%s] Error executing action "%s" for event %s',
                        event_id,
                        action,
                        event,
                    )
                except Exception:  # pylint: disable=broad-except
                    LOGGER.exception("[%s] Error executing an action")

            if getattr(action, "oneshot", False):
                oneshot_actions.append(action)

        for action in oneshot_actions:
            self.actions[event].remove(action)

        if not suppress_logs:
            LOGGER.debug("[%s] Finished firing event %s", event_id, event)

        self.extra_info[event]["last_finished"] = time.time()
        self.extra_info[event]["last_duration"] = time.time() - start_time

    def _unregister_event(self, event: str, source: str) -> bool:
        suppress_logs = _suppress_logs(event)
        if not suppress_logs:
            LOGGER.debug(
                "Unregistering event %s from source %s", event, source
            )

        if event not in self.events:
            LOGGER.error("Attempt to unregister unknown event %s", event)
            return False

        if source not in self.events[event]:
            LOGGER.error(
                "Attempt to unregister unknown source %s from event %s",
                source,
                event,
            )
            return False

        self.events[event] -= {source}
        if not self.events[event]:
            del self.events[event]

        return True

    def unregister_event(self, event: str, source: str) -> None:
        """Unregister an event from a source"""
        if self._unregister_event(event, source):
            self.unregister_source(source, force=None)

    def unregister_source(
        self,
        source: str,
        *,
        force: Optional[bool] = False,
    ) -> None:
        """Unregister an event source

        Args:
            force: If True, unregisters a source even when it still has
                events associated.
        """
        LOGGER.debug(
            "Removing source %s%s", source, " with force" if force else ""
        )

        events = self.get_events_by_source(source)
        if events:
            if force is False:
                LOGGER.error(
                    "Attempt to unregister source %s,"
                    " which is used for %d events: %s",
                    source,
                    len(events),
                    ", ".join(events),
                )
            if not force:
                return

            for ev in events:
                self._unregister_event(ev, source)

        if source in self.sources:
            self.sources.remove(source)

    def register_action(
        self,
        event: str,
        action: RegistrableAction,
        *,
        oneshot: bool = False,
    ) -> None:
        """Register an action to execute when the ``event`` fires

        Args:
            oneshot: Only execute the action once and remove it afterwards
        """
        action_obj: Optional[ActionCallable]
        if isinstance(action, str):
            action_obj = doorpi.actions.from_string(action)
        elif callable(action):
            action_obj = action
        else:
            raise ValueError("action must be a str or callable")

        if action_obj is None:
            return

        self.actions.setdefault(event, []).append(action_obj)

        LOGGER.trace("Registered action %s for event %s", action, event)

    __call__ = fire_event

def _suppress_logs(event_name: str) -> bool:
    return "OnTime" in event_name


import time

from Bot.Plugins.Base import PluginBase

class ClientHistoryPlugin(PluginBase):
    """
    This plugin write the current timestamp + user count at that time in the database everytime the usercount changes.
    Useful to plot teamspeak activity.

    The plugin provides no commands.

    optional example json ( can be inserted in config.json under plugins ):

    "mydayyy_client_history": {
        "table_name": "MydayyyClientHistory"
    }
    """

    def __init__(self, bot_instance):
        super().__init__(bot_instance)

        self.mysql = bot_instance.get_mysql_instance()

        if self.mysql is None:
            print("ClientHistory requires mysql. Exiting.")
            exit()

        self.client_history_table = bot_instance.get_user_setting(
            "mydayyy_client_history.table_name") or "MydayyyClientHistory"

        self.setup_table()

    def on_initial_data(self, client_list, channel_list):
        self.insert_client_count(len(client_list))

    def on_client_joined(self, event):
        self.insert_client_count(len(self.bot_instance.get_clients()))

    def on_client_left(self, event):
        self.insert_client_count(len(self.bot_instance.get_clients())-1)

    # MYSQL FUNCTIONALITY
    def insert_client_count(self, count, timestamp=None):
        if timestamp is None:
            timestamp = time.time()
        query = "INSERT INTO `{0}` (Count, Timestamp) VALUES (%s, %s)".format(self.client_history_table)
        self.bot_instance.execute_query(query, count, timestamp)

    def setup_table(self):
        self.bot_instance.execute_query("SET sql_notes = 0;")

        query = "CREATE TABLE IF NOT EXISTS `{0}` (" \
                "`Id` int(11) NOT NULL AUTO_INCREMENT, " \
                "`Count` int(11) DEFAULT NULL, " \
                "`Timestamp` int(11) DEFAULT NULL, " \
                "PRIMARY KEY (`Id`))".format(self.client_history_table)

        self.bot_instance.execute_query(query)

        self.bot_instance.execute_query("SET sql_notes = 1;")


import fruits_menu
import csv

### csvファイルの読み込み
def set_item_master_csv(csv_file):
	with open(csv_file,encoding="utf_8",newline="") as items_csv:
		item_master = csv.reader(items_csv)
		next(item_master)
		# for文で、アイテム数分リストに.append
		L_items = []
		for item in item_master:
			L_items.append(fruits_menu.Item(item[0],item[1],int(item[2])))

	# 商品クラスの入ったリストを返す
	return L_items

### メイン処理
def main():
	# マスタ登録
	item_master = set_item_master_csv("item_master.csv")

	# オーダー登録
	order=fruits_menu.Order(item_master)
	order.add_item_order("001",1)
	order.add_item_order("002",1)
	order.add_item_order("003",1)

	# オーダー入力
	while True:
		print("\n---現在の注文状況---")
		order.view_item_master()

		while True:
			f_order=input("注文を追加しますか？(y/n)")
			if f_order == "n":
				break
			elif f_order == "y":
				#注文できる商品を表示
				input_code = input("注文する商品のコードを入力して下さい:")
				input_code = input_code.zfill(3)
				order_item = order.code_to(input_code)
				if order_item != False:
					try:
						print(order_item,end=" の")
						input_cnt = int(input("注文数を入力して下さい:"))
						if 0 < input_cnt < 100:
							order.add_item_order(input_code,input_cnt)
							break
						elif input_cnt> 99 :
							print("一度に100個以上注文する事はできません。")
					except ValueError:
						pass
					print("注文可能な数を入力して下さい。")

			else:
				print("y か n を入力して下さい：")
				continue
		if f_order == "n":
			print("・\n・\n・")
			order.view_item_master()
			f_order = input("ご注文は以上で宜しいですか？(y/n):")
			if f_order == "y":
				break

	# 支払い処理
	print(f"\n合計 {order.order_price}円になります。")
	while True:
		try:
			cash = int(input("お支払い金額を入力して下さい："))
			order.order_cash = cash
			if order.order_price == cash:
				print(f"{cash}円丁度、お預かりします。")
			elif order.order_price < cash:
				print(f"{cash}円、お預かりします。")
				print(f"お釣り {cash-order.order_price}円のお返しになります。")
			else:
				print("金額が足りません。")
				continue

			# レシート.txtを作成
			f_order = order.receipt_txt()
			if f_order != "Error":
				print("レシートのお渡しになります。" + f_order)
				print("ご注文、ありがとうございました！")
			else:
				print("注文が重複しています。")
			break
		except ValueError:
			print("入力された金額を認識できません。")
			pass

if __name__ == "__main__":
	main()


import xlrd

file_Location = "C:/Users/Dou/Desktop/公示公告成果/历史遗留矿山核查图斑数据2022-06-20 11_13.xls"
workbook = xlrd.open_workbook(file_Location)
sheet = workbook.sheet_by_name('Export')

curr_col = 5
goal_col = 6
k_col =10
col1 = sheet.col(curr_col)
col2 = sheet.col(goal_col)
col3 = sheet.col(k_col)

# 提取列数据
# for i in col1:
#     if i!=None:
#         it=i.value
#         print(it)

# 比较列数据
for i in col1:
    for j in col2:
        if i.value==j.value:
            print(i.value)

# 选择出长列中不等于短列的数据

# a = set(col1)
# b = set(col2)
# c = a - b
#
# for i in c:
#     print(i.value)


from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import datetime

from googlecloudsdk.api_lib.storage import cloud_api
from googlecloudsdk.api_lib.storage import errors as api_errors
from googlecloudsdk.command_lib.storage import errors as command_errors
from googlecloudsdk.command_lib.storage import manifest_util
from googlecloudsdk.command_lib.storage import storage_url
from googlecloudsdk.command_lib.storage.resources import resource_util
from googlecloudsdk.command_lib.storage.tasks import task
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
from googlecloudsdk.core import properties

_EARLY_DELETION_MINIMUM_DAYS = {
    'nearline': 30,
    'coldline': 90,
    'archive': 365,
}

class CopyTask(task.Task):
  """Parent task that handles common attributes and an __init__ status print."""

  def __init__(
      self,
      source_resource,
      destination_resource,
      posix_to_set=None,
      print_source_version=False,
      user_request_args=None,
      verbose=False,
  ):
    """Initializes task.

    Args:
      source_resource (resource_reference.Resource): Source resource to copy.
      destination_resource (resource_reference.Resource): Target resource to
        copy to.
      posix_to_set (PosixAttributes|None): POSIX info set as custom cloud
        metadata on target.
      print_source_version (bool): Print source object version in status message
        enabled by the `verbose` kwarg.
      user_request_args (UserRequestArgs|None): Various user-set values
        typically converted to an API-specific RequestConfig.
      verbose (bool): Print a "copying" status message on initialization.
    """
    super(CopyTask, self).__init__()
    self._source_resource = source_resource
    self._destination_resource = destination_resource
    self._posix_to_set = posix_to_set
    self._print_source_version = print_source_version
    self._user_request_args = user_request_args
    self._verbose = verbose

    self._send_manifest_messages = bool(
        self._user_request_args and self._user_request_args.manifest_path
    )

    if verbose:
      if print_source_version:
        source_string = source_resource.storage_url.url_string
      else:
        source_string = source_resource.storage_url.versionless_url_string
      log.status.Print(
          'Copying {} to {}'.format(
              source_string,
              destination_resource.storage_url.versionless_url_string,
          )
      )

class CopyTaskWithExitHandler(CopyTask):
  """Parent task that overrides exit handler for copy tasks."""

  def exit_handler(self, error=None, task_status_queue=None):
    """Send copy result info to manifest if requested."""
    if error and self._send_manifest_messages:
      if not task_status_queue:
        raise command_errors.Error(
            'Unable to send message to manifest for source: {}'.format(
                self._source_resource
            )
        )
      manifest_util.send_error_message(task_status_queue, self._source_resource,
                                       self._destination_resource, error)

def get_no_clobber_message(destination_url):
  """Returns standardized no clobber warning."""
  return 'Skipping existing destination item (no-clobber): {}'.format(
      destination_url)

def check_for_cloud_clobber(user_request_args, api_client,
                            destination_resource):
  """Returns if cloud destination object exists if no-clobber enabled."""
  if not (user_request_args and user_request_args.no_clobber):
    return False
  try:
    api_client.get_object_metadata(
        destination_resource.storage_url.bucket_name,
        destination_resource.storage_url.object_name,
        fields_scope=cloud_api.FieldsScope.SHORT)
  except api_errors.NotFoundError:
    return False
  return True

def get_generation_match_value(request_config):
  """Prioritizes user-input generation over no-clobber zero value."""
  if request_config.precondition_generation_match is not None:
    return request_config.precondition_generation_match
  if request_config.no_clobber:
    return 0
  return None

def raise_if_mv_early_deletion_fee_applies(object_resource):
  """Raises error if Google Cloud Storage object will incur an extra charge."""
  if not (properties.VALUES.storage.check_mv_early_deletion_fee.GetBool() and
          object_resource.storage_url.scheme is storage_url.ProviderPrefix.GCS
          and object_resource.creation_time and
          object_resource.storage_class in _EARLY_DELETION_MINIMUM_DAYS):
    return

  minimum_lifetime = _EARLY_DELETION_MINIMUM_DAYS[
      object_resource.storage_class.lower()]
  creation_datetime_utc = resource_util.convert_datetime_object_to_utc(
      object_resource.creation_time)
  current_datetime_utc = resource_util.convert_datetime_object_to_utc(
      datetime.datetime.now())

  if current_datetime_utc < creation_datetime_utc + datetime.timedelta(
      days=minimum_lifetime):
    raise exceptions.Error(
        ('Deleting {} may incur an early deletion charge. Note: the source'
         ' object of a mv operation is deleted.\nThe object appears to have'
         ' been created on {}, and the minimum time before deletion for the {}'
         ' storage class is {} days.\nTo allow deleting the object anyways, run'
         ' "gcloud config set storage/check_mv_early_deletion_fee False"'
        ).format(object_resource, object_resource.creation_time,
                 object_resource.storage_class, minimum_lifetime))


from collections import defaultdict
from gtnlplib.clf_base import predict,make_feature_vector,argmax

def perceptron_update(x,y,weights,labels):
    """compute the perceptron update for a single instance

    :param x: instance, a counter of base features and weights
    :param y: label, a string
    :param weights: a weight vector, represented as a dict
    :param labels: set of possible labels
    :returns: updates to weights, which should be added to weights
    :rtype: defaultdict

    """
    y_hat, scores = predict(x, weights, labels)
    f_x_y = make_feature_vector(x, y)
    f_x_y_hat = make_feature_vector(x, y_hat)

    update = defaultdict(float)

    diffKeys = set(f_x_y.keys()) - set(f_x_y_hat.keys())

    for key in diffKeys:
        update[key] = f_x_y.get(key)

    diffKeys = set(f_x_y_hat.keys()) - set(f_x_y.keys())

    for key in diffKeys:
        update[key] = 0.0 - f_x_y_hat.get(key)

    return update

def estimate_perceptron(x,y,N_its):
    """estimate perceptron weights for N_its iterations over the dataset (x,y)

    :param x: instance, a counter of base features and weights
    :param y: label, a string
    :param N_its: number of iterations over the entire dataset
    :returns: weight dictionary
    :returns: list of weights dictionaries at each iteration
    :rtype: defaultdict, list

    """
    labels = set(y)
    weights = defaultdict(float)
    weight_history = []
    for it in xrange(N_its):

        for x_i,y_i in zip(x,y):

            new_weight = perceptron_update(x_i,y_i,weights,labels)

            for key in new_weight.keys():
                weights[key] = weights[key] + new_weight[key]

        weight_history.append(weights.copy())
    return weights, weight_history

def estimate_avg_perceptron(x, y, N_its):
    """estimate averaged perceptron classifier

    :param x: instance, a counter of base features and weights
    :param y: label, a string
    :param N_its: number of iterations over the entire dataset
    :returns: weight dictionary
    :returns: list of weights dictionaries at each iteration
    :rtype: defaultdict, list

    """
    labels = set(y)
    w_sum = defaultdict(float)  # hint
    avg_weights = defaultdict(float)
    weight_history = []

    t = 1.0  # hint
    for it in xrange(N_its):
        for x_i, y_i in zip(x, y):
            weight_new = perceptron_update(x_i, y_i, avg_weights, labels)

            for key in weight_new.keys():
                w_sum[key] = w_sum[key] + weight_new[key] * t
                avg_weights[key] = avg_weights[key] + weight_new[key]

            t = t + 1
        weight_history.append(avg_weights.copy())

    for key in w_sum.keys():
        avg_weights[key] = avg_weights[key] - (w_sum[key] / t)

    return avg_weights, weight_history


import csv
from my_utils import fRead

def genRChangeHistogram (dstFilename, srcFilename, nNodes, dstMac, binWidth = 200):
    # Initialization of local variables
    convFactor = 1
    retransmitterDict = {}
    binStart = 0
    # Initialization of Counters per Bin
    totalRChangeCounter = 0
    rChangeCountList = [ 0 for i in range(nNodes) ]

    dictReport = fRead.get_csvdict (srcFilename)
    try:
        record = next (dictReport)
    except:
        print("No routes found, skipping generation of histogram file")
        return 0
    # Determine units of time and set convFactor variable
    timeStr = record['Time']
    timeUnit = timeStr[-2:]
    if timeUnit == 'ns':
        convFactor = 1000000
    elif timeUnit == 'us':
        convFactor = 1000
    # Process first record
    time = float(timeStr[:-2]) / convFactor
    binStart = (time // binWidth) * binWidth
    binEnd = binStart + binWidth
    node = int(record['Node'])
    # We don't care if the route change correspond to a destination different to the one with mac dstMac
    if record['Destination'] == dstMac:
        retransmitterDict[node] = record['Retransmitter']
        rChangeCountList[node] += 1
        totalRChangeCounter += 1
    # Create headers row for output csv file
    row = ['Start', 'End'] +  ['Node-{0:02d}'.format(i) for i in range (nNodes)]

    with open(dstFilename, 'w', newline='') as csvfile:
        filewriter = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
        filewriter.writerow(row)
        for record in dictReport:
            time = float(record['Time'][:-2])/convFactor
            while time > binEnd:
                filewriter.writerow ([binStart, binEnd] + rChangeCountList)
                rChangeCountList = [ 0 for i in range(nNodes) ]
                binStart = binEnd
                binEnd = binStart + binWidth
            if record['Destination'] == dstMac:
                node = int(record['Node'])
                if (node in retransmitterDict and retransmitterDict[node] != record['Retransmitter']) or (node not in retransmitterDict):
                     retransmitterDict[node] = record['Retransmitter']
                     rChangeCountList[node] += 1
                     totalRChangeCounter += 1
        filewriter.writerow ([binStart, binEnd] + rChangeCountList)
    return totalRChangeCounter

# import fRead.def myfunc():
#     doc = "The myfunc property."
#     def fget(self):
#         return self._myfunc
#     def fset(self, value):
#         self._myfunc = value
#     def fdel(self):
#         del self._myfunc
#     return locals()
# myfunc = property(**myfunc())


# -*- coding: utf-8 -*-
"""
Created on Wed Oct 28 19:41:28 2020

@author: arkad
"""
from copy import deepcopy

def info_check(info):
    """ Funkcja do wprowadzenia danych rna/dna/bialek

            Args:
                response (str) : "dna"/"rna"/"bialko"
                info (str) : ciag znaków
            Returns:
                info (str): ciag dna/rna/bialek
    """
    if not isinstance(info, str):
        raise TypeError("Błędny typ danych")
    if info is None or info is '':
        raise TypeError("Brak danych do sprawdzenia")
    info = info.upper()
    z=0
    while z < (len(info)):
        if info[z].upper() not in ['A', 'C', 'G', 'T']: # sprawdzenie czy znaki są poprawne
            raise ValueError("Błędnie podana sekwencja DNA")
        else:
            z+=1
    return info

def aub(tab_napis1,tab_napis2):
    """ Funkcja znajdująca częsc wszystkie mozliwe n-gramy tablic n-gramow

            Args:
                tab_napis1 (list): tablica n-gramow pierwszego wyrazu
                tab_napis2 (list): tablica n-gramow drugiego wyrazu
            Returns:
                anb (list): tablica wszyskich mozliwych ngramow wyrazow dla kolejno (2-gramów, 3-gramów i 4-gramów)
    """

    if not isinstance(tab_napis1, list) or not isinstance(tab_napis2, list):
        raise TypeError("Błędny typ danych")
    for i in tab_napis1:
        for z in i:
            if not isinstance(z, str):
                raise ValueError("Błędny typ danych")
    for i in tab_napis2:
        for z in i:
            if not isinstance(z, str):
                raise ValueError("Błędny typ danych")

    aub = []
    i_napis1 = 0
    while i_napis1 <= (len(tab_napis1)-1):
        if tab_napis1[i_napis1] not in aub:
            aub.append(tab_napis1[i_napis1]) #napierw dodajemy wszystkie wyrazy pierwszego napisu
        i_napis1+=1

    i_aub = 0
    i_napis2 = 0
    while i_aub <= (len(aub)-1):
        while i_napis2 <= (len(tab_napis2)-1):
            tab_pomoc = deepcopy(tab_napis2[i_napis2]) #tworzę nową tablice z tymi samymi wartosciami
            i_pomoc = 0
            while i_pomoc <= (len(tab_pomoc)-1):
                if tab_pomoc[i_pomoc] not in aub[i_aub]:
                    aub[i_aub].append(tab_pomoc[i_pomoc]) #dopisuję do tablicy aub wartosci z tablicy tab_napis2 ktorych nie ma w tab_napis1
                i_pomoc+=1
            i_aub+=1
            i_napis2+=1
    return aub

def anb(tab_napis1,tab_napis2):
    """ Funkcja znajdująca częsc wspolna tablic n-gramow

            Args:
                tab_napis1 (list): tablica n-gramow pierwszego wyrazu
                tab_napis2 (list): tablica n-gramow drugiego wyrazu
            Returns:
                aub (list): tablica czesci wspolnej ngramow wyrazow dla kolejno (2-gramów, 3-gramów i 4-gramów)
    """
    if not isinstance(tab_napis1, list) or not isinstance(tab_napis2, list):
        raise TypeError("Błędny typ danych")
    for i in tab_napis1:
        for z in i:
            if not isinstance(z, str):
                raise ValueError("Błędny typ danych")
    for i in tab_napis2:
        for z in i:
            if not isinstance(z, str):
                raise ValueError("Błędny typ danych")
    anb = []
    anb_pomoc = []
    i_anb=0
    while i_anb<=(len(tab_napis1)-1):
        tab_pomoc1 = deepcopy(tab_napis1[i_anb])
        tab_pomoc2 = deepcopy(tab_napis2[i_anb])
        i_pomoc1 = 0
        i_pomoc2 = 0
        while i_pomoc1 <= (len(tab_pomoc1)-1):
            while i_pomoc2 <= (len(tab_pomoc2)-1):
                if tab_pomoc2[i_pomoc2] == tab_pomoc1[i_pomoc1]:
                    if tab_pomoc2[i_pomoc2] not in anb_pomoc:
                        anb_pomoc.append(tab_pomoc2[i_pomoc2]) #dopisywane do tablicy anb_pomoc sa wartosci ktore znajduja sie w obu tablicach poczatkowych i nie sa juz w tablicy anb
                i_pomoc2+=1
            i_pomoc2=0
            i_pomoc1+=1
        anb.append(anb_pomoc) #anb_pomoc do anb
        anb_pomoc = []
        i_anb+=1
    return anb

def jaccard(aub, anb):
    """ Funkcja obliczajaca prawdopodobienstwo jaccarda

            Args:
                aub (list): tablica wszyskich mozliwych n-gramow obu wyrazow
                anb (list): tablica wspolnych n-gramow obu wyrazow
            Returns:
                J (list): tablica podobieństw jaccarda dla kolejno (2-gramów, 3-gramów i 4-gramów)
    """
    J = []
    i = 0
    while i<=(len(aub)-1):
        jac = len(anb[i])/len(aub[i]) #proste obliczenie
        J.append(jac)
        i+=1
    return J

def ngramy(napis1,napis2,min_dlugosc_wyrazow,max_dlugosc_wyrazow):
    """ Funkcja dzieląca wyrazy na n-gramy, znajdująca ich częsc wspólną oraz
        wszyskie możliwe n-gramy a następnie obliczajaca prawdopodobienstwo jaccarda

            Args:
                napis1 (str): dowolny ciąg zanków
                napis2 (str): dowolny ciag znaków
                min_dlogosc_wyrazow (int) : dlugosc najmniejszego ngramu
                max_dlugosc_wyrazow (int) : maksymalna dlugosc ngramow
            Returns:
                ngramy (list): tablica ngramow o podanych dlugosciach (np. 2-gramów, 3-gramów i 4-gramów)
    """
    if not isinstance(napis1, str) or not isinstance(napis2, str):
        raise TypeError("Błędny typ danych")
    if min_dlugosc_wyrazow>max_dlugosc_wyrazow:
        raise ValueError("Błąd podczas podawania parametrów")
    if len(napis1)<max_dlugosc_wyrazow or len(napis2)<max_dlugosc_wyrazow:
        raise IndexError("Zbyt krótka długosc słowa na podany podział")

    temp_min = min_dlugosc_wyrazow
    temp_max = max_dlugosc_wyrazow

    #podzial napisu1 na n-gramy i dopisanie ich do tablicy tab_napis1
    tab_napis1 = []
    while min_dlugosc_wyrazow<=max_dlugosc_wyrazow: #do n-rgamow o dlugosci 4
        tab1=[]
        i=0
        while i<=(len(napis1)-1):
            if len(napis1[i:(i+min_dlugosc_wyrazow)])> (min_dlugosc_wyrazow-1):
                if napis1[i:(i+min_dlugosc_wyrazow)] not in tab1:
                    tab1.append(napis1[i:(i+min_dlugosc_wyrazow)]) #dodanie do tablicy n-gramow
            i+=1
        tab_napis1.append(tab1)
        min_dlugosc_wyrazow+=1

    #podzial napisu2 na n-gramy i dopisanie ich do tablicy tab_napis2
    min_dlugosc_wyrazow =  temp_min
    max_dlugosc_wyrazow = temp_max
    tab_napis2 = []
    while min_dlugosc_wyrazow<=max_dlugosc_wyrazow:
        tab2=[]
        i=0
        while i<=(len(napis2)-1):
            if len(napis2[i:(i+min_dlugosc_wyrazow)])> (min_dlugosc_wyrazow-1):
                if napis2[i:(i+min_dlugosc_wyrazow)] not in tab2:
                    tab2.append(napis2[i:(i+min_dlugosc_wyrazow)])
            i+=1
        tab_napis2.append(tab2)
        min_dlugosc_wyrazow+=1
    ngramy = [tab_napis1, tab_napis2]
    return ngramy


# -*- coding: utf-8 -*-
from common.models.pay.PayOrder import  PayOrder
from common.libs.Helper import getFormatDate
from common.libs.pay.PayService import PayService
import datetime
from application import app,db
'''
python manager.py runjob -m pay/index
'''

class JobTask():
	def __init__(self):
		pass
	def run(self,params):
		now = datetime.datetime.now()
		date_before_30min = now + datetime.timedelta( minutes = -30 )
		list = PayOrder.query.filter_by( status = -8 ).\
			filter( PayOrder.created_time <= getFormatDate( date = date_before_30min ) ).all()
		if not list:
			app.logger.info("no data~~")
			return

		pay_target = PayService()
		for item in list:
			pay_target.closeOrder( pay_order_id = item.id )
		app.logger.info("it's over~~")