import os
from deeppavlov import configs, train_model, build_model
from deeppavlov.core.common.file import read_json

class DeepPavlovWrapper:
	def fit_model(self):
		self.model_config = read_json(configs.doc_retrieval.ru_ranker_tfidf_wiki)
		self.model_config["dataset_reader"]["data_path"] = os.path.abspath(os.getcwd())+"/Resourses"
		self.model_config["dataset_reader"]["dataset_format"] = "txt"
		self.model_config["train"]["batch_size"] = 100
		print("work!")
		self.doc_retrieval = train_model(self.model_config)
		self.squad = build_model(configs.squad.squad_ru_rubert_infer, download=True)
		self.odqa = build_model(configs.odqa.ru_odqa_infer_wiki_rubert, download=False)

	def get_answer_on_question(self, question):
		answers = self.odqa([question])
		print(answers)
		return answers


import numpy as np
import matplotlib.pyplot as plt

def lin_reg(X,Y,a,itr):
    m = X.shape[0]
    w,b = 0,0

    for i in range(itr):
        Y_pred = w * X + b
        dw = (1/m) * np.sum((Y_pred - Y) * X)
        db = (1/m) * np.sum((Y_pred - Y))
        w = w - a * dw
        b = b - a * db

    return (w,b)

train_data = np.loadtxt("train.csv",skiprows=1,delimiter=',')
X_train = train_data[:,0]
Y_train = train_data[:,1]

w,b = lin_reg(X_train,Y_train,0.00001,10000)

test_data = np.loadtxt("test.csv",skiprows=1,delimiter=',')
X_test = test_data[:,0]
Y_test = test_data[:,1]

c = X_test.shape[0]
Y_test_pred = w * X_test + b

rmse = (np.sum((Y_test_pred - Y_test) ** 2)/c)**0.5
print(rmse)

plt.scatter(X_train,Y_train,s=10,label='Train Values')
plt.scatter(X_test,Y_test_pred,s=10,c='red',label = 'Predicted Values')
plt.legend()
plt.show()


#!/usr/bin/env python
# coding: utf-8

#
#
# ### Step 1. Import the necessary libraries

# In[27]:

import pandas as pd

# ### Step 2. Import the dataset Euro_2012_stats_TEAM

# ### Step 3. Assign it to a variable called euro12.

# In[176]:

euro12 = pd.read_csv("Euro_2012_stats_TEAM.csv")
euro12

# ### Step 4. Select only the Goal column.

# In[162]:

euro = (euro12['Goals'])
euro

# ### Step 5. How many team participated in the Euro2012?

# In[145]:

euro = len(euro12)
print("Numbers of Team participated: ",euro)

# ### Step 6. What is the number of columns in the dataset?

# In[178]:

euro = len(euro12.columns)
print("Numbers of Columns: ",euro)

# ### Step 7. View only the columns Team, Yellow Cards and Red Cards and assign them to a dataframe called discipline

# In[34]:

discipline = pd.read_csv("Euro_2012_stats_TEAM.csv" , usecols = ['Yellow Cards', 'Red Cards'])
discipline

# ### Step 8. Sort the teams by Red Cards, then to Yellow Cards

# In[146]:

euro1 = discipline.sort_values(by=['Red Cards' , 'Yellow Cards'])
euro1

# ### Step 9. Calculate the mean Yellow Cards given per Team

# In[149]:

e = df["Yellow Cards"].mean()
print("Mean Yellow Card Given per Team: %.1f" %e)

# ### Step 10. Filter teams that scored more than 6 goals

# In[150]:

is_6 = euro12['Goals']>6
euro_6 = euro12[is_6]
print(euro_6.head)

# ### Step 11. Select the teams that start with G

# In[155]:

euro = euro12[5:7]
euro

# ### Step 12. Select the first 7 columns

# In[156]:

euro = euro12.iloc[:,0:7]
euro

# ### Step 13. Select all columns except the last 3.

# In[157]:

euro = euro12.iloc[:,:-3]
euro

# ### Step 14. Present only the Shooting Accuracy from England, Italy and Russia

# In[158]:

euro = euro12.loc[[3,7,12],["Team","Shooting Accuracy"]]
euro

# ### Step 15. Use apply method on Goal Column to make a new column called Performance, using following conditions
#
# 1. If Goals are less than or equal to 2, peformance is **Below Avg**
# 2. If Goals are more than 2 and less than or equal to 5, peformance is **Average**
# 3. If Goals are more than 5 and less than or equal to 10, peformance is **Above Average**
# 4. If Goals are more than 10 then peformance is **Excellent**

# In[159]:

def performance(x):
    if x <= 2:
        return "Below Average"
    elif x > 2 and x <= 5:
        return "Average"
    elif x > 5 and x <= 10:
        return "Above Average"
    elif x > 10:
        return "Excellent"
euro12["Performance"] = euro12["Goals"].apply(performance)
euro12[["Team","Goals","Performance"]]

# In[ ]:


import pandas as pd
import re
import torch
from tqdm import tqdm
from sklearn.metrics import confusion_matrix

class RuleBasedModel():
    def __init__(self, offensive_dictionary : pd.DataFrame, ambiguous_dictionary : pd.DataFrame, ner_tokenizer, ner_model, ner_labels, preprocessor):
        self.offensive_dictionary = offensive_dictionary
        self.ambiguous_dictionary = ambiguous_dictionary
        self.ner_tokenizer = ner_tokenizer
        self.ner_model = ner_model
        self.ner_labels = ner_labels
        self.preprocessor = preprocessor

    def offensive_rulebased_model(self, tweet : str):
        for index, row in self.offensive_dictionary.iterrows():
            if row['SearchType'] == 'normal':
                if re.search(row['Word'], tweet) is not None:
                    return 1, row['Word']
            if row['SearchType'] == 'before':
                if re.search("[^\u0622-\u06CC]" + row['Word'], tweet) is not None or re.search("^" + row['Word'], tweet) is not None:
                    return 1, row['Word']
            if row['SearchType'] == 'after':
                if re.search(row['Word'] + "[^\u0622-\u06CC]", tweet) is not None or re.search(row['Word'] + "$", tweet) is not None:
                    return 1, row['Word']
            if row['SearchType'] == 'both':
                if re.search("[^\u0622-\u06CC]" + row['Word'] + "[^\u0622-\u06CC]", tweet) is not None or \
                    re.search("^" + row['Word'] + "[^\u0622-\u06CC]", tweet) is not None or \
                    re.search("[^\u0622-\u06CC]" + row['Word'] + "$", tweet) is not None or \
                    re.search("^" + row['Word'] + "$", tweet) is not None:
                    return 1, row['Word']
        return 0, ""

    def ner_rulebased_model(self, tweet : str):
        tokens = self.ner_tokenizer.tokenize(self.ner_tokenizer.decode(self.ner_tokenizer.encode(tweet)))
        inputs = self.ner_tokenizer.encode(tweet, return_tensors="pt")
        outputs = self.ner_model(inputs)[0]
        predictions = torch.argmax(outputs, axis=2)
        predictions = [(token, self.ner_labels[prediction]) for token, prediction in zip(tokens, predictions[0].numpy())]
        for i, (token, token_type) in enumerate(predictions):
            if token_type != 'O' and predictions[i+1][0] in list(self.ambiguous_dictionary.loc[self.ambiguous_dictionary["jointNER"]==1]['Word']):
                return 1, token +" "+ predictions[i+1][0]
        return 0, ""

    def __call__(self, tweet : str):
      predicted, keyword = self.offensive_rulebased_model(tweet)
      if predicted == 1:
          return predicted, keyword, "Offensive"
      else:
          predicted, keyword = self.ner_rulebased_model(tweet)
      if predicted == 1:
          return predicted, keyword, "NER"
      else:
        return 0, "", ""

    def run(self, dataset, mod):
        TP_List = pd.DataFrame(columns=["id", "keyword", "tweet", "model_decision"])
        FP_List = pd.DataFrame(columns=["id", "keyword", "tweet", "model_decision"])
        FN_List = pd.DataFrame(columns=["id", "tweet", "model_decision"])
        TN_List = pd.DataFrame(columns=["id", "tweet", "model_decision"])
        y_pred = []
        y_true = []
        for index, tweetrow in tqdm(dataset.iterrows()):
            inputtweet = tweetrow['tweet']

            inputId = tweetrow['id']
            inputtweet = self.preprocessor(inputtweet)
            predicted, foundword, model_decision = self(inputtweet)
            y_pred.append(predicted)
            if mod == "inference":
                continue

            inputlabel = tweetrow['label']
            y_true.append(inputlabel)

            if predicted == 1 and inputlabel == 1:
                new_record = pd.DataFrame([[inputId, foundword, inputtweet, model_decision]], columns=["id", "keyword", "tweet", "model_decision"])
                TP_List = pd.concat([TP_List, new_record])
            if predicted == 1 and inputlabel == 0:
                new_record = pd.DataFrame([[inputId, foundword, inputtweet, model_decision]], columns=["id", "keyword", "tweet", "model_decision"])
                FP_List = pd.concat([FP_List, new_record])
            if predicted == 0 and inputlabel == 1:
                new_record = pd.DataFrame([[inputId, inputtweet, model_decision]], columns=["id", "tweet", "model_decision"])
                FN_List = pd.concat([FN_List, new_record])
            if predicted == 0 and inputlabel == 0:
                new_record = pd.DataFrame([[inputId, inputtweet, model_decision]], columns=["id", "tweet", "model_decision"])
                TN_List = pd.concat([TN_List, new_record])
        conf = None
        if mod == "eval":
            conf = confusion_matrix(y_true, y_pred)
        return y_true, y_pred, TP_List, FP_List, FN_List, TN_List, conf


import numpy as np
import biorbd_casadi as biorbd

def to_spatial_vector(f_ext: np.ndarray) -> biorbd.VecBiorbdSpatialVector:
    """
    Converts a 6 x n_external_force np.array into biorbd spatial vector

    Parameters
    ----------
    f_ext: np.ndarray
        The array to convert

    Returns
    -------
    The converted array
    """

    vector = biorbd.VecBiorbdSpatialVector()
    for idx in range(f_ext.shape[1]):
        vector.append(biorbd.SpatialVector(f_ext[:, idx]))
    return vector

def transport_spatial_force(
        spatial_force:  biorbd.SpatialVector,
        current_application_point: np.ndarray,
        new_application_point: np.ndarray,
) -> biorbd.SpatialVector:
    """
    Transports a spatial force from one point to another
    """

    forces = spatial_force.to_mx()[3:]
    torques = spatial_force.to_mx()[:3]
    # Torque transport, Bour's formula
    torques += np.cross(current_application_point - new_application_point,
            forces)

    return biorbd.SpatialVector(np.concatenate((torques, forces)))

