## time-tracker-webservice  solution
import flask
import pprint

app = flask.Flask(__name__)

tasks = [
    {
        'id': 1,
        'name': u'fixing bug #1',
        'time_spent': 20  # in mins
    },
    {
        'id': 2,
        'name': u'customer support',
        'time_spent': 30
    }
]

# find the task from the list, None if not found
def find_task(task_id):
    for task in tasks:
        if task['id'] == task_id:
            return task

@app.route('/')
def index():
    ret_value = {'status' : 'ok'}
    return flask.jsonify(ret_value)

## ----------- list all tasks --------
@app.route('/tasks/', methods=['GET'])
@app.route('/tasks/list', methods=['GET'])
def get_tasks_list():
    ## TODO
    ## Hint : set tasks as 'tasks'
    ret_value = {'status' : 'ok',\
                 'tasks' : '???'}
    if app.debug:
        print("get_tasks_list:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
    return flask.jsonify(ret_value)
## ----------- end: list all tasks --------

## ----------- get ONE task --------
@app.route('/task/<int:task_id>', methods=['GET'])
def get_task(task_id):
    ret_value = {}
    task = find_task(task_id)
    if task:
        ## TODO : set task to the found task
        ## Hint :
        ret_value['status'] = 'ok'
        ret_value['task'] = '???'
    else:
        ret_value['status'] = 'error'
        ret_value['description'] = 'no task with id {}'.format(task_id)
        #flask.abort(404)

    if app.debug:
        print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
    return flask.jsonify(ret_value)
## ----------- end: get ONE task --------

## ----------- create new task --------
@app.route('/task/new', methods=['POST'])
def create_task():
    ret_value = {}
    if not flask.request.json or not 'name' in flask.request.json:
        ret_value['status'] = 'error'
        ret_value['description'] = "need 'name' for task"
    else: # create a new task
        ## TODO : create a task
        ## Hint : name = flask.request.json['name']
        ## Hint : time_spent = 0
        task =  {
            'id': tasks[-1]['id'] + 1,
            'name': '???',
            'time_spent' : '???'
        }

        ## TODO : append the newly created task to the tasks list
        ## Hint : append
        # tasks.???(task)

        ret_value['status'] = 'ok'
        ret_value['task'] = task

    if app.debug:
        print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
    return flask.jsonify(ret_value)
## ----------- end: create new task --------

## ----------- update a task --------
@app.route('/task/update/<int:task_id>', methods=['PUT', 'POST'])
def update_task(task_id):
    ret_value = {}
    task = find_task(task_id)
    if not task:
        ret_value['status'] = 'error'
        ret_value['description'] = 'no task with id {}'.format(task_id)
        if app.debug:
            print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
        return flask.jsonify(ret_value)
        #flask.abort(404)
    if not flask.request.json:
        ret_value['status'] = 'error'
        ret_value['description'] = 'missing parameters'
        if app.debug:
            print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
        return flask.jsonify(ret_value)

    if not 'time' in flask.request.json:
        ret_value['status'] = 'error'
        ret_value['description'] = "missing 'time'"
        if app.debug:
            print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
        return flask.jsonify(ret_value)

    # now update the task
    time = flask.request.json['time']
    ## TODO : add time to time_spent below
    # task ['time_spent'] += int(???)

    ret_value['status'] = 'ok'
    ret_value['task'] = task
    if app.debug:
        print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
    return flask.jsonify(ret_value)
## ----------- end : update a task --------

## ----------- delete a task --------
@app.route('/task/delete/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
    task = find_task(task_id)
    if not task:
        ret_value = { 'status' : 'error',
                      'description' : 'no task with id {}'.format(task_id)}
        if app.debug:
           print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
        return flask.jsonify(ret_value)
        #flask.abort(404)

    ## TODO : remove the task from tasks list below
    ## hint : remove
    # tasks.???(task)
    ret_value = { 'status' : 'ok',
                  'description' : 'removed task id {}'.format(task_id)}
    if app.debug:
        print("get_task:Returning \n{}".format(pprint.pformat(ret_value, indent=4)))
    return flask.jsonify(ret_value)
## ----------- end : delete a task --------

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


# 测试自动发送QQ消息

import win32gui
import win32api
import win32con
import win32clipboard as w
import time

def send(name, msg):
    #打开剪贴板
    w.OpenClipboard()
    #清空剪贴板
    w.EmptyClipboard()
    #设置剪贴板内容
    w.SetClipboardData(win32con.CF_UNICODETEXT, msg)
    #获取剪贴板内容
    date = w.GetClipboardData()
    #关闭剪贴板
    w.CloseClipboard()
    #获取qq窗口句柄
    handle = win32gui.FindWindow(None, name)
    if handle == 0:
        print('未找到窗口！')
    #显示窗口
    win32gui.ShowWindow(handle,win32con.SW_SHOW)
    # win32gui.ShowWindow(handle,win32con.SW_SHOWNORMAL)
    #把剪切板内容粘贴到qq窗口
    win32gui.SendMessage(handle, win32con.WM_PASTE, 0, 0)
    #按下后松开回车键，发送消息
    win32gui.SendMessage(handle, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
    win32gui.SendMessage(handle, win32con.WM_KEYUP, win32con.VK_RETURN, 0)
    time.sleep(2)#延缓进程

def main():
    name = 'hdfx_聊天' #QQ聊天窗口的名字
    print('开始')
    for i in range(1,2):
    # send(name, '第'+str(i)+'次测试')
        send(name,'测试一下' + str(i))
    print('结束')

main()


'''
    - BFS 이용
    - python3 시간초과, pypy3 통과
    - python3 넘길 수 있도록 재풀이 필요
'''

import sys
from collections import deque

N, M = map(int, sys.stdin.readline().split())
table = [list(map(int, sys.stdin.readline().split())) for _ in range(N)]
max_val = float('-inf')

for i in range(0, N):
    for j in range(0, M):
        q = deque([(i, j, i, j, table[i][j])])
        count = 0
        while q:
            if count == 3:
                break
            for _ in range(len(q)):
                x, y, px, py, v = q.popleft()
                for a, b in (0, 1), (1, 0), (0, -1), (-1, 0):
                    if 0 <= x + a < N and 0 <= y + b < M:
                        if x + a == px and y + b == py:
                            continue
                        else:
                            q.append((x + a, y + b, x, y, table[x + a][y + b] + v))
            count += 1

        # BFS로 가려낼 수 없는 케이스 : 'ㅗ' 모양 테크노미로
        expt_case = []
        for a, b in (0, 1), (1, 0), (0, -1), (-1, 0):
            if 0 <= i + a < N and 0 <= j + b < M:
                if a == 0 and b == 1:
                    if 0 <= i + a - 1 < N and 0 <= i + a + 1 < N:
                        expt_case.append(
                            table[i][j] + table[i + a][j + b] + table[i + a - 1][j + b] + table[i + a + 1][j + b])
                elif a == 1 and b == 0:
                    if 0 <= j + b - 1 < M and 0 <= j + b + 1 < M:
                        expt_case.append(
                            table[i][j] + table[i + a][j + b] + table[i + a][j + b - 1] + table[i + a][j + b + 1])
                elif a == 0 and b == -1:
                    if 0 <= i + a - 1 < N and 0 <= i + a + 1 < N:
                        expt_case.append(
                            table[i][j] + table[i + a][j + b] + table[i + a - 1][j + b] + table[i + a + 1][j + b])
                else:
                    if 0 <= j + b - 1 < M and 0 <= j + b + 1 < M:
                        expt_case.append(
                            table[i][j] + table[i + a][j + b] + table[i + a][j + b - 1] + table[i + a][j + b + 1])
        if expt_case:
            val = max(max(list(q), key=lambda x: x[4])[4], max(expt_case))
        else:
            val = max(list(q), key=lambda x: x[4])[4]
        if val > max_val:
            max_val = val

print(max_val)


import socket
import os

class Client():

    def __init__(self,):
        self.s = self.connect()
        self.s.settimeout(0.1)
        self.parse_reply()

    def connect(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(('192.168.100.5', 1234))
        return s

    def parse_reply(self):
        rep = ""
        try:
            while True:
                data = self.s.recv(1024).strip()
                if not data:
                    break
                reply = data.decode('utf-8')
                print(reply)
                rep = rep + reply
        except socket.timeout:           #TEMPORARY SOLUTION
            pass
        except socket.error as e:
            print(str(e) + " UNHANDLED ERROR")
        finally:
            return rep

    def sendall(self, command):
        self.s.sendall(str.encode(command))

    def DOWNLOAD(self, file_name):
        self.sendall("DOWNLOAD")
        self.parse_reply()
        file_name = file_name.split()
        self.sendall(file_name[0])
        f = open(file_name[1], 'wb')  # open in binary
        try:
            l = self.s.recv(1024)
            if l.decode('utf-8') == "File not found":
                print("file not found")
                os.remove(file_name[1])
                return
            while l:
                f.write(l)
                l = self.s.recv(1024)
        except socket.timeout:
            pass
        finally:
            f.close()

    def UPLOAD(self, file_names):
        self.sendall("UPLOAD")
        self.parse_reply()
        file_name = file_names.split()
        try:
            f = open(file_name[0], 'rb')  # open in binary
            self.sendall(file_name[1])
            self.s.recv(1024)
            while True:
                l = f.read(1024)
                if not l:
                    f.close()
                    break
                self.s.send(l)
        except socket.timeout:
            f.close()
        except FileNotFoundError:
            self.sendall("File not found")
            print("File not found")
        self.s.recv(1024)

    def LS(self):
        self.sendall("LS")
        return self.parse_reply()

    def QUIT(self, answer):
        self.sendall("QUIT")
        self.parse_reply()
        self.sendall(answer)

    def CD(self, directory):
        self.sendall("CD")
        self.parse_reply()
        self.sendall(directory)
        return self.parse_reply()

    def PWD(self):
        self.sendall("PWD")
        return self.parse_reply()

    def __dir(self, statment, name):
        self.sendall(statment)
        self.parse_reply()
        self.sendall(name)
        return self.parse_reply()

    def MKDIR(self, name_of_folder):
        self.__dir("MKDIR", name_of_folder)

    def RMDIR(self, dir):
        self.__dir("RMDIR", dir)

    def CP(self, from_to):
        self.__dir("CP", from_to)

    def RM(self, dir):
        self.__dir("RM", dir)

    def MV(self, dir):
        self.__dir("MV", dir)

    def RENAME(self, dir):
        self.__dir("RENAME", dir)

    def ISFILE(self, dir):
        return self.__dir("ISFILE", dir)

if __name__ == '__main__':
    Client()


import pickle, h5py

h5fille = 'datasets/VG_GQA/GQA_imdb_1024.h5'
resultfile = 'results/predictions.pl'
with open(resultfile, 'rb') as f:
    data = pickle.load(f)

h5f = h5py.File(h5fille, 'r')
for i, ids in enumerate(h5f['image_ids']):
    index = ids.decode("utf-8")
    data[index]['image_heights'] = h5f['image_heights'][i]
    data[index]['image_widths'] = h5f['image_widths'][i]
    data[index]['original_heights'] = h5f['original_heights'][i]
    data[index]['original_widths'] = h5f['original_widths'][i]

newfile = 'results/predictions_new.pl'
with open(newfile, 'wb') as f:
    pickle.dump(data, f)


import base64
import krakenex
import decimal
import time
import pandas as pd
pd.options.mode.chained_assignment = None
import os
import sqlite3
import sys
import kraken_data as kd

class KrakenStrategy(object):
    """ Backtesting module for kraken investment strategies
    """

    def __init__(self,pair,interval,now=time.time()):
        """Return an analysis object
        """
        self.k = krakenex.API()
        self.pair = pair
        self.interval = interval
        self.now = now

        self.kd = kd.KrakenData()

        if os.name == 'nt':
            self.k.load_key(r'C:\krak\kraken.key')
        elif os.name == 'posix':
            self.k.load_key(r'/home/ngs90/Dokumenter/krak/kraken.key')

    def simple_strategy(self):
        pair = self.pair
        interval =self.interval
        now = self.now
        kd = self.kd

        h = kd.GetHistorical(pair=pair,
                            interval=interval,
                            since=0,now=now)

        #print(h)
        p = kd.GetTickerPair(pair=pair, now=now)
        #print(p)

        #sys.exit()

        # Calculate returns for all subintervals of form [interval_start+i,interval_end] for i in [0,interval_end-interval_start]
        h['return'] = h['price_close'].apply(lambda x: float(p) / float(x) - 1)

        #print(h)

        # Get the current time
        now = time.time()

        # Timestamps important for buy signals
        t1, s1 = now, now
        tx = now - 60 * 60 * 10 # 24 hours ago
        txx = now - 60 * 60 * 5 # 12 hours ago
        ty = now - 60 * 60 * 2  # 2 hours
        tyy = now - 60 * 30  # 30 minuts ago

        # Timestamps important for sell signals
        sx = now - 60 * 60 * 12  # 12 hours ago
        sxx = now - 60 * 60 * 6 # 6 hours ago
        sy = now - 60 * 60 * 4  # 4 hours ago
        syy = now - 60 * 60 * 1  # 1 hour ago

        # Limits
        x = 0 #-0.05  # check if fallen more than x%
        y = 0 #0.01  # check if risen more than y%

        z = 0 #0.05  # check if risen more than z%
        v = 0 #0  # check if risen less than v%

        #print('Strategy:')
        #print('     Buy: ')
        ##print('         Timewindow: '+str(time.ctime(decimal.Decimal(t0)))+' and '+str(time.ctime(decimal.Decimal(t1))))
        #print('         IF')
        #print('             Exists return less than '+str(x)+' for a timeinterval between now ('+str(time.ctime(now))+') and a point within the following interval: '+str(time.ctime(decimal.Decimal(tx)))+' and '+str(time.ctime(decimal.Decimal(txx))))
        #print('         AND IF')
        #print('             Exists return larger than '+ str(y) +' for a timeinterval between now (' + str(time.ctime(now)) + ') and a point within the following interval: ' + str(time.ctime(decimal.Decimal(ty))) + ' and ' + str(time.ctime(decimal.Decimal(tyy))))
        #print('     Sell:')
        ##print('         Timewindow: '+str(time.ctime(decimal.Decimal(s0)))+' and '+str(time.ctime(decimal.Decimal(s1))))
        #print('         IF')
        #print('             Exists return larger than '+str(z)+' for a timeinterval between now ('+str(time.ctime(now))+') and a point within the following interval:  '+str(time.ctime(decimal.Decimal(sx)))+' and '+str(time.ctime(decimal.Decimal(sxx))))
        #print('         AND IF')
        #print('             Exists return less than '+str(v)+' for a timeinterval between now ('+str(time.ctime(now))+') and a point within the following interval:  '+str(time.ctime(decimal.Decimal(sy)))+' and '+str(time.ctime(decimal.Decimal(syy))))

        h_tx = h[(h['timestamp_id'] > tx) & (h['timestamp_id'] < txx)]
        h_ty = h[(h['timestamp_id'] > ty) & (h['timestamp_id'] < tyy)]
        h_sx = h[(h['timestamp_id'] > sx) & (h['timestamp_id'] > sxx)]
        h_sy = h[(h['timestamp_id'] > sy) & (h['timestamp_id'] < syy)]

        h_tx['check'] = h_tx['return'] < x
        h_ty['check'] = h_ty['return'] > y
        h_sx['check'] = h_sx['return'] > z
        h_sy['check'] = h_sy['return'] < v

        #print(now)
        #print(h['timestamp_id'] > tx)
        #print(txx,tx)
        #print(h['timestamp_id'])

        action = []

        if ((h_tx['check'] == True).any() & (h_ty['check'] == True).any()):
            #print('We buy beucase of the following data:')
            #print('Check if return >' + str(x))
            #print(h_t0[h_t0['return'] > x])
            #print('Check if return <' + str(y))
            #print(h_tx[h_tx['return'] < y])
            #print('Now we buy!')
            action.append('buy')

        elif ((h_sx['check'] == True).any() & (h_sy['check'] == True).any()):
            #print('We sell because of the following data:')
            #print('Check if return >' + str(z))
            #print(h_s0[h_s0['return'] > z])
            #print('Check if return <' + str(v))
            #print(h_sx[h_sx['return'] < v])
            #print('Now we sell!')
            action.append('sell')

        else:
            action.append('none')

        print(h_tx['check'])
        print(h_ty['check'])
        print(h_sx['check'])
        print(h_sy['check'])

        #h['check1'] = h['price_close'].apply(lambda x: float(p) / float(x) - 1 > 0.05)
        #h['check1'] = h['price_close'].apply(lambda x: float(p) / float(x) - 1 > 0.05)

        return action

if __name__ == '__main__':
    print('kraken strategy:')
    #pair = 'XXBTZEUR'
    pair = 'XETCZEUR'
    interval = 30  # in minutes
    now = time.time() #- 60*60*24*10
    #print(now)
    #print(time.ctime(now))

    #ks = KrakenStrategy(pair=pair, interval=interval, now=now)
    #ks.simple_strategy()

    #kd_temp = kd.KrakenData()
    #x = kd_temp.GetHistorical(pair=pair,interval=interval)
    #print(x)

    ks = KrakenStrategy(pair=pair, interval=interval, now=now)
    x = ks.simple_strategy()
    print(x)

    #sys.exit()

    for my_now in range(int(now)-60*60*24*10,int(now),60*interval):
        ks = KrakenStrategy(pair=pair, interval=interval, now=my_now)
        x = ks.simple_strategy()
        print(my_now,'Actions: '+str(x))


import jax.numpy as np
from .halfedge_lengths import halfedge_lengths_squared

def tip_angles(V, F):
	'''
	TIP_ANGLES computes the tip angles of a mesh (the angle at every corner)

	Inputs:
	V: (|V|,3) numpy ndarray of vertex positions
	F: (|F|,3) numpy ndarray of face indices

	Outputs:
	A: (|F|,3) numpy ndarray of tip angles at each corner of each face (in [0,pi))
	'''

	return tip_angles_intrinsic(halfedge_lengths_squared(V,F))

def tip_angles_intrinsic(l_sq):
	'''
	TIP_ANGLES_INTRINSIC computes the tip angles of a mesh (the angle at every
						 corner) given squared halfedge lengths

	Inputs:
	l_sq: (|F|,3) numpy ndarray of squared halfedge lenghts.
			   Our halfedge convention identifies each halfedge by the index
			   of the face and the opposite vertex within the face:
			   (face, opposite vertex)

	Outputs:
	A: (|F|,3) numpy ndarray of tip angles at each corner of each face (in [0,pi))
	'''

	#Use the cosine rule
	a_sq = np.expand_dims(l_sq[:,0], axis=1)
	b_sq = np.expand_dims(l_sq[:,1], axis=1)
	c_sq = np.expand_dims(l_sq[:,2], axis=1)
	a = np.sqrt(a_sq)
	b = np.sqrt(b_sq)
	c = np.sqrt(c_sq)

	cos_angles = np.concatenate((
			(b_sq + c_sq - a_sq) / (2.*b*c),
			(a_sq + c_sq - b_sq) / (2.*a*c),
			(a_sq + b_sq - c_sq) / (2.*a*b)
		), axis=1).clip(-1,1)

	return np.arccos(cos_angles)


from bittrex_arbitrage_client import BittrexArbitrageClient
from bithumb_arbitrage_client import BithumbArbitrageClient
from arbitrage_finder import ArbitrageFinder
from utils import Trade, TradeStage
import datetime
import time
from math import *
import sys
import json
import os

def load_keys(path):
    with open(path) as key_file:
        keys = key_file.readlines()

    keys = [key.strip() for key in keys]

    return keys

def monitor_arbitrage(key_folder_path):
    #load API keys
    bittrex_keys = load_keys(key_folder_path+'/bittrex_keys.txt')
    bithumb_keys = load_keys(key_folder_path+'/bithumb_keys.txt')

    #contants
    ARBITRAGE_OPPORTUNITY_WAIT_MIN = 60*24 #search for arbitrage oppertunities for a day at most
    PROFIT_THRESHOLD = .012
    PRINT_TOP_TRADES = True
    LOOPS = 20

    print("Setting Up Exchanges")
    #exchange constants
    DEBUG = True

    #instanciate exchanges
    bittrexName = 'bittrex'
    bittrexBaseCurrencies = ['BTC'] #ETH and XMR are also base currencies but we'll experiment with this later
    bittrexTradableCurrencies = ['BTC','ETH','ETC','LTC','DASH'] #XRP has a minimum amt which an address can hold (this may cause issues... avoid for now)
    bittrexMinFunds = 50 # 50 USD
    isStartingExchange = True
    bittrexArbitrageClient = BittrexArbitrageClient(bittrex_keys[0],
        bittrex_keys[1],
        bittrexName,
        bittrexBaseCurrencies,
        bittrexTradableCurrencies,
        bittrexMinFunds,
        isStartingExchange,
        DEBUG)

    bithumbName = 'bithumb'
    bithumbBaseCurrencies = ['KRW']
    bithumbTradableCurrencies = ['BTC','ETH','ETC','LTC','DASH']
    isStartingExchange = False
    bithumbMinFunds = 50000 #approximately 50 USD of KRW
    bithumbArbitrageClient = BithumbArbitrageClient(bithumb_keys[0],
        bithumb_keys[1],
        bithumbName,
        bithumbBaseCurrencies,
        bithumbTradableCurrencies,
        bithumbMinFunds,
        isStartingExchange,
        DEBUG)

    #instanciate an arbitrage finder
    arbFinder = ArbitrageFinder()

    curTrade = Trade([])
    for loop in range(LOOPS):
        print("Loop: "+str(loop))
        arbFinder.find_arbitrage_bittrex_bithum(bittrexArbitrageClient, bithumbArbitrageClient, ARBITRAGE_OPPORTUNITY_WAIT_MIN, PROFIT_THRESHOLD, curTrade, PRINT_TOP_TRADES)

if __name__ == '__main__':
    monitor_arbitrage(sys.argv[1])


import os
import csv

VoterCount = 0
Khan = 0
Correy = 0
Li = 0
OTooley = 0
Winner = ''

csvpath = os.path.join('..','Resources','election_data.csv')

with open(csvpath) as csvfile:

    csvreader =csv.reader(csvfile,delimiter=',')

    csv_header = next(csvreader)
    #print(f"CSV  Header : {csv_header}")

    for row in csvreader:
        VoterCount =VoterCount + 1
        if row[2] == "Khan" :
            Khan = Khan +1
        elif row[2] == "Correy" :
            Correy = Correy +1
        elif row[2] == "Li" :
            Li = Li +1
        elif row[2] == "O'Tooley" :
            OTooley = OTooley + 1
        else:
            print("None of these candidates match")

if Khan >= Correy and Khan >= Li and Khan >= OTooley :
    Winner = "Khan"
elif Correy >= Khan and Correy >= Li and Correy >= OTooley :
    Winner = "Correy"
elif Li >= Khan and Li >= Correy and Li >= OTooley :
    Winner = "Li"
else:
    Winner = "O'Tooley"

KhanPercent = round((Khan/VoterCount) * 100,4)
CorreyPercent = round((Correy/VoterCount)*100,4)
LiPercent = round((Li/VoterCount)*100,4)
OTooleyPercent = round((OTooley/VoterCount)*100,4)

print("Election Results")
print("-----------------------------------")
print (f'Total Votes:  {VoterCount}')
print("-----------------------------------")
print(f'Khan: {KhanPercent}%    ({Khan})')
print(f'Correy: {CorreyPercent}%  ({Correy})')
print(f'Li: {LiPercent}%  ({Li})')
print(f"O'Tooley: {OTooleyPercent}%  ({OTooley})")
print("-----------------------------------")
print(f'Winner:  {Winner}')
print("-----------------------------------")

output_file = os.path.join("output.txt")

with open(output_file, "w") as datafile:
    writer = csv.writer(datafile)
    writer.writerow(["Election Results"])
    writer.writerow(["-----------------------------------"])
    writer.writerow (['Total Votes:  ' +  str(VoterCount)])
    writer.writerow(["-----------------------------------"])
    writer.writerow(['Khan:   ' + str(KhanPercent)+'%    '    +'('+str(Khan)+')'])
    writer.writerow(['Correy: '+str(CorreyPercent)+'%    '+  '('+str(Correy)+')'])
    writer.writerow(['Li:  '+str(LiPercent)+'%     ' + '('+str(Li)+')'])
    writer.writerow(["O'Tooley: "+ str(OTooleyPercent) +"%    "+  "("+str(OTooley) +")"])
    writer.writerow(["-----------------------------------"])
    writer.writerow(['Winner:  '+Winner])
    writer.writerow(["-----------------------------------"])


def calculate_total_return(stake, odds):
    if type(stake) not in [int, float]:
        raise TypeError("Inputs for stake must be a compatible number")
    if type(odds) not in [int, float]:
        raise TypeError("Inputs for odds must be a compatible number")
    if stake < 0:
        raise ValueError("stake cannot be negative")
    if odds <= 0:
        raise ValueError("Odds cannot be Negative or Zero")
    total_return = stake * odds
    return total_return

def total_profit(stake, odds):
    if type(stake) not in [int, float]:
        raise TypeError("Inputs for stake must be a compatible number")
    if type(odds) not in [int, float]:
        raise TypeError("Inputs for odds must be a compatible number")
    if stake < 0:
        raise ValueError("stake cannot be negative")
    if odds <= 0:
        raise ValueError("Odds cannot be Negative or Zero")
    profit = (stake * odds) - stake
    return profit

def decimal_percentage_conversion(decimal):
    if type(decimal) not in [int, float]:
        raise TypeError("Decimal input must be a decimal")
    if decimal < 0:
        raise ValueError("Decimal input cannot be less than 0")
    percentage = 100 / decimal
    return percentage

def fractional_percentage_conversion(numerator, denominator):
    if type(numerator) not in [int]:
        raise TypeError("Input must be a whole number")
    if type(denominator) not in [int]:
        raise TypeError("Input must be a whole number")
    if numerator <= 0 or denominator <= 0:
        raise ValueError("Inputs must be greater than Zero")
    percentage = (denominator / (numerator + denominator)) * 100
    return percentage

def fraction_to_decimal_conversion(numerator, denominator):
    if type(numerator) not in [int] or type(denominator) not in [int]:
        raise TypeError("Inputs must be whole numbers")
    if numerator <= 0 or denominator <= 0:
        raise ValueError("Inputs cannot be equal to or less than 0")
    decimal = (numerator / denominator) + 1
    return decimal

def decimal_to_fraction_conversion(decimal): #SORT THIS ONE OUT. INCOMPLETE
    decimal_minus_stake = decimal - 1
    if decimal_minus_stake == int:
        numerator = decimal_minus_stake
    elif decimal_minus_stake == float:
        decimal_minus_stake


import numpy as np
import scipy as sp
import math
import matplotlib.pyplot as plt
from matplotlib import animation

def coord(x,y,p):
	return x*(p) + y

L = 4  #diameter of the circle is four
R = L/2.0 # radius of the circle

N = 40 #per unit of length

w = L
h = L

x_int = w*N
y_int = h*N

delta_x = float(1)/(N)

d = (x_int+1)*(y_int+1)
M = np.zeros((d,d))
b = np.zeros(d)

for i in xrange(x_int+1):
	for j in xrange(y_int+1):
		current_position = coord(i,j,y_int+1)
		left = coord(i,j-1,y_int+1)
		right = coord(i,j+1, y_int+1)
		up = coord(i-1,j,y_int+1)
		down = coord(i+1,j,y_int+1)

		x_position = float(i)/N #not sure
		y_position = float(j)/N #not sure
		dist = np.sqrt((x_position-w/2.0)**2 + (y_position-h/2.0)**2)
		if dist >= R:
			M[current_position][current_position] = 1
			continue

		if (x_position == 2.6) and (y_position == 3.2):
			M[current_position][current_position] = 1
			b[current_position] = 1
			continue

		M[current_position][current_position] = -4
		M[current_position][left] = 1
		M[current_position][right] = 1
		M[current_position][up]=1
		M[current_position][down]=1

#print(M)
#c = sp.sparse.linalg.spsolve(M,b)
c = np.linalg.solve(M,b)

concentration = np.reshape(c,(x_int+1,y_int+1))

concentration = concentration.T

fig = plt.figure()
ax = plt.axes(xlim=(0,x_int), ylim=(0,y_int))

color_map = plt.get_cmap('RdGy_r')
im = ax.imshow(concentration,interpolation='nearest',cmap=color_map)
cb = fig.colorbar(im, ax=ax)

plt.xlabel('x')
plt.ylabel('y')

plt.show()
fig.savefig("diffusion_direct1_"+str(N)+".png")


from flask.blueprints import Blueprint
from rh.util import RHTimeFns

EPOCH_SYNC = RHTimeFns.MonotonicEpochSync()

def createBlueprint(sample_listener):
    APP = Blueprint('rssi', __name__)

    @APP.route('/rssi')
    def rssi_data():
        rssis_by_node = sample_listener.get_rssis()
        lifetimes_by_node = sample_listener.get_lifetimes()
        nodes = set()
        nodes.update(rssis_by_node)
        nodes.update(lifetimes_by_node)
        payload = {}
        for node in sorted(nodes):
            node_samples = {}
            rssi_samples = rssis_by_node.get(node)
            if rssi_samples:
                node_samples['rssi'] = [{'t': EPOCH_SYNC.monotonic_to_epoch_millis(s[0]), 'y': s[1]} for s in rssi_samples]
            lifetime_samples = lifetimes_by_node.get(node)
            if lifetime_samples:
                node_samples['lifetime'] = [{'t': EPOCH_SYNC.monotonic_to_epoch_millis(s[0]), 'y': s[1]} for s in lifetime_samples]
            payload[str(node)] = node_samples
        return payload

    return APP


# -*- coding: utf-8 -*-
"""
Colour Rendering Index
======================

Defines *Colour Rendering Index* (CRI) computation objects:

-   :class:`colour.quality.ColourRendering_Specification_CRI`
-   :func:`colour.colour_rendering_index`

References
----------
-   :cite:`Ohno2008a` : Ohno, Yoshiro, & Davis, W. (2008). NIST CQS simulation
    (Version 7.4) [Computer software].
    https://drive.google.com/file/d/1PsuU6QjUJjCX6tQyCud6ul2Tbs8rYWW9/view?\
usp=sharing
"""

import numpy as np
from collections import namedtuple

from colour.algebra import euclidean_distance, spow
from colour.colorimetry import (
    SPECTRAL_SHAPE_DEFAULT, sd_CIE_illuminant_D_series,
    MSDS_CMFS_STANDARD_OBSERVER, sd_blackbody, sd_to_XYZ)
from colour.quality.datasets.tcs import INDEXES_TO_NAMES_TCS, SDS_TCS
from colour.models import UCS_to_uv, XYZ_to_UCS, XYZ_to_xyY
from colour.temperature import CCT_to_xy_CIE_D, uv_to_CCT_Robertson1968
from colour.utilities import domain_range_scale

__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2013-2021 - Colour Developers'
__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-developers@colour-science.org'
__status__ = 'Production'

__all__ = [
    'TCS_ColorimetryData', 'TCS_ColourQualityScaleData',
    'ColourRendering_Specification_CRI', 'colour_rendering_index',
    'tcs_colorimetry_data', 'colour_rendering_indexes'
]

class TCS_ColorimetryData(
        namedtuple('TCS_ColorimetryData', ('name', 'XYZ', 'uv', 'UVW'))):
    """
    Defines the the class storing *test colour samples* colorimetry data.
    """

class TCS_ColourQualityScaleData(
        namedtuple('TCS_ColourQualityScaleData', ('name', 'Q_a'))):
    """
    Defines the the class storing *test colour samples* colour rendering
    index data.
    """

class ColourRendering_Specification_CRI(
        namedtuple('ColourRendering_Specification_CRI',
                   ('name', 'Q_a', 'Q_as', 'colorimetry_data'))):
    """
    Defines the *Colour Rendering Index* (CRI) colour quality specification.

    Parameters
    ----------
    name : unicode
        Name of the test spectral distribution.
    Q_a : numeric
        *Colour Rendering Index* (CRI) :math:`Q_a`.
    Q_as : dict
        Individual *colour rendering indexes* data for each sample.
    colorimetry_data : tuple
        Colorimetry data for the test and reference computations.

    References
    ----------
    :cite:`Ohno2008a`
    """

def colour_rendering_index(sd_test, additional_data=False):
    """
    Returns the *Colour Rendering Index* (CRI) :math:`Q_a` of given spectral
    distribution.

    Parameters
    ----------
    sd_test : SpectralDistribution
        Test spectral distribution.
    additional_data : bool, optional
        Whether to output additional data.

    Returns
    -------
    numeric or ColourRendering_Specification_CRI
        *Colour Rendering Index* (CRI).

    References
    ----------
    :cite:`Ohno2008a`

    Examples
    --------
    >>> from colour import SDS_ILLUMINANTS
    >>> sd = SDS_ILLUMINANTS['FL2']
    >>> colour_rendering_index(sd)  # doctest: +ELLIPSIS
    64.2337241...
    """

    cmfs = MSDS_CMFS_STANDARD_OBSERVER[
        'CIE 1931 2 Degree Standard Observer'].copy().trim(
            SPECTRAL_SHAPE_DEFAULT)

    shape = cmfs.shape
    sd_test = sd_test.copy().align(shape)
    tcs_sds = {sd.name: sd.copy().align(shape) for sd in SDS_TCS.values()}

    with domain_range_scale('1'):
        XYZ = sd_to_XYZ(sd_test, cmfs)

    uv = UCS_to_uv(XYZ_to_UCS(XYZ))
    CCT, _D_uv = uv_to_CCT_Robertson1968(uv)

    if CCT < 5000:
        sd_reference = sd_blackbody(CCT, shape)
    else:
        xy = CCT_to_xy_CIE_D(CCT)
        sd_reference = sd_CIE_illuminant_D_series(xy)
        sd_reference.align(shape)

    test_tcs_colorimetry_data = tcs_colorimetry_data(
        sd_test, sd_reference, tcs_sds, cmfs, chromatic_adaptation=True)

    reference_tcs_colorimetry_data = tcs_colorimetry_data(
        sd_reference, sd_reference, tcs_sds, cmfs)

    Q_as = colour_rendering_indexes(test_tcs_colorimetry_data,
                                    reference_tcs_colorimetry_data)

    Q_a = np.average(
        [v.Q_a for k, v in Q_as.items() if k in (1, 2, 3, 4, 5, 6, 7, 8)])

    if additional_data:
        return ColourRendering_Specification_CRI(
            sd_test.name, Q_a, Q_as,
            (test_tcs_colorimetry_data, reference_tcs_colorimetry_data))
    else:
        return Q_a

def tcs_colorimetry_data(sd_t, sd_r, sds_tcs, cmfs,
                         chromatic_adaptation=False):
    """
    Returns the *test colour samples* colorimetry data.

    Parameters
    ----------
    sd_t : SpectralDistribution
        Test spectral distribution.
    sd_r : SpectralDistribution
        Reference spectral distribution.
    sds_tcs : dict
        *Test colour samples* spectral distributions.
    cmfs : XYZ_ColourMatchingFunctions
        Standard observer colour matching functions.
    chromatic_adaptation : bool, optional
        Perform chromatic adaptation.

    Returns
    -------
    list
        *Test colour samples* colorimetry data.
    """

    XYZ_t = sd_to_XYZ(sd_t, cmfs)
    uv_t = UCS_to_uv(XYZ_to_UCS(XYZ_t))
    u_t, v_t = uv_t[0], uv_t[1]

    XYZ_r = sd_to_XYZ(sd_r, cmfs)
    uv_r = UCS_to_uv(XYZ_to_UCS(XYZ_r))
    u_r, v_r = uv_r[0], uv_r[1]

    tcs_data = []
    for _key, value in sorted(INDEXES_TO_NAMES_TCS.items()):
        sd_tcs = sds_tcs[value]
        XYZ_tcs = sd_to_XYZ(sd_tcs, cmfs, sd_t)
        xyY_tcs = XYZ_to_xyY(XYZ_tcs)
        uv_tcs = UCS_to_uv(XYZ_to_UCS(XYZ_tcs))
        u_tcs, v_tcs = uv_tcs[0], uv_tcs[1]

        if chromatic_adaptation:

            def c(x, y):
                """
                Computes the :math:`c` term.
                """

                return (4 - x - 10 * y) / y

            def d(x, y):
                """
                Computes the :math:`d` term.
                """

                return (1.708 * y + 0.404 - 1.481 * x) / y

            c_t, d_t = c(u_t, v_t), d(u_t, v_t)
            c_r, d_r = c(u_r, v_r), d(u_r, v_r)
            tcs_c, tcs_d = c(u_tcs, v_tcs), d(u_tcs, v_tcs)
            u_tcs = (
                (10.872 + 0.404 * c_r / c_t * tcs_c - 4 * d_r / d_t * tcs_d) /
                (16.518 + 1.481 * c_r / c_t * tcs_c - d_r / d_t * tcs_d))
            v_tcs = (5.52 /
                     (16.518 + 1.481 * c_r / c_t * tcs_c - d_r / d_t * tcs_d))

        W_tcs = 25 * spow(xyY_tcs[-1], 1 / 3) - 17
        U_tcs = 13 * W_tcs * (u_tcs - u_r)
        V_tcs = 13 * W_tcs * (v_tcs - v_r)

        tcs_data.append(
            TCS_ColorimetryData(sd_tcs.name, XYZ_tcs, uv_tcs,
                                np.array([U_tcs, V_tcs, W_tcs])))

    return tcs_data

def colour_rendering_indexes(test_data, reference_data):
    """
    Returns the *test colour samples* rendering indexes :math:`Q_a`.

    Parameters
    ----------
    test_data : list
        Test data.
    reference_data : list
        Reference data.

    Returns
    -------
    dict
        *Test colour samples* *Colour Rendering Index* (CRI).
    """

    Q_as = {}
    for i, _ in enumerate(test_data):
        Q_as[i + 1] = TCS_ColourQualityScaleData(
            test_data[i].name, 100 -
            4.6 * euclidean_distance(reference_data[i].UVW, test_data[i].UVW))
    return Q_as


def solution(roundTrips):
    roundTripList = roundTrips.split(',')
    closestDistance = float(roundTripList[0])*172
    smallestIndex = 0
    if len(roundTripList)>=5:
        for index in range(1,len(roundTripList)):
            distance = float(roundTripList[index])*172
            if distance < closestDistance:
                smallestIndex = index
                closestDistance = distance
    else:
        smallestIndex=-1
        closestDistance=-1
    closestObject = [str(smallestIndex),str(closestDistance)]

    return closestObject

print(solution("0.5,2.1,0.3,1.8,2.3"))
print(solution("0.1,2.0,1.6,0.05"))
print(solution("0.3,4.0,3.2,0.5,0.1"))


def feichongfu(N,S):
    dicxx={}
    for j in S:
        if j not in dicxx.keys:
            dicxx[j]=1
        else:
            dicxx[j]=dicxx[j]+1
    a=list(dicxx.keys())[list(dicxx.values()).index(1)]
    return a[0]

T=int(input())
for i in range(T):
    N=int(input())
    S=input()
    print(feichongfu(N,S))


# i_scan.py
import sys, os

here = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.normpath(os.path.join(here, '../src')))

from phasematching import *
import matplotlib
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import MaxNLocator, LinearLocator

num = 100
iscan = np.linspace(3, 30, num)*.8
pd = 120e-15
spot = 17e-6

harm = np.array(np.zeros(num))
Lcoh = np.array(np.zeros(num))
ion = np.array(np.zeros(num))
Labs = np.array(np.zeros(num))
Lmed = np.array(np.zeros(num))
phiSS = np.array(np.zeros(num))
dphi = np.array(np.zeros(num))
freq = np.array(np.zeros(num))
pred = np.array(np.zeros(num))
buildup = np.array(np.zeros(num))

for i in range(num):
    sim = phase_matching('Xe', 17,  iscan[i] ,  pd, spot, 1070e-9,  .005, 0.10e-3,  300, 0, .008,0, 'on')#.01
    harm[i], Lcoh[i], ion[i], Labs[i], Lmed[i], phiSS[i], dphi[i], freq[i], pred[i], buildup[i] = sim.int_harmonic_yield()

fig, ax = plt.subplots(2, 3, figsize = (15,8))
matplotlib.rcParams.update({'font.size': 16})

ax[0,0].plot(iscan  , harm, 'k-', linewidth = 2)
ax[0,0].set_xlabel('Injected power [W]')
ax[0,0].set_ylabel('Harmonic Yield [arb.]')

ax[0,1].plot(iscan  , Lcoh * 10 ** 3, 'k-', linewidth = 2, label = 'Coherence Length')
ax[0,1].plot(iscan  , Lmed * 10 ** 3, 'r-', linewidth = 2, label = 'Medium Length')
ax[0,1].plot(iscan  , Labs * 10 ** 3, 'b-', linewidth = 2, label = 'Absorption Length')
ax[0,1].set_xlabel('Injected power [W]')
ax[0,1].set_ylabel('Length [mm]')
ax[0,1].set_title(sim.Atom + ' at ' + str(sim.q) + ' Harmonic')
ax[0,1].legend(loc = 'center right', prop={'size':12})

ax[0,2].plot(iscan  , buildup*iscan*(1-pred), 'k-', linewidth = 2, label = 'Reduced')
ax[0,2].plot(iscan  , buildup*iscan, 'r-', linewidth = 2, label = 'No Gas')
ax[0,2].yaxis.set_major_locator(LinearLocator(5))
ax2 = ax[0,2].twinx()
ax[0,2].set_ylim(min(buildup*iscan*(1-pred)),max(buildup*iscan*(1-pred)))
ax2.plot(iscan  , (2*buildup*iscan*(1-pred)/(np.pi*154e6 * pd * (spot)**2))*10**-18, 'k-')
ax2.set_ylabel('Peak Intensity [10$^{14}$ W cm$^{-2}$]')
ax2.set_ylim(min((2*buildup*iscan*(1-pred)/(np.pi*154e6 * pd * (spot)**2))*10**-18),max((2*buildup*iscan*(1-pred)/(np.pi*154e6 * pd * (spot)**2))*10**-18))
ax2.yaxis.set_major_locator(LinearLocator(5))
ax2.grid()

ax[0,2].legend(loc = 2)
ax[0,2].set_xlabel('Injected power [W]')
ax[0,2].set_ylabel('IC Power [W]')

ax[1,0].plot(iscan  , ion, 'm-', linewidth = 2, label = 'Ionization Fraction')
# ylim(.01,1)
ax[1,0].set_xlabel('Injected power [W]')
ax[1,0].set_ylabel('Ionization Fraction')

ax[1,1].plot(iscan  , Lcoh / Labs, 'k-', linewidth = 2, label = 'L_coh / L_abs ( > 3)')
ax[1,1].plot(iscan  , Lmed / Labs, 'r-', linewidth = 2, label = 'L_med / L_abs ( > 5)')
ax[1,1].set_xlabel('Injected power [W]')
ax[1,1].set_ylabel('Ratio')
ax[1,1].legend(prop={'size':12})

ax[1,2].plot(iscan, phiSS, 'k-', linewidth = 2, label = 'Steady State Phase')
ax[1,2].yaxis.set_major_locator(LinearLocator(5))

ax2 = ax[1,2].twinx()
ax2.plot(iscan, dphi, 'r-', linewidth = 2, label = 'Phase Change')
ax2.set_ylabel('Phase Shift over pulse [rad]', color = 'r')

ax[1,2].set_xlabel('Injected power [W]')
ax[1,2].set_ylabel('Steady State Phase Shift [rad]')
ax2.yaxis.set_major_locator(LinearLocator(5))
for tl in ax2.get_yticklabels():
    tl.set_color('r')
ax2.grid()

fig.set_tight_layout(True)
plt.show()


from django.urls import path

from .views import (InventoryCreateAPIView, InventoryDestroyAPIView,
                    InventoryDetailAPIView, InventoryListAPIView,
                    InventoryUpdateAPIView)

app_name = 'inventory-api'
urlpatterns = [
    path('', InventoryListAPIView.as_view(), name='list'),
    path('create/', InventoryCreateAPIView.as_view(), name='create'),
    path('<int:pk>', InventoryDetailAPIView.as_view(), name='detail'),
    path('<int:pk>/edit', InventoryUpdateAPIView.as_view(), name='update'),
    path('<int:pk>/delete', InventoryDestroyAPIView.as_view(), name='delete'),
]


import random
from typing import Dict, List, Tuple

from axelrod.action import Action
from axelrod.player import Player
from axelrod.random_ import random_choice
from axelrod.strategy_transformers import FinalTransformer
from scipy.stats import chisquare
from axelrod.strategies.memoryone import MemoryOnePlayer

C, D = Action.C, Action.D

class Graaskamp(Player):
    """
    This strategy follows the following rules:

    Play Tit For Tat for the first 50 rounds;

    Defects on round 51;

    Plays 5 further rounds of Tit For Tat;

    A check is then made to see if the opponent is playing randomly
    in which case it defects for the rest of the game;

    The strategy also checks to see if the opponent is playing Tit
    For Tat. If so it plays Tit For Tat. If not it cooperates and
    randomly defects every 5 to 15 moves.

    - Graaskamp: [Axelrod1980]_
    """

    name = "Graaskamp"
    classifier = {
        "memory_depth": float("inf"),
        "stochastic": True,
        "makes_use_of": set(),
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }

    def __init__(self, alpha: float = 0.05) -> None:
        """
        Parameters
        ----------
        alpha: float
            The significant level of p-value from chi-squared test with
            alpha == 0.05 by default.
        """
        super().__init__()
        self.alpha = alpha
        self.opponent_is_random = False

    def strategy(self, opponent: Player) -> Action:
        round_number = len(self.history) + 1

        if round_number == 0:
            return C
        if (0 < round_number < 50):
            return D if opponent.history[-1] == D else C
        if round_number == 51:
            return D
        if (51 < round_number < 56):
            return D if opponent.history[-1] == D else C
        if round_number == 56:
            p_value = chisquare([opponent.cooperations, opponent.defections]).p_value
            self.opponent_is_random = p_value >= self.alpha
        if self.opponent_is_random:
            return D


# -*- coding: utf-8 -*-
from openerp import models, fields, tools,api
from openerp.exceptions import Warning
import openerp

class InvoiceEnhanced(models.Model):

    _inherit = 'account.invoice'

    def pdc_pay_customer(self, cr, uid, ids, context=None):
        if not ids: return []
        dummy, view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'steel_pdc', 'view_pdc_receipt_dialog_form')

        inv = self.browse(cr, uid, ids[0], context=context)
        return {
            'name': "Pay Invoice",
            'view_mode': 'form',
            'view_id': view_id,
            'view_type': 'form',
            'res_model': 'post.dated.check',
            'type': 'ir.actions.act_window',
            'nodestroy': True,
            'target': 'new',
            'domain': '[]',
            'context': {
                'payment_expected_currency': inv.currency_id.id,
                'default_partner_id': self.pool.get('res.partner')._find_accounting_partner(inv.partner_id).id,
                'default_amount': inv.type in ('out_refund', 'in_refund') and -inv.residual or inv.residual,
                'default_reference': inv.name,
                'close_after_process': True,
                'invoice_type': inv.type,
                'invoice_id': inv.id,
                'default_type': inv.type in ('out_invoice','out_refund') and 'receipt' or 'payment',
                'type': inv.type in ('out_invoice','out_refund') and 'receipt' or 'payment',
                'cost_center_id': inv.cost_center_id.id
            }
        }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:


import chainer
from chainer import training
from chainer.training import extensions
from chainer import optimizers

from chainet.model import alex
from chainet.model import vgg16
from chainet.model import darknet19
import os
import glob
from PIL import Image
import numpy as np

class PreprocessedDataset(chainer.dataset.DatasetMixin):
    def __init__(self, path, filelist, random=True):
        self.base = filelist
        self.path = path

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

    def get_example(self, i):
        # It reads the i-th image/label pair and return a preprocessed image.
        # It applies following preprocesses:
        imgfilepath = self.base[i]
        anno_path = self.path+'labels/'+os.path.splitext(os.path.basename(imgfilepath))[0] +'.txt'
        with open(anno_path,'r') as f:
            annodata = f.read()
        label = annodata.split()[0]
        img = Image.open(imgfilepath)
        r,g,b = img.split()
        rImgData = np.asarray(np.float32(r)/255.0)
        gImgData = np.asarray(np.float32(g)/255.0)
        bImgData = np.asarray(np.float32(b)/255.0)
        imgData = np.asarray([rImgData,gImgData,bImgData])
        labelData = np.int32(label)
        return imgData, labelData

class TestModeEvaluator(extensions.Evaluator):
    def evaluate(self):
        model = self.get_target('main')
        model.train = False
        ret = super(TestModeEvaluator, self).evaluate()
        model.train = True
        return ret

def train(mode, arch, cfg, gpu):
    datapath = 'data/'
    print(mode, arch, cfg)
    batchsize = 32
    val_batchsize = 50
    loaderjob = 1
    epoch = 5
    archs = {
        'alex': alex.AlexNet(),
        'vgg':  vgg16.VggNet(),
        'darknet19': darknet19.Darknet19Trainer(darknet19.DarkNet19())
        }
    print(arch)
    model = archs[arch]
    if gpu >= 0:
        chainer.cuda.get_device(gpu).use()
        model.to_gpu()

    print('hey')
# Load the datasets
    traindatasetpath = os.getcwd() +'/'+ datapath + 'train/'
    testdatasetpath = os.getcwd() +'/'+ datapath + 'test/'
# generate labeledDataset
    dataTuppleList = []
    trainfiles = glob.glob(traindatasetpath+'images/*.jpg')
    valfiles = glob.glob(testdatasetpath+'images/*.jpg')
    train = PreprocessedDataset(traindatasetpath, trainfiles)
    val = PreprocessedDataset(testdatasetpath, valfiles, False)
    print('PreprocessedDataset done')

# Set up an optimizer
    optimizer = optimizers.MomentumSGD(lr=0.001, momentum=0.9)
#    optimizer.use_cleargrads()
    optimizer.setup(model)
#    optimizer.add_hook(chainer.optimizer.WeightDecay(0.0005))

# the training/validation.
    train_iter = chainer.iterators.MultiprocessIterator(train, batchsize, n_processes=loaderjob)
    val_iter = chainer.iterators.MultiprocessIterator(val, val_batchsize, repeat=False, n_processes=loaderjob)

# Set up a trainer
    updater = training.StandardUpdater(train_iter, optimizer, device=gpu)
    trainer = training.Trainer(updater, (epoch, 'epoch'), 'result')

    trainer.extend(extensions.Evaluator(val_iter, model, device=gpu))
    trainer.extend(extensions.LogReport())
    trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'elapsed_time']))
    trainer.extend(extensions.ProgressBar())
    trainer.run()

    if gpu >= 0:
        model.to_cpu()

