import logging
from collections import namedtuple

import numpy as np
from numba import njit, prange

from . import basic
from .mf_common import BiasMFPredictor, MFPredictor
from ..matrix import sparse_ratings, _CSR
from .. import util
from ..math.solve import _dposv

_logger = logging.getLogger(__name__)

Context = namedtuple('Context', [
    'users', 'items',
    'user_matrix', 'item_matrix'
])

@njit(parallel=True, nogil=True)
def _train_matrix(mat: _CSR, other: np.ndarray, reg: float):
    "One half of an explicit ALS training round."
    nr = mat.nrows
    nf = other.shape[1]
    regI = np.identity(nf) * reg
    assert mat.ncols == other.shape[0]
    result = np.zeros((nr, nf))
    for i in prange(nr):
        cols = mat.row_cs(i)
        if len(cols) == 0:
            continue

        vals = mat.row_vs(i)
        M = other[cols, :]
        MMT = M.T @ M
        # assert MMT.shape[0] == ctx.n_features
        # assert MMT.shape[1] == ctx.n_features
        A = MMT + regI * len(cols)
        V = M.T @ vals
        # and solve
        _dposv(A, V, True)
        result[i, :] = V

    return result

@njit(parallel=True, nogil=True)
def _train_implicit_matrix(mat: _CSR, other: np.ndarray, reg: float):
    "One half of an implicit ALS training round."
    nr = mat.nrows
    nc = other.shape[0]
    nf = other.shape[1]
    assert mat.ncols == nc
    regmat = np.identity(nf) * reg
    Ot = other.T
    OtO = Ot @ other
    OtOr = OtO + regmat
    assert OtO.shape[0] == OtO.shape[1]
    assert OtO.shape[0] == nf
    result = np.zeros((nr, nf))
    for i in prange(nr):
        cols = mat.row_cs(i)
        if len(cols) == 0:
            continue

        rates = mat.row_vs(i)

        # we can optimize by only considering the nonzero entries of Cu-I
        # this means we only need the corresponding matrix columns
        M = other[cols, :]
        # Compute M^T C_u M, restricted to these nonzero entries
        MMT = (M.T.copy() * rates) @ M
        # assert MMT.shape[0] == ctx.n_features
        # assert MMT.shape[1] == ctx.n_features
        # Build the matrix for solving
        A = OtOr + MMT
        # Compute RHS - only used columns (p_ui != 0) values needed
        # Cu is rates + 1 for the cols, so just trim Ot
        y = Ot[:, cols] @ (rates + 1.0)
        # and solve
        _dposv(A, y, True)
        # assert len(uv) == ctx.n_features
        result[i, :] = y

    return result

class BiasedMF(BiasMFPredictor):
    """
    Biased matrix factorization trained with alternating least squares [ZWSP2008]_.  This is a
    prediction-oriented algorithm suitable for explicit feedback data.

    .. [ZWSP2008] Yunhong Zhou, Dennis Wilkinson, Robert Schreiber, and Rong Pan. 2008.
        Large-Scale Parallel Collaborative Filtering for the Netflix Prize.
        In +Algorithmic Aspects in Information and Management_, LNCS 5034, 337–348.
        DOI `10.1007/978-3-540-68880-8_32 <http://dx.doi.org/10.1007/978-3-540-68880-8_32>`_.

    Args:
        features(int): the number of features to train
        iterations(int): the number of iterations to train
        reg(double): the regularization factor
        damping(double): damping factor for the underlying mean
    """
    timer = None

    def __init__(self, features, *, iterations=20, reg=0.1, damping=5, bias=True):
        self.features = features
        self.iterations = iterations
        self.regularization = reg
        self.damping = damping
        if bias is True:
            self.bias = basic.Bias(damping=damping)
        else:
            self.bias = bias

    def fit(self, ratings):
        """
        Run ALS to train a model.

        Args:
            ratings: the ratings data frame.

        Returns:
            The algorithm (for chaining).
        """
        self.timer = util.Stopwatch()

        if self.bias is not None:
            _logger.info('[%s] fitting bias model', self.timer)
            self.bias.fit(ratings)

        current, bias, uctx, ictx = self._initial_model(ratings)

        _logger.info('[%s] training biased MF model with ALS for %d features',
                     self.timer, self.features)
        for epoch, model in enumerate(self._train_iters(current, uctx, ictx)):
            current = model

        _logger.info('trained model in %s', self.timer)

        # unpack and de-Series bias
        gb, ub, ib = bias
        self.global_bias_ = gb
        self.user_bias_ = np.require(ub.values, None, 'C') if ub is not None else None
        self.item_bias_ = np.require(ib.values, None, 'C') if ib is not None else None

        self.item_index_ = current.items
        self.user_index_ = current.users
        self.item_features_ = current.item_matrix
        self.user_features_ = current.user_matrix

        return self

    def _initial_model(self, ratings, bias=None):
        "Initialize a model and build contexts."
        rmat, users, items = sparse_ratings(ratings)
        n_users = len(users)
        n_items = len(items)

        rmat, bias = self._normalize(rmat, users, items)

        _logger.debug('setting up contexts')
        trmat = rmat.transpose()

        _logger.debug('initializing item matrix')
        imat = np.random.randn(n_items, self.features) * 0.01
        umat = np.full((n_users, self.features), np.nan)

        return Context(users, items, umat, imat), bias, rmat, trmat

    def _normalize(self, ratings, users, items):
        "Apply bias normalization to the data in preparation for training."
        n_users = len(users)
        n_items = len(items)
        assert ratings.nrows == n_users
        assert ratings.ncols == n_items

        if self.bias is not None:
            gbias = self.bias.mean_
            ibias = self.bias.item_offsets_
            ubias = self.bias.user_offsets_
        else:
            gbias = 0
            ibias = ubias = None

        _logger.info('[%s] normalizing %dx%d matrix (%d nnz)',
                     self.timer, n_users, n_items, ratings.nnz)
        ratings.values = ratings.values - gbias
        if ibias is not None:
            ibias = ibias.reindex(items, fill_value=0)
            ratings.values = ratings.values - ibias.values[ratings.colinds]
        if ubias is not None:
            ubias = ubias.reindex(users, fill_value=0)
            # create a user index array the size of the data
            reps = np.repeat(np.arange(len(users), dtype=np.int32),
                             ratings.row_nnzs())
            assert len(reps) == ratings.nnz
            # subtract user means
            ratings.values = ratings.values - ubias.values[reps]
            del reps

        return ratings, (gbias, ubias, ibias)

    def _train_iters(self, current, uctx, ictx):
        "Generator of training iterations."
        for epoch in range(self.iterations):
            umat = _train_matrix(uctx.N, current.item_matrix, self.regularization)
            _logger.debug('[%s] finished user epoch %d', self.timer, epoch)
            imat = _train_matrix(ictx.N, umat, self.regularization)
            _logger.debug('[%s] finished item epoch %d', self.timer, epoch)
            di = np.linalg.norm(imat - current.item_matrix, 'fro')
            du = np.linalg.norm(umat - current.user_matrix, 'fro')
            _logger.info('[%s] finished epoch %d (|ΔI|=%.3f, |ΔU|=%.3f)', self.timer, epoch, di, du)
            current = current._replace(user_matrix=umat, item_matrix=imat)
            yield current

    def predict_for_user(self, user, items, ratings=None):
        # look up user index
        return self.score_by_ids(user, items)

    def __str__(self):
        return 'als.BiasedMF(features={}, regularization={})'.\
            format(self.features, self.regularization)

class ImplicitMF(MFPredictor):
    """
    Implicit matrix factorization trained with alternating least squares [HKV2008]_.  This
    algorithm outputs 'predictions', but they are not on a meaningful scale.  If its input
    data contains ``rating`` values, these will be used as the 'confidence' values; otherwise,
    confidence will be 1 for every rated item.

    .. [HKV2008] Y. Hu, Y. Koren, and C. Volinsky. 2008.
       Collaborative Filtering for Implicit Feedback Datasets.
       In _Proceedings of the 2008 Eighth IEEE International Conference on Data Mining_, 263–272.
       DOI `10.1109/ICDM.2008.22 <http://dx.doi.org/10.1109/ICDM.2008.22>`_

    Args:
        features(int): the number of features to train
        iterations(int): the number of iterations to train
        reg(double): the regularization factor
        weight(double): the scaling weight for positive samples (:math:`\\alpha` in [HKV2008]_).
    """
    timer = None

    def __init__(self, features, *, iterations=20, reg=0.1, weight=40):
        self.features = features
        self.iterations = iterations
        self.reg = reg
        self.weight = weight

    def fit(self, ratings):
        self.timer = util.Stopwatch()
        current, uctx, ictx = self._initial_model(ratings)

        _logger.info('[%s] training implicit MF model with ALS for %d features',
                     self.timer, self.features)
        _logger.info('have %d observations for %d users and %d items',
                     uctx.nnz, uctx.nrows, ictx.nrows)
        for model in self._train_iters(current, uctx, ictx):
            current = model

        _logger.info('[%s] finished training model with %d features',
                     self.timer, self.features)

        self.item_index_ = current.items
        self.user_index_ = current.users
        self.item_features_ = current.item_matrix
        self.user_features_ = current.user_matrix

        return self

    def _train_iters(self, current, uctx, ictx):
        "Generator of training iterations."
        for epoch in range(self.iterations):
            umat = _train_implicit_matrix(uctx.N, current.item_matrix,
                                          self.reg)
            _logger.debug('[%s] finished user epoch %d', self.timer, epoch)
            imat = _train_implicit_matrix(ictx.N, umat, self.reg)
            _logger.debug('[%s] finished item epoch %d', self.timer, epoch)
            di = np.linalg.norm(imat - current.item_matrix, 'fro')
            du = np.linalg.norm(umat - current.user_matrix, 'fro')
            _logger.info('[%s] finished epoch %d (|ΔI|=%.3f, |ΔU|=%.3f)', self.timer, epoch, di, du)
            current = current._replace(user_matrix=umat, item_matrix=imat)
            yield current

    def _initial_model(self, ratings):
        "Initialize a model and build contexts."

        rmat, users, items = sparse_ratings(ratings)
        n_users = len(users)
        n_items = len(items)

        _logger.debug('setting up contexts')
        # force values to exist
        if rmat.values is None:
            rmat.values = np.ones(rmat.nnz)
        rmat.values *= self.weight
        trmat = rmat.transpose()

        imat = np.random.randn(n_items, self.features) * 0.01
        imat = np.square(imat)
        umat = np.full((n_users, self.features), np.nan)

        return Context(users, items, umat, imat), rmat, trmat

    def predict_for_user(self, user, items, ratings=None):
        # look up user index
        return self.score_by_ids(user, items)

    def __str__(self):
        return 'als.ImplicitMF(features={}, reg={}, w={})'.\
            format(self.features, self.reg, self.weight)


import numpy as np
import numdifftools as nd
import math
from numpy import linalg as LA

#define initial point
x= ([-2,3.5])

#define function
def fmain(x):
    return 3+(x[0]-1.5*x[1])**2+(x[1]-2)**2

g = nd.Gradient(fmain)(x)

f_r = fmain(x)

def goldensection(fmain,x,p):
        s_min = 0
        s_max = 1
        dx = 10**-4
        to = 0.38197
        eps = dx/(s_max-s_min)
        N = int(np.around((-2.078)*(math.log(eps))))
        N = N+1

        s1 = s_min + to * (s_max-s_min)
        f1 = fmain(x+s1*p)
        s2 =  s_max - to * (s_max-s_min)
        f2 = fmain(x+s2*p)

        for k in range(N):
            if f2<f1:
                s_min =s1
                s1 = s2
                f1 =f2
                s2 =  s_max - to * (s_max-s_min)
                f2 = fmain(x+s2*p)
            elif f1<f2:
                    s_max = s2
                    s2 = s1
                    f2 = f1
                    s1 = s_min + to * (s_max-s_min)
                    f1 = fmain(x+s1*p)
        s = (s_min+s_max)/2
        return s

loop = 1
nu_iteration = 0
while loop:

    nu_iteration = nu_iteration + 1
    Gradient = nd.Gradient(fmain)(x)
    p = - Gradient
    s = goldensection(fmain,x,p)
    dx = s * p
    x = x + dx
    F_r=fmain(x)
    print(s,np.transpose(x),np.transpose(Gradient),F_r)
    if LA.norm(Gradient) < 10**-4:
        loop = 0


#!/usr/local/PROGRAMS/XTAL/GIT-AMi_Image_Analysis/python/venvs/AMI_IMAGE_ANALYSIS_TENSORFLOW1/bin/python
# -*- coding: utf-8 -*-
"""
Created on Mon Dec 16 14:46:09 2019

@author: ludovic pecqueur

usage:
    Execute this script in the directory containing the images to crop
    this will create a directory cropped.
    start the script by typing:
    python3 autocrop.py

    Function is now called within GUI.
    Can still be used as standalone script
"""