class ExternalForce:
    """
    This class allow to manage external forces efficiently
    """
    def __init__(self,
                 force_in_global: np.ndarray,
                 torque_in_global: np.ndarray,
                 application_point_in_global: np.ndarray,
                ):
        """
        Parameters
        ----------
        force_in_global: np.ndarray
            The force in global reference frame
        torque_in_global: np.ndarray
            The torque in global reference frame
        application_point_in_global: np.ndarray
            The application point in global reference frame
        """
        self._force_in_global = force_in_global
        self._torque_in_global = torque_in_global
        self._application_point_in_global = application_point_in_global

    @property
    def spatial_vector_at_origin(self):
        """
        Returns
        -------
        The spatial vector at the origin. This is the required format for the external forces in biorbd
        and in the formalism of Featherstone (Rigid Body Dynamics Algorithm)
        """

        spatial_vector = transport_spatial_force(
            biorbd.SpatialVector(np.concatenate((self._torque_in_global, self._force_in_global))),
            self._application_point_in_global,
            np.zeros(3),
        )

        return spatial_vector

    @property
    def spatial_vector(self):
        """
        Returns
        -------
        The spatial vector.
        """

        return biorbd.SpatialVector(np.concatenate((self._torque_in_global, self._force_in_global)))

    @classmethod
    def from_local_coordinate_system(cls,
                                     force_in_local: np.ndarray,
                                     torque_in_local: np.ndarray,
                                     application_point_in_local: np.ndarray,
                                     rototranslation_of_local_system_in_global: np.ndarray,
                                     ):
        """
        This function creates an external force from a local coordinate system

        Parameters
        ----------
        force_in_local: np.ndarray
            The force in local reference frame
        torque_in_local: np.ndarray
            The torque in local reference frame
        application_point_in_local: np.ndarray
            The application point in local reference frame
        rototranslation_of_local_system_in_global: np.ndarray
            The rototranslation of the local system in global reference frame [4 x 4], aka homogeneous matrix

        Returns
        -------
        The external force object
        """

        # Convert the force and torque to global reference frame
        force_in_global = rototranslation_of_local_system_in_global[:3, :3] @ force_in_local
        torque_in_global = rototranslation_of_local_system_in_global[:3, :3] @ torque_in_local

        # Convert the application point to global reference frame
        application_point_in_global = (rototranslation_of_local_system_in_global[:3, :3] @ application_point_in_local
                                       + rototranslation_of_local_system_in_global[:3, 3])

        return cls(force_in_global, torque_in_global, application_point_in_global)


from .swarmclient import SwarmClient
from .swarmmanager import SwarmManager
from .udpserver import UDPServer
from .commcodes import coco

from . import onedrone as mavlink

import struct
import logging
import socket
import threading
import time

logger = logging.getLogger(__name__)

#from pymavlink.dialects.v20 import ardupilotmega as mavlink2

class Mavpacker(object):

    def __init__(self, udpserver : UDPServer):
        self.output = open('mavpacker.log','wb')
        self.mav = mavlink.MAVLink(self.output)
        self.mav.robust_parsing= True
        self.udp_server = udpserver
        self.client = None

    def __del__(self):
        self.output.close()

    def check_client(self, client: SwarmClient):
        self.client = client
        packet_buffer=client.packet_buffer
        packet_buffer.process_packet_buffer()
        if (not len(packet_buffer.stream_buffer)):
            return
        packet_buffer.stream_buffer_lock.acquire()
        self.mav.buf = packet_buffer.stream_buffer
        self.mav.buf_index = 0
        self.parse_mav_buffer()

        #remove buffer elements that have been already parsed
        packet_buffer.stream_buffer = self.mav.buf[self.mav.buf_index:]
        packet_buffer.stream_buffer_lock.release()

    def parse_mav_buffer(self):
        continue_parsing = True
        old_buf_index = 0
        while continue_parsing:
            try:
                msg = self.mav.parse_char('')
                if msg:
                    self.handle_mav_msg(msg)
                elif msg ==None :
                    if self.mav.buf_index and (old_buf_index != self.mav.buf_index) :
                        logger.info(f'MAVPACK | Dropping bad data because of No MAVLINK Message:{self.mav.buf[old_buf_index]}')

            except mavlink.MAVError:
                self.mav.buf_index =old_buf_index + 1
                logger.info(f'MAVPACK | Dropping bad data because of MAVError:{self.mav.buf[old_buf_index]}')

            #check if end condition is met
            if old_buf_index == self.mav.buf_index:
                continue_parsing= False
            else:
                old_buf_index = self.mav.buf_index

    def handle_mav_msg(self, msg):
            client =  self.client

            if msg.get_msgId() == -1 : # Bad Data!
                logger.debug(f'MAVPACK | Dropping data because of BAD DATA Mavlink Message:{msg.get_msgbuf()}')
            else:
                if msg._header.srcSystem == client.id:
                    client.mav_id_correct = True
                    self.udp_server.publish_via_udp(msg.get_msgbuf())
                    try:
                        logger.info(f'MAVPACK | Sending as SrcSystem {msg._header.srcSystem} via upd: {msg.to_json()}')
                    except TypeError:
                        logger.debug(f'MAVPACK | Sending via udp RAW {msg.get_msgbuf()}')

                else:
                    logger.warning(f'MAVPACKER|  Client #{client.id:04x} tried to send as #{msg._header.srcSystem:02x} MSG: {msg.to_json()}')
                    client.mav_id_correct = False
                    self.set_client_id(client)

    def set_client_id(self, client:SwarmClient):

        if time.time() - client.mav_id_request_sent > 2:
            logger.debug(f'MAVPACKER| Setting Client ID for Client #{client.id:04x}')

            # send new SYSID
            param_id= b"SYSID_THISMAV"
            param_value = client.id / 1.0
            param_type = mavlink.MAV_PARAM_TYPE_INT16
            msg = self.mav.param_set_encode(0, 0, param_id, param_value, param_type)
            client.tx_lock.acquire()
            client.tx_buffer = bytearray(msg.pack(self.mav))
            client.tx_lock.release()

            #request reboot
            msg = self.mav.command_long_encode(0, 0, mavlink.MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 0, 1, 1, 0, 0, 0, 0, 0)

            client.tx_lock.acquire()
            client.tx_buffer += bytearray(msg.pack(self.mav))
            client.tx_lock.release()

            client.mav_id_request_sent = time.time()
        else:
            logger.debug(f'MAVPACKER | Not sending MAV ID request again')

    def request_client_id(self, client:SwarmClient):
        param_id= b"SYSID_THISMAV"
        param_index = 1
        msg = self.mav.param_request_read_encode(0,0,param_id, param_index)
        client.tx_lock.acquire()
        client.tx_buffer += msg.pack(self.mav)
        client.tx_lock.release()

    def request_parameters(self, client:SwarmClient):
        logger.info('MAVPACK | Requesting parameters')
        msg = self.mav.MAVLink_param_request_list_message(0,0)
        client.tx_lock.acquire()
        client.tx_buffer += msg.pack(self.mav)
        client.tx_lock.release()


from nltk.corpus import wordnet as wn

def verb_or_not(word):
    '''
    # AN EXAMPLE USAGE: Determine whether a word is a verb (that can be potentially treated as an event)
    words = ['left', 'led', 'Food', 'temperature', 'sicknesses']
    for w in words:
        print(verb_or_not(w))
    '''
    for meaning in wn.synsets(word):
        if meaning.pos() == 'v':
            return 1
    return 0

import json
import requests
import pprint
from datetime import datetime
pp = pprint.PrettyPrinter(indent=4)

def ee_to_ta(file_name, extracted_events):
    '''
    ee_to_ta converter: from event extraction result to ta
    event extraction version: the one that outputs "extracted_events.json" at Jul 22, 2021 06:15
    file path: /shared/hzhangal/Projects/zero-event-extraction/quizlet6/quizlet6_data/extracted_events.json

    input:
    @file_name: e.g., 'quizlet6_data/L0C04CJ13.rsd.txt'
    @extracted_events: the dict loaded from "extracted_events.json"

    output:
    extracted_events in ta format
    '''
    fname = file_name.split("/")[1]
    #original_content = extracted_events[file_name]['original_content']  # too noisy, so abort
    #sentences = extracted_events[file_name]['sentences']  # too noisy, so abort
    #text = ' '.join(sentences)
    events = extracted_events[file_name]['events']
    text = ''

    '''prepare for ta slots'''
    tokens = []
    relations = []
    constituents = []
    sentEndPos = []
    sentence_id = -1
    for sent in events:
        if len(sent) > 0:  # ignore the sent if it's blank (of great possibility)
            sentence_id += 1
            tokens.extend(sent[0]['tokens'])
            text += ' '.join(sent[0]['tokens'])
            text += ' '
            sentEndPos.append(len(text))
        for event in sent:
            trigger  = ' '.join(sent[0]['tokens'][event['trigger']['position'][0]:event['trigger']['position'][1]])
            if verb_or_not(trigger):
                constituents.append({"start": event['trigger']['position'][0], \
                                     "end": event['trigger']['position'][1], \
                                     "label": "event", \
                                     "properties": {'sentence_id': sentence_id, \
                                                    'predicate': trigger,\
                                                    'SenseNumber': '', \
                                                    }, \
                                     "score": 1.0, \
                                     })

    '''start to construct ta from here'''
    ta = {}
    ta["corpusID"] = fname
    ta["id"] = ""
    ta["sentences"] = {"generator": "ee_to_ta", "score":1.0, "sentenceEndPositions": sentEndPos}
    ta["text"] = text
    ta["tokens"] = tokens
    ta["views"] = [{"viewData": [{"constituents": constituents, \
                                  "generator": "cogcomp_kairos_event_ie_v1.0", \
                                  "relations": relations, \
                                  "score": 1.0, \
                                  "viewName": "event_extraction", \
                                  "viewType": 'edu.illinois.cs.cogcomp.core.datastructures.textannotation.PredicateArgumentView', \
                                 }],\
                    'viewName': 'Event_extraction'
                   }]
    return ta

def fullTextDuration(ta, out_f):
    url = 'http://127.0.0.1:5000/annotate_no_gurobi'
    payload = json.dumps(ta)
    file_name = ta["corpusID"]
    headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
    r = requests.post(url, data=payload, headers=headers)
    try:
        data = json.loads(r.text)
        print("Writing results for " + file_name + "...")
        with open(out_f, 'w') as outfile:
            json.dump(data, outfile)
        return 0

    except:
        print("ERROR occurs in processing " + file_name + "!")
        return 1

import operator
def order_by(origin, ee):
    '''
    Given the relations between each pair of events temporally, and also the distance between them
    We can construct a sequence of events
    On an axis, the event "origin" happens at time 0,
    if event A is before "origin" by distance of x, it happens at -x
    We can choose each event as an origin
    And induce n possible sequences of temporally ordered events
    We choose the most possible sequence that gets most votes
    '''
    event_map = {origin: 0}
    for relation in ee['views'][0]['viewData'][0]['relations']:
        if relation['srcConstituent'] == origin or relation['targetConstituent'] == origin:
            if relation['relationName'] == 'before':
                if relation['srcConstituent'] == origin:
                    event_map[relation['targetConstituent']] = relation['properties']['distance']
                else:
                    event_map[relation['srcConstituent']] = (-1) * relation['properties']['distance']
            else:
                if relation['srcConstituent'] == origin:
                    event_map[relation['targetConstituent']] = (-1) * relation['properties']['distance']
                else:
                    event_map[relation['srcConstituent']] = relation['properties']['distance']

    sorted_e = sorted(event_map.items(), key=operator.itemgetter(1))
    return [m[0] for m in sorted_e]

json_file = '/shared/hzhangal/Projects/zero-event-extraction/quizlet6/quizlet6_data/extracted_events.json'
dir_path = "/shared/why16gzl/Projects/KAIROS/Quizlet/Quizlet_6/te_out/"