def predict():
    pass

def valid():
    pass


#!/usr/bin/env python3

import unittest
from Crypto.Random import random
from Crypto.Random.random import randint
from Crypto.PublicKey import RSA

MLEN = 256
NLEN = 1024
RLEN = NLEN-MLEN-1

def _mod_mult_inv(x, modulo):
    t1, t2, r1, r2 = 0, 1, modulo, x
    while r2 != 0:
        q = (-1 if (r1<0)!=(r2<0) else 1) * (r1 // abs(r2))
        t1, t2, r1, r2 = t2, t1-q*t2, r2, r1-q*r2
    return (t1 if t1>0 else t1+modulo)

class PaddedRSA():
    def __init__(self):
        self.N, self.e, self.d = self.gen()

    def gen(self):
        rsa = RSA.generate(1024)
        p = getattr(rsa.key, 'p')
        q = getattr(rsa.key, 'q')
        N = p*q
        e = 2**16 + 1 # assume phi > e, usually
        d = _mod_mult_inv(e, (p-1)*(q-1))
        return N, e, d

    def enc(self, m):
        r = randint(0, 2**RLEN)
        m2 = (r << MLEN) | m
        return pow(m2, self.e, self.N)

    def dec(self, c):
        m2 = pow(c, self.d, self.N)
        return m2 & (2**MLEN - 1)

class Tests(unittest.TestCase):
    def _rand_msg(self):
        return randint(0, 2**(MLEN//8))

    def test_enc_and_dec(self):
        """Encrypt and decrypt using own RSA"""
        m = self._rand_msg()    # generate random message
        rsa = PaddedRSA()       # initialize RSA class
        c = rsa.enc(m)          # encrypt the message
        m2 = rsa.dec(c)         # decrypt the message
        self.assertEqual(m, m2) # message should be unchanged

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


# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json

class Track:
    """
    Represents an individual track on Amazon Music. This will be returned from
    one of the other calls and cannot be created directly.

    Key properties are:

    * `name` - Track name
    * `artist` - Track artist
    * `album` - Album containing the track
    * `albumArtist` - Primary artist for the album
    * `coverUrl` - URL containing cover art for the track/album.
    * `streamUrl` - URL of M3U playlist allowing the track to be streamed.
    """

    def __init__(self, amzn, data):
        """
        Internal use only.

        :param amzn: AmazonMusic object, used to make API calls.
        :param data: JSON data structure for the track, from Amazon Music.
                     Supported data structures are from `mpqs` and `muse`.
        """
        try:
            self._amzn = amzn
            self._url = None

            self.json = data
            self.name = data.get('name') or data['title']
            self.artist = data.get('artistName') or data['artist']['name']
            self.album = data['album'].get('name') or data['album'].get(
                'title')
            self.album_artist = data['album'].get(
                'artistName') or data['album'].get('albumArtistName',
                                                   self.artist)

            self.cover_url = None
            if 'artUrlMap' in data:
                self.cover_url = data['artUrlMap'].get(
                    'FULL', data['artUrlMap'].get('LARGE'))
            elif 'image' in data['album']:
                self.cover_url = data['album']['image']

            if 'identifierType' in data:
                self.identifier_type = data['identifierType']
                self.identifier = data['identifier']
            else:
                self.identifier_type = 'ASIN'
                self.identifier = data['asin']

            self.duration = data.get('durationInSeconds', data.get('duration'))

        except KeyError as e:
            e.args = ('{} not found in {}'.format(
                e.args[0], json.dumps(data, sort_keys=True)),)
            raise

    def url(self):
        """
        Return the URL for an M3U playlist for the track, allowing it to be streamed.
        The playlist seems to consist of individual chunks of the song, in ~10s segments,
        so a player capable of playing playlists seamless is required, such as VLC.
        """
        if self._url is None:
            stream_json = self._amzn.call(
                'dmls/',
                'com.amazon.digitalmusiclocator.DigitalMusicLocatorServiceExternal.getRestrictedStreamingURL',
                {
                    'customerId': self._amzn.customer_id,
                    'deviceToken': {
                        'deviceTypeId': self._amzn.device_type,
                        'deviceId': self._amzn.device_id,
                    },
                    'appMetadata': {
                        'https': 'true'
                    },
                    'clientMetadata': {
                        'clientId': 'WebCP',
                    },
                    'contentId': {
                        'identifier': self.identifier,
                        'identifierType': self.identifier_type,
                        'bitRate': 'HIGH',
                        'contentDuration': self.duration
                    }
                })

            if 'statusCode' in stream_json and stream_json['statusCode'] == 'MAX_CONCURRENCY_REACHED':
                raise Exception(stream_json['statusCode'])

            try:
                self._url = stream_json['contentResponse']['urlList'][0]
            except KeyError as e:
                e.args = ('{} not found in {}'.format(
                    e.args[0], json.dumps(stream_json, sort_keys=True)),)
                raise

        return self._url


import re
def gemiddelde():
    s = input('Put your thing here: ')
    count = len(re.findall('[a-zA-Z]', s))
    a = len(s.split())

    print(count, a)
    som = count / a
    print(som)

gemiddelde()


# DOESN'T WORK YET

# Currently gets errors like:

"""
Traceback (most recent call last):
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3267, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-85af1f3b28dd>", line 1, in <module>
    runfile('/Users/joshuafass/Documents/GitHub/bayes-implicit-solvent/bayes_implicit_solvent/continuous_parameter_experiments/elemental_types_mala_jax2.py', wdir='/Users/joshuafass/Documents/GitHub/bayes-implicit-solvent/bayes_implicit_solvent/continuous_parameter_experiments')
  File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/Users/joshuafass/Documents/GitHub/bayes-implicit-solvent/bayes_implicit_solvent/continuous_parameter_experiments/elemental_types_mala_jax2.py", line 148, in <module>
    mala_result = MALA(x0, log_prob_fun, grad(log_prob_fun), n_steps=1000, stepsize=0.001)
  File "/Users/joshuafass/Documents/GitHub/bayes-implicit-solvent/bayes_implicit_solvent/samplers.py", line 232, in MALA
    grads = [grad_log_prob_fun(traj[-1])]
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/api.py", line 206, in grad_f
    ans, g = value_and_grad_f(*args, **kwargs)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/api.py", line 241, in value_and_grad_f
    ans, vjp_py = vjp(f_partial, *dyn_args)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/api.py", line 563, in vjp
    out_primal, out_vjp = ad.vjp(jaxtree_fun, primals_flat)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/interpreters/ad.py", line 76, in vjp
    out_primal, pval, jaxpr, consts = linearize(traceable, *primals)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/interpreters/ad.py", line 69, in linearize
    jaxpr, out_pval, consts = pe.trace_to_jaxpr(jvpfun, in_pvals)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/interpreters/partial_eval.py", line 314, in trace_to_jaxpr
    jaxpr, (out_pval, consts, env) = fun.call_wrapped(pvals, **kwargs)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/linear_util.py", line 86, in call_wrapped
    ans = self.f(*args, **self.kwargs)
  File "/Users/joshuafass/Documents/GitHub/bayes-implicit-solvent/bayes_implicit_solvent/continuous_parameter_experiments/elemental_types_mala_jax2.py", line 146, in log_prob_fun
    return np.sum(norm.logpdf(theta - prior_location)) + log_likelihood_of_params(theta)# - penalty
  File "/Users/joshuafass/Documents/GitHub/bayes-implicit-solvent/bayes_implicit_solvent/continuous_parameter_experiments/elemental_types_mala_jax2.py", line 137, in log_likelihood_of_params
    return log_likelihood(predictions)
  File "/Users/joshuafass/Documents/GitHub/bayes-implicit-solvent/bayes_implicit_solvent/continuous_parameter_experiments/elemental_types_mala_jax2.py", line 121, in log_likelihood
    return np.sum(norm.logpdf(predictions, loc=expt_means, scale=expt_uncs))
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/scipy/stats/norm.py", line 28, in logpdf
    x, loc, scale = _promote_args_like(osp_stats.norm.logpdf, x, loc, scale)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/numpy/lax_numpy.py", line 192, in _promote_args_like
    return _promote_shapes(*_promote_to_result_dtype(op, *args))
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/numpy/lax_numpy.py", line 164, in _promote_to_result_dtype
    to_dtype = _result_dtype(op, *args)
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/jax/numpy/lax_numpy.py", line 171, in _result_dtype
    return _dtype(op(*args))
  File "/Users/joshuafass/anaconda3/lib/python3.7/site-packages/scipy/stats/_distn_infrastructure.py", line 1700, in logpdf
    putmask(output, (1-cond0)+np.isnan(x), self.badvalue)
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
"""

# UPDATE MARCH 10: Runs now, if I replace norm.logpdf with raw numpy...
# However, it hits NaNs immediately, and never accepts any proposals

# UPDATE: It works, but it's way slower than it should be...
# UPDATE: When I include jit compilation, it's super super slow to get started... Like, tens of minutes...

from jax import numpy as np
from numpy import load, random, savez
from bayes_implicit_solvent.molecule import Molecule
from simtk import unit

def sample_path_to_unitted_snapshots(path_to_npy_samples):
    xyz = load(path_to_npy_samples)
    traj = [snapshot * unit.nanometer for snapshot in xyz]
    return traj

from glob import glob
from pkg_resources import resource_filename

data_path = resource_filename('bayes_implicit_solvent',
                              'data')
ll = 'gaussian'  # or 'student-t'
randomize_theta0 = False
n_conf = 25

path_to_vacuum_samples = resource_filename('bayes_implicit_solvent',
                                           'vacuum_samples/short_run/vacuum_samples_*.npy')
paths_to_samples = glob(path_to_vacuum_samples)
random.seed(0)
random.shuffle(paths_to_samples)
paths_to_samples = paths_to_samples[::2]

print('number of molecules being considered: {}'.format(len(paths_to_samples)))

def extract_cid_key(path):
    i = path.find('mobley_')
    j = path.find('.npy')
    return path[i:j]

cids = list(map(extract_cid_key, paths_to_samples))
print('first few CIDs', cids[:5])

mols = []

n_configuration_samples = n_conf  # TODO: Since this is cheaper, can probably modify this a bit...

name = 'n_config={}_{}_ll'.format(n_configuration_samples, ll)

from bayes_implicit_solvent.freesolv import cid_to_smiles

from bayes_implicit_solvent.constants import beta
def unreduce(value):
    """Input value is in units of kB T, turn it into units of kilocalorie_per_mole"""
    return value / (beta * unit.kilocalorie_per_mole)

for path in paths_to_samples:
    cid = extract_cid_key(path)
    smiles = cid_to_smiles[cid]
    vacuum_samples = sample_path_to_unitted_snapshots(path)
    thinning = int(len(vacuum_samples) / n_configuration_samples)
    mol = Molecule(smiles, vacuum_samples=vacuum_samples[::thinning], ll=ll)

    if (unreduce(mol.experimental_value) > -15) and (unreduce(mol.experimental_value) < 5):
        mols.append(mol)
    else:
        print('discarding {} ({}) because its free energy was outside of the range [-15, +5] kcal/mol'.format(smiles, cid))

element_inds = []
all_elements = ['S', 'Cl', 'F', 'C', 'I', 'N', 'Br', 'H', 'P', 'O']
N = len(all_elements)
element_dict = dict(zip(all_elements, range(len(all_elements))))

initial_radius_dict = dict(H=0.12, C=0.17, N=0.155, O=0.15, F=0.15,
                   P=0.185, S=0.18, Cl=0.17, Br=0.15, I=0.15)
initial_scaling_factor_dict = dict(H=0.85, C=0.72, N=0.79, O=0.85, F=0.88,
                           P=0.86, S=0.96, Cl=0.80, Br=0.80, I=0.80)

for mol in mols:
    element_inds.append(np.array([element_dict[a.element.symbol] for a in list(mol.top.atoms())]))

from jax import jit, vmap
from bayes_implicit_solvent.gb_models.jax_gb_models import compute_OBC_energy_vectorized
from bayes_implicit_solvent.solvation_free_energy import kj_mol_to_kT, one_sided_exp

@jit
def predict_solvation_free_energy_jax(theta, distance_matrices, charges, element_ind_array):
    radii_, scaling_factors_ = theta[:N], theta[N:]

    radii = radii_[element_ind_array]
    scaling_factors = scaling_factors_[element_ind_array]

    @jit
    def compute_component(distance_matrix):
        return compute_OBC_energy_vectorized(distance_matrix, radii, scaling_factors, charges)

    W_F = vmap(compute_component)(distance_matrices)

    w_F = W_F * kj_mol_to_kT
    return one_sided_exp(w_F)
#_ = predict_solvation_free_energy_jax(np.ones(N * 2))
#return predict_solvation_free_energy_jax

distance_matrices = [mol.distance_matrices for mol in mols]
charges = [mol.charges for mol in mols]

#TODO: vmap and JIT this...
@jit
def get_predictions(theta):
    return np.array([predict_solvation_free_energy_jax(theta, distance_matrices[i], charges[i], element_inds[i]) for i in range(len(mols))])

expt_means = np.array([mol.experimental_value for mol in mols])
expt_uncs = np.array([mol.experimental_uncertainty for mol in mols])

from scipy.stats import t as student_t
from jax.scipy.stats import norm

@jit
def log_likelihood(predictions):
    return np.sum(-((predictions - expt_means)**2 / (expt_uncs**2)))
    #return np.sum(norm.logpdf(predictions, loc=expt_means, scale=expt_uncs))
    #return np.sum(student_t.logpdf(predictions, loc=expt_means,
    #                 scale=expt_uncs,
    #                 df=7))

initial_radius_array = [initial_radius_dict[a] for a in all_elements]
initial_scaling_factor_array = [initial_scaling_factor_dict[a] for a in all_elements]
prior_location = np.array(initial_radius_array + initial_scaling_factor_array) # mbondi2 set, except not differentiation H from HN...
#prior_location = np.array([0.17, 0.12, 0.72, 0.85]) # mbondi2 set
from jax import grad

@jit
def log_prior(theta):
    return - np.sum(theta**2)

if __name__ == '__main__':

    @jit
    def log_likelihood_of_params(theta):
        predictions = get_predictions(theta)
        return log_likelihood(predictions)

    from bayes_implicit_solvent.samplers import random_walk_mh, MALA, langevin
    x0 = np.array(prior_location)
    v0 = random.randn(len(prior_location)) * 0.01

    @jit
    def log_prob_fun(theta):
        #penalty = min(0.0, 0.01 - np.min(theta))**2
        #penalty += min(0.0, np.max(theta) - 5.0)**2
        # return np.sum(norm.logpdf(theta - prior_location)) + log_likelihood_of_params(theta)# - penalty
        return log_prior(theta) + log_likelihood_of_params(theta)

    #mh_result = random_walk_mh(x0, log_prob_fun, n_steps=100000, stepsize=0.001)
    #mala_result = MALA(x0, log_prob_fun, grad(log_prob_fun), n_steps=1000, stepsize=0.00001)

    #traj, log_prob_traj, grads, acceptance_probs, stepsizes = mala_result
    # np.savez('freesolv_mala_jax.npz',
    #          traj=traj,
    #          log_prob_traj=log_prob_traj,
    #          acceptance_probs=acceptance_probs,
    #          stepsizes=stepsizes,
    #          expt_means=expt_means,
    #          expt_uncs=expt_uncs,
    #          cids=cids,
    #          elements=all_elements,
    #          )

    stepsize = 0.0001
    collision_rate = 1/stepsize

    langevin_result = langevin(x0, v0, log_prob_fun,
                               grad(log_prob_fun),
                               stepsize=stepsize,
                               collision_rate=collision_rate,
                               n_steps=1000)
    traj, log_probs = langevin_result
    savez('freesolv_langevin_jax_big_collision_rate_march13.npz',
             traj=traj,
             log_prob_traj=log_probs,
             expt_means=expt_means,
             expt_uncs=expt_uncs,
             cids=cids,
             elements=all_elements,
             )


#!/usr/bin/env python3
import sys
import bluetooth
import os
import time
import sqlite3 as db
from sense_hat import SenseHat
from time import sleep

# Author Tim Novice sn: s3572290 RMIT
#
# Adapted code from Week 5 tutorial task 'findmyphone.py'.
# Pairs to a know Bluetooth device and sends weather notifications.
#

userds = '/database/a1data.db'

# Write bt details to database
def setBtData(user_name, device_name):
    try:
        params = (user_name, device_name)
        conn = db.connect(userds)
        curs = conn.cursor()
        curs.execute("INSERT INTO BT_data values(?, ?)", params)
    # Handles db locking
    except db.OperationalError as e:
        if ("locked" in str(e)):
            sleep(1)
        else:
            raise
    except KeyboardInterrupt:
        conn.commit()
        conn.close()
        # Kill db connection in case close() gets locked up
        conn.interrupt()
    finally:
        conn.commit()
        conn.close()

# Searches database for bt details and then tries to pair
def getBtData():
    try:
        conn = db.connect(userds)
        curs = conn.cursor()
        curs.execute(
                "SELECT * FROM BT_data ORDER BY user_name DESC LIMIT 1")
        dbData = curs.fetchall()
        user_name = []
        device_name = []
        if (dbData is not None):
            for row in reversed(dbData):
                user_name.append(row[0])
                device_name.append(row[1])
        conn.close()
        return user_name, device_name
    # Handles db locking
    except db.OperationalError as e:
        if ("locked" in str(e)):
            sleep(1)
        else:
            raise

# Search for device based on device's name
def search(user_name, device_name):
    try:
        while True:
            device_address = None
            dt = time.strftime("%a, %d %b %y %H:%M:%S", time.localtime())
            print("\nCurrently: {}".format(dt))
            time.sleep(3)
            nearby_devices = bluetooth.discover_devices()
            for mac_address in nearby_devices:
                if device_name == bluetooth.lookup_name(
                        mac_address, timeout=5):
                    device_address = mac_address
                    break
            if device_address is not None:
                print(
                    "Hi {}! Your phone ({}) has the MAC address: {}".format(
                        user_name, device_name, device_address))
                sense = SenseHat()
                temp = round(sense.get_temperature(), 1)
                sense.show_message(
                    "Hi {}! The Current Temp is {}*c".format(
                        user_name, temp), scroll_speed=0.05)
            else:
                print("No device located in range ...")
    except KeyboardInterrupt:
        print("Bluetooth disconnected")
        sys.exit()

# Main method
def main():
    # user_name, device_name = getBtData()
    user_name = input("Enter your name: ")
    device_name = input("Enter the name of your phone: ")
    setBtData(user_name, device_name)
    search(user_name, device_name)

main()


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

from flask import current_app, request
from flask.ext.restful import abort
from sqlalchemy.orm.exc import NoResultFound
import requests

class UriResourceGetter(object):
    def __init__(self, root_url, resource_type, resource_name):
        self.root_url = root_url
        self.resource_type = resource_type
        self.resource_name = resource_name

    def get_for_uri(self, uri, cookies=None):
        try:
            return current_app.db_session.query(self.resource_type).filter(self.resource_type.uri == uri).one()
        except NoResultFound:
            return self.copy_from_web(uri, cookies=cookies)

    def copy_from_web(self, uri, cookies=None):
        content = self.get_from_web(uri, cookies=cookies)
        uri = content["uri"]
        resource = self.resource_type(uri=uri)
        current_app.db_session.add(resource)
        current_app.db_session.commit()
        current_app.db_session.refresh(resource)
        return resource

    def get_from_web(self, uri, cookies=None):
        url = self.root_url + uri
        if cookies is None:
            cookies = request.cookies
        response = requests.get(url, cookies=cookies)
        if response.status_code == 200:
            return json.loads(response.content)
        abort(404, __error__=["No %s found." % self.resource_name])


import pandas as pd
import numpy as np
from pandas import DataFrame, Series
import os, math, pickle
import matplotlib.pyplot as plt
import seaborn as sns

from datetime import datetime, date, time, timedelta
import calendar

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error

import math

import keras
from keras.models import Sequential, load_model
from keras.layers import Dense, Activation, Dropout, LSTM, CuDNNLSTM
from keras.optimizers import Adam
from keras.utils import np_utils

### Data Load
data = pd.read_csv('./data/lstm-revenue-estimation.csv')
data['date'] = pd.to_datetime(data['date']) # change object type to date type
data['revCum'] = data.groupby(['su', pd.Grouper(key='date', freq='M')])['rev'].apply(lambda x: x.cumsum())
data['depCum'] = data.groupby(['su', pd.Grouper(key='date', freq='M')])['dep'].apply(lambda x: x.cumsum())
data.head()

### Data Plot 1
fig = plt.figure(figsize=(17,12))
plt.rc('font', size=8)
ax1 = fig.add_subplot(2, 1, 1)
ax1.plot(data['rev'], color='blue', label='Revenue')
ax1.plot(data['dep'], color='red', label='Deposit', alpha=0.5)
ax1.set_title('Daily Revenue & Deposit Plot')
ax1.legend(loc='best'); ax1.set_xticks([])
    # Line Plot about Revenue and Deposit. It's unable to find an order.

ax2 = fig.add_subplot(2, 1, 2)
ax2.plot(data['revCum'], color='blue', label='Monthly Cumulative Revenue')
ax2.plot(data['depCum'], color='red', label='Monthly Cumulative Deposit', alpha=0.5)
ax2.set_title('Monthly Cumulative Revenue & Deposit Plot -- Peak points are the last day of each months')
ax2.legend(loc='best'); ax2.set_xticks([])
    # Line Plot about Monthly Cumulative Revenue and Deposit. It seems strong relationship between cumulative revenue and deposit.
plt.show()

### Data Plot 2
fig, ax = plt.subplots(2, 2, figsize=(17,12))
plt.rc('font', size=8)
ax[0,0].boxplot((data['rev'], data['revCum']), labels=['Revenue', 'Cumulative Revenue'])
ax[0,0].set_title('Box Plot')

ax[0,1].hist(data['rev'], bins=10, color='green', alpha=.9, label='Revenue')
ax[0,1].hist(data['revCum'], bins=10, color='blue', alpha=.5, label='Cumulative Revenue')
ax[0,1].legend(loc='best'); ax[0,1].set_title('Histogram : Revenue vs Cumulative Revenue')

ax[1,0].scatter(data['rev'], data['dep']); ax[1,0].set_title('Scatter Plot : Revenue vs Deposit')
ax[1,0].set_xlabel('Revenue'); ax[1,0].set_ylabel('Deposit')

ax[1,1].scatter(data['revCum'], data['depCum']); ax[1,1].set_title('Scatter Plot : Cumulative Revenue vs Deposit')
ax[1,1].set_xlabel('Cumulative Revenue'); ax[1,1].set_ylabel('Cumulative Deposit')

plt.show()
    # Cumulative data has features of linearity and uniform

### Correlation
dataCorr = data.drop(['su', 'date'], axis=1).corr()
sns.heatmap(dataCorr, annot=True, fmt='.2f', cmap='Blues')
plt.show()
    # Seemingly, there is less correlation between revenue & deposit
    # On the other hand, there is strong correlation between cumulative revenue & deposit
    # I'll make 2 data pipelines. First one is daily cumulative revenue estimation model.
    # Second one is Cumulative deposit regression model by monthly cumulative revenue estimation.

### Rearrange Every Month's days to 28 days : Shrink to 28 days for easy data input to models
data['days'] = data['date'].apply(lambda x: x.day)
data['days'] = data['days'].where(data['days'] <= 28, 28)

data = data.groupby(['su', pd.Grouper(key='date', freq='M'), 'days']).agg({'rev':'sum', 'dep':'sum'}).reset_index()
for col in ['rev', 'dep']:
    data[col+'Cum'] = data.groupby(['su', pd.Grouper(key='date', freq='M')])[col].apply(lambda x: x.cumsum())
data.head(30) # Every months days is binded 28 days

### Split Train / Test Data
trainData = data.query("date <= '2018-08-31'")
testData = data.query("date > '2018-08-31'")

### The fuction of making X / Y labeled data for model.
def dataset(set, lookBack = 27):
    x, y = [], []
    for i in range(len(set) - lookBack):
        x.append(set[i:i+lookBack])
        y.append(set[i+lookBack, 0])
    return np.array(x), np.array(y).reshape(len(y), 1)
    # X has time-sequence data from lookback to present(t-lookback to t). Y has a future data (t+1)

### Scaling(0-1) Cumulative Revenue and Days
scaler = MinMaxScaler(feature_range=(0, 1))
trainDataScaled = scaler.fit_transform(trainData[['revCum']].values) # Scaling data range from 0 to 1
trainDataScaledDays = trainData[['days']].values / 28 # Scaling days range from 0 to 1
trainDataScaled = np.hstack((trainDataScaled, trainDataScaledDays)) # Cumulative revenue & days(1 - 28) are input data

testDataScaled = scaler.transform(testData[['revCum']].values)
testDataScaledDays = testData[['days']].values / 28 # Scaling days range from 0 to 1
testDataScaled = np.hstack((testDataScaled, testDataScaledDays)) # Cumulative revenue & days(1 - 28) are input data

del trainDataScaledDays, testDataScaledDays

### Save a Scaler
output = open('./scaler/scaler1.pkl', 'wb')
pickle.dump(scaler, output)
output.close()
del output

### Produce X / Y Data for model
lookBack = 27
X_train, Y_train = dataset(trainDataScaled, lookBack)
X_test, Y_test = dataset(testDataScaled, lookBack)

### Model Parameters
epochs = 2000
batch_size = 50
optm = Adam(lr=0.0001)

### Establish Stateless LSTM Model
modelLstm = Sequential()
modelLstm.add(CuDNNLSTM(64, input_shape=(X_train.shape[1], X_train.shape[2]), return_sequences=True)) # First layer's sequence to next layer
modelLstm.add(Dropout(0.3))
modelLstm.add(CuDNNLSTM(64))
modelLstm.add(Dropout(0.3))
modelLstm.add(Dense(1)) # Output without activation, because the result is regression.
modelLstm.summary()
modelLstm.compile(loss='mse', optimizer=optm) # To minimize mean squared error

earlyStop = keras.callbacks.EarlyStopping(patience=100, monitor='loss') # Early stop
modelpath='./model/LSTM-stateless-{epoch:04d}-{loss:.6f}.hdf5'
ckpt = keras.callbacks.ModelCheckpoint(filepath=modelpath, monitor='loss', verbose=1, save_best_only=True) # Checkpoints

histLstm = modelLstm.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1, shuffle=False, callbacks=[earlyStop, ckpt])
    ## Learning Stateless LSTM Model

### Establish Stateful LSTM Model
modelLstmStateful = Sequential()
modelLstmStateful.add(CuDNNLSTM(64, batch_input_shape=(1, X_train.shape[1], X_train.shape[2]), stateful=True, return_sequences=True)) # First layer's sequence to next layer
modelLstmStateful.add(Dropout(0.3))
modelLstmStateful.add(CuDNNLSTM(64))
modelLstmStateful.add(Dropout(0.3))
modelLstmStateful.add(Dense(1)) # Output without activation, because the result is regression.
modelLstmStateful.summary()
modelLstmStateful.compile(loss='mse', optimizer=optm) # To minimize mean squared error

modelpath='./model/LSTM-stateful-{epoch:04d}-{loss:.6f}.hdf5'
ckpt = keras.callbacks.ModelCheckpoint(filepath=modelpath, monitor='loss', verbose=1, save_best_only=True) # Checkpoints

epochs = 1000 # Reset Epochs : Stateful LSTM model is slow to learn.

lstmLoss = []
for i in range(epochs):
    print('\n **** epoch : %d'%i)
    histLstmStateful = modelLstmStateful.fit(X_train, Y_train, batch_size=1, epochs=1, verbose=1, shuffle=False, callbacks=[ckpt])
    lstmLoss.append(histLstmStateful.history['loss'][0])
    modelLstmStateful.reset_states()
        # Learning LSTM Model

modelLstm = load_model('./model/LSTM-stateless-1679-0.000891.hdf5')
modelLstmStateful = load_model('./model/LSTM-stateful-0001-0.001021.hdf5')

### Loss Plot between LSTM(Stateless) vs LSTM(Stateful)
plt.figure()
plt.ylim(0, .02)
plt.plot(histLstm.history['loss'], color='blue', label='Stateless')
plt.plot(lstmLoss, color='green', label='Stateful', alpha=.5)
plt.legend(loc='best')
plt.title('Loss - LSTM(Stateless) vs (Stateful)')
plt.show()
    # DNN loss plot is gradually decreasing. On the other hand, LSTM is very moody. But performance is better.

### Estimation Functions : Models estimate whole daily cumulative revenue by using own produced data (based on past 27 days cumulative revenue)
def estLstm(data, duration): # Stateless LSTM model estimation
    dataTotal = []
    dataTemp1 = scaler.transform(data[['revCum']].values)
    dataTemp2 = data[['days']].values / 28
    dataTemp = np.hstack((dataTemp1, dataTemp2))
    dataTemp = list(dataTemp)

    for i in range(duration):
        temp = dataTemp[-1*lookBack:]
        temp = np.array(temp).reshape(1, lookBack, 2)
        temp_predict = modelLstm.predict(temp)

        j = (lambda x: 28 if (x+1) % 28 == 0 else (x+1) % 28)(i)

        dataTemp.append([temp_predict[0, 0], j / 28])
        dataTotal.append(temp_predict[0, 0])

    return np.array(dataTotal).reshape(len(dataTotal), 1)

def estLstmStateful(data, duration): # Stateless LSTM model estimation
    dataTotal = []
    dataTemp1 = scaler.transform(data[['revCum']].values)
    dataTemp2 = data[['days']].values / 28
    dataTemp = np.hstack((dataTemp1, dataTemp2))
    dataTemp = list(dataTemp)

    for i in range(duration):
        temp = dataTemp[-1*lookBack:]
        temp = np.array(temp).reshape(1, lookBack, 2)
        temp_predict = modelLstmStateful.predict(temp, batch_size=1)

        j = (lambda x: 28 if (x+1) % 28 == 0 else (x+1) % 28)(i)

        dataTemp.append([temp_predict[0, 0], j / 28])
        dataTotal.append(temp_predict[0, 0])

    return np.array(dataTotal).reshape(len(dataTotal), 1)

def estLstmCombined(data, duration): # Stateless LSTM model estimation
    dataTotal = []
    dataTemp1 = scaler.transform(data[['revCum']].values)
    dataTemp2 = data[['days']].values / 28
    dataTemp = np.hstack((dataTemp1, dataTemp2))
    dataTemp = list(dataTemp)

    for i in range(duration):
        temp = dataTemp[-1*lookBack:]
        temp = np.array(temp).reshape(1, lookBack, 2)
        temp_predict = (modelLstmStateful.predict(temp, batch_size=1) + modelLstm.predict(temp)) / 2

        j = (lambda x: 28 if (x+1) % 28 == 0 else (x+1) % 28)(i)

        dataTemp.append([temp_predict[0, 0], j / 28])
        dataTotal.append(temp_predict[0, 0])

    return np.array(dataTotal).reshape(len(dataTotal), 1)

### Estimate 3 Months Cumulative Revenue
dataPast = data.query("'2018-09-01' > date").reset_index(drop=True)
dataActual = data.query("'2018-09-01' <= date").reset_index(drop=True) # revenue from 2018.09 - 2018.11

dataActualScaled = scaler.transform(dataActual[['revCum']].values)
dataPredictLstm = estLstm(dataPast, 28*3) # Stateless LSTM for 3 month estimation
dataPredictLstmStateful = estLstmStateful(dataPast, 28*3) # Stateful LSTM for 3 month estimation
dataPredictLstmCombined = estLstmCombined(dataPast, 28*3)

### Plot : Actual vs DNN vs LSTM(Stateless) vs LSTM(Stateful)
fig, ax = plt.subplots(2,1, figsize=(18,10))
plt.rc('font', size=8)
ax[0].plot(dataActualScaled, color='red', label='Actual')
ax[0].plot(dataPredictLstm, color='green', alpha=0.5, label='LSTM Stateless')
ax[0].plot(dataPredictLstmStateful, color='orange', alpha=0.5, label='LSTM Stateful')
ax[0].plot(dataPredictLstmCombined, color='purple', alpha=0.5, label='LSTM Combined')
ax[0].set_title('Cumulative Revenue : Actual vs DNN vs LSTM(Stateless) vs LSTM(Stateful) : from 2018-09 to 2018-11\n * Peak points are total revenue of each months')
ax[0].set_ylabel('Cumulative Revenue'); ax[0].legend(loc='best')

ax[1].plot(dataActualScaled, color='red', label='Actual')
ax[1].plot(dataPredictLstm, color='green', alpha=0.5, label='LSTM Stateless')
ax[1].plot(dataPredictLstmStateful, color='orange', alpha=0.5, label='LSTM Stateful')
ax[1].plot(dataPredictLstmCombined, color='purple', alpha=0.5, label='LSTM Combined')
ax[1].set_title('Magnify Peaks')
ax[1].set_ylabel('Cumulative Revenue'); ax[1].legend(loc='best')
ax[1].set_ylim(dataActualScaled.max()*0.95, dataActualScaled.max()*1.05)

plt.show()
    # Stateless LSTM model is slighty better than Statelful LSTM model. I take Stateless LSTM model

### RMSE of each Models
print(dataActualScaled[27::28]) # Total revenue of each month

rmseLSTM = math.sqrt(mean_squared_error(dataActualScaled[27::28], dataPredictLstm[27::28]))
rmseLSTMStateful = math.sqrt(mean_squared_error(dataActualScaled[27::28], dataPredictLstmStateful[27::28]))
rmseLSTMCombined = math.sqrt(mean_squared_error(dataActualScaled[27::28], dataPredictLstmCombined[27::28]))
rmseData = DataFrame([rmseLSTM, rmseLSTMStateful, rmseLSTMCombined], index=['Stateless', 'Stateful', 'Combined'], columns=['RMSE'])

print('# RMSE of 3 Models #\n', rmseData, sep='') # Combined model has lowest mean squared error


"""Autoupdate older conda dependencies in the requirements section."""
from __future__ import absolute_import

import collections
import re
import xml.etree.ElementTree as ET

import packaging.version
import requests
from galaxy.tool_util.deps import conda_util

import planemo.conda
from planemo.io import error, info

def find_macros(xml_tree):
    """
    Get macros from the XML tree
    """
    macros = []
    for macro_import in xml_tree.iter("import"):
        macros.append(macro_import.text)
    return macros

def get_requirements(xml_tree):
    """
    Get requirements from the XML tree
    """
    requirements = {}
    main_req = None
    for requirement in xml_tree.iter("requirement"):
        if requirement.attrib.get('version') == '@TOOL_VERSION@':
            main_req = requirement.text
        else:
            requirements[requirement.text] = {'tag': ET.tostring(requirement, encoding="unicode").strip(), 'text': requirement.attrib.get('version')}
    return requirements, main_req

def get_tokens(xml_tree):
    """
    Get tokens from the XML tree
    """
    tokens = {}
    for token in xml_tree.iter("token"):
        tokens[token.attrib['name']] = {'tag': ET.tostring(token, encoding="unicode").strip(), 'text': token.text}
    return tokens

def check_conda(tool_name, ctx, **kwds):
    """
    Get the most up-to-date conda version for a tool requirement
    """
    conda_context = planemo.conda.build_conda_context(ctx, **kwds)
    if not conda_context.is_conda_installed():
        # check directly via Anaconda API
        r = requests.get('https://api.anaconda.org/search', params={'name': tool_name})
        search_results = sum([n['versions'] for n in r.json() if n['name'] == tool_name and n['owner'] in kwds['conda_ensure_channels']], [])
        return sorted(search_results, key=lambda n: packaging.version.parse(n))[-1]

    target = planemo.conda.conda_util.CondaTarget(tool_name)
    search_results = conda_util.best_search_result(target, conda_context=conda_context)
    return search_results[0]['version']

def update_xml(tool_path, xml_tree, tags_to_update, wrapper_version_token, is_macro=False):
    """
    Write modified XML to tool_path
    """
    def update_token(xml_text, tag, token_value):
        new_tag = f'>{token_value}<'.join(re.split('>.*<', tag))
        return re.sub(tag, new_tag, xml_text)

    def update_requirement(xml_text, tag, requirement_value):
        new_tag = f'version="{requirement_value}"'.join(re.split('version=".*"', tag))
        return re.sub(tag, new_tag, xml_text)

    with open(tool_path, 'r+', newline='') as f:
        xml_text = f.read()
        for tag_to_update in tags_to_update:
            if tag_to_update['type'] == 'token':
                xml_text = update_token(xml_text, tag_to_update['tag'], tag_to_update['value'])
            if tag_to_update['type'] == 'requirement':
                xml_text = update_requirement(xml_text, tag_to_update['tag'], tag_to_update['value'])
        if wrapper_version_token == 0 and not is_macro:
            # i.e. @VERSION_SUFFIX@ not specified so update the version directly in the tool tag
            tool_tag = re.sub('version="@TOOL_VERSION@.*?"', 'version="@TOOL_VERSION@+galaxy0"',
                              re.findall('<tool .*version="@TOOL_VERSION@.*">', xml_text)[0])
            xml_text = re.sub('<tool .*version="@TOOL_VERSION@.*">', tool_tag, xml_text)
        f.seek(0)
        f.truncate()
        f.write(xml_text)

def create_requirement_dict(xml_files, skip_reqs):
    """
    Create dict with requirements and find main requirement
    """
    requirements = {}
    main_req = None
    for k, v in xml_files.items():
        file_reqs, file_main_req = get_requirements(v)
        requirements[k] = {k: v for k, v in file_reqs.items() if k not in skip_reqs}
        if file_main_req:
            if main_req:
                error('Multiple requirements use the token @TOOL_VERSION@!')
            main_req = (file_main_req, k)
    if not main_req:
        error('No requirement uses the token @TOOL_VERSION@!')
    return requirements, main_req

def create_token_dict(ctx, xml_files, main_req, **kwds):
    """
    Create dict with relevant tokens and check conda requirements for main
    """
    tokens = {}
    current_main_req, updated_main_req = None, None
    xml_to_update = collections.defaultdict(list)
    for k, v in xml_files.items():
        tokens[k] = get_tokens(v)
        # check if it is @TOOL_VERSION@ and if so do check_conda
        if '@TOOL_VERSION@' in tokens[k]:
            current_main_req = tokens[k]['@TOOL_VERSION@']['text']
            updated_main_req = check_conda(main_req[0], ctx, **kwds)
            if current_main_req:
                xml_to_update[k].append({'type': 'token', 'tag': tokens[k]['@TOOL_VERSION@']['tag'], 'value': updated_main_req})

    return tokens, xml_to_update, current_main_req, updated_main_req

def perform_required_update(ctx, xml_files, tool_path, requirements, tokens, xml_to_update, wrapper_version_token, **kwds):
    """
    Carry out the update, if requirements are out-of-date
    """
    # check all requirements
    for k, v in requirements.items():
        for req in v:
            req_check = check_conda(req, ctx, **kwds)
            # print(req_check, v[req]['text'])
            if req_check != v[req]['text']:
                xml_to_update[k].append({'type': 'requirement', 'tag': v[req]['tag'], 'value': req_check})

    # check all tokens, if wrapper_version_token exists
    if wrapper_version_token:
        for k, v in tokens.items():
            if wrapper_version_token in v:
                xml_to_update[k].append({'type': 'token', 'tag': v[wrapper_version_token]['tag'], 'value': 0})

    # finally, update each file separately
    for k, v in xml_files.items():
        update_xml(k, v, xml_to_update[k], wrapper_version_token, is_macro=(k != tool_path))
    info(f"Tool {tool_path} successfully updated.")
    return set(xml_files)

def autoupdate_tool(ctx, tool_path, modified_files=set(), **kwds):
    """
    Autoupdate an XML file
    """
    # create a dict of all files that need editing - wrapper plus macros
    xml_files = {tool_path: ET.parse(tool_path)}

    # get name of token which defines the wrapper version; if just an integer, None
    versions = xml_files[tool_path].getroot().attrib.get('version')
    if versions:
        versions = versions.split('+galaxy')
        if versions[0] != '@TOOL_VERSION@':
            error('Tool version does not contain @TOOL_VERSION@ as required by autoupdate.')
            return
        elif len(versions) == 1:
            wrapper_version_token = None
        else:
            if versions[1][0] == versions[1][-1] == '@':
                wrapper_version_token = versions[1]
            else:
                wrapper_version_token = 0  # assume an int
    else:
        wrapper_version_token = None

    # add macros to xml_files
    for macro in find_macros(xml_files[tool_path]):
        macro_path = '/'.join(tool_path.split('/')[:-1] + [macro])
        xml_files[macro_path] = ET.parse(macro_path)

    requirements, main_req = create_requirement_dict(xml_files, kwds.get('skip_requirements', '').split(','))
    tokens, xml_to_update, current_main_req, updated_main_req = create_token_dict(ctx, xml_files, main_req, **kwds)

    if current_main_req == updated_main_req and not (modified_files & set(xml_files)):
        info(f"No updates required or made to {tool_path}.")
        return  # end here if no update needed

    if kwds.get('dry_run'):
        error(f"Update required to {tool_path}! Tool main requirement has version {current_main_req}, newest conda version is {updated_main_req}")
        return

    else:
        info(f"Updating {tool_path.split('/')[-1]} from version {current_main_req} to {updated_main_req}")
        return perform_required_update(ctx, xml_files, tool_path, requirements, tokens, xml_to_update, wrapper_version_token, **kwds)

def _update_wf(config, workflow_id, instance=False):
    """
    Recursively update a workflow, including subworkflows
    """
    wf = config.user_gi.make_get_request(f'{config.user_gi.url}/workflows/{workflow_id}', params={'instance': instance}).json()
    for step in wf['steps'].values():
        if step['type'] == 'subworkflow':
            # update subworkflows before the main workflow
            _update_wf(config, step['workflow_id'], instance=True)
    config.user_gi.workflows.refactor_workflow(workflow_id, actions=[{"action_type": "upgrade_all_steps"}])

def autoupdate_wf(ctx, config, wf):
    workflow_id = config.workflow_id_for_runnable(wf)
    _update_wf(config, workflow_id)
    return config.user_gi.workflows.export_workflow_dict(workflow_id)


import os
import glob
import json
from joblib import Parallel, delayed

from ..retino_HCP.utils import *

with open('../settings.json') as f:
    json_s = f.read()
    analysis_info = json.loads(json_s)

base_dir = analysis_info['cluster_base_folder']

subject_directories = [fn for fn in glob.glob(os.path.join(base_dir, '*')) if os.path.isdir(fn)]

for sd in subject_directories:
    for hemi in ["L","R"]: # gifti files are separated into different hemis
        # get ordered files
        rawest_gii_files = [glob.glob(os.path.join(sd, '*%s*_%s.func.gii'%(run, hemi)))[0] for run in analysis_info["run_order"]]
        # temporal preprocessing

        pp_out_files = Parallel(n_jobs=6)(delayed(sg_psc_gii)(gii_file) for gii_file in rawest_gii_files)

        # each pair averaged:
        av_wedge_file = average_phase_encoded_giis(pp_out_files[0],pp_out_files[1])
        av_ring_file = average_phase_encoded_giis(pp_out_files[2],pp_out_files[3])
        av_bar_file = average_bar_giis(pp_out_files[4],pp_out_files[5])

#################################################################################
#####
#####   conversion to GII
#####
#################################################################################

with open('../settings.json') as f:
    json_s = f.read()
    analysis_info = json.loads(json_s)

base_dir = analysis_info['cluster_base_folder']

subject_directories = sorted([fn for fn in glob.glob(os.path.join(base_dir, '*')) if os.path.isdir(fn)])

for sd in subject_directories[:10]:
    cii_files = glob.glob(os.path.join(sd,'*av_est.nii'))

    wbc = """wb_command -cifti-separate {cii} \
 COLUMN -volume-all {cii_n}_data_sub.nii \
 -metric CORTEX_LEFT {cii_n}_L.func.gii \
 -metric CORTEX_RIGHT {cii_n}_R.func.gii &"""

    for cii in cii_files:
        wbc_c = wbc.format(cii=cii, cii_n=cii[:-4])

        # if cii == cii_files[-1]:
        #     wbc_c = wbc_c[:-1]
        print(wbc_c)
        os.system(wbc_c)


from flask import session
from flask import redirect

from functools import wraps

debug = True

def login_required(f):
	'''
	Decorates routes to require login
	'''

	@wraps(f)
	def decorated_function(*args, **kwargs):
		if debug == True:
			session['user_id'] = '3'
			session['2fa_enabled'] = 'false'
			session['2fa_verified'] = 'true'

			# print session.get('user_id')
			# print session.get('2fa_enabled')
			# print session.get('2fa_verified')

		else:
			if session.get('user_id') == None:
				return redirect('/login')

			if session.get('2fa_enabled') == 'true' and session.get('2fa_verified') != 'true':
				return redirect('/otp')

		return f(*args, **kwargs)
	return decorated_function


# site settings rest api serializers

from rest_framework import serializers
from app_dir.modules.finance.fee.models import FeeStructure as Table
from app_dir.modules.finance.fee.models import FeeItem as Item
from structlog import get_logger
import re

logger = get_logger(__name__)
global fields, module
module = 'fee'
fields = ('id',
          'name',
          'academic_year',
          'course',
          'term',
          'compulsory_amount',
          'amount')

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = (
                'id',
                'name',
                'amount',
                'compulsory',
                'choice')

class TableListSerializer(serializers.ModelSerializer):
    academic_name = serializers.SerializerMethodField()
    course_name = serializers.SerializerMethodField()
    term_name = serializers.SerializerMethodField()
    update_url = serializers.HyperlinkedIdentityField(view_name=module+':update')
    update_view_url = serializers.HyperlinkedIdentityField(view_name=module+':update-view')
    delete_url = serializers.HyperlinkedIdentityField(view_name=module+':api-delete')
    fee_items = ItemSerializer(many=True)

    class Meta:
        model = Table
        fields = fields + ('course_name', 'term_name', 'academic_name', 'update_view_url', 'update_url', 'delete_url', 'fee_items',)

    def get_academic_name(self, obj):
        try:
            return obj.academic_year.name
        except:
            return ''

    def get_course_name(self, obj):
        try:
            return obj.course.name
        except:
            return ''

    def get_term_name(self, obj):
        try:
            return obj.term.name
        except:
            return ''

class CreateListSerializer(serializers.ModelSerializer):
    fee_items = serializers.JSONField(write_only=True)

    class Meta:
        model = Table
        fields = fields + ('fee_items',)

    def create(self, validated_data):
        instance = Table()
        if validated_data.get('academic_year'):
            instance.academic_year = validated_data.get('academic_year')
        if validated_data.get('term'):
            instance.term = validated_data.get('term')
        if validated_data.get('course'):
            instance.course = validated_data.get('course')
        if validated_data.get('amount'):
            instance.amount = validated_data.get('amount')
        try:
            fee_items = validated_data.pop('fee_items')
        except:
            raise serializers.ValidationError('Fee items field should not be empty')

        instance.save()

        for fee_item in fee_items:
            fee_item['id'] = None
            fee_item['name'] = re.sub(r'\d', '', fee_item['name']).replace('[.]','')
            try:
                fee_item['choice']['id'] = fee_item['_id']
            except:
                pass
            del fee_item['values']
            del fee_item['update_url']
            del fee_item['update_view_url']
            del fee_item['delete_url']
            del fee_item['_id']
            logger.info(fee_item)
            Item.objects.create(fee=instance, **fee_item)

        return instance

class UpdateSerializer(serializers.ModelSerializer):
    values = serializers.JSONField(write_only=True)
    fee_items = ItemSerializer(many=True, required=False)

    class Meta:
        model = Table
        fields = fields + ('fee_items', 'values')

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.academic_year = validated_data.get('academic_year', instance.academic_year)
        instance.term = validated_data.get('term', instance.term)
        instance.course = validated_data.get('course', instance.course)
        instance.amount = validated_data.get('amount', instance.amount)

        try:
            fee_items = validated_data.pop('values')
        except:
            raise serializers.ValidationError('Fee items field should not be empty')

        instance.save()
        instance.fee_items.all().delete()
        for fee_item in fee_items:
            fee_item['id'] = None
            logger.info(fee_item.get('compulsory'))
            fee_item['name'] = re.sub(r'\d', '', fee_item['name']).replace('[.]','')
            try:
                del fee_item['update_url']
                del fee_item['delete_url']
                del fee_item['update_view_url']
                del fee_item['_id']
                del fee_item['values']
                del fee_item['value']
                fee_item['choice']['id'] = fee_item['_id']
            except:
                pass

            try:
                fee_item['choice']['id'] = int(fee_item['choice']['id'])
            except:
                pass

            logger.info(fee_item)
            Item.objects.create(fee=instance, **fee_item)

        return instance