import os
import re
from pathlib import Path
import cv2
import numpy as np
from preferences import DetectCircle as pref

_nsre = re.compile('([0-9]+)') #used to sort alphanumerics

def natural_sort_key(s):
     return [int(text) if text.isdigit() else text.lower()
             for text in re.split(_nsre, s)]

def crop_ROI(image, output_dir, well):
    x, y, r = find_best_circle(image)
    if x==0 or y==0: #If No circle was detected
        print("CROPPED image for well %s is empty, NOT SAVED"%well)
        return False
    r=r+20
    Ymax, Xmax =image.shape[0], image.shape[1]
    if y-r<0:ymin=0
    else:ymin=y-r
    if y+r>Ymax:ymax=Ymax
    else:ymax=y+r
    if x-r<0:xmin=0
    else:xmin=x-r
    if x+r>Xmax:xmax=Xmax
    else: xmax=x+r
    cropped=image[ymin:ymax, xmin:xmax]
    # cropped=image[y-r:y+r, x-r:x+r]
    # print("CROPPED image size well %s "%well, cropped.shape, "r=", r)

    path=Path(output_dir).joinpath("cropped",well+".jpg")

    #Only save images with bytes otherwise print error message
    if cropped.shape[0] != 0 and  cropped.shape[1] != 0:
        cv2.imwrite(str(path), cropped)
        # print("well %s saved to %s"%(well, path))
    else:
        print("CROPPED image for well %s is empty, NOT SAVED"%well)
        return False

def find_best_circle(image):
    '''this is an overkill function title'''
    # image = cv2.resize(image,(599,450), interpolation = cv2.INTER_AREA)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # gray_blurred = cv2.blur(gray, (3, 3))
    gray_blurred = cv2.GaussianBlur(gray, (3, 3),1)
    w,h = gray.shape[1],gray.shape[0]
    # circles = cv2.HoughCircles(gray_blurred,
    #                 cv2.HOUGH_GRADIENT, 1, pref.minDistance, param1 = pref.param1,
    #             param2 = pref.param2, minRadius = pref.minRadius, maxRadius = pref.maxRadius)

    #Try to enhance edges
    smooth = cv2.addWeighted(gray_blurred,1.5,gray,-0.5,0)
    circles = cv2.HoughCircles(smooth,
                cv2.HOUGH_GRADIENT, 1, pref.minDistance, param1 = pref.param1,
            param2 = pref.param2, minRadius = pref.minRadius, maxRadius = pref.maxRadius)

    R, X, Y = 0, 0, 0
    euclidians=[]

    #Find detected circle with max radius closest to center of image, temporary bad solution
    if circles is not None:
        circles = np.uint16(np.around(circles))
        for pt in circles[0, :]:
            x, y, r = pt[0], pt[1], pt[2]
            euclidian=np.sqrt((x - w*0.5)**2+(y - h*0.5)**2)
            euclidians.append((euclidian,r,x,y))
        for i in euclidians:
            if r>R and i[0]==min(euclidians)[0]:
                R = int(i[1])
                X = int(i[2])
                Y = int(i[3])
    # if circles is not None:
    #     print("DISTANCES to image center for %s"%well, euclidians, "MIN distance to image center", min(euclidians))
    del euclidians
    return X,Y,R

if __name__ == "__main__":
    Ext=[".tif",".tiff",".TIFF",".jpg", ".jpeg",".JPG",".JPEG",".png",".PNG"]
    directory = os.getcwd()
    print("directory ", directory)
    files, well_images= [],[]

    try:
        os.mkdir('cropped')
    except OSError:
            print ("Creation of the directory %s failed" % 'cropped')
    else:
            print ("Successfully created the directory %s " % 'cropped')

    for file in os.listdir(directory):
        if os.path.splitext(file)[1] in Ext:
            files.append(os.path.join(directory, file))

    files.sort(key=natural_sort_key)

    errors, error_list = 0, []
    for _file in files:
        img = cv2.imread(_file, cv2.IMREAD_COLOR)
        well=os.path.splitext(os.path.basename(_file))[0]
        output=crop_ROI(img, directory, well)
        if output is False:
            errors +=1
            error_list.append(os.path.basename(_file))
        del img, output

    log=Path(directory).joinpath("cropped","autocrop.log")
    with open(log, 'w') as f:
        if errors!=0:
            f.write("File(s) that could not be processed correctly \n")
            for err in error_list: f.write(err+"\n")
        else:
            f.write("All Files could be processed.")

    print('''
%s file(s) were not processed.
For more information check log file %s

You can use the tool Check_Circle_detection.py filename to check
and modify detection parameters.
'''%(errors, log))


from Model import *
import numpy as np
def Hp(world):

    sum=0
    dif=np.zeros(4)
    i=0
    for hero in world.my_heroes:
       dif[i]=hero.max_hp - hero.current_hp
       sum = sum + hero.max_hp
       i=i+1
    return  1-(dif.sum()/sum)
def hp_invision(world) :
    prod=0
    opp_hp=np.zeros(4)
    i=0
    for hero in world.opp_heroes:
        if hero.current_cell.row == -1:
            opp_hp[i]= 1
        else:
            opp_hp[i]=hero.current_hp
        i=i+1
    return np.prod(opp_hp)


# 3.4 Файловый ввод/вывод

"""
На прошлой неделе мы сжимали строки, используя кодирование повторов. Теперь нашей задачей будет восстановление
исходной строки обратно.
Напишите программу, которая считывает из файла строку, соответствующую тексту, сжатому с помощью кодирования повторов,
и производит обратную операцию, получая исходный текст.
Запишите полученный текст в файл и прикрепите его, как ответ на это задание.
В исходном тексте не встречаются цифры, так что код однозначно интерпретируем.
Sample Input: a3b4c2e10b1
Sample Output: aaabbbbcceeeeeeeeeeb
"""

with open('D:\Python\dataset_3363_2.txt') as inf:
    s = inf.readline()
    resultString = ''
    lineLen = len(s) - 1
    i = 0
    while i < lineLen:
        number = ''
        letter = s[i]
        i += 1
        while s[i] in '0123456789':
            number += str(s[i])
            i += 1
            if i > lineLen:
                break
        resultString += letter * int(number)

with open('D:\Python\dataset_3363_result.txt', 'w', encoding='utf-8') as inf:
    inf.write(resultString)


import requests
import json

def main(kw):
    base_url = 'https://fanyi.baidu.com/sug'
    data = {
        'kw': kw
    }
    #求取data数组转换为字符串的长度
    data_len = len(str(data))

    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest',
        'referer': 'https://fanyi.baidu.com/',
        #将data字符串长度，从整型转换为字符串
        'content-length': str(data_len),
        'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
    }

    response = requests.post(base_url, headers = headers, data = data)

    #print(response.text)
    '''
    {"errno":0,"data":[{"k":"python","v":"n. \u87d2; \u86ba\u86c7;"},{"k":"pythons","v":"n. \u87d2; \u86ba\u86c7;  python\u7684\u590d\u6570;"}]}
    '''

    #处理异步请求json数据
    json_data = json.loads(response.text)

    #print(json_data)
    '''
    n. 蟒; 蚺蛇;
    n. 蟒; 蚺蛇;  python的复数;
    '''

    results = ''
    for data in json_data['data']:
        results += data['v'] + '\n'
    print(results)

if __name__ == '__main__':
    #kw = 'china'
    kw = input("Input a word： \n")
    main(kw)


import argparse
import os

import cv2
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

import kornia as dgm

def load_homography(file_name):
    """Loads an homography from text file."""
    assert os.path.isfile(file_name), "Invalid file {}".format(file_name)
    return torch.from_numpy(np.loadtxt(file_name)).float()

def load_image(file_name):
    """Loads the image with OpenCV and converts to torch.Tensor"""
    assert os.path.isfile(file_name), "Invalid file {}".format(file_name)

    # load image with OpenCV
    img = cv2.imread(file_name, cv2.IMREAD_COLOR)

    # convert image to torch tensor
    tensor = dgm.utils.image_to_tensor(img).float() / 255.0
    tensor = tensor.view(1, *tensor.shape)  # 1xCxHxW

    return tensor, img

class MyHomography(nn.Module):
    def __init__(self):
        super(MyHomography, self).__init__()
        self.homo = nn.Parameter(torch.Tensor(3, 3))

        self.reset_parameters()

    def reset_parameters(self):
        torch.nn.init.eye_(self.homo)

    def forward(self):
        return torch.unsqueeze(self.homo, dim=0)  # 1x3x3

def HomographyRegressionApp():
    # Training settings
    parser = argparse.ArgumentParser(description='Homography Regression with photometric loss.')
    parser.add_argument('--input-dir', type=str, required=True, help='the path to the directory with the input data.')
    parser.add_argument('--output-dir', type=str, required=True, help='the path to output the results.')
    parser.add_argument(
        '--num-iterations', type=int, default=1000, metavar='N', help='number of training iterations (default: 1000)'
    )
    parser.add_argument('--lr', type=float, default=1e-3, metavar='LR', help='learning rate (default: 1e-3)')
    parser.add_argument('--cuda', action='store_true', default=False, help='enables CUDA training')
    parser.add_argument('--seed', type=int, default=666, metavar='S', help='random seed (default: 666)')
    parser.add_argument(
        '--log-interval',
        type=int,
        default=10,
        metavar='N',
        help='how many batches to wait before logging training status',
    )
    parser.add_argument(
        '--log-interval-vis',
        type=int,
        default=100,
        metavar='N',
        help='how many batches to wait before visual logging training status',
    )
    args = parser.parse_args()

    # define the device to use for inference
    use_cuda = args.cuda and torch.cuda.is_available()
    device = torch.device('cuda' if use_cuda else 'cpu')

    torch.manual_seed(args.seed)

    # load the data
    img_src, _ = load_image(os.path.join(args.input_dir, 'img1.ppm'))
    img_dst, _ = load_image(os.path.join(args.input_dir, 'img2.ppm'))
    dst_homo_src_gt = load_homography(os.path.join(args.input_dir, 'H1to2p'))

    # instantiate the homography warper from `kornia`
    height, width = img_src.shape[-2:]
    warper = dgm.HomographyWarper(height, width)

    # create the homography as the parameter to be optimized
    dst_homo_src = MyHomography().to(device)

    # create optimizer
    optimizer = optim.Adam(dst_homo_src.parameters(), lr=args.lr)

    # main training loop

    for iter_idx in range(args.num_iterations):
        # send data to device
        img_src, img_dst = img_src.to(device), img_dst.to(device)

        # warp the reference image to the destiny with current homography
        img_src_to_dst = warper(img_src, dst_homo_src())

        # compute the photometric loss
        loss = F.l1_loss(img_src_to_dst, img_dst, reduction='none')

        # propagate the error just for a fixed window
        w_size = 100  # window size
        h_2, w_2 = height // 2, width // 2
        loss = loss[..., h_2 - w_size : h_2 + w_size, w_2 - w_size : w_2 + w_size]
        loss = torch.mean(loss)

        # compute gradient and update optimizer parameters
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if iter_idx % args.log_interval == 0:
            print('Train iteration: {}/{}\tLoss: {:.6}'.format(iter_idx, args.num_iterations, loss.item()))
            print(dst_homo_src.homo)

        def draw_rectangle(image, dst_homo_src):
            height, width = image.shape[:2]
            pts_src = torch.FloatTensor(
                [[[-1, -1], [1, -1], [1, 1], [-1, 1]]]  # top-left  # bottom-left  # bottom-right  # top-right
            ).to(dst_homo_src.device)
            # transform points
            pts_dst = dgm.transform_points(torch.inverse(dst_homo_src), pts_src)

            def compute_factor(size):
                return 1.0 * size / 2

            def convert_coordinates_to_pixel(coordinates, factor):
                return factor * (coordinates + 1.0)

            # compute convertion factor
            x_factor = compute_factor(width - 1)
            y_factor = compute_factor(height - 1)
            pts_dst = pts_dst.cpu().squeeze().detach().numpy()
            pts_dst[..., 0] = convert_coordinates_to_pixel(pts_dst[..., 0], x_factor)
            pts_dst[..., 1] = convert_coordinates_to_pixel(pts_dst[..., 1], y_factor)

            # do the actual drawing
            for i in range(4):
                pt_i, pt_ii = tuple(pts_dst[i % 4]), tuple(pts_dst[(i + 1) % 4])
                image = cv2.line(image, pt_i, pt_ii, (255, 0, 0), 3)
            return image

        if iter_idx % args.log_interval_vis == 0:
            # merge warped and target image for visualization
            img_src_to_dst = warper(img_src, dst_homo_src())
            img_vis = 255.0 * 0.5 * (img_src_to_dst + img_dst)
            img_vis_np = dgm.utils.tensor_to_image(img_vis)
            image_draw = draw_rectangle(img_vis_np, dst_homo_src())
            # save warped image to disk
            file_name = os.path.join(args.output_dir, 'warped_{}.png'.format(iter_idx))
            cv2.imwrite(file_name, image_draw)