with open(json_file) as f:
    ee = json.load(f)
    # Test
    #if True:
    #    file_name = "quizlet6_data/L0C04CJ13.rsd.txt"
    for file_name in ee.keys():
        ta = ee_to_ta(file_name, ee)
        out_f = dir_path + ta["corpusID"] + ".json"
        fullTextDuration(ta, out_f)
        with open(out_f) as f:
            ta = json.load(f)
        possible_timeline = {}
        for i in range(len(ta['views'][0]['viewData'][0]['constituents'])):
            temp_order = repr(order_by(i, ta))
            if temp_order not in possible_timeline.keys():
                possible_timeline[temp_order] = 1
            else:
                possible_timeline[temp_order] += 1

        ta['views'][0]['viewData'][0]['temporalOrder'] = max(possible_timeline.items(), key=operator.itemgetter(1))[0]
        now = datetime.now()
        ta['timestamp'] = now.strftime("%d/%m/%Y %H:%M:%S")
        with open(out_f, 'w') as outfile:
            json.dump(ta, outfile)


H, W = [int(hw) for hw in input().split()]
HW = []
for _ in range(H):
    A = [int(a) for a in input().split()]
    HW.append(A)

# 嬉しい経路数
ans = 0
# 経路全列挙
for order in range(2 ** (H + W - 2)):
    h, w = 0, 0
    # マスの管理
    seen = set()
    seen.add(HW[0][0])
    # 経路の管理
    for i in range(H + W - 2):
        print("order:", order, "i:", i, "h:", h, "w:", w, "value:", order >> i & 1)
        if order >> i & 1:
            h += 1
            # 外に出ちゃってる
            if h == H:
                break
            # 嬉しくない
            if HW[h][w] in seen:
                break

        else:
            w += 1
            # 外に出ちゃってる
            if w == W:
                break
            # 嬉しくない
            if HW[h][w] in seen:
                break
        seen.add(HW[h][w])
    else:
        print(seen)
        ans += 1
print(ans)


from flask import request
from functools import wraps
from webview import token as wv_token

from server.error import UAError
from server.error import CSRFError

import os

PYWEBVIEW_UA = "pywebview-client/1.0 pywebview-ui/3.0.0"
ui_dev = os.environ.get("UI_APP_DEV", default=None)
app_dev = os.environ.get("APP_DEV", default=None)

def verify_csrf(function):
    """
    verify csrf token
    """

    @wraps(function)
    def verify_csrf_token(*args, **kwargs):
        if ui_dev or app_dev:
            return function(*args, **kwargs)

        try:
            token_header = request.headers["PCSRFWV-Token"]

            if token_header == wv_token:
                return function(*args, **kwargs)

            elif token_header != wv_token:
                raise CSRFError("CSRFHeaderInvalid", "CSRF Header Invalid", 401)

        except KeyError:
            if KeyError:
                raise CSRFError("CSRFHeaderMissing", "CSRF Header Missing", 401)

    return verify_csrf_token

def verify_ua(function):
    """
    verify user agent
    """

    @wraps(function)
    def verify_user_agent(*args, **kwargs):
        if ui_dev or app_dev:
            return function(*args, **kwargs)

        try:
            headers = request.headers["User-Agent"]
            if headers == PYWEBVIEW_UA:
                return function(*args, **kwargs)

            else:
                raise UAError("UANotAccepted", "User Agent not accepted", 401)
        except:
            raise UAError("UANotAccepted", "User Agent not accepted", 401)

    return verify_user_agent


import numpy as np
from matplotlib import gridspec
import matplotlib.pyplot as plt
import ROOT

def readFile(filename):
    Etrue, totpe, sigma, sigmaErr = [], [], [], []
    with open(filename) as f:
        for lines in f.readlines():
            line = lines.strip("\n")
            data = line.split(" ")
            Etrue.append(float(data[0]))
            totpe.append(float(data[1]))
            sigma.append(float(data[2]))
            sigmaErr.append(float(data[3]))

    Etrue = np.array(Etrue)
    totpe = np.array(totpe)
    sigma = np.array(sigma)
    sigmaErr = np.array(sigmaErr)

    return Etrue, totpe, sigma, sigmaErr

def param(npe):
    p1, p2 = 2.34299e+00, 4.95424e-03
    return p1*npe + p2*npe**2

def main():
    covE, covPE, cov, covErr = readFile("../data/electron/elecPECov1.txt")
    sctE, sctPE, sctSigma, sctSigmaErr = readFile("../data/electron/elecSctPEResol1.txt")
    cerE, cerPE, cerSigma, cerSigmaErr = readFile("../data/electron/elecCerPEResol1.txt")

    E, correlation, correlation_err = [], [], []

    sctNPE, cerNPE, covArr, covErrArr = [], [], [], []
    sctSPE, cerSPE, sctSPEerr, cerSPEerr = [], [], [], []

    for i in range(55, len(covE), 10):
        if sctSigma[i] == 0 or cerSigma[i] == 0:
            continue
        E.append(covE[i])
        sctNPE.append(sctPE[i])
        cerNPE.append(cerPE[i])
        sctSPE.append(sctSigma[i])
        cerSPE.append(cerSigma[i])
        sctSPEerr.append(sctSigmaErr[i])
        cerSPEerr.append(cerSigmaErr[i])
        covArr.append(cov[i])
        covErrArr.append(covErr[i])
        correlation.append(cov[i]/sctSigma[i]/cerSigma[i])
        correlation_err.append( np.sqrt( covErr[i]**2/(sctSigma[i]*cerSigma[i])**2  \
            + (cov[i]/sctSigma[i])**2 * cerSigmaErr[i]**2/cerSigma[i]**4 +          \
            + (cov[i]/cerSigma[i])**2 * sctSigmaErr[i]**2/sctSigma[i]**4 ) )

    covArr = np.array(covArr)
    cerNPE = np.array(cerNPE)
    sctNPE = np.array(sctNPE)
    cerSPE = np.array(cerSPE)
    cerSPEerr = np.array(cerSPEerr)
    sctSPE = np.array(sctSPE)
    sctSPEerr = np.array(sctSPEerr)
    correlation = np.array(correlation)
    correlation_err = np.array(correlation_err)

    #plt.errorbar(E, correlation*E/cerNPE, yerr=correlation_err*E/cerNPE, fmt="-", color="chocolate")
    #plt.plot(E, correlation/np.sqrt(cerNPE)*50, "-", color="chocolate")

    #plt.plot(E, covArr/np.sqrt(sctNPE*cerNPE) )

    g1 = ROOT.TGraphErrors()
    for i in range(len(covArr)):
        g1.SetPoint(i, cerNPE[i]+sctNPE[i], covArr[i])
        g1.SetPointError(i, 0, covErrArr[i])

    f1 = ROOT.TF1("f1", "[0]+[1]*x+[2]*x*x", 0, 15000)
    f1.FixParameter(0, 0)
    g1.Fit(f1, "RE")
    q0 = f1.GetParameter(0)
    q1 = f1.GetParameter(1)
    q2 = f1.GetParameter(2)

    npe1 = np.arange(0, 15000, 100)
    fit1 = q0 + q1*npe1 + q2*npe1**2

    plt.errorbar(sctNPE+cerNPE, covArr, yerr=covErrArr, fmt="o")
    plt.plot(npe1, fit1, "-")
    plt.show()

    """
    pois = []
    for i in np.arange(sctNPE.min()-10, sctNPE.max()+10, 100):
        pois.append(i)
    poisC = []
    for i in np.arange(cerNPE.min()-10, cerNPE.max()+10, 100):
        poisC.append(i)
    poisC = np.array(poisC)

    fig = plt.figure(figsize=(12, 5))
    spec = gridspec.GridSpec(ncols=2, nrows=1)

    ax1 = fig.add_subplot(spec[0])
    ax3 = fig.add_subplot(spec[1])

    es = 3134.078/2.223
    sctNPE = np.array(sctNPE)
    sctSPE = np.array(sctSPE)
    cerNPE = np.array(cerNPE)
    cerSPE = np.array(cerSPE)
    pois = np.array(pois)
    poisC = np.array(poisC)

    ax1.errorbar(sctNPE/es, sctSPE**2/es**2, yerr=sctSPE*2*sctSPEerr/es/es, fmt="o", ms=4, color='blue')
    ax1.plot(pois/es, pois/es/es, "--", color="darkviolet", lw=2, label="Poisson")
    ax1.errorbar(cerNPE/es, cerSPE**2/es**2, yerr=cerSPE*2*cerSPEerr/es/es, fmt="o", ms=4, color='seagreen', zorder=1)
    #ax1.plot(poisC/es, poisC/es/es, "--", color="darkviolet", label="Poisson")
    ax1.plot(poisC/es, param(poisC)/es/es, "-", lw=2, color="orange", label="Parameterisation", zorder=2)
    ax1.text(4, 0.0022, r"$\sigma_s$", color="blue", fontsize=16)
    ax1.text(1, 0.0025, r"$\sigma_C$", color="seagreen", fontsize=16)
    #ax1.semilogx()
    #ax2 = ax1.twiny()
    #ax2.errorbar(cerNPE/es, cerSPE**2/es**2, yerr=cerSPE*2*cerSPEerr, fmt="o", ms=4, color='seagreen', label="Simulation", zorder=1)
    #ax2.plot(poisC/es, poisC/es, "--", color="darkviolet", label="Poisson")
    #ax2.plot(poisC, param(poisC), "-", lw=2, color="chocolate", label="Parameterisation", zorder=2)
    ax1.set_xlabel("NPE/A [MeV]", fontsize=17, color='black')
    ax1.set_ylabel(r"$\sigma^2$[MeV$^2$]", fontsize=17, labelpad=0.2)
    #ax2.set_xlabel(r"$N_{Cer}$", fontsize=14, color='seagreen')
    ax1.tick_params(axis='x', which='major', labelsize=16, labelcolor='black')
    ax1.tick_params(axis='y', which='major', labelsize=16, labelcolor='black')
    ax1.grid(axis='both')
    ax1.legend(loc="upper left", prop={'size' : 15})
    #ax2.tick_params(axis='x', which='major', labelsize=12, labelcolor='seagreen')
    #ax2.legend(loc="upper left", prop={'size' : 14})

    ax3.errorbar(E, correlation, yerr=correlation_err, fmt="o", ms=5, color="peru")

    ax3.grid(True)
    ax3.set_ylim(-0.1, 0.5)
    ax3.set_xlabel(r"$E_{dep}$/MeV", fontsize=17)
    ax3.set_ylabel("correlation coefficient", fontsize=17)
    ax3.tick_params(axis='both', which='major', labelsize=16)

    plt.tight_layout()
    plt.savefig("stddev+cov.pdf")

    plt.show()

    fig, ax = plt.subplots()
    ax.errorbar(E, correlation, yerr=correlation_err, fmt="o", color="#DA4510")
    #plt.errorbar(sctNPE+cerNPE, correlation, yerr=correlation_err, fmt="o", color="#FF7447")

    ax.grid(True)
    #plt.xlabel("NPE", fontsize=14)
    ax.set_xlabel(r"$E_{dep}$/MeV", fontsize=14)
    ax.set_ylabel("correlation coefficient", fontsize=14)
    ax.tick_params(axis='both', which='major', labelsize=12)

    plt.savefig("Corr2Edep.pdf")

    plt.show()

    """

if __name__ == "__main__":
    main()


# Various ways to represent structured data in strings,
# for use in web forms or in CSV files.
#
# Some of these methods are extremely similar to each other, but they
# originated in different places in the app or different points in the
# process.  They are collected here to document the various formats
# used, and hopefully to make it easier to merge or prune them in the
# future.

import copy
from datetime import datetime
import json
import logging
logger = logging.getLogger(__name__)
import re
from typing import Any, Dict, List, Match, Optional, Set, Tuple, Union

from dateutil import parser
from jinja2 import Template

from DDR import config

def normalize_string(text: str) -> str:
    if text == None:
        return u''
    elif not isinstance(text, str):
        return text
    elif not text:
        return u''
    return str(text).replace('\r\n', '\n').replace('\r', '\n').strip()

def load_dirty_json(text: str):
    # http://grimhacker.com/2016/04/24/loading-dirty-json-with-python/
    regex_replace = [
        (r"([ \{,:\[])(u)?'([^']+)'", r'\1"\3"'),
        (r" False([, \}\]])", r' false\1'),
        (r" True([, \}\]])", r' true\1')
    ]
    for r, s in regex_replace:
        text = re.sub(r, s, text)
    return json.loads(text)

def strip_list(data: List[Any]) -> List[Any]:
    """Remove empty list items (ex: ['not empty, '']

    @param data: list
    @returns: list
    """
    return [
        item for item in data
        if item and (not item == 0)
    ]

def render(template: str, data: Dict[str, str]) -> str:
    """Render a Jinja2 template.

    @param template: str Jinja2-formatted template
    @param data: dict
    """
    return Template(template).render(data=data)

def coerce_text(data: Union[int,datetime,str]) -> Optional[str]:
    """Ensure types (ints,datetimes) are converted to text
    """
    if isinstance(data, int):
        return str(data)
    elif isinstance(data, datetime):
        return datetime_to_text(data)
    return data

# boolean --------------------------------------------------------------

def text_to_boolean(value: str) -> bool:
    if value:
        if isinstance(value, bool):
            return value
        elif isinstance(value, int) and value:
            return True
        elif isinstance(value, str):
            if value.isdigit() and int(value):
                return True
            if value in ['true', 'True']:
                return True
    return False

# datetime -------------------------------------------------------------
#
# format = '%Y-%m-%dT%H:%M:%S'
# text = '1970-1-1T00:00:00'
# data = datetime.datetime(1970, 1, 1, 0, 0)
#

ALT_DATETIME_FORMATS = [
    '%Y-%m-%dT%H:%M:%S:%f',
    '%Y-%m-%dT%H:%M:%S.%f',
    '%Y-%m-%d %H:%M:%S.%f',
    '%Y-%m-%d %H:%M:%S',
    '%Y-%m-%dT%H:%M:%S%Z%z',
    '%Y-%m-%dT%H:%M:%S%Z',
    '%Y-%m-%dT%H:%M:%S%z',
    '%Y-%m-%dT%H:%M:%S',
    '%Y-%m-%dT%H:%M:%S.%f%Z%z',
    '%Y-%m-%dT%H:%M:%S.%f%Z',
    '%Y-%m-%dT%H:%M:%S.%f%z',
]

def text_to_datetime(text: str,
                     fmt: str=config.DATETIME_FORMAT) -> Optional[datetime]:
    """Load datatime from text in specified format.

    TODO timezone!
    TODO use dateparse or something?

    @param text: str
    @param fmt: str
    @returns: datetime
    """
    if isinstance(text, datetime):
        return text
    text = normalize_string(text)
    try:
        return parser.parse(text)
    except:
        # try a bunch of old/messed up formats
        for fmt in ALT_DATETIME_FORMATS:
            try:
                return datetime.strptime(text, fmt)
            except:
                pass
    return None

def datetime_to_text(data: datetime, fmt: str=config.DATETIME_FORMAT) -> Optional[str]:
    """Dump datetime to text suitable for a CSV field.

    TODO timezone!

    @param data: datetime
    @returns: str
    """
    if not data:
        return None
    if isinstance(data, str):
        return data
    if not isinstance(data, datetime):
        raise Exception(f'Cannot strformat "{date}": not a datetime.')
    return datetime.strftime(data, fmt)

# list ----------------------------------------------------------------
#
# text0 = 'thing1; thing2'
# text1 = [
#     'thing1',
#     'thing2',
# ]
# data = ['thing1', 'thing2']
#

LIST_SEPARATOR = ';'
LIST_SEPARATOR_SPACE = '%s ' % LIST_SEPARATOR

def _is_listofstrs(data: List[str]) -> bool:
    if isinstance(data, list):
        num_strs = 0
        for x in data:
            if isinstance(x, str):
                num_strs += 1
        if num_strs == len(data):
            return True
    return False

def text_to_list(text: str, separator: str=LIST_SEPARATOR) -> List[str]:
    """
    @param text: str
    @param separator: str
    @returns: list
    """
    if isinstance(text, list):
        return text
    text = normalize_string(text)
    if not text:
        return []
    data = []
    for item in text.split(separator):
        item = item.strip()
        if item:
            data.append(item)
    return data

def list_to_text(data: List[str], separator: str=LIST_SEPARATOR_SPACE) -> str:
    """
    @param data: list
    @param separator: str
    @returns: str
    """
    return separator.join(data)

# dict -----------------------------------------------------------------
#
# Much DDR data is structured as lists of dicts, one dict per record.
# These functions are intended for recognizing text strings from these records.
#
# text_bracketid = 'ABC [123]'
# text_nolabels  = 'ABC:123'
# text_labels    = 'term:ABC|id:123'
# data = {'term':'ABC', 'id':'123'}
#

def _is_text_labels(text: str, separators: List[str]=[':','|']) -> bool:
    # both separators
    sepsfound = [s for s in separators if s in text]
    if len(sepsfound) == len(separators):
        return True
    return False

def textlabels_to_dict(text: str,
                       keys: List[str],
                       separators: List[str]=[':','|']) -> Dict[str,str]:
    """
    @param text: str
    @param keys: list
    @param separators: list
    @returns: dict
    """
    if not text:
        return {}
    data = {}
    for item in text.split(separators[1]):
        if item:
            key,val = item.split(separators[0], 1)
            data[key] = val
    return data

def dict_to_textlabels(data: Dict[str,str],
                       keys: List[str],
                       separators: List[str]) -> str:
    return separators[1].join([
        separators[0].join([
            key, data[key]
        ])
        for key in keys
    ])

# text_nolabels  = 'ABC:123'
# data = {'term':'ABC', 'id':123}

def _is_text_nolabels(text: str, separators: List[str]=[':','|']) -> bool:
    # Only first separator present
    if (separators[0] in text) and not (separators[1] in text):
        return True
    return False

def textnolabels_to_dict(text: str,
                         keys: List[str],
                         separator: str=':') -> Dict[str,str]:
    """
    @param text: str
    @param keys: list
    @param separator: str
    @returns: dict
    """
    if not text:
        return {}
    if not separator in text:
        raise Exception('Text does not contain "%s": "%s"' % (separator, text))
    values = text.split(separator, 1)
    if not len(values) == len(keys):
        raise Exception('Text contains more than %s values: "%s".' % (len(keys), text))
    data = {
        key: values[n]
        for n,key in enumerate(keys)
    }
    return data

def dict_to_textnolabels(data: Dict[str,str],
                         keys: List[str],
                         separator: str) -> str:
    return separator.join([
        data[key] for key in keys
    ])

# text_bracketid = 'ABC [123]'
# data = {'term':'ABC', 'id':123}

TEXT_BRACKETID_TEMPLATE = '{term} [{id}]'
TEXT_BRACKETID_REGEX = re.compile(r'(?P<term>[\w\d -:()_,`\'"]+)\s\[(?P<id>\d+)\]')

def _is_text_bracketid(text: str) -> Union[Match[str], bool]:
    if text:
        m = re.search(TEXT_BRACKETID_REGEX, text)
        if m and (len(m.groups()) == 2) and m.groups()[1].isdigit():
            return m
    return False

def textbracketid_to_dict(text, keys=['term', 'id'], pattern=TEXT_BRACKETID_REGEX, match=None):
    """
    @param text: str
    @param keys: list
    @param pattern: re.RegexObject
    @param match: re.MatchObject
    @returns: dict
    """
    text = normalize_string(text).replace('\n',' ')
    if not text:
        return {}
    if match:
        m = match
    elif pattern:
        m = re.search(pattern, text)
    if m:
        if m.groups() and (len(m.groups()) == len(keys)):
            return {
                key: m.groups()[n]
                for n,key in enumerate(keys)
            }
    return {}

def dict_to_textbracketid(data: Dict[str,str], keys: List[str]) -> str:
    if isinstance(data, str):
        return data
    if len(keys) != 2:
        raise Exception('Cannot format "Topic [ID]" data: too many keys. "%s"' % data)
    if not 'id' in list(data.keys()):
        raise Exception('No "id" field in data: "%s".' % data)
    data_ = copy.deepcopy(data)
    d = {'id': data_.pop('id')}
    d['term'] = list(data_.values())[0]
    return TEXT_BRACKETID_TEMPLATE.format(**d)

def text_to_dict(text: str, keys: List[str]) -> Dict[str,str]:
    """Convert various text formats to dict

    If text cannot be converted it will be assigned to keys[0] in a dict

    @param text: str Normalized text
    @param keys: list
    @returns: dict
    """
    text = normalize_string(text).replace('\n',' ')
    if not text:
        return {}
    match = _is_text_bracketid(text)
    if match:
        data = textbracketid_to_dict(text, match=match)
    elif _is_text_labels(text, separators=[':','|']):
        data = textlabels_to_dict(text, keys, separators=[':','|'])
    elif _is_text_nolabels(text):
        data = textnolabels_to_dict(text, keys, separator=':')
    else:
        raise Exception('text_to_dict could not parse "%s"' % text)
    # strip strings, force int values to int
    d = {}
    for key,val in data.items():
        if isinstance(val, str):
            d[key] = val.strip()
        else:
            d[key] = val
    return d

def dict_to_text(data: Dict[str,str],
                 keys: List[str],
                 style: str='labels',
                 nolabelsep: str=':',
                 labelseps: List[str]=[':','|']) -> str:
    """Renders single dict record to text in specified style.

    @param data: dict
    @param keys: list Dictionary keys in order they should be printed.
    @param style: str 'labels', 'nolabels', 'bracketid'
    @param nolabelsep: str
    @param labelseps: list
    @returns: str
    """
    assert style in ['labels', 'nolabels', 'bracketid']
    if style == 'bracketid':
        return dict_to_textbracketid(data, keys)
    elif style == 'nolabels':
        return dict_to_textnolabels(data, keys, nolabelsep)
    else:
        return dict_to_textlabels(data, keys, labelseps)

# kvlist ---------------------------------------------------------------
#
# text = 'name1:author; name2:photog'
# data = [
#     {u'name1': u'author'},
#     {u'name2': u'photog'}
# ]
#

def _is_kvlist(text: str) -> bool:
    if isinstance(text, list):
        matches = 0
        for item in text:
            if isinstance(item, dict):
                matches += 1
        if matches == len(text):
            return True
    return False

def text_to_kvlist(text: str) -> Union[Any, List[Dict[str,str]]]:
    if _is_kvlist(text):
        return text
    text = normalize_string(text)
    if not text:
        return []
    data = []
    for item in text.split(';'):
        item = item.strip()
        if item:
            if not ':' in item:
                raise Exception('Malformed data: %s' % text)
            key,val = item.strip().split(':')
            data.append({
                key.strip(): val.strip()
            })
    return data

def kvlist_to_text(data: List[Dict[str,str]]) -> str:
    items = []
    for d in data:
        i = [k+':'+v for k,v in d.items()]
        item = '; '.join(i)
        items.append(item)
    text = '; '.join(items)
    return text

# labelledlist ---------------------------------------------------------
#
# Filter list of key:value pairs, keeping just the keys.
# NOTE: This is a one-way conversion.
#
# text = 'eng'
# data = [u'eng']
# text = 'eng;jpn')
# data = [u'eng', u'jpn']
# text = 'eng:English'
# data = [u'eng']
# text = 'eng:English; jpn:Japanese'
# data = [u'eng', u'jpn']
#