if __name__ == "__main__":
    HomographyRegressionApp()


# encoding:utf-8
'''
@Author: catnlp
@Email: wk_nlp@163.com
@Time: 2018/4/27 19:07
'''
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable
import numpy as np
import visdom
import math

torch.manual_seed(100)

# Hyper Parameters
sequence_length = 28
input_size = 28
hidden_size = 128
num_layers = 2
num_classes = 10
batch_size = 100
num_epochs = 100
learning_rate = 0.01

# MNIST Dataset
train_dataset = dsets.MNIST(root='../data/', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = dsets.MNIST(root='../data/', train=False, transform=transforms.ToTensor())

# Data Loader (Input Pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

# RNN Model (Many-to-One)
class base_RNNModel(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes, bias=True):
        super(base_RNNModel, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.num_classes = num_classes
        self.rnn = nn.RNN(input_size, hidden_size, num_layers=num_layers, bias=bias, batch_first=True)
        self.fc = nn.Linear(hidden_size, num_classes, bias=bias)

        self.reset_parameters()

    def reset_parameters(self):
        stdv = 1.0 / math.sqrt(self.hidden_size)
        for weight in self.parameters():
            weight.data.uniform_(-stdv, stdv)

    def forward(self, x):
        # set initial states
        # initial_states = [Variable(torch.zeros(x.size(0), self.hidden_size)) for _ in range(self.num_layers)]

        # forward propagate RNN
        out, _ = self.rnn(x)
        # print('out0-------')
        # print(out.size())
        out = out[:, -1, :]
        # print('out1------')
        # print(out.size())
        out.view(-1, self.hidden_size)
        # print('out2----------')
        # print(out.size())
        out = self.fc(out)
        # print('out3--------')
        # print(out.size())
        out = out.view(-1, self.num_classes)
        # print('out4----------')
        # print(out.size())
        return out

base_model = base_RNNModel(input_size, hidden_size, num_layers, num_classes, bias=True)

criterion = nn.CrossEntropyLoss()

# Test the Model
def evaluate(model):
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = Variable(images.view(-1, sequence_length, input_size))
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()
    accuracy = 100.0 * correct / total
    print('Test Accuracy of the model on the 10000 test images: %.2f %%' % accuracy)
    return accuracy

# Train the Model
def train(model, model_name, save_path):
    vis = visdom.Visdom()
    best_accuracy = 0
    losses = []
    accuracy = []
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
    for epoch in range(num_epochs):
        model.train(True)
        for i, (images, labels) in enumerate(train_loader):
            images = Variable(images.view(-1, sequence_length, input_size))
            labels = Variable(labels)

            optimizer.zero_grad()
            outputs = model(images)
            loss = criterion(outputs, labels)
            sample_loss = loss.data
            loss.backward()
            optimizer.step()

            if (i + 1) % 100 == 0:
                # draw the loss line
                losses.append(sample_loss)
                vis.line(np.array(losses), X=np.array([i for i in range(len(losses))]),
                         win=model_name+'_loss', opts={'title': model_name+'_loss', 'legend': ['loss']})
                print('Epoch [%d], Step [%d], Loss: %.4f' % (epoch+1, i+1, sample_loss))
        model.train(False)
        current_accuracy = evaluate(model)

        # draw the accuracy line
        accuracy.append(current_accuracy)
        vis.line(np.array(accuracy), X=np.array([i for i in range(len(accuracy))]),
                 win=model_name+'_accuracy', opts={'title': model_name+'_accuracy', 'legend': ['accuracy']})
        if(current_accuracy > best_accuracy):
            best_accuracy = current_accuracy
            torch.save(model.state_dict(), save_path)
    print('Best Accuracy of the model on the 10000 test images: %.2f %%' % best_accuracy)

train(base_model, 'base_RNN', '../models/base_RNN.pkl')


import glob
import os
import time
import datetime
import io

name = '/home/john/Desktop/REU/Tweets/rawtweets/*.txt'

class tweet:
    def __init__(self, t, u, w):
        self.t = t
        self.u = u
        self.w = w

for fileName in glob.glob(name):
    f = open(fileName, 'r')
    #go through each Tweet object
    #create one by one (DONT STORE EVERYTHIGN IN MEMO)
    #Check if a file with that date exists
    #if not create one
    #else go to the file:
    #write down the Tweet component of the object

    lines = []
    for line in f:
        line = line.strip()
        lines.append(line)
        if line.startswith("W"):
            theTweet = tweet(t=lines[-3], u=lines[-2], w=lines[-1])
            lines = []
            uglyDate = (theTweet.t).split()[1]
            newDate = datetime.datetime.strptime(uglyDate, '%Y-%m-%d').strftime('%m%d%y')
            #print(newDate)

            TweetMessage = (theTweet.w)[2:]

            theTweetDateFile = '/home/john/Desktop/REU/Tweets/processedTweets/'+newDate+'.txt'

            if(os.path.isfile(theTweetDateFile)):
                with io.FileIO(theTweetDateFile, 'a') as tweetFile:
                    tweetFile.write("\n")
                    tweetFile.write(TweetMessage)
            else:
                ##create a new file
                with io.FileIO(theTweetDateFile, 'w') as tweetFile:
                    tweetFile.write("\n")
                    tweetFile.write(TweetMessage)


#design inspired from https://github.com/KeithGalli/GUI/blob/master/WeatherApp.py
#time taken 2.568
import tkinter as tk

from tkinter import ttk
from tkscrolledframe import ScrolledFrame
from tkinter import filedialog,messagebox
import os
from extractGUI import *
from tkinter.messagebox import showerror
import time

HEIGHT = 900
WIDTH = 1400
PATH="tets"
listSheet=[]
listCol=[]
root = tk.Tk()
general_checkbuttons={}
hasPress=False
style = ttk.Style()

style.configure('Button', foreground='Green')

def UploadAction(event=None):
    try:
       # print("yes")
        filename = filedialog.askopenfilename(title = "Select .xlsx file",filetypes = [("XLSX Files",".xlsx")])
        global PATH

        PATH=filename
        print(PATH)
        canvas2.pack_forget()
        label.config(text="File: {}".format(PATH))
        global listSheet
        listSheet=return_sheet(PATH)
        mycomboSheet.config(values=listSheet)
        mycomboSheet.current(0)
        canvas.pack()
    except(OSError,FileNotFoundError):
        showerror("Error", message=root.filename)
        root.destroy()

        print(f'Unable to find or open <{root.filename}>')
    except Exception as error:
        showerror("Error", message="Error occured! Please choose a file next time")
        root.destroy()

def on_selectSheet(event=None):
    global listColumn
    listColumn=return_column(PATH,mycomboSheet.get())
    show_frame = tk.Frame(canvas, bg='#6DD5ED', bd=10)
    show_frame.place(relx=0.5, rely=0.25, relwidth=0.8, relheight=0.12 ,anchor='n')

    labelColumn = tk.Label(show_frame,text="Choose Column",bg='#6DD5ED')
    labelColumn.place(rely=0,relx=0.5,relwidth=1, relheight=0.25,anchor="n")

    myComboColumn=ttk.Combobox(show_frame,state="readonly",values=listColumn)
    myComboColumn.place(relwidth=1, relheight=0.45,rely=0.4)
    myComboColumn.current(0)
    # print(myComboColumn.get())

    myComboColumn.bind('<<ComboboxSelected>>', on_selectColumn)

def on_selectColumn(eventObject):
    global value
    value=return_value(PATH,mycomboSheet.get(),eventObject.widget.get())
    global chosenSheet
    chosenSheet=mycomboSheet.get()
    global chosenColumn
    chosenColumn=eventObject.widget.get()
    value=list(value)
    create_column(value)
def callback(valueVar):
    print(valueVar.get())
def valueSearch(valStr):
    # var=tk.StringVar()
    # var.set(valStr)
    # var.trace("w", callback(var))

    print(valStr)

def create_column(currentValue):
    show_scroll=tk.Label(canvas,text="Choose word to replace" ,bg='#6DD5ED', bd=10)
    show_scroll.place(relx=0.5, rely=0.4, relwidth=0.8, relheight=0.05, anchor='n')
    sf = ScrolledFrame(canvas)
    sf.place(relx=0.5, rely=0.45, relwidth=0.8, relheight=0.35, anchor='n')

    # Bind the arrow keys and scroll wheel
    sf.bind_arrow_keys(canvas)
    sf.bind_scroll_wheel(canvas)

    # Create a frame within the ScrolledFrame
    inner_frame = sf.display_widget(tk.Frame)
    global general_checkbuttons
    general_checkbuttons = {}
    col=3
    counterX=0
    counterY=0
    arrayAns=[]
   # print(currentValue)
    # currentValue=["A","B","C","D","A","B","C","D","A","B","C","D","A","B","C","D"]
    root.grid_columnconfigure(4, minsize=50)
    for i in range(len(currentValue)):
        for y in range(col):
            if counterX % col!= 0 or i==0:
                cal=i%col

                cb = tk.Checkbutton(inner_frame, font=(None, 12),variable=currentValue[i],text=currentValue[i], wraplength=250)
                cb.grid(row=counterY, column=cal, sticky="w", pady=1, padx=1)
                general_checkbuttons[i] = cb
                break
            elif counterX %col ==0:
                cal=i%col

                counterY+=1
                cb = tk.Checkbutton(inner_frame, font=(None, 12),variable=currentValue[i],text=currentValue[i], wraplength=250)

                cb.grid(row=counterY, column=cal, sticky="w", pady=1, padx=1)
                general_checkbuttons[i] = cb
                break

        counterX+=1
    frameSearch=tk.Frame(canvas,bd=5,bg="#6DD5ED")
    frameSearch.place(rely=0.80,relx=0.1,relwidth=0.74, relheight=0.04)
    entrySearch=tk.Entry(frameSearch)
    entrySearch.place(relwidth=1)
    entrySearch.insert(0, 'Search for words')
    entrySearch.bind("<FocusIn>", lambda args: entrySearch.delete('0', 'end'))

    entrySearch.bind("<KeyPress>", lambda args: valueSearch(entrySearch.get(),currentValue))

    buttonWord = tk.Button(canvas, text='Choose Word', command=lambda:extractChecked(general_checkbuttons,currentValue,True))
    buttonWord.place(rely=0.80,relx=0.84)

def extractChecked(check,valueArray,pressed):
    array=[]
    for i in range(len(valueArray)):
        cb = check[i]
        varname = cb.cget("variable")
        value = canvas.getvar(varname)
        if value=="1":
            array.append(valueArray[i])
    frame3 = tk.Frame(canvas, bg='#6DD5ED',bd=10)
    frame3.place(relwidth=0.8, relheight=0.1,rely=0.86,relx=0.1)
    label= tk.Label(frame3,text="Editing column in file: {}".format(PATH),bg='#6DD5ED')
    label.place(rely=0.06,relx=0.5,anchor="center")
    entry1 = tk.Entry (frame3)
    entry1.place(relwidth=1, relheight=0.6,rely=0.38)
    global hasPress
    hasPress=pressed
    buttonSubmit = tk.Button(canvas, text='Submit',command=lambda: confirm(array,entry1))
    buttonSubmit.place(rely=0.95,relx=0.86)
def clear():

    for i in general_checkbuttons:
        general_checkbuttons[i].deselect()   # forget checkbutton
        # i.destroy()
def confirm(array,entry1):
    check =entry1.get() if entry1.get()!="" else ""
    global hasPress
    #print("hasPress:", hasPress)
    if hasPress==True and len(array)>0 :
        message=messagebox.askquestion(title=None, message="Do you wish to submit {}".format( check ), icon='question')
        if message =="yes":
            # print("Yesssss",array)
            start = time.process_time()

            createDict(PATH,check,array,chosenColumn,chosenSheet)
            clear()
            value=list(return_value(PATH,chosenSheet,chosenColumn))
            # print("Value: ",value)
            create_column(value)
            hasPress=False
            print(time.process_time() - start)

            messagebox.showinfo("showinfo", "Successful!")

        else:
            # print("No")
            hasPress=False
    else:
        showerror("Error", message="Please reselect word and press 'Choose Word' ")
        hasPress=False

def getChecked(value):
   # print(cb.cget("text"))
    for i in range(value):
        cb = general_checkbuttons[i]

        varname = cb.cget("variable")
        value = canvas.getvar(varname)
       # print(f"{i}: {value}")

def page1():
    message=messagebox.askquestion(title=None, message="Do you wish to exit?", icon='question')
    if message =="yes":
        print("Yesssss")
        root.destroy()
    else:
        return

def page2():
    canvas2.pack_forget()
    canvas.pack()

canvas2 = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas2.pack()

main_frame = tk.Frame(canvas2,bg='#6DD5ED')
main_frame.place(relwidth=1, relheight=1)

labelMain=tk.Label(main_frame,text="Word Converter",bg="#6DD5ED",font=("Helvetica", 48))
labelMain.place(relx=0.5,rely=0.4,anchor="center")

buttonFile = ttk.Button(main_frame, text='Choose File', command= UploadAction)
buttonFile.place(rely=0.5,relx=0.5,anchor="center")

#### First Canvas ##################################

canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack_forget()

# background_image = tk.PhotoImage(file='Cool Blues.png')
background_label = tk.Label(canvas, bg='#40C8E7')
background_label.place(relwidth=1, relheight=1)

############## top frame #################
frame = tk.Frame(canvas,bg='#6DD5ED', bd=5)
frame.place(relx=0.5, rely=0.02, relwidth=0.8, relheight=0.05, anchor='n')
label= tk.Label(frame,text="Editing column in file: {}".format(PATH),bg='#6DD5ED')
label.place(relwidth=1, relheight=1)
############## end top frame #################

###############show sheet ##############################

show_sheet= tk.Frame(canvas, bg='#6DD5ED', bd=10)
show_sheet.place(relx=0.5, rely=0.1, relwidth=0.8, relheight=0.12, anchor='n')

labelSheet = tk.Label(show_sheet,text="Choose Sheet",bg='#6DD5ED')
labelSheet.place(rely=0,relx=0.5,relwidth=1, relheight=0.25,anchor="n")

mycomboSheet=ttk.Combobox(show_sheet,state="readonly",values=listSheet)
mycomboSheet.place(relwidth=1, relheight=0.4,rely=0.4)
mycomboSheet.bind('<<ComboboxSelected>>', on_selectSheet)

buttonClose=tk.Button(canvas, text='Exit',command=page1)
buttonClose.place(anchor="nw")

root.mainloop()


# -*- coding: utf-8 -*-
# @Author: Weijia Sun
# @Date:   2020-04-13 16:36:22
# @Last Modified by:   Weijia Sun
# @Last Modified time: 2020-04-13 16:36:28
# Copyright 2019 Weijia Sun, MIT license
import os.path
import re

from setuptools import find_packages, setup

def find_version(*paths):
    fname = os.path.join(os.path.dirname(__file__), *paths)
    with open(fname) as fp:
        code = fp.read()
    match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", code, re.M)
    if match:
        return match.group(1)
    raise RuntimeError("Unable to find version string.")

VERSION = find_version('acc', '__init__.py')
DESCRIPTION = 'Auto-Correlogram Calculation in seismology'
# LONG_DESCRIPTION = (
#     'Please look at the project site for tutorials and information.')
with open("README.md", "r") as fh:
    LONG_DESCRIPTION = fh.read()

ENTRY_POINTS = {
    'console_scripts': ['acc=acc.main:run',
                        ]}

#REQUIRES = ['cartopy', "click", 'commentjson', 'geographiclib',
REQUIRES = ["click", 'commentjson', 'geographiclib',
            'matplotlib>=2', 'numpy',
            'obspy>=1.0.3', "pandas",
            'setuptools', 'shapely', 'scipy>=0.19.0', 'tqdm', "netCDF4"
            ]

# EXTRAS_REQUIRE = {
#     'doc': ['sphinx', 'alabaster'],  # and decorator, obspy
#     'h5': ['obspyh5>=0.3']}

CLASSIFIERS = [
    'Environment :: Console',
    'Intended Audience :: Science/Research',
    'License :: OSI Approved :: MIT License',
    'Operating System :: OS Independent',
    'Programming Language :: Python :: 3',
    'Programming Language :: Python :: 3.3',
    'Programming Language :: Python :: 3.4',
    'Programming Language :: Python :: 3.5',
    'Programming Language :: Python :: 3.6',
    'Programming Language :: Python :: 3.7',
    'Programming Language :: Python :: 3.8',
    'Topic :: Scientific/Engineering :: Physics'
]

setup(name='seis-acc',
      version=VERSION,
      description=DESCRIPTION,
      long_description=LONG_DESCRIPTION,
      long_description_content_type="text/markdown",
      url='https://github.com/weijias-opensource/acc',
      author='Weijia SUN',
      author_email='weijia_sun@163.com',
      license='MIT',
      packages=find_packages(),
      package_dir={'acc': 'acc'},
      install_requires=REQUIRES,
      # extras_require=EXTRAS_REQUIRE,
      entry_points=ENTRY_POINTS,
      # please note the entry_points
      # The magic is in the entry_points parameter. Below console_scripts, each line identifies one console script.
      # The first part before the equals sign (=) is the name of the script that should be generated,
      # the second part is the import path followed by a colon (:) with the Click command.
      # entry_points={"console_scripts": ['acc=acc.main:run',],},
      include_package_data=True,
      zip_safe=False,
      classifiers=CLASSIFIERS
      )


#!/usr/bin/env python
import numpy as np
import csv

fp = open('src/mapdata.csv', 'r')
lines=fp.readlines()
matrix=lines[0].split(',')
for aa in range(len(matrix)):
    matrix[aa]=int(matrix[aa])
dim = np.sqrt(len(matrix))
dim=int(dim)
m=[[0 for i in range(dim)] for j in range(dim)]
c=0
R=0.1
for a in range(dim):
    for b in range(dim):
        m[dim-a-1][b]=matrix[c]
        c=c+1

h=0
for c in range(dim):
    for d in range(dim):
        if m[c][d]==100 or m[c][d]==-1:
            h=h+1

f=0
matt=[[0 for i in range(8)] for j in range(h)]
g=1
for c in range(dim):
    for d in range(dim):
        if m[c][d]==100 or m[c][d]==-1:
            X=c/10-4.8
            Y=d/10-4.8
            if d!=0:
                if m[c][d-1]==100 or m[c][d-1]==-1:
                    matt[f-1][0]=1000
                    matt[f][0]=X-R/2
                    matt[f][1]=Y-R/2-(g*R)
                    matt[f][2]=X+R/2
                    matt[f][3]=Y-R/2-(g*R)
                    matt[f][4]=X-R/2
                    matt[f][5]=Y+R/2
                    matt[f][6]=X+R/2
                    matt[f][7]=Y+R/2
                    g=g+1
                else:
                    g=1
                    matt[f][0]=X-R/2
                    matt[f][1]=Y-R/2
                    matt[f][2]=X+R/2
                    matt[f][3]=Y-R/2
                    matt[f][4]=X-R/2
                    matt[f][5]=Y+R/2
                    matt[f][6]=X+R/2
                    matt[f][7]=Y+R/2
            else:
                g=1
                matt[f][0]=X-R/2
                matt[f][1]=Y-R/2
                matt[f][2]=X+R/2
                matt[f][3]=Y-R/2
                matt[f][4]=X-R/2
                matt[f][5]=Y+R/2
                matt[f][6]=X+R/2
                matt[f][7]=Y+R/2
            f=f+1

f=0
for e in range(len(matt)):
    if matt[e][0]!=1000:
        f=f+1

matty=[[0 for i in range(8)] for j in range(f)]

f=0
for e in range(len(matt)):
    if matt[e][0]!=1000:
        matty[f]=matt[e]
        f=f+1
g=1
for e in range(len(matty)):
    if e>1:
        if matty[e][1]==matty[e-1][1] and matty[e][5]==matty[e-1][5]:
            matty[e-1][0]=1000
            matty[e][0]=matty[e][0]-(g*R)
            matty[e][4]=matty[e][4]-(g*R)
            g=g+1
        else:
            g=1

f=0
for e in range(len(matty)):
    if matty[e][0]!=1000:
        f=f+1

mat=[[0 for i in range(8)] for j in range(f)]

f=0
for e in range(len(matty)):
    if matty[e][0]!=1000:
        mat[f]=matty[e]
        f=f+1

print(len(mat))

with open('prm_obstacles.csv', 'w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow([-5, 5, -5, 5])
    writer.writerow([0.14, 0.14])
    writer.writerow([0, 0, 0, -1, -1, 1])
    for e in range(len(mat)):
        writer.writerow(mat[e])

    writer.writerow([-5, 5, -4.7, 5, -5, -5, -4.7, -5])
    writer.writerow([-4.7, 5, 4.7, 5, -4.7, 4.7, 4.7, 4.7])
    writer.writerow([4.7, 5, 5, 5, 4.7, -5, 5, -5])
    writer.writerow([-4.7, -4.7, 4.7, -4.7, -4.7, -5, 4.7, -5])


from __future__ import print_function
import sys
sys.path.append('/home/is/takatomo-k/work/End-to-End/lstm/att_mt_emph_trans/donet/')
import chainer
import component as com
import chainer.functions as F
import chainer.links as L
from chainer import cuda
import numpy as np
import os
from chainer import serializers
import json
import ConfigParser
#import configparser
from chainer import optimizers

class Trainer(object):
    def __init__(self, grad_clip=5., opt_type="Adam", lr=0.001, lr_descend=1.8, lr_thres=0.00001):
        print("~~~~~ Training settings ~~~~~~~")
        print('~ Inital learning rate: %5f' % (lr))
        print('~ learning rate descend rate: %f' % (lr_descend))
        print('~ threshold of stop training: %5f' % (lr_thres))

        if opt_type == 'Adam':
            print('~ Optimizer: Adam')
            self.optimizer = optimizers.Adam()
        elif opt_type == 'RMSpropGraves':
            print('~ Optimizer RMSpropGraves')
            self.optimizer = optimizers.RMSpropGraves(lr=lr)
        else:
            print('Optimizer %s not supported' % opt_type)
            exit(1)
        print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')

        self.grad_clip = grad_clip
        self.lr_thres = lr_thres
        self.accum_loss = 0
        self.lr_descend = lr_descend
        self.model = None

    def continue_train(self):
        if self.optimizer.lr < self.lr_thres:
            return False
        else:
            return True

    @property
    def lr(self):
        return self.optimizer.lr

    @lr.setter
    def lr(self, lr):
        self.optimizer.lr = lr

    def descend_lr(self):
        print('Descending')
        self.optimizer.lr /= self.lr_descend

    def set_model(self, model):
        self.model = model
        self.optimizer.setup(self.model)
        self.optimizer.add_hook(chainer.optimizer.GradientClipping(self.grad_clip))

    def update_params(self):
        if not isinstance(self.accum_loss, int):
            self.model.zerograds()
            self.accum_loss.backward()
            self.accum_loss.unchain_backward()  # truncate
            self.accum_loss = 0
            self.optimizer.update()

    def add_loss(self, loss):
        self.accum_loss += loss


import tkinter as tk
from tkinter import ttk
import random as rand
from PIL import ImageTk, Image
import json
import Char as char
import Init_lists as lists

LARGE_FONT = ("Verdana", 12)

# Can put inheritance into these parathemcies
class dnd_char_Sheet(tk.Tk):
    # init method is initalisation class. When the class runs this will imidately will run
    def __init__(self):
        # initalise tkinter as well
        tk.Tk.__init__(self)
        self.container = tk.Frame(self)

        #self.container.pack(side='top', fill='both', expand=True)
        self.container.grid(row=0,column=0)

        self.container.grid_rowconfigure(0, weight=1)
        self.container.grid_columnconfigure(0, weight=1)

        self.menubar = tk.Menu(self.container)
        self.filemenu = tk.Menu(self.menubar, tearoff=0)
        self.filemenu.add_command(label="Save Settings")
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Exit", command=quit)

        self.spell_menu = tk.Menu(self.menubar, tearoff=0)
        self.lvl_menu = tk.Menu(self.spell_menu, tearoff=0)
        self.class_menu = tk.Menu(self.spell_menu, tearoff=0)

        for i in range(0, 8):
            self.lvl_menu.add_command(label=i)

        for i in ['Ranger', 'Barbarian', 'Paladin', 'Bard', 'Cleric', 'Druid', 'Fighter', 'Monk', 'Rouge', 'Sorcerer',
                  'Warlock', 'Wizard']:
            self.class_menu.add_command(label=i)

        self.class_menu.add_command(label="hello")
        self.spell_menu.add_cascade(label="By Level", menu=self.lvl_menu)
        self.spell_menu.add_cascade(label="By Class", menu=self.class_menu)

        self.menubar.add_cascade(label="File", menu=self.filemenu)
        self.menubar.add_cascade(label="Edit")
        self.menubar.add_cascade(label="Spells", menu=self.spell_menu)

        self.menubar.entryconfigure("Spells", state="disabled")

        tk.Tk.config(self, menu=self.menubar)

        self.frames = {}

        for F in (StartPage, Page_One):
            self.init_frames(F)

        self.show_frame(StartPage)

    def show_frame(self, page):
        frame = self.frames[page]
        frame.tkraise()

    def init_frames(self, page):
        frame = page(self.container, self)
        self.frames[page] = frame
        frame.grid(row=0, column=0, sticky="nsew")

    def show_page(self, page):
        frame = page(self.container, self)
        self.frames[page] = frame

    def show_char_sheet(self):
        self.init_frames(Page_Two)
        self.show_frame(Page_Two)
        self.spell_menu.add_command(label="Spells", command=lambda: self.show_page(Spell_Page))
        # self.char_menu.add_command(label="Level Up",command = lambda :self.show_page(level_up_page))
        #self.menubar.entryconfigure("Character", state="normal")
        self.menubar.entryconfigure("Spells", state="normal")

class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="DnD Character Sheet and Database", font=LARGE_FONT)
        label.grid(padx=10, pady=10, row=0, column=2)

        Button1 = ttk.Button(self, text="New Char Sheet", command=lambda: controller.show_frame(Page_One))
        Button1.grid(padx=10, pady=10, row=1, column=2)

        Button2 = ttk.Button(self, text="Load Char Sheet", command=lambda: controller.show_page(test_page))
        Button2.grid(padx=10, pady=10, row=2, column=2)

        Button3 = ttk.Button(self, text="Weapons DataBase", command=lambda: controller.show_page(Weapons_Page))
        Button3.grid(padx=10, pady=10, row=3, column=2)

        Button5 = ttk.Button(self, text="Spells DataBase", command=lambda: controller.show_page(Spell_Page))
        Button5.grid(padx=10, pady=10, row=4, column=2)

        Button4 = ttk.Button(self, text="Dice", command=lambda: controller.show_page(Dice_Page))
        Button4.grid(padx=10, pady=10, row=5, column=2)

    def load(self):
        print("Need to implement loading a charsheet")

class Weapons_Page(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        win = tk.Toplevel()

class Dice_Page(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        die_win = tk.Toplevel()

        title = tk.Label(die_win,text="Dice Roller")
        title.grid(row=0,column=0,columnspan=2,padx=10,pady=10)

        title_number = tk.Label(die_win,text="Number")
        title_number.grid(row=0,column=2)

        title_result = tk.Label(die_win,text="Result")
        title_result.grid(row=0,column=4)

        d4 = tk.Label(die_win, text="d4")
        d4.grid(row=1, column=1)
        self.d4_number = tk.Entry(die_win, width=5)
        self.d4_number.insert(0, '0')
        self.d4_number.grid(row=1, column=2, pady=10)
        self.d4_result = tk.Entry(die_win, width=15)
        self.d4_result.grid(row=1, column=4, padx=10)
        d4_roll = tk.Button(die_win, text="Roll",
                            command=lambda: Dice_Page.roll(self, 4, self.d4_result, self.d4_number.get()))
        d4_roll.grid(row=1, column=3, padx=10)
        self.img4 = ImageTk.PhotoImage(Image.open('Dice_pics\d4b.jpg'))
        panel4 = tk.Label(die_win,image=self.img4)
        panel4.grid(row=1,column=0)

        d6 = tk.Label(die_win, text="d6")
        d6.grid(row=2, column=1)
        self.d6_number = tk.Entry(die_win, width=5)
        self.d6_number.insert(0, '0')
        self.d6_number.grid(row=2, column=2, pady=10)
        self.d6_result = tk.Entry(die_win, width=15)
        self.d6_result.grid(row=2, column=4, padx=10)
        d6_roll = tk.Button(die_win, text="Roll",
                            command=lambda: Dice_Page.roll(self, 6, self.d6_result, self.d6_number.get()))
        d6_roll.grid(row=2, column=3, padx=10)
        self.img6 = ImageTk.PhotoImage(Image.open('Dice_pics\d6b.jpg'))
        panel6 = tk.Label(die_win,image=self.img6)
        panel6.grid(row=2,column=0)

        d8 = tk.Label(die_win, text="d8")
        d8.grid(row=3, column=1)
        self.d8_number = tk.Entry(die_win, width=5)
        self.d8_number.insert(0, '0')
        self.d8_number.grid(row=3, column=2, pady=10)
        self.d8_result = tk.Entry(die_win, width=15)
        self.d8_result.grid(row=3, column=4, padx=10)
        d8_roll = tk.Button(die_win, text="Roll",
                            command=lambda: Dice_Page.roll(self, 8, self.d8_result, self.d8_number.get()))
        d8_roll.grid(row=3, column=3, padx=10)
        self.img8 = ImageTk.PhotoImage(Image.open('Dice_pics\d8b.jpg'))
        panel8 = tk.Label(die_win,image=self.img8)
        panel8.grid(row=3,column=0)

        d10 = tk.Label(die_win, text="d10")
        d10.grid(row=4, column=1)
        self.d10_number = tk.Entry(die_win, width=5)
        self.d10_number.insert(0, '0')
        self.d10_number.grid(row=4, column=2, pady=10)
        self.d10_result = tk.Entry(die_win, width=15)
        self.d10_result.grid(row=4, column=4, padx=10)
        d10_roll = tk.Button(die_win, text="Roll",
                            command=lambda: Dice_Page.roll(self, 10, self.d10_result, self.d10_number.get()))
        d10_roll.grid(row=4, column=3, padx=10)
        self.img10 = ImageTk.PhotoImage(Image.open('Dice_pics\d10b.jpg'))
        panel10 = tk.Label(die_win,image=self.img10)
        panel10.grid(row=4,column=0)

        d12 = tk.Label(die_win, text="d12")
        d12.grid(row=5, column=1)
        self.d12_number = tk.Entry(die_win, width=5)
        self.d12_number.insert(0, '0')
        self.d12_number.grid(row=5, column=2, pady=10)
        self.d12_result = tk.Entry(die_win, width=15)
        self.d12_result.grid(row=5, column=4, padx=10)
        d12_roll = tk.Button(die_win, text="Roll",
                            command=lambda: Dice_Page.roll(self, 12, self.d12_result, self.d12_number.get()))
        d12_roll.grid(row=5, column=3, padx=10)
        self.img12 = ImageTk.PhotoImage(Image.open('Dice_pics\d12b.jpg'))
        panel12 = tk.Label(die_win,image=self.img12)
        panel12.grid(row=5,column=0)

        d20 = tk.Label(die_win, text="d20")
        d20.grid(row=6, column=1)
        self.d20_number = tk.Entry(die_win, width=5)
        self.d20_number.insert(0, '0')
        self.d20_number.grid(row=6, column=2, pady=10)
        self.d20_result = tk.Entry(die_win, width=15)
        self.d20_result.grid(row=6, column=4, padx=10)
        d20_roll = tk.Button(die_win, text="Roll",
                            command=lambda: Dice_Page.roll(self, 20, self.d20_result, self.d20_number.get()))
        d20_roll.grid(row=6, column=3, padx=10)
        self.img20 = ImageTk.PhotoImage(Image.open('Dice_pics\d20b.jpg'))
        panel20 = tk.Label(die_win,image=self.img20)
        panel20.grid(row=6,column=0)

        d100 = tk.Label(die_win, text="d100")
        d100.grid(row=7, column=1)
        self.d100_number = tk.Entry(die_win, width=5)
        self.d100_number.insert(0, '0')
        self.d100_number.grid(row=7, column=2, pady=10)
        self.d100_result = tk.Entry(die_win, width=15)
        self.d100_result.grid(row=7, column=4, padx=10)
        d100_roll = tk.Button(die_win, text="Roll",
                            command=lambda: Dice_Page.roll(self, 100, self.d100_result, self.d100_number.get()))
        d100_roll.grid(row=7, column=3, padx=10)
        self.img100 = ImageTk.PhotoImage(Image.open('Dice_pics\d100b.jpg'))
        panel100 = tk.Label(die_win,image=self.img100)
        panel100.grid(row=7,column=0)

    def roll(self,dice,box,number):
        box.delete(0, 'end')
        try:
            if int(number) > 0:
                box.insert(0, rand.randint(1, dice))
                if int(number) > 1:
                    for i in range(0, int(number) - 1):
                        box.insert(0, str(rand.randint(1, dice)) + ',')
        except:
            print('Enter a Valid Number of Dice Please')

class Spell_Page(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        win = tk.Toplevel()
        search_Box_Frame = tk.Frame(win)
        spell_List_Frame = tk.Frame(win)
        spell_Description_Frame = tk.Frame(win)

        self.spell_search_var = tk.StringVar()
        self.spell_search_var.trace("w", self.update_spell_list)
        self.Search_Box = ttk.Entry(search_Box_Frame, textvariable=self.spell_search_var)
        self.spell_lbox = tk.Listbox(spell_List_Frame, width=20, height=30)
        self.Search_Label = tk.Label(search_Box_Frame, text='Enter Spell Name Here')
        self.Search_Label.grid(row=0, column=0)
        self.spell_lbox.bind("<Double-Button-1>", self.OnDouble_Spell)

        self.spell_lbox.grid(row=0, column=0)
        self.Search_Box.grid(row=0, column=1)

        self.name_var = tk.StringVar()
        self.name_var.set('')
        spell_Name_label = tk.Label(spell_Description_Frame, text="Name")
        spell_Name_label.grid(row=0, column=0)

        spell_Name_Entry = ttk.Entry(spell_Description_Frame, textvariable=self.name_var)
        spell_Name_Entry.grid(row=0, column=1)

        spell_Description_label = tk.Label(spell_Description_Frame, text='Description')
        spell_Description_label.grid(row=1, column=0, columnspan=2)
        self.spell_Description_Box = tk.Text(spell_Description_Frame, width=20, height=10)
        self.spell_Description_Box.grid(row=2, column=0, columnspan=2)
        self.spell_Description_Box.config(wrap=tk.WORD)

        spell_Materials_label = tk.Label(spell_Description_Frame, text='Materials')
        spell_Materials_label.grid(row=8, column=0, columnspan=2)
        self.spell_Materials_Box = tk.Text(spell_Description_Frame, width=20, height=10)
        self.spell_Materials_Box.grid(row=9, column=0, columnspan=2)
        self.spell_Materials_Box.config(wrap=tk.WORD)

        self.range_var = tk.StringVar()
        self.range_var.set('')
        spell_Range_label = tk.Label(spell_Description_Frame, text="Range")
        spell_Range_label.grid(row=3, column=0)

        spell_Range_Entry = ttk.Entry(spell_Description_Frame, textvariable=self.range_var)
        spell_Range_Entry.grid(row=3, column=1)

        spell_Duration_label = tk.Label(spell_Description_Frame, text="Duration")
        spell_Duration_label.grid(row=4, column=0)

        self.duration_var = tk.StringVar()
        self.duration_var.set('')
        spell_Duration_Entry = ttk.Entry(spell_Description_Frame, textvariable=self.duration_var)
        spell_Duration_Entry.grid(row=4, column=1)

        spell_Level_label = tk.Label(spell_Description_Frame, text="Level")
        spell_Level_label.grid(row=5, column=0)

        self.lvl_var = tk.StringVar()
        self.lvl_var.set('')
        spell_Level_Entry = ttk.Entry(spell_Description_Frame, textvariable=self.lvl_var)
        spell_Level_Entry.grid(row=5, column=1)

        self.concentration_var = tk.IntVar()
        self.concentration_chk_box = tk.Checkbutton(spell_Description_Frame, text="Concentration",
                                                    variable=self.concentration_var)
        self.concentration_chk_box.grid(row=6, column=0, columnspan=2)

        spell_Casting_label = tk.Label(spell_Description_Frame, text="Casting Time")
        spell_Casting_label.grid(row=7, column=0)

        self.casting_var = tk.StringVar()
        self.casting_var.set('')
        spell_Casting_Entry = ttk.Entry(spell_Description_Frame, textvariable=self.casting_var)
        spell_Casting_Entry.grid(row=7, column=1)

        search_Box_Frame.grid(row=0, column=0, columnspan=2, pady=10)
        spell_List_Frame.grid(row=1, column=0, padx=10)
        spell_Description_Frame.grid(row=1, column=1, padx=10)

        self.update_spell_list()

    def update_spell_list(self, *args):
        search_term = self.spell_search_var.get()

        with open(lists.Path_to_Spells, encoding='utf-8') as file:
            spell_data = json.load(file)
        self.spells = []
        self.desc = []
        self.range = []
        self.duration = []
        self.lvl = []
        self.concentration = []
        self.casting = []
        self.materials = []

        for spell in spell_data['spells']:
            self.spells.append(spell['name'])
            self.desc.append(spell['desc'])
            self.range.append(spell['range'])
            self.duration.append(spell['duration'])
            self.lvl.append(spell['level'])
            self.concentration.append(spell['concentration'])
            self.casting.append(spell['casting_time'])
            try:
                self.materials.append(spell['material'])
            except Exception:
                self.materials.append('No Materials Required')

        self.spell_lbox.delete(0, tk.END)

        for item in self.spells:
            if search_term.lower() in item.lower():
                self.spell_lbox.insert(tk.END, item)

    def OnDouble_Spell(self, event):
        widget = event.widget
        selection = widget.curselection()
        value = widget.get(selection[0])
        location = self.spells.index(value)
        self.name_var.set(self.spells[location])
        self.range_var.set(self.range[location])
        self.duration_var.set(self.duration[location])
        self.casting_var.set(self.casting[location])
        self.lvl_var.set(self.lvl[location])
        self.spell_Description_Box.insert('1.0', self.desc[location])
        self.spell_Materials_Box.insert('1.0', self.materials[location])
        if (self.concentration[location] == 'yes'):
            self.concentration_var.set('1')
        else:
            self.concentration_var.set('0')

class Page_One(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.create_page(controller)

    def create_page(self, controller):
        label = ttk.Label(self, text="Enter The info About your Character", font=LARGE_FONT)
        label.grid(row=0, column=0, columnspan=2, padx=30)

        Label_Name = ttk.Label(self, text="Name")
        Label_Name.grid(row=1, column=0)
        self.Entry_Name = ttk.Entry(self)
        self.Entry_Name.grid(row=1, column=1)

        Races = {'Half Elf', 'Gnome', 'Half Orc', 'DragonBorn', 'Tiefling', 'Dwarf'
            ,'Elf', 'Halfling', 'Human'}
        Alignments = {'Lawful Good', 'Neutral Good', 'Chaotic Good ', 'Lawful neutral', 'True neutral',
                      'Chaotic neutral', 'Lawful evil', 'Neutral evil', 'Chaotic evil'}
        Class = {'Ranger': 6, 'Barbarian': 8, 'Paladin': 6, 'Bard': 5, 'Cleric': 5
            , 'Druid': 5, 'Fighter': 6, 'Monk': 5, 'Rouge': 5, 'Sorcerer': 4,
                 'Warlock': 5, 'Wizard': 4}
        self.tkvar_R = tk.StringVar()
        self.tkvar_A = tk.StringVar()
        self.tkvar_C = tk.StringVar()

        self.tkvar_R.set('')
        self.tkvar_A.set('')
        self.tkvar_C.set('')

        # put a trace on te class variable to check when it changes

        Label_Class = tk.Label(self, text="Class")
        Label_Class.grid(row=2, column=0)
        Class_Menu = ttk.OptionMenu(self, self.tkvar_C, *Class)
        Class_Menu.grid(row=2, column=1)
        self.img=ImageTk.PhotoImage(Image.open("Class_icons/Ranger.jpg"))
        Label_Class_Img = ttk.Label(self,image = self.img)
        Label_Class_Img.image = self.img
        Label_Class_Img.grid(row=2,column=2)

        Label_Race = tk.Label(self, text="Race")
        Label_Race.grid(row=3, column=0)
        Race_Menu = ttk.OptionMenu(self, self.tkvar_R, *Races)
        Race_Menu.grid(row=3, column=1)

        Label_Alignment = tk.Label(self, text="Alignment")
        Label_Alignment.grid(row=4, column=0)
        Alignment_Menu = ttk.OptionMenu(self, self.tkvar_A, *Alignments)
        Alignment_Menu.grid(row=4, column=1)

        Label_str = ttk.Label(self, text="Strength")
        Label_dex = ttk.Label(self, text="Dexterity")
        Label_const = ttk.Label(self, text="Constitution")
        Label_int = ttk.Label(self, text="Intelligence")
        Label_wis = ttk.Label(self, text="Wisdom")
        Label_char = ttk.Label(self, text="Charisma")

        self.Entry_str = ttk.Entry(self)
        self.Entry_dex = ttk.Entry(self)
        self.Entry_const = ttk.Entry(self)
        self.Entry_int = ttk.Entry(self)
        self.Entry_wis = ttk.Entry(self)
        self.Entry_char = ttk.Entry(self)

        Label_str.grid(row=5, column=0)
        self.Entry_str.grid(row=5, column=1)
        Label_dex.grid(row=6, column=0)
        self.Entry_dex.grid(row=6, column=1)
        Label_const.grid(row=7, column=0)
        self.Entry_const.grid(row=7, column=1)
        Label_int.grid(row=8, column=0)
        self.Entry_int.grid(row=8, column=1)
        Label_wis.grid(row=9, column=0)
        self.Entry_wis.grid(row=9, column=1)
        Label_char.grid(row=10, column=0)
        self.Entry_char.grid(row=10, column=1)

        Button2 = ttk.Button(self, text="Back", command=lambda: controller.show_frame(StartPage))
        Button2.grid(row=11, column=0)

        Button_new = ttk.Button(self, text="Make new Character",
                                command=lambda: Page_One.save(self, Page_One, controller))
        Button_new.grid(row=11, column=2)

        Button_roll = ttk.Button(self, text="Roll for Stats", command=lambda: Page_One.roll(self, Page_One))
        Button_roll.grid(row=11, column=1)

    def roll(self, page):
        rolls = []
        results = []
        sum = 0
        for i in range(0, 6):
            for i in range(0, 4):
                rolls.append(rand.randint(1, 6))
                sum += rolls[i]
            sum = sum - min(rolls)
            results.append(sum)
            rolls = []
            sum = 0
        self.Entry_str.delete(0, 100)
        self.Entry_str.insert(0, str(results[0]))
        self.Entry_dex.delete(0, 100)
        self.Entry_dex.insert(0, str(results[1]))
        self.Entry_const.delete(0, 100)
        self.Entry_const.insert(0, str(results[2]))
        self.Entry_int.delete(0, 100)
        self.Entry_int.insert(0, str(results[3]))
        self.Entry_wis.delete(0, 100)
        self.Entry_wis.insert(0, str(results[4]))
        self.Entry_char.delete(0, 100)
        self.Entry_char.insert(0, str(results[5]))

    def save(self, page, controller):
        '''
        Structure of File will be
        Name,Class,Race,Alignment,str,dex,const,int,wis,char
        '''
        file = open("Data_File.txt", "w")
        file.write(str(self.Entry_Name.get()) + ',' + str(self.tkvar_C.get()) + ',' + str(self.tkvar_R.get()) +
                   ',' + str(self.tkvar_A.get()) + ',' + str(self.Entry_str.get()) + ',' + str(self.Entry_dex.get())
                   + ',' + str(self.Entry_const.get()) + ',' + str(self.Entry_int.get()) + ',' + str(
            self.Entry_wis.get())
                   + ',' + str(self.Entry_char.get()))
        char.Name = self.Entry_Name.get()
        char.clss = self.tkvar_C.get()
        char.race = self.tkvar_R.get()
        char.alignment = self.tkvar_R.get()
        char.str = self.Entry_str.get()
        char.dex = self.Entry_dex.get()
        char.const = self.Entry_const.get()
        char.int = self.Entry_int.get()
        char.wis = self.Entry_wis.get()
        char.char = self.Entry_char.get()

        file.close()
        controller.show_char_sheet()

class Page_Two(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        Frame1 = tk.Frame(self)  # Description Frame
        Frame2 = tk.Frame(self)  # Stats Frame
        Frame3 = tk.Frame(self)  # Items Frame
        Frame4 = tk.Frame(self)  # Spells Frame

        # Description of the Character
        Label_Name = tk.Label(Frame1, text="Name").grid(row=0, column=0)
        self.Name_var = tk.StringVar()
        self.Name_var.set('Holder')
        self.Name = tk.Label(Frame1, textvariable=self.Name_var).grid(row=0, column=1)
        self.Char_Data = []

        Label_Class = tk.Label(Frame1, text="Class").grid(row=0, column=2)
        self.Class_var = tk.StringVar()
        self.Class_var.set(char.clss)
        self.Class = tk.Label(Frame1, textvariable=self.Class_var).grid(row=0, column=3)

        Label_Level = tk.Label(Frame1, text="Level").grid(row=0, column=4)
        self.lvl_var = tk.StringVar()
        self.lvl_var.set(char.level)
        self.Level = tk.Label(Frame1, textvariable=self.lvl_var).grid(row=0, column=5)
        self.lvl_up_button = tk.Button(Frame1, text="Level Up", command=lambda: Page_Two.lvlup(self))
        self.lvl_up_button.grid(row=0, column=6)

        Label_Race = tk.Label(Frame1, text="Race").grid(row=1, column=0)
        self.race_var = tk.StringVar()
        self.race_var.set('Holder')
        self.Race = tk.Label(Frame1, textvariable=self.race_var).grid(row=1, column=1)

        Label_Alignment = tk.Label(Frame1, text="Alignment").grid(row=1, column=2)
        self.Alig_var = tk.StringVar()
        self.Alig_var.set('Holder')
        self.Alignment = tk.Label(Frame1, textvariable=self.Alig_var).grid(row=1, column=3)

        Label_Proficiency = tk.Label(Frame1, text="Proficiency").grid(row=2, column=0)
        self.Prof_var = tk.StringVar()
        self.Prof_var.set('Holder')
        self.Prof = tk.Label(Frame1, textvariable=self.Prof_var).grid(row=2, column=1)

        Label_HP = tk.Label(Frame1, text="Hit Points").grid(row=2, column=2)
        self.HP_var = tk.StringVar()
        self.HP_var.set('Holder')
        self.HP = tk.Label(Frame1, textvariable=self.HP_var).grid(row=2, column=3)
        self.HP_change = tk.Button(Frame1,text = "+/-",command = lambda :Page_Two.edit_HP(self))
        self.HP_change.grid(row=2, column=4)

        Label_Init = tk.Label(Frame1, text="Initiative").grid(row=2, column=5)
        self.init_Entry = ttk.Entry(Frame1)
        self.init_Entry.grid(row=2, column=6)

        Label_Insipr = tk.Label(Frame1, text="Inspiration").grid(row=3, column=0)
        self.Insipr_Entry = ttk.Entry(Frame1)
        self.Insipr_Entry.grid(row=3, column=1)

        Label_AC = tk.Label(Frame1, text="Armour Class").grid(row=3, column=2)
        self.AC_Entry = ttk.Entry(Frame1)
        self.AC_Entry.grid(row=3, column=3)

        # Stats Code

        Label_str = tk.Label(Frame2, text="Strength").grid(row=0, column=0, pady=30)
        Label_dex = tk.Label(Frame2, text="Dexterity").grid(row=1, column=0, pady=30)
        Label_const = tk.Label(Frame2, text="Constitution").grid(row=2, column=0, pady=30)
        Label_Int = tk.Label(Frame2, text="Intelligence").grid(row=3, column=0, pady=30)
        Label_Wis = tk.Label(Frame2, text="Wisdom").grid(row=4, column=0, pady=30)
        Label_Char = tk.Label(Frame2, text="Charisma").grid(row=5, column=0, pady=30)

        self.str_var = tk.StringVar()
        self.dex_var = tk.StringVar()
        self.const_var = tk.StringVar()
        self.int_var = tk.StringVar()
        self.wis_var = tk.StringVar()
        self.char_var = tk.StringVar()

        self.str_var.set('Holder')
        self.dex_var.set('Holder')
        self.const_var.set('Holder')
        self.int_var.set('Holder')
        self.wis_var.set('Holder')
        self.char_var.set('Holder')

        self.str_var_mod = tk.StringVar()
        self.dex_var_mod = tk.StringVar()
        self.const_var_mod = tk.StringVar()
        self.int_var_mod = tk.StringVar()
        self.wis_var_mod = tk.StringVar()
        self.char_var_mod = tk.StringVar()

        self.str_var_mod.set('0')
        self.dex_var_mod.set('0')
        self.const_var_mod.set('0')
        self.int_var_mod.set('0')
        self.wis_var_mod.set('0')
        self.char_var_mod.set('0')

        Label_str_stat = tk.Label(Frame2, textvariable=self.str_var).grid(row=0, column=1)
        Label_dex_stat = tk.Label(Frame2, textvariable=self.dex_var).grid(row=1, column=1)
        Label_const_stat = tk.Label(Frame2, textvariable=self.const_var).grid(row=2, column=1)
        Label_Int_stat = tk.Label(Frame2, textvariable=self.int_var).grid(row=3, column=1)
        Label_Wis_stat = tk.Label(Frame2, textvariable=self.wis_var).grid(row=4, column=1)
        Label_Char_stat = tk.Label(Frame2, textvariable=self.char_var).grid(row=5, column=1)

        Label_str_mod = tk.Label(Frame2, textvariable=self.str_var_mod).grid(row=0, column=2)
        Label_dex_mod = tk.Label(Frame2, textvariable=self.dex_var_mod).grid(row=1, column=2)
        Label_const_mod = tk.Label(Frame2, textvariable=self.const_var_mod).grid(row=2, column=2)
        Label_Int_mod = tk.Label(Frame2, textvariable=self.int_var_mod).grid(row=3, column=2)
        Label_Wis_mod = tk.Label(Frame2, textvariable=self.wis_var_mod).grid(row=4, column=2)
        Label_Char_mod = tk.Label(Frame2, textvariable=self.char_var_mod).grid(row=5, column=2)

        # Items and weapons code

        Label_Wpns = tk.Label(Frame3, text="Weapons").grid(row=0, column=0)
        Label_Amr = tk.Label(Frame3, text="Armour").grid(row=0, column=2)

        self.Weapon_Text = tk.Text(Frame3, height=20, width=20)
        self.Armour_Text = tk.Text(Frame3, height=20, width=20)

        self.Weapon_Text.config(wrap=tk.WORD)
        self.Armour_Text.config(wrap=tk.WORD)

        self.Weapon_Text.grid(row=1, column=0, columnspan=2)
        self.Armour_Text.grid(row=1, column=2, columnspan=2)

        Wpn_Button = ttk.Button(Frame3, text='+', command=lambda: Page_Two.add_wpn(self))
        Wpn_Button.grid(row=0, column=1)

        Amr_Button = ttk.Button(Frame3, text='+', command=lambda: Page_Two.add_amr(self))
        Amr_Button.grid(row=0, column=3)

        # spell code

        Label_Spells = tk.Label(Frame4, text="Spells").grid(row=0, column=0)
        Spells_Text = tk.Text(Frame4, height=20, width=40)
        Spells_Text.grid(row=1, column=0)
        Spells_Text.config(wrap=tk.WORD)

        spell_Button = tk.Button(Frame4, text="+", command=lambda: Page_Two.add_spell(self))
        spell_Button.grid(row=0, column=1, sticky=tk.W)
        Page_Two.update(self)
        Frame1.grid(row=0, column=0, columnspan=2)
        Frame2.grid(row=1, column=0, rowspan=2)
        Frame3.grid(row=1, column=1)
        Frame4.grid(row=2, column=1)

        # update all of the stats for the characyer and save the hitpoints as they are not somthing whihc is set they
        # are calculated
        Page_Two.update_stat_mod(self)
        Page_Two.prof_update(self)
        Page_Two.HP_Set(self)

    def edit_HP(self):
        hp_edit = tk.Toplevel()

        label = tk.Label(hp_edit,text = "Enter Damage/Healing")
        label.grid(row=0,column=0,padx=10,pady=10)

        self.Entry = tk.Entry(hp_edit)
        self.Entry.grid(row=0,column=1,padx=10,pady=10)

        confirm = tk.Button(hp_edit,text="Confirm",command = lambda :Page_Two.confirm_hp_chg(self,self.Entry.get(),hp_edit))
        confirm.grid(row=1,column=0,columnspan=2)

    def confirm_hp_chg(self,change,page):
        char.current_hit_points = int(char.current_hit_points) + int(change)
        self.HP_var.set(str(char.current_hit_points) + "/" + str(char.max_hit_points))
        page.destroy()

    def lvl_up_confirm(self,page):

        #stats update
        if (self.level == 4 or self.level == 8 or self.level == 12 or self.level == 16 or self.level == 19):
            char.str = self.str_spinbox.get()
            char.dex = self.dex_spinbox.get()
            char.const = self.const_spinbox.get()
            char.wis = self.wis_spinbox.get()
            char.int = self.int_spinbox.get()
            char.char = self.char_spinbox.get()

        char.level = self.level
        char.max_hit_points = self.new_hp
        char.current_hit_points = self.new_hp
        self.level_up_update()
        page.destroy()

    def lvlup(self):
        lvl_win = tk.Toplevel()

        self.level = char.level + 1
        Title = tk.Label(lvl_win, text="Level Up")
        Title.grid(row=0, column=0, columnspan=11)
        msg = "Level:" + str(char.level) + " -> " + str(char.level + 1)
        message = tk.Label(lvl_win, text=msg)
        message.grid(row=1, column=0, columnspan=11)

        # HP level up
        current_hp = char.max_hit_points
        const_mod = int((int(char.const) - 10) / 2)
        cls = char.clss
        roll = rand.randint(1, Page_Two.hp_switch(cls))
        self.new_hp = current_hp + const_mod + roll

        hp_msg = "Hit Points:" + str(current_hp) + " -> " + str(self.new_hp)
        hp_message = tk.Label(lvl_win, text=hp_msg)
        hp_message.grid(row=2, column=0, columnspan=11)

        lvlup_desc = tk.Text(lvl_win, height=5, width=30)
        lvlup_desc.grid(row=3, column=0, columnspan=11)
        lvlup_desc.insert(tk.INSERT, str(lists.level_up_descp[int(self.level) - 1][self.class_switch(cls)]))

        if (self.level == 4 or self.level == 8 or self.level == 12 or self.level == 16 or self.level == 19):
            str_label = tk.Label(lvl_win, text="Str")
            str_label.grid(row=4, column=0)
            dex_label = tk.Label(lvl_win, text="Dex")
            dex_label.grid(row=4, column=2)
            const_label = tk.Label(lvl_win, text="Const")
            const_label.grid(row=4, column=4)
            wis_label = tk.Label(lvl_win, text="Wis")
            wis_label.grid(row=4, column=6)
            int_label = tk.Label(lvl_win, text="Int")
            int_label.grid(row=4, column=8)
            char_label = tk.Label(lvl_win, text="Char")
            char_label.grid(row=4, column=10)

            self.str_spinbox = tk.Spinbox(lvl_win, from_=0, to=20, width=0)
            self.str_spinbox.grid(row=4, column=1)
            self.dex_spinbox = tk.Spinbox(lvl_win, from_=0, to=20, width=0)
            self.dex_spinbox.grid(row=4, column=3)
            self.const_spinbox = tk.Spinbox(lvl_win, from_=0, to=20, width=0)
            self.const_spinbox.grid(row=4, column=5)
            self.wis_spinbox = tk.Spinbox(lvl_win, from_=0, to=20, width=0)
            self.wis_spinbox.grid(row=4, column=7)
            self.int_spinbox = tk.Spinbox(lvl_win, from_=0, to=20, width=0)
            self.int_spinbox.grid(row=4, column=9)
            self.char_spinbox = tk.Spinbox(lvl_win, from_=0, to=20, width=0)
            self.char_spinbox.grid(row=4, column=11)

            #get the inital values to compare to the new ones and add them up as somthing to compare it too

            self.str_spinbox.delete(0, "end")
            self.str_spinbox.insert(0, int(char.str))
            self.dex_spinbox.delete(0, "end")
            self.dex_spinbox.insert(0, int(char.dex))
            self.const_spinbox.delete(0, "end")
            self.const_spinbox.insert(0, int(char.const))
            self.wis_spinbox.delete(0, "end")
            self.wis_spinbox.insert(0, int(char.wis))
            self.int_spinbox.delete(0, "end")
            self.int_spinbox.insert(0, int(char.int))
            self.char_spinbox.delete(0, "end")
            self.char_spinbox.insert(0, int(char.char))

        conf = tk.Button(lvl_win, text="Confirm", command=lambda: Page_Two.lvl_up_confirm(self,lvl_win))
        conf.grid(row=5, column=0, columnspan=11)

    def class_switch(self, cls):
        # method which returns the location of a specific class within the level_desp list
        class_switcher = {'Barbarian': 0, 'Bard': 1, 'Cleric': 2, 'Druid': 3, 'Fighter': 4, 'Monk': 5, 'Paladin': 6,
                          'Ranger': 7,
                          'Rouge': 8, 'Sorcerer': 9, 'Warlock': 10, 'Wizard': 11}
        return class_switcher.get(cls, "Nothing")

    def HP_Set(self):
        hp_base = Page_Two.hp_switch(self.Class_var.get())
        max = hp_base + int(self.const_var_mod.get())
        self.HP_var.set(str(max) + "/" + str(max))
        char.max_hit_points = max
        char.current_hit_points = max

    def hp_switch(player_class):
        switcher = {'Ranger': 10, 'Barbarian': 12, 'Paladin': 10, 'Bard': 8, 'Cleric': 8
            , 'Druid': 8, 'Fighter': 10, 'Monk': 8, 'Rouge': 8, 'Sorcerer': 6, 'Warlock': 8, 'Wizard': 6}
        return switcher.get(player_class, "nothing")

    def prof_update(self):
        self.Prof_var.set(int((float(self.lvl_var.get()) - 1) / 4) + 2)

    def update_stat_mod(self):
        self.str_var_mod.set(int((int(self.str_var.get()) - 10) / 2))
        self.dex_var_mod.set(int((int(self.dex_var.get()) - 10) / 2))
        self.const_var_mod.set(int((int(self.const_var.get()) - 10) / 2))
        self.wis_var_mod.set(int((int(self.wis_var.get()) - 10) / 2))
        self.int_var_mod.set(int((int(self.int_var.get()) - 10) / 2))
        self.char_var_mod.set(int((int(self.char_var.get()) - 10) / 2))

    def add_wpn(self):
        # create child window
        win = tk.Toplevel()
        self.search_var = tk.StringVar()
        self.search_var.trace("w", self.update_wpn_list)
        self.entry = tk.Entry(win, textvariable=self.search_var, width=13)
        self.lbox = tk.Listbox(win, width=45, height=15)
        self.Search_Label = tk.Label(win, text="Enter Name of Weapon")
        self.lbox.bind("<Double-Button-1>", self.OnDouble)

        self.entry.grid(row=0, column=1, padx=10, pady=3)
        self.Search_Label.grid(row=0, column=0, padx=10, pady=3)
        self.lbox.grid(row=1, column=0, padx=10, pady=3, columnspan=2)

        self.update_wpn_list()

    def add_amr(self):
        # create child window
        win = tk.Toplevel()
        self.search_var = tk.StringVar()
        self.search_var.trace("w", self.update_amr_list)
        self.entry = tk.Entry(win, textvariable=self.search_var, width=13)
        self.lbox = tk.Listbox(win, width=45, height=15)
        self.Search_Label = tk.Label(win, text="Enter Name of Armour")
        self.lbox.bind("<Double-Button-1>", self.OnDouble_amr)

        self.entry.grid(row=0, column=1, padx=10, pady=3)
        self.Search_Label.grid(row=0, column=0, padx=10, pady=3)
        self.lbox.grid(row=1, column=0, padx=10, pady=3, columnspan=2)

        self.update_amr_list()

    def add_spell(self):
        # create child window
        win = tk.Toplevel()
        self.search_var = tk.StringVar()
        self.search_var.trace("w", self.update_amr_list)
        self.entry = tk.Entry(win, textvariable=self.search_var, width=13)
        self.lbox = tk.Listbox(win, width=45, height=15)
        self.Search_Label = tk.Label(win, text="Enter Name of Spell")
        self.lbox.bind("<Double-Button-1>", self.OnDouble_amr)

        self.entry.grid(row=0, column=1, padx=10, pady=3)
        self.Search_Label.grid(row=0, column=0, padx=10, pady=3)
        self.lbox.grid(row=1, column=0, padx=10, pady=3, columnspan=2)

    def update_wpn_list(self, *args):
        search_term = self.search_var.get()

        with open(lists.Path_to_Martial_Melee_Weapons, encoding='utf-8') as f:
            data = json.load(f)
        with open(lists.Path_to_Martial_Ranged_Weapons, encoding='utf-8') as f1:
            data1 = json.load(f1)
        with open(lists.Path_to_Firearms, encoding='utf-8') as f2:
            data2 = json.load(f2)
        with open(lists.Path_to_Simple_Melee_Weapons, encoding='utf-8') as f3:
            data3 = json.load(f3)
        with open(lists.Path_to_Simple_Ranged_Weapons, encoding='utf-8') as f4:
            data4 = json.load(f4)
        self.weapons = []
        self.cost = []
        self.damage = []
        self.weight = []
        self.properties = []

        for weapon in data['Melee_Weapons']:
            self.weapons.append(weapon['Name'])
            self.cost.append(weapon['Cost'])
            self.damage.append(weapon['Damage'])
            self.weight.append(weapon['Weight'])
            self.properties.append(weapon['Properties'])

        for weapon in data1['Ranged_Weapons']:
            self.weapons.append(weapon['Name'])
            self.cost.append(weapon['Cost'])
            self.damage.append(weapon['Damage'])
            self.weight.append(weapon['Weight'])
            self.properties.append(weapon['Properties'])

        for weapon in data2['firearms']:
            self.weapons.append(weapon['Name'])
            self.cost.append(weapon['Cost'])
            self.damage.append(weapon['Damage'])
            self.weight.append(weapon['Weight'])
            self.properties.append(weapon['Properties'])

        for weapon in data3['Simple_Melee']:
            self.weapons.append(weapon['Name'])
            self.cost.append(weapon['Cost'])
            self.damage.append(weapon['Damage'])
            self.weight.append(weapon['Weight'])
            self.properties.append(weapon['Properties'])

        for weapon in data4['Simple_Ranged_Weapons']:
            self.weapons.append(weapon['Name'])
            self.cost.append(weapon['Cost'])
            self.damage.append(weapon['Damage'])
            self.weight.append(weapon['Weight'])
            self.properties.append(weapon['Properties'])

        self.lbox.delete(0, tk.END)

        for item in self.weapons:
            if search_term.lower() in item.lower():
                self.lbox.insert(tk.END, item)

    def update_amr_list(self, *args):
        search_term = self.search_var.get()

        self.armour = ['Padded', 'Leather', 'Studded Leather', 'Hide', 'Chain Shirt'
            , 'Scale Mail', 'Breastplate', 'Half Plate', 'Ring Mail',
                       'Chain Mail', 'Splint', 'Plate', 'Sheild']

        self.lbox.delete(0, tk.END)

        for item in self.armour:
            if search_term.lower() in item.lower():
                self.lbox.insert(tk.END, item)

    def OnDouble(self, event):
        widget = event.widget
        selection = widget.curselection()
        value = widget.get(selection[0])
        # self.select_var.set(value)
        location = self.weapons.index(value)
        self.Weapon_Text.insert('1.0', self.weapons[location] + " " + self.damage[location] + "\n")

    def OnDouble_amr(self, event):
        widget = event.widget
        selection = widget.curselection()
        value = widget.get(selection[0])
        # self.select_var.set(value)
        location = self.armour.index(value)
        self.Armour_Text.insert('1.0', self.armour[location] + "\n")

    def update(self):
        self.Name_var.set(char.Name)
        self.Class_var.set(char.clss)
        self.race_var.set(char.race)
        self.Alig_var.set(char.alignment)
        self.str_var.set(char.str)
        self.dex_var.set(char.dex)
        self.const_var.set(char.const)
        self.int_var.set(char.int)
        self.wis_var.set(char.wis)
        self.char_var.set(char.char)
        self.HP_var.set(char.max_hit_points)

    def level_up_update(self):
        self.str_var.set(char.str)
        self.dex_var.set(char.dex)
        self.const_var.set(char.const)
        self.int_var.set(char.int)
        self.wis_var.set(char.wis)
        self.char_var.set(char.char)
        self.HP_var.set(str(char.max_hit_points) + "/" + str(char.max_hit_points))
        self.lvl_var.set(char.level)

        self.update_stat_mod()

app = dnd_char_Sheet()
LEVEL = tk.StringVar()
LEVEL.set('1')
app.mainloop()


#script utilizing Beautiful Soup and requests to grab the lastest review scores from Pitchfork
from bs4 import BeautifulSoup
import requests

#urls to use
base_url = "https://pitchfork.com"
page_link = "https://pitchfork.com/reviews/albums"

#review index page
page_response = requests.get(page_link, timeout=5)

page_content = BeautifulSoup(page_response.content, "html.parser")

reviews = page_content.find_all('div', attrs={"class":"review"})

review_list = {}

for review in reviews:
    #get link to review from index page
    review_link = review.find('a', attrs={"class":"review__link"})
    review_url = str(base_url + review_link['href'])
    #get html from score page
    score_page_response = requests.get(review_url, timeout=5)
    score_page_content = BeautifulSoup(score_page_response.content, "html.parser")
    #scrape artist name, artist album, review score, and abstract from the review
    artist_name = score_page_content.find("ul", attrs={"class":"artist-list"}).text
    album_name = score_page_content.find("h1", attrs={"class":"single-album-tombstone__review-title"}).text
    review_score = score_page_content.find("span", attrs={"class":"score"}).text
    review_abstract = score_page_content.find("div", attrs={"class":"review-detail__abstract"}).text

    print ("Artist: " + artist_name + " Album: " + album_name + " Score: " + review_score + " Abstract: " + review_abstract + " Link: " + review_url)


# Our modules

# NumPy is a library for the Python programming language, adding support for large, multi-dimensional arrays and matrices, along with a large collection of high-level mathematical functions to operate on these arrays
import numpy as np
# Matplotlib is a plotting library for python and pyplot gives us a MatLab like plotting framework. We will use this in our plotter function to plot data.
import matplotlib.pyplot as plt
# Seaborn is a Python data visualization library based on matplotlib. It provides a high-level interface for drawing attractive and informative statistical graphics
import seaborn as sns
# Allows us to test parameters of classification algorithms and find the best one
from sklearn.model_selection import GridSearchCV
# Logistic Regression classification algorithm
from sklearn.linear_model import LogisticRegression
# Support Vector Machine classification algorithm
from sklearn.svm import SVC
# Decision Tree classification algorithm
from sklearn.tree import DecisionTreeClassifier
# K Nearest Neighbors classification algorithm
from sklearn.neighbors import KNeighborsClassifier
# Confusion Matrix classification
from sklearn.metrics import confusion_matrix

# ADGSTUDIOS 2021
class adgmodel:
    def plot_confusion_matrix(self, y_test, y_pred, title, truelbl, falselbl):
        try:
            print("")
            ticklabels = []
            ticklabels.append(truelbl)
            ticklabels.append(falselbl)
            cm = confusion_matrix(y_test, y_pred)
            ax = plt.subplot()
            sns.heatmap(cm, annot=True, ax=ax)
            ax.set_xlabel('Predicted labels')
            ax.set_ylabel('True labels')
            ax.set_title(title)
            ax.xaxis.set_ticklabels(ticklabels)
            ax.yaxis.set_ticklabels(ticklabels)
        except Exception as e:
            print('Error : ADGMLCLASS \n', e)

    def __logregcv(self, X_test, Y_test, X_train, Y_train, Parameters):
        if len(Parameters) > 0:
            parameters = Parameters
            pass
        else:
            parameters = {"C": [0.01, 0.1, 1], 'penalty': [
                'l2'], 'solver': ['lbfgs']}  # l1 lasso l2 ridge
            print("using parameters", parameters,
                  "Logistic Regression Algorithm")

        try:
            lr = LogisticRegression()
            gscv = GridSearchCV(lr, parameters, scoring='accuracy', cv=10)
            logreg_cv = gscv.fit(X_train, Y_train)
            print("tuned hyperparameters :(best parameters) ",
                  logreg_cv.best_params_)
            print("accuracy :", logreg_cv.best_score_)

            yhat = logreg_cv.predict(X_test)
            self.plot_confusion_matrix(
                Y_test, yhat, 'Confusion Matrix', '+', '-')
            return logreg_cv.best_score_
        except Exception as e:
            print('Error : ADGMLCLASS \n', e)

    def __svmcv(self, X_test, Y_test, X_train, Y_train, Parameters):
        if len(Parameters) > 0:
            parameters = Parameters
        else:

            parameters = {'kernel': ('linear', 'rbf', 'poly', 'rbf', 'sigmoid'),
                          'C': np.logspace(-3, 3, 5),
                          'gamma': np.logspace(-3, 3, 5)}

            print("using parameters", parameters,
                  "Support Vector Machine Algorithm")

        try:
            svm = SVC()
            gscv = GridSearchCV(svm, parameters, scoring='accuracy', cv=10)
            svm_cv = gscv.fit(X_train, Y_train)
            print("tuned hyperparameters :(best parameters) ", svm_cv.best_params_)
            print("accuracy :", svm_cv.best_score_)

            yhat = svm_cv.predict(X_test)
            self.plot_confusion_matrix(
                Y_test, yhat, 'Confusion Matrix', '+', '-')
            return svm_cv.best_score_

        except Exception as e:
            print('Error : ADGMLCLASS \n', e)

    def __tree(self, X_test, Y_test, X_train, Y_train, Parameters):
        if len(Parameters) > 0:
            parameters = Parameters
        else:
            parameters = {'criterion': ['gini', 'entropy'],
                          'splitter': ['best', 'random'],
                          'max_depth': [2*n for n in range(1, 10)],
                          'max_features': ['auto', 'sqrt'],
                          'min_samples_leaf': [1, 2, 4],
                          'min_samples_split': [2, 5, 10]}

            print("using parameters", parameters,
                  "Support Vector Machine Algorithm")
        try:
            tree = DecisionTreeClassifier()
            gscv = GridSearchCV(tree, parameters, scoring='accuracy', cv=10)
            tree_cv = gscv.fit(X_train, Y_train)

            print("tuned hyperparameters :(best parameters) ",
                  tree_cv.best_params_)
            print("accuracy :", tree_cv.best_score_)

            yhat = tree_cv.predict(X_test)
            self.plot_confusion_matrix(
                Y_test, yhat, 'Confusion Matrix', '+', '-')
            return tree_cv.best_score_
        except Exception as e:
            print('Error : ADGMLCLASS \n', e)

    def __knn(self, X_test, Y_test, X_train, Y_train, Parameters):
            if len(Parameters) > 0:
                parameters = Parameters
                pass
            else:
                parameters = {'n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                              'algorithm': ['auto', 'ball_tree', 'kd_tree', 'brute'],
                              'p': [1, 2]}

                print("using parameters", parameters, "KNN Algorithm")

            try:
                KNN = KNeighborsClassifier()
                gscv = GridSearchCV(KNN, parameters, scoring='accuracy', cv=10)
                knn_cv = gscv.fit(X_train, Y_train)

                print("tuned hyperparameters :(best parameters) ",
                      knn_cv.best_params_)
                print("accuracy :", knn_cv.best_score_)
                yhat = knn_cv.predict(X_test)
                self.plot_confusion_matrix(
                    Y_test, yhat, 'Confusion Matrix', '+', '-')
                return knn_cv.best_score_
            except Exception as e:
                print('Error : ADGMLCLASS \n', e)

    def Train(self, Model, X_test, Y_test, X_train, Y_train, Parameters):
        try:
            if Model == 'svm':
                self.__svmcv(X_test, Y_test,
                             X_train, Y_train, Parameters)
            if Model == 'tree':
                self.__tree(X_test, Y_test, X_train, Y_train, Parameters)
            if Model == 'knn':
                self.__knn(X_test, Y_test, X_train, Y_train, Parameters)
            if Model == 'LogisticRegression':
                self.__logregcv(X_test, Y_test,
                                X_train, Y_train, Parameters)

        except Exception as e:
            print('Error : ADGMLCLASS \n', e)
            print('\n')
            print('Current Models that are supported is this version is :',
                  'svm,tree,knn,LogisticRegression - Type it as a string when using the function')

    def FindBestModel(self, X_test, Y_test, X_train, Y_train):
        print(
            'Finding best model please wait using the default ADG Optimized ML Formula...')
        algorithms = {'KNN': self.__knn(X_test, Y_test, X_train, Y_train,''), 'Tree': self.__tree(X_test, Y_test, X_train, Y_train,''),
                      'LogisticRegression': self.__tree( X_test, Y_test, X_train, Y_train,''), 'SVM': self.__svmcv(X_test, Y_test, X_train, Y_train,'')}
        bestalgorithm = max(algorithms, key=algorithms.get)
        print('Best Algorithm is', bestalgorithm,
              'with a score of', algorithms[bestalgorithm])


import os
import yaml

class Keys:
    USER = 'user'
    CHARSET = 'charset'
    LENGTH = 'length'
    ACCOUNTS = 'accounts'

ENTRY_SEPARATOR = '|'
def entrykey(user, domain):
    if user:
        return "{}{}{}".format(user, ENTRY_SEPARATOR, domain)
    else:
        return domain

def entrysplit(entry):
    index = entry.rfind(ENTRY_SEPARATOR)
    if index == -1:
        return (None, entry)

    return (entry[:index], entry[index+1:])

def readfile(args):
    path = os.path.join(args.dir, args.file)
    return yaml.load(open(path, 'r'))

def writefile(args, data):
    path = os.path.join(args.dir, args.file)
    with open(path, 'w') as fp:
        yaml.dump(data, fp, default_flow_style=False)