def text_to_labelledlist(text: str) -> List[str]:
    text = normalize_string(text)
    if not text:
        return []
    data = []
    for x in text.split(';'):
        x = x.strip()
        if x:
            if ':' in x:
                # NOTE: we're keeping the KEY, discarding the VALUE
                key,val = x.strip().split(':')
                data.append(key)
            else:
                data.append(x.strip())
    return data

def labelledlist_to_text(data: List[str], separator: str='; ') -> str:
    return separator.join(data)

# listofdicts ----------------------------------------------------------
#
# Converts between labelled fields in text to list-of-dicts.
#
# text0 = 'url:http://abc.org/|label:ABC'
# data0 = [
#     {'label': 'ABC', 'url': 'http://abc.org/'}
# ]
#
# text1 = 'url:http://abc.org/|label:ABC; url:http://def.org/|label:DEF'
# data1 = [
#     {'label': 'ABC', 'url': 'http://abc.org/'},
#     {'label': 'DEF', 'url': 'http://def.org/'}
# ]
#
# text2 = 'label:Pre WWII|end:1941; label:WWII|start:1941|end:1944; label:Post WWII|start:1944;'
# data2 = [
#     {'label':'Pre WWII', 'end':'1941'},
#     {'label':'WWII', 'start':'1941', 'end':'1944'},
#     {'label':'Post WWII', 'start':'1944'}
# ]
#

def _is_listofdicts(data: Union[Any, List[Dict[str,str]]]) -> bool:
    if isinstance(data, list):
        num_dicts = 0
        for x in data:
            if isinstance(x, dict):
                num_dicts += 1
        if num_dicts == len(data):
            return True
    return False

def text_to_dicts(text: str,
                  terms: List[str],
                  separator: str=';') -> Union[Any, List[Dict[str,str]]]:
    if _is_listofdicts(text):
        return text
    text = normalize_string(text)
    if not text:
        return []
    dicts = []
    for line in text.split(separator):
        line = line.strip()
        d = text_to_dict(line, terms)
        if d:
            dicts.append(d)
    return dicts

def _setsplitnum(separator: str, split1x: List[str]) -> int:
    if separator in split1x:
        return 1
    return -1

LISTOFDICTS_SEPARATORS = [':', '|', ';']
LISTOFDICTS_SPLIT1X = [':']

def text_to_listofdicts(text: str,
                        separators: List[str]=LISTOFDICTS_SEPARATORS,
                        split1x: List[str]=LISTOFDICTS_SPLIT1X
) -> List[Dict[str,str]]:
    text = normalize_string(text).replace('\\n','').replace('\n','')
    if not text:
        return []
    splitnum1 = _setsplitnum(separators[-1], split1x)
    splitnum2 = _setsplitnum(separators[-2], split1x)
    splitnum3 = _setsplitnum(separators[-3], split1x)
    # parse it up
    dicts = []
    for line in text.split(separators[-1], splitnum1):
        # clean up line, skip if empty
        l = line.strip()
        if l:
            items = l.split(separators[-2], splitnum2)
        else:
            items = []
        d = {}
        for item in items:
            i = item.strip()
            if i:
                key,val = i.split(separators[-3], splitnum3)
                d[key.strip()] = val.strip()
        # don't append empty dicts
        if d:
            dicts.append(d)
    return dicts

def listofdicts_to_text(data: List[Dict[str,str]],
                        terms: List[str]=[],
                        separators: List[str]=LISTOFDICTS_SEPARATORS,
                        newlines: bool=True) -> str:
    if not data:
        return ''
    if isinstance(data, str):
        data = text_to_listofdicts(data)
    lines = []
    for datum in data:
        if terms:
            items = [
                separators[0].join([key, str(datum.get(key,''))])
                for key in terms
                if datum.get(key)
            ]
        else:
            items = [
                separators[0].join(keyval)
                for keyval in datum.items()
            ]
        line = separators[1].join(items)
        lines.append(line)
    if newlines:
        separators2 = '%s\n' % separators[2]
    else:
        separators2 = separators[2]
    return separators2.join(lines)

# textnolabels <> listofdicts ------------------------------------------
#
# This format is like listofdicts but the text form has no labels
# and records are optionally separated by (semicolons and) newlines.
# Labels must be provided for the encoding step.
#
# Text can contain one key-val pair
#
#     text1a = "ABC:http://abc.org"
#     text1b = "ABC:http://abc.org;"
#     data1 = [
#         {'label': 'ABC', 'url': 'http://abc.org'}
#     ]
#
# or multiple key-val pairs.
#
#     text2a = "ABC:http://abc.org;DEF:http://def.org"
#     text2b = "ABC:http://abc.org;DEF:http://def.org;"
#     text2c = "ABC:http://abc.org;
#               DEF:http://def.org;"
#     data2 = [
#         {'label': 'ABC', 'url': 'http://abc.org'},
#         {'label': 'DEF', 'url': 'http://def.org'}
#     ]
#
# Old JSON data may be a list of strings rather than dicts.
#
#     data3 = [
#         'ABC:http://abc.org',
#         'DEF:http://def.org'
#     ]
#     text3 = "ABC:http://abc.org;
#              DEF:http://def.org;"
#
#     data4 = [
#         'ABC [123]',
#         'DEF [456]'
#     ]
#     text4 = "term:ABC|id:123;
#              term:DEF|id:456"

TEXTNOLABELS_LISTOFDICTS_SEPARATORS = [':', ';']

def textnolabels_to_listofdicts(
        text: str,
        keys: List[str],
        separators: List[str]=TEXTNOLABELS_LISTOFDICTS_SEPARATORS
) -> List[Dict[str,str]]:
    """
    @param text: str
    @param keys: list
    @param separators: list
    @returns: list of dicts
    """
    text = normalize_string(text)
    if not text:
        return []
    data = []
    for n in text.split(separators[0]):
        values = n.strip().split(separators[1], 1) # only split on first colon
        d = {
            keys[n]: value.strip()
            for n,value in enumerate(values)
        }
        data.append(d)
    return data

def listofdicts_to_textnolabels(
        data: List[Dict[str,str]],
        keys: List[str],
        separators: List[str]=TEXTNOLABELS_LISTOFDICTS_SEPARATORS,
        separator: str=':') -> str:
    """
    @param data: list of dicts
    @param keys: list
    @param separators: list
    @param separator: str
    @returns: str
    """
    # split string into list (see data0)
    if isinstance(data, str) and (separators[1] in data):
        data = data.split(separators[1])
    if not isinstance(data, list):
        raise Exception('Data is not a list "%s".' % data)

    items = []
    for n in data:
        # string (see data1)
        if isinstance(n, str):
            values = n.strip().split(separators[0], 1)
            item = separator.join(values)
            items.append(item)

        # dict (see data2)
        elif isinstance(n, dict):
            # just the values, no keys
            values = [str(n[key]) for key in keys]
            item = separator.join(values)
            items.append(item)

    joiner = '%s\n' % separators[1]
    return joiner.join(items)

# bracketids -----------------------------------------------------------
#
# List of bracketid items.
#
# text = ''
# data = []
#
# text = "ABC: DEF [123]; ABC: XYZ [456]"
# text = [
#     "ABC: DEF [123]",
#     "ABC: XYZ [456]",
# ]
# data = [
#     {"term": "ABC: DEF", "id": '123'},
#     {"term": "ABC: XYZ", "id": '456'},
# ]

def text_to_bracketids(text: str,
                       fieldnames: List[str]=[]) -> List[Dict[str,str]]:
    data = []
    # might already be listofdicts or listofstrs
    if text and isinstance(text, list):
        if _is_listofdicts(text):
            data = text
        elif _is_listofstrs(text):
            data = [
                text_to_dict(item, fieldnames)
                for item in text
            ]
    # old-skool string
    elif text and isinstance(text, str):
        data = [
            text_to_dict(item, fieldnames)
            for item in text.split(';')
        ]
    return data

# rolepeople -----------------------------------------------------------
#
# List listofdicts but adds default key:val pairs if missing
#
# text = ''
# data = []
#
# text = "Watanabe, Joe"
# data = [
#     {'namepart': 'Watanabe, Joe', 'role': 'author'}
# ]
#
# text = "Masuda, Kikuye [42]:narrator"
# data = [
#     {'namepart': 'Masuda, Kikuye', 'role': 'narrator', 'oh_id': 42}
# ]
#
# text = "Watanabe, Joe:author; Masuda, Kikuye:narrator"
# text = [
#     'Watanabe, Joe: author',
#     'Masuda, Kikuye [42]: narrator'
# ]
# text = [
#     {'namepart': 'Watanabe, Joe', 'role': 'author'}
#     {'namepart': 'Masuda, Kikuye', 'role': 'narrator', 'oh_id': 42}
# ]
# data = [
#     {'namepart': 'Watanabe, Joe', 'role': 'author'}
#     {'namepart': 'Masuda, Kikuye', 'role': 'narrator', 'oh_id': 42}
# ]
#

def _filter_rolepeople(data: List[Dict[str,str]]) -> List[Dict[str,str]]:
    """Processes persons/creators data already in list-of-dicts format
    filters out items with empty nameparts
    prevents this: [{'namepart': '', 'role': 'author'}]
    """
    data = [
        item for item in data
        if item.get('namepart')  # and item.get('role')
    ]
    # convert old 'id' to oral history id
    for item in data:
        if item.get('id'):
            item['oh_id'] = item.pop('id')
        # make sure oh_id is int
        if item.get('oh_id'):
            item['oh_id'] = int(item['oh_id'])
    return data

# TODO add type hints
def _parse_rolepeople_text(texts, default):
    """Parses rolepeople format used to represent persons/creators in CSV
    """
    data = []
    for text in _unroll_gloppy_list(texts):
        txt = text.strip()
        if txt:
            item = copy.deepcopy(default)
            # TODO clean this up

            if ('|' in txt) and (':' in txt):
                # ex: "namepart:Sadako Kashiwagi|role:narrator|oh_id:856"
                for chunk in txt.split('|'):
                    key,val = chunk.split(':')
                    item[key.strip()] = val.strip()

            elif ':' in txt:
                # ex: "Sadako Kashiwagi:narrator"
                # ex: 'namepart: Yasuda, Mitsu;\n'
                key,value = txt.split(':')
                if key.strip() in default.keys():
                    # ex: 'namepart: Yasuda, Mitsu;\n'
                    item[key.strip()] = value.strip()
                else:
                    # ex: "Sadako Kashiwagi:narrator"
                    item['namepart'] = key.strip()
                    item['role'] = value.strip()

            else:
                # ex: "Sadako Kashiwagi"
                item['namepart'] = txt

            # obsolete/original narrator ID format: 'Masuda, Kikuye [42]'
            if item.get('role') and item['role'] == 'narrator' and not item.get('oh_id'):
                # "namepart: Masuda, Kikuye [42] | role: narrator"
                m = re.search('([\w\s,-]+) \[(\d+)]', item['namepart'])
                if m and m.groups() and len(m.groups()) == 2:
                    item['namepart'] = m.groups()[0]
                    item['oh_id'] = m.groups()[1]
                # "Masuda, Kikuye [42]:narrator"
                m1 = re.search('([\w\s,-]+) \[(\d+)]:narrator', txt)
                if m1 and m1.groups() and len(m1.groups()) == 2:
                    item['namepart'] = m1.groups()[0]
                    item['oh_id'] = m1.groups()[1]

            # convert old 'name' to 'namepart'
            if item.get('name') and not item.get('namepart'):
                item['namepart'] = item.pop('name')

            # convert old 'id' to oral history id
            if item.get('id'):
                item['oh_id'] = item.pop('id')

            # old bracketid format
            match = _is_text_bracketid(item.get('namepart',''))
            if match:
                item['namepart'] = match.groupdict()['term'].strip()
                #item['oh_id'] = match.groupdict()['oh_id'].strip()

            # make sure oh_id is int
            if item.get('oh_id'):
                item['oh_id'] = int(item['oh_id'])

            data.append(item)
    return data

def _unroll_gloppy_list(text: list) -> List[str]:
    """Lists of rolepeople from e.g. forms might have multiple items in a line

    e.g. ['Lastname1,Firstname1; Lastname2,Firstname2', 'Lastname3,Firstname3']
    """
    new_list = []
    while(text):
        # split if there are more than one items in a listitem
        # append the first item to the new list
        items = text.pop(0).split(';', 1) # split on the first semicolon
        if len(items) == 1:
            new_list.append(items[0].strip())  # the last one
        elif len(items) > 1:
            first,others = items
            new_list.append(first.strip())
            # stick remainders onto front of list to preserve order
            new_list.insert(0, others.strip())
    return new_list

def text_to_rolepeople(text: str, default: dict) -> List[Dict[str,str]]:
    if not text:
        return []

    # might already be listofdicts or listofstrs
    if isinstance(text, list):
        if _is_listofdicts(text):  # from JSON
            return _filter_rolepeople(text)
        elif _is_listofstrs(text): # from CSV
            data = _parse_rolepeople_text(text, default)
            return _filter_rolepeople(data)

    text = normalize_string(text)

    # or it might be JSON
    if ('{' in text) or ('[' in text):
        try:
            data = json.loads(text)
        except ValueError:
            try:
                data = load_dirty_json(text)
            except ValueError:
                data = []
        if data:
            return _filter_rolepeople(data)

    # looks like it's raw text
    data = _parse_rolepeople_text(text.split(';'), default)
    return _filter_rolepeople(data)

def rolepeople_to_text(data: List[Dict[str,str]], field_order: List[str]=[]) -> str:
    """Convert list of dicts to string "KEY:VAL|KEY:VAL|...; KEY:VAL|KEY:VAL|..."
    """
    if isinstance(data, str):
        text = data
    else:
        items = []
        for d in data:
            if isinstance(d, str):
                # strings probably formatted or close enough
                items.append(d)
            elif isinstance(d, dict):
                if field_order:
                    # coerce dict items into specified order
                    fields_values = [
                        f"{fieldname}: {d[fieldname]}"
                        for fieldname in field_order
                        if d.get(fieldname)
                    ]
                else:
                    # or just in whatever order they came in
                    fields_values = [
                        f'{key}: {val}'
                        for key,val in d.items()
                    ]
                items.append(
                    ' | '.join(fields_values)
                )
        text = '; '.join(items).strip()
    return text


## Tran Nhiem -- 2022/05
from typing import Optional, Sequence
from torch.optim import SGD, Adam, AdamW
import torch.nn as nn
from torch.optim.lr_scheduler import MultiStepLR, ReduceLROnPlateau, LinearLR, CosineAnnealingLR,CosineAnnealingWarmRestarts
import pytorch_lightning as pl
import torch.nn.functional as F
from torchmetrics import Accuracy
from neural_nets_architecture.resnet import ResNet18, ResNet34, ResNet50, ResNet101, ResNet152
#from efficient_training_neural_Nets.neural_nets_architecture.resnet import ResNet18, ResNet34, ResNet50, ResNet101, ResNet152

def checkModel(dict, key):
    """Checking Available ResNet Models"""
    if key in dict.keys():
        print(f"Your {key} is available")
    else:
        print(f"Your {key}  is current not support :( please check the name Carefully !!")

def checkOptimizer(dict, key):
    """Checking Available Optimizer"""
    if key in dict.keys():
        print(f"Your {key} is available")
    else:
        print(f"Your {key}  is current not support :( please check the name Carefully !!")

model_available={
    'resnet18': ResNet18,
    'resnet34': ResNet34,
    'resnet50': ResNet50,
    'resnet101': ResNet101,
    'resnet152': ResNet152,
}

class lightning_model(pl.LightningModule):
    def __init__(self,
        backbone_architecture: str,
        batch_size: int ,
        lr: float,
        scheduler: str,
        weight_decay: float,
        num_classes: int ,
        arch_width_mu: int or float,
        optimizer_type: str,
        momentum: float,
        epochs: int,
        data_length: int,
        lr_decay_steps: Optional[Sequence[int]] = None,
        task: Optional[str]="classification",
        metric: str = "Accuracy",

        **kwargs
    ):
        super().__init__()
        self.backbone_architecture= backbone_architecture
        self.width_mult=arch_width_mu
        self.batch_size= batch_size
        self.optimizer_type= optimizer_type
        self.momentum=momentum
        self.num_classes= num_classes
        self.lr = lr
        self.epochs=epochs
        self.data_length=data_length
        self.weight_decay = weight_decay
        self.lr_decay_steps = lr_decay_steps
        self.task = task
        self.scheduler = scheduler
        print(self.lr)
        self.__build_model()
        self.accuracy_1= Accuracy()
        self.accuracy_5= Accuracy(top_k=5)
        self.metric=metric
        self.criterion = nn.CrossEntropyLoss()

    @property
    def optimizer_config(self):
        optimizer_available={
            'SGD':  SGD(self.parameters(), lr=self.lr, momentum=self.momentum, weight_decay = self.weight_decay, nesterov=True),
            'Adam': Adam(self.parameters(), lr=self.lr, betas=(0.9, 0.999), weight_decay= self.weight_decay),
            'AdamW': AdamW(self.parameters(), lr=self.lr, betas=(0.9, 0.999), weight_decay= self.weight_decay),
        }
        return optimizer_available

    def __build_model(self):
        checkModel(model_available, self.backbone_architecture)
        self.model=model_available[self.backbone_architecture](num_classes=self.num_classes, wm=self.width_mult, m_transfer=False )

    def forward(self, x):
        x=self.model(x)
        return x

    def training_step(self, batch, batch_idx):
        x, y = batch
        y_logits=self.forward(x)
        train_loss=F.cross_entropy(y_logits, y)
        # print("ground_truth", y[0])
        # print("prediction", y_logits[0].argmax(dim=-1))

        if self.metric == 'Accuracy':
            acc1= self.accuracy_1(y_logits, y)
            acc5 = self.accuracy_5(y_logits, y)
            log = {"train_loss": train_loss, "train_acc1": acc1, "train_acc5": acc5}
        else:
            raise ValueError("The metric is not support yet")

        self.log_dict(log, on_epoch=True, sync_dist=True)
        return train_loss

    def validation_step(self, batch, batch_idx):
        x, y = batch

        batch_size=x.size(0)
        y_logits=self.forward(x)
        val_loss=F.cross_entropy(y_logits, y)
        if self.metric == 'Accuracy':
            acc1= self.accuracy_1(y_logits, y)
            acc5 = self.accuracy_5(y_logits, y)
            #result = {"batch_size": batch_size,"val_loss": val_loss, "val_acc1": acc1, "val_acc5": acc5}
            result = {"val_loss": val_loss, "val_acc1": acc1, "val_acc5": acc5}
        else:
            raise ValueError("The metric is not support yet")
        self.log_dict(result,on_epoch=True, sync_dist=True)

        return val_loss

    def test_step(self, batch, batch_idx):
        x, y = batch
        batch_size=x.size(0)
        y_logits=self.forward(x)
        test_loss=F.cross_entropy(y_logits, y)
        #train_loss = F.nll_loss(y_logits, y)

        if self.metric == 'Accuracy':
            acc1= self.accuracy_1(y_logits, y)
            acc5 = self.accuracy_5(y_logits, y)
            result = {"test_loss": test_loss, "test_acc1": acc1, "test_acc5": acc5}

            #result = {"batch_size": batch_size,"test_loss": val_loss, "test_acc1": acc1, "test_acc5": acc5}
        else:
            raise ValueError("The metric is not support yet")

        self.log_dict(result,on_epoch=True, sync_dist=True)

        return test_loss

    def configure_optimizers(self):

        optimizer_available=self.optimizer_config
        checkOptimizer(optimizer_available, self.optimizer_type)
        optimizer=optimizer_available[self.optimizer_type]

       ## Configure Learning Rate Schedule
        if self.scheduler == 'step':
            scheduler = MultiStepLR(optimizer, self.lr_decay_steps, gamma=0.5)
            return [optimizer], [scheduler]
        elif self.scheduler == 'reduce_plateau':
            #scheduler = ReduceLROnPlateau(optimizer, patience=8, factor=0.5)
            scheduler = {"scheduler": ReduceLROnPlateau(optimizer, patience=8, factor=0.5,),  "monitor": "val_loss"}
            return [optimizer], [scheduler]
        elif self.scheduler=="linear":
            scheduler = LinearLR( optimizer, start_factor=0.5, total_iters=self.epochs/2)
            return [optimizer], [scheduler]
        elif self.scheduler=="cosineAnnealing":
            scheduler = CosineAnnealingLR(optimizer, eta_min=1e-8,T_max=int((self.data_length/self.batch_size)*self.epochs) )
            return [optimizer], [scheduler]
        elif self.scheduler=="ConsineAnl_warmup":
            scheduler = CosineAnnealingWarmRestarts(optimizer,T_0=int(((self.data_length/self.batch_size)*self.epochs)/2), T_mult=1, eta_min=1e-8)
            return [optimizer], [scheduler]
        else:
            print('you are not implementing any Learning schedule')
            return optimizer

    def __weighted_mean(self, outputs, key, batch_size_key):
        value=0
        n=0
        for out in outputs:
            value += out[batch_size_key] +out[key]
            n+= out[batch_size_key]
        value=value/n
        return value.squeeze(0)

if __name__=="__main__":
    print("Hoooray ~ You are testing the lightning Module ~")
    print("Oh wait you are not define any testing module yet")


from func_update_table import read_data

#"Tarih", "Lokasyon", "İrsaliye No", "Önceki Miktar", "İşlem", "Sonraki Miktar"

def submit(namebox, stockbox, combobox_name, unit, file_name):

    # Retrieve user inputs from entry fields

    try:
        name = namebox.get()
        stock = stockbox.get()
        stock = float(stock)
    except ValueError:
        return

    if unit == "":
        return

    data = [["Başlangıç Stoğu","","",stock,stock,stock]]

    with open(file_name, "a") as file:

        file.write(str(name))
        file.write("-")
        file.write(unit)
        file.write("=")
        file.write(str(data))
        file.write("\n")

    names = read_data(file_name)
    names = [i for i in names]
    combobox_name.configure(values=names)


from graphics import *
import numpy as np
import math as math
import os

class Board:
    def __init__(self, solution=[[]], size=10, cellSize=20, offset=100):
        self.size = size
        self.cellSize = cellSize
        self.offset = offset
        self.cells = [[Cell(r, c, cellSize) for r in range(self.size)] for c in range(self.size)]
        self.solutionBoard = solution
        self.userBoard = [[0 for i in range(self.size)] for i in range(self.size)]
        self.button = Rectangle(Point(0, 0), Point(self.cellSize * 2, self.cellSize))
        self.buttonText = Text(self.button.getCenter(), '')

    def getPoints(self, row, column):
        p1 = Point(
            (column * self.cellSize + self.offset),
            (row * self.cellSize + self.offset))
        p2 = Point(
            ((column + 1) * self.cellSize + self.offset),
            ((row + 1) * self.cellSize + self.offset))
        return p1, p2

    def drawBoard(self, WIN):
        button = Rectangle(Point(0, 0), Point(self.cellSize*2, self.cellSize))

        for row in range(self.size):
            for column in range(self.size):
                p1, p2 = self.getPoints(row, column)
                self.cells[row][column].drawCell(p1, p2, WIN)

    def getIndex(self, click):

        index = math.floor((click.x - self.offset) / self.cellSize)
        index = index + ((math.floor((click.y - self.offset) / self.cellSize) * self.size))
        return index

    def countCol(self, col):
        count1 = 0
        count2 = 0

        for idx in range(len(self.userBoard)):
            if self.userBoard[idx][col] == 1:
                count1 += 1

        for idx in range(len(self.solutionBoard)):
            if self.solutionBoard[idx][col] == 1:
                count2 += 1

        return count1 >= count2

    def colorCol(self, col, WIN, flag):
        greyRect = Rectangle(Point(self.cellSize * col + self.offset, 0),
                             Point(self.cellSize * col + (self.offset + self.cellSize),
                                   self.offset - 1))
        if flag == 1:
            greyRect.setFill(color_rgb(218, 218, 218))
            greyRect.setOutline(color_rgb(218, 218, 218))
        else:
            greyRect.setFill(color_rgb(240, 240, 240))
            greyRect.setOutline(color_rgb(240, 240, 240))

        greyRect.draw(WIN)

    def countRow(self, row):
        count1 = 0
        count2 = 0

        for idx in range(len(self.userBoard)):
            if self.userBoard[row][idx] == 1:
                count1 += 1

        for idx in range(len(self.solutionBoard)):
            if self.solutionBoard[row][idx] == 1:
                count2 += 1

        return count1 >= count2

    def colorRow(self, row, WIN, flag):
        greyRect = Rectangle(Point(0, self.cellSize * row + self.offset),
                             Point(self.offset - 1,
                                   self.cellSize * row + (self.offset + self.cellSize)))
        if flag == 1:
            greyRect.setFill(color_rgb(218, 218, 218))
            greyRect.setOutline(color_rgb(218, 218, 218))
        else:
            greyRect.setFill(color_rgb(240, 240, 240))
            greyRect.setOutline(color_rgb(240, 240, 240))

        greyRect.draw(WIN)

    def click(self, WIN):
        playing = True
        click = WIN.getMouse()
        side = WIN.getSide()
        #if WIN.checkKey() == 'x':
        if side == 3:
            crossOut = True
            print('x')
        else:
            crossOut = False
        for row in range(self.size):
            for column in range(self.size):
                p1, p2 = self.getPoints(row, column)
                index = self.getIndex(click)

                if click.x > p1.x and click.x < p2.x and click.y > p1.y and click.y < p2.y:
                    if crossOut:
                        if self.cells[row][column].state == 'blank':
                            self.cells[row][column].state = 'crossedOut'
                        elif self.cells[row][column].state == 'crossedOut':
                            self.cells[row][column].state = 'blank'
                    else:
                        if self.cells[row][column].state == 'blank':
                            self.cells[row][column].state = 'filled'
                            self.userBoard[row][column] = 1
                        elif self.cells[row][column].state == 'filled':
                            self.cells[row][column].state = 'blank'
                            self.userBoard[row][column] = 0

                    self.cells[row][column].drawCell(p1, p2, WIN)

                    if len(self.solutionBoard) != 0:
                        if self.countCol(column):
                            self.colorCol(column, WIN, 1)
                        else:
                            self.colorCol(column, WIN, 0)

                        if self.countRow(row):
                            self.colorRow(row, WIN, 1)
                        else:
                            self.colorRow(row, WIN, 0)

                        self.columnSequence(WIN)
                        self.rowSequence(WIN)

                    if self.userBoard == self.solutionBoard:
                        playing = False

                        winner = Rectangle(Point(0, 0), Point(WIN.getHeight(), WIN.getWidth()))
                        winner.setFill('white')
                        winnerText = Text(winner.getCenter(), 'WINNER!')
                        winner.draw(WIN)
                        winnerText.draw(WIN)
                p2 = self.button.getP2()
                buttonX = p2.x
                buttonY = p2.y

                if click.x < buttonX and click.y < buttonY:
                    playing = False
        return playing

    def creationMode(self, WIN):

        self.button.setFill('blue')
        self.buttonText.setText('save')
        self.buttonText.setTextColor("white")
        self.button.draw(WIN)
        self.buttonText.draw(WIN)

        creating = True
        while creating:
            creating = self.click(WIN)

        # print(self.userBoard)
        self.playMode(self.userBoard, WIN)

    def playMode(self, solution, WIN):
        self.solutionBoard = self.userBoard
        self.rowSequence(WIN)
        self.columnSequence(WIN)

        self.button.undraw()
        self.buttonText.undraw()
        self.solutionBoard = solution
        self.button.setFill('red')
        self.buttonText.setText('quit')
        self.buttonText.setTextColor("white")
        self.button.draw(WIN)
        self.buttonText.draw(WIN)

        for row in range(self.size):
            for column in range(self.size):
                p1, p2 = self.getPoints(row, column)
                if self.cells[row][column].state == 'filled':
                    self.cells[row][column].state = 'blank'
                    self.cells[row][column].drawCell(p1, p2, WIN)

        playing = True

        self.userBoard = [[0 for i in range(self.size)] for i in range(self.size)]

        while playing:
            playing = self.click(WIN)

    def rowSequence(self, WIN):
        rowCount = 0
        for r in range(self.size):
            row = []
            for c in range(self.size):
                row.append(self.solutionBoard[r][c])
            sequence = self.sequence(row)

            anchor = self.offset - (len(sequence) * 3 + 5)
            halfCell = int(self.cellSize/2)

            rowText = Text(
                Point(anchor, self.cellSize * rowCount + (self.offset + halfCell)),
                sequence)

            if sequence == [0]:
                greyRect = Rectangle(Point(0, self.cellSize * rowCount + self.offset),
                                     Point(self.offset - 1, self.cellSize * rowCount + (self.offset + self.cellSize)))
                greyRect.setFill(color_rgb(218, 218, 218))
                greyRect.setOutline(color_rgb(218, 218, 218))
                greyRect.draw(WIN)

            rowText.setSize(halfCell)
            rowText.draw(WIN)
            rowCount += 1

    def columnSequence(self, WIN):
        colCount = 0
        for r in range(self.size):
            column = []
            for c in range(self.size):
                column.append(self.solutionBoard[c][r])
            sequence = self.sequence(column)

            halfCell = int(self.cellSize / 2)
            anchor = self.offset - (len(sequence) * self.cellSize) + halfCell
            for idx in range(len(sequence)):
                rowText = Text(
                    Point(self.cellSize * colCount + (self.offset + halfCell),
                          anchor + self.cellSize * idx),
                    sequence[idx])

                if sequence == [0]:
                    greyRect = Rectangle(Point(self.cellSize * colCount + self.offset, 0),
                                         Point(self.cellSize * colCount + (self.offset + self.cellSize),
                                               self.offset-1))
                    greyRect.setFill(color_rgb(218, 218, 218))
                    greyRect.setOutline(color_rgb(218, 218, 218))
                    greyRect.draw(WIN)

                rowText.setSize(halfCell)
                rowText.draw(WIN)
            colCount += 1

    def sequence(self, a):
        sequence = []
        count = 0
        for i in range(len(a)):
            if i < len(a) - 1:
                if a[i] == 1:
                    count += 1
                if a[i + 1] == 0:
                    if count != 0:
                        sequence.append(count)
                        count = 0
            else:
                if a[i] == 1:
                    count += 1
                if count != 0:
                    sequence.append(count)
        if len(sequence) == 0:
            sequence.append(0)
        return sequence

    def boardToString(self):
        string = str(self.userBoard)
        simpleArray = []

        for idx in string:
            if idx == 0 or idx == 1:
                simpleArray.append(idx)
        return simpleArray

    def showSolution(self, WIN):
        for x in range(len(self.solutionBoard)):
            for y in range(len(self.solutionBoard)):
                if self.solutionBoard[y][x] == 1:
                    p1, p2 = self.getPoints(x, y)
                    self.cells[x][y].state = 'filled'
                    self.userBoard[x][y] = 1
                    self.cells[x][y].drawCell(p1, p2, WIN)

class Cell:
    def __init__(self, row, column, size=20, state='blank'):
        self.state = state
        self.row = row
        self.column = column
        self.size = size

    def drawCell(self, p1, p2, WIN):
        cell = Rectangle(p1, p2)
        textPoint = Point(p1.x + self.size/2, p1.y + self.size/2)
        crossOutText = Text(textPoint, '')
        crossOutText.setSize(self.size)
        if self.state == 'filled':
            cell.setFill('green')
            crossOutText.setText('')
        elif self.state == 'crossedOut':
            crossOutText.setText('X')
        else:
            cell.setFill('white')
            crossOutText.setText('')

        crossOutText.draw(WIN)
        cell.draw(WIN)

def menu(WIN):

    width = int(WIN.getHeight()/2)
    height = int(WIN.getWidth()/10)
    buttonX = WIN.getWidth()/2 - (width / 2)
    buttonY = WIN.getHeight()/2

    playBoard = Rectangle(Point(buttonX, buttonY), Point(buttonX + width, buttonY + height))
    playBoard.setFill('blue')
    playBoardText = Text(Point(buttonX + (width / 2), buttonY + (height / 2)), 'PLAY')
    playBoardText.setTextColor('white')
    playBoard.draw(WIN)
    playBoardText.draw(WIN)

    newY = buttonY + height + 10

    createBoard = Rectangle(Point(buttonX, newY), Point(buttonX + width, newY + height))
    createBoard.setFill('blue')
    createBoardText = Text(Point(buttonX + (width/2), newY + (height/2)), 'CREATE')
    createBoardText.setTextColor('white')
    createBoard.draw(WIN)
    createBoardText.draw(WIN)

    newY = newY + height + 10

    uploadImage = Rectangle(Point(buttonX, newY), Point(buttonX + width, newY + height))
    uploadImage.setFill('blue')
    uploadImageText = Text(Point(buttonX + (width / 2), newY + (height / 2)), 'IMAGE')
    uploadImageText.setTextColor('white')
    uploadImage.draw(WIN)
    uploadImageText.draw(WIN)

    value = ''
    while value == '':
        click = WIN.getMouse()

        if buttonX < click.x < buttonX + width:
            if buttonY < click.y < buttonY + height:
                value = 'play'

        newY = buttonY + height + 10

        if buttonX < click.x < buttonX + width:
            if buttonY + height + 10 < click.y < newY + height:
                value = 'create'

        newY = newY + height + 10

        if buttonX < click.x < buttonX + width:
            if buttonY + ((height + 10) * 2) < click.y < newY + height:
                value = 'image'
                WIN.close()

    createBoard.undraw()
    createBoardText.undraw()
    playBoard.undraw()
    playBoardText.undraw()
    uploadImage.undraw()
    uploadImageText.undraw()
    return value

def selectBoard(WIN):
    home = Rectangle(Point(0, 0), Point(40, 20))
    home.setFill('green')
    home.setOutline('green')
    homeText = Text(Point(20, 10), "HOME")
    homeText.setSize(10)
    homeText.setTextColor('white')
    home.draw(WIN)
    homeText.draw(WIN)

    all_files = os.listdir("sequences/")

    width = 150
    height = 30

    for idx in range(len(all_files)):
        buttonX = WIN.getWidth() / 2 - (width / 2)
        buttonY = WIN.getHeight() / 3 + (height * idx) + (15 * idx)
        chooseBoard = Rectangle(Point(buttonX, buttonY), Point(buttonX + width, buttonY + height))
        chooseBoard.setFill('blue')
        chooseBoardText = Text(Point(buttonX + (width / 2), buttonY + (height / 2)), all_files[idx])
        chooseBoardText.setTextColor('white')
        chooseBoard.draw(WIN)
        chooseBoardText.draw(WIN)

    string = ''
    while string == '':
        click = WIN.getMouse()

        if 0 < click.x < 40:
            if 0 < click.y < 20:
                clear = Rectangle(Point(0, 0), Point(WIN.getHeight(), WIN.getWidth()))
                clear.setFill('white')
                clear.draw(WIN)
                menu(WIN)

        for idx in range(len(all_files)):
            buttonX = WIN.getWidth() / 2 - (width / 2)
            buttonY = WIN.getHeight() / 3 + (height * idx) + (15 * idx)

            if (buttonX < click.x < buttonX + width):
                if (buttonY < click.y < buttonY + height):
                    index = idx
                    string = 'CHRIST'

    with open(os.path.join('sequences/', all_files[index]), 'rt') as fd:
        sequence = fd.readline()

    clear = Rectangle(Point(0, 0), Point(WIN.getHeight(), WIN.getWidth()))
    clear.setFill('white')
    clear.draw(WIN)

    seq = []
    for idx in sequence:
        if idx == '1':
            seq.append(1)
        elif idx == '0':
            seq.append(0)

    size = int(len(seq)/len(seq))
    # CHANGE THE HARD CODING LATER!

    newSeq = [[0 for i in range(10)] for i in range(10)]
    print(len(newSeq))
    print()
    print()

    list = []
    rowCount = 0
    for idx in range(len(seq)-1):

        list.append(seq[idx])
        if idx > 1 and (idx+1) % 10 == 0:
            print(list)

            for idx2 in range(len(list)):
                newSeq[rowCount][idx2] = list[idx2]

            rowCount += 1
            list.clear()

    print(newSeq)
    print(len(newSeq[0]))

    WIN.close()
    return newSeq

def imageToBoard():
    mona = Image(Point(0, 0), "mona.gif")
    avgColor = []

    for width in range(mona.getWidth()):
        for height in range(mona.getHeight()):
            list = mona.getPixel(width, height)
            sum = 0
            for val in list:
                sum += val
            sum /= 3
            if sum > 255/2:
                avgColor.append(0)
            else:
                avgColor.append(1)

    newSeq = [[0 for i in range(100)] for i in range(100)]

    list = []
    rowCount = 0
    for idx in range(len(avgColor)-1):

        list.append(avgColor[idx])
        if idx > 1 and (idx+1) % 100 == 0:
            #print(list)

            for idx2 in range(len(list)):
                newSeq[rowCount][idx2] = list[idx2]

            rowCount += 1
            list.clear()

    #print(newSeq)
    #print(len(newSeq[1]))

    return newSeq

def numToString(num):
    switcher = {
        0: "10 x 10",
        1: "15 x 15",
        2: "20 x 20",
        3: "25 x 25",
        4: "100 x 100"
    }
    return switcher.get(num)

def idxToSize(num):
    switcher = {
        0: 5,
        1: 10,
        2: 15,
        3: 20,
        4: 25,
        5: 100
    }
    return switcher.get(num)

def createMenu(WIN):

    home = Rectangle(Point(0, 0), Point(40, 20))
    home.setFill('green')
    home.setOutline('green')
    homeText = Text(Point(20, 10), 'HOME')
    homeText.setSize(10)
    homeText.setTextColor('white')
    home.draw(WIN)
    homeText.draw(WIN)

    width = 150
    height = 30
    buttonX = WIN.getWidth() / 2 - (width / 2)
    buttonY = WIN.getHeight() / 5

    button = Rectangle(Point(buttonX, buttonY), Point(buttonX + width, buttonY + height))
    button.setFill('blue')
    buttonText = Text(Point(buttonX + (width / 2), buttonY + (height / 2)), '5 X 5')
    buttonText.setTextColor('white')
    button.draw(WIN)
    buttonText.draw(WIN)

    for idx in range(5):
        cloneB = button.clone()
        cloneT = buttonText.clone()
        cloneB.move(0, (idx+1)*(height+10))
        cloneT.move(0, (idx+1)*(height+10))
        string = numToString(idx)
        cloneT.setText(string)
        cloneB.draw(WIN)
        cloneT.draw(WIN)

    string = ''
    while string == '':
        click = WIN.getMouse()
        if 0 < click.x < 40:
            if 0 < click.y < 20:
                clear = Rectangle(Point(0, 0), Point(WIN.getHeight(), WIN.getWidth()))
                clear.setFill('white')
                clear.draw(WIN)
                menu(WIN)

        for idx in range(6):
            if buttonX < click.x < buttonX + width:
                if buttonY + idx*(height+10) < click.y < (buttonY + idx*(height+10)) + height:
                    string = idxToSize(idx)

    WIN.close()
    return string

def main():
    WIN = GraphWin('Menu', 300, 300)
    string = menu(WIN)

    if string == 'play':
        seq = selectBoard(WIN)
        board = Board(seq)
        board.solutionBoard = seq
        board.userBoard = seq

        windowSize = board.size * board.cellSize + board.offset
        WIN = GraphWin('Game', windowSize, windowSize)
        board.drawBoard(WIN)

        board.playMode(seq, WIN)

    if string == 'create':
        size = createMenu(WIN)
        board = Board([], size)
        #board.size = size
        windowSize = board.size * board.cellSize + board.offset
        WIN = GraphWin("Game", windowSize, windowSize)
        board.drawBoard(WIN)
        print(board.size)
        print(len(board.userBoard))
        board.creationMode(WIN)

    if string == 'image':
        seq = imageToBoard()
        print(seq)
        board = Board(seq, 100, 10, 500)
        windowSize = board.size * board.cellSize + board.offset
        WIN = GraphWin('Game', windowSize, windowSize)
        board.size = 100
        board.solutionBoard = seq
        board.cellSize = 10
        board.offset = 500
        board.drawBoard(WIN)
        board.userBoard = seq
        board.showSolution(WIN)

        board.playMode(seq, WIN)

    WIN.getMouse()
    WIN.close()

main()


'''
예상할 수 없는 함수 : 매개변수에 전달되는 인자가 여러개일경우 한곳에 받아 줄 수 있는 기능
def 함수명(*파라미터)
    실행문들...
'''
def sum(*num): #던져줄 변수가 몇개인지 몰라~ *은 단일값이어도 튜플로 인식
    tot = 0
    print(num)
    print(type(num))
    for i in num:
        tot += i
    return tot

print(sum(10,20))

print("hello", "hahahaha")

print("*"*100)
def calc(oper, *num, test="hahahahah"):
    if oper == 'sum':
        tot = 0
        for i in num:
            tot += i
    elif oper == 'mul':
        tot = 1
        for i in num:
            tot *= i
        print(tot)
        return tot

result = calc("sum", 10, 20, 30, 40, test="kakakakakak")
print(result)


from typing import List
class MedianOfTwoSortedArrays(object):
  def findMedianSortedArrays(self, num1: List[int], num2: List[int]):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :rtype: float
    """
    n = len(num1) + len(num2)
    self.num1 = num1
    self.num2 = num2
    if n % 2 == 0:
      n1 = self.getMedian(n // 2 - 1, 0, len(num1), 0, len(num2))
      # print(n1)
      n2 = self.getMedian(n // 2, 0, len(num1), 0, len(num2))
      # print(n2)
      return float(n1 + n2) / 2
    return self.getMedian(n //2, 0, len(num1), 0, len(num2))

  def getMedian(self, idx, left1: int, right1: int, left2: int, right2: int):
    # if one of it len is 0 return other's kth
    num1Len = right1 - left1
    num2Len = right2 - left2
    # print(idx, left1, right1, left2, right2)

    if num1Len == 0:
      return self.num2[left2+idx]
    if num2Len == 0:
      return self.num1[left1 +idx]
    # if k == 0, return smaller one
    if idx == 0:
      return min(self.num1[left1], self.num2[left2])
    # if half is still larger than one of the num, make the other half
    halfIdx = (idx + 1) // 2
    if num1Len < halfIdx:
      return self.getMedian(idx - halfIdx, left1, right1, left2+halfIdx, right2)
    if num2Len < halfIdx:
      return self.getMedian(idx - halfIdx, left1+halfIdx, right1, left2, right2)

    a = self.num1[left1 + halfIdx - 1]
    b = self.num2[left2 + halfIdx - 1]
    if a < b:
      return self.getMedian(idx - halfIdx,left1+halfIdx, right1, left2, right2)

    return self.getMedian(idx - halfIdx, left1, right1, left2+halfIdx, right2)

m = MedianOfTwoSortedArrays()
print(m.findMedianSortedArrays([1,2], [3,4]))


# Time Complexity: O(n1+n2)
# Space Complexity: O(n1+n2)

def merge2sorted(a1,a2):
	n1 = len(a1)
	n2 = len(a2)
	a3 = [None]*(n1+n2)

	i, j, k= 0, 0, 0

	#traverse both arrays
	while i<n1 and j<n2:
		if a1[i] < a2[j]:
			a3[k] = a1[i]
			k += 1
			i += 1
		else:
			a3[k] = a2[j]
			k += 1
			j += 1
	# strore remaining elements of first array
	while i < n1:
		a3[k] = a1[i]
		k  += 1
		i  += 1

	# store remaining elements of second array
	while j < n2:
		a3[k] = a2[j]
		k += 1
		j += 1

	return a3

a1=[1,2,3,4,5]
a2=[2,4,5,5,9]

#a1 = [1,3,4,5]
#a2 = [2,4,6,8]

print(merge2sorted(a1,a2))


from random import shuffle,randint
list1 = ['Hello', 'The', 'World']

n = randint(0,len(list1)-1)
print("So Random : ", n)
a = list1[n]
k = list(list1[n])
shuffle(k)
print(k)

m = input("Nhap Tu Ban Doan : ")
if m == a:
    print("You Are Right")
else:
    print("You Are Wrong")


from django.conf import settings
from django.test import TestCase

from reviewboard.admin import checks

class UpdateTests(TestCase):
    """Tests for update required pages"""

    def tearDown(self):
        # Make sure we don't break further tests by resetting this fully.
        checks.reset_check_cache()

    def testManualUpdatesRequired(self):
        """Testing check_updates_required with valid configuration"""
        # NOTE: This is assuming the install is fine. It should be given
        #       that we set things like the uploaded path correctly to
        #       a known good directory before starting unit tests.
        updates_required = checks.check_updates_required()

        self.assertEqual(len(updates_required), 0)

    def testManualUpdatesRequiredBadUpload(self):
        """Testing check_updates_required with a bad upload directory"""
        old_media_root = settings.MEDIA_ROOT
        settings.MEDIA_ROOT = "/"
        checks.reset_check_cache()

        updates_required = checks.check_updates_required()
        settings.MEDIA_ROOT = old_media_root

        self.assertEqual(len(updates_required), 1)

        url, data = updates_required[0]
        self.assertEqual(url, "admin/manual-updates/media-upload-dir.html")

        response = self.client.get("/")
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, "admin/manual_updates_required.html")