#!/usr/bin/env python
import os
import glob
import optparse

import cv2
import torch
import numpy as np

from PIL import Image
from torch import nn
from torchvision import transforms
from torch.utils.data import Dataset, DataLoader

# - Fixed seed (PyTorch, Numpy, Python)
# - What is accuracy, precicion, recall?
# - Model checkpoints
# - Use nn.Sequential in Model.forward()
# - Have a description on the final YOLO layers, how would we implement it?
#   Tranforming(Rotation, Scaling)?
# - Learn about regularization. Implement in model, save as different checkpoints.

## Things we should need in the final result
# - Save error and verification error to file so we can inspect it as a graph
# -

class CatsAndDogsDataset(Dataset):
    def __init__(self, f_name, transform):
        self.transform = transform
        self.dogcat_list = []

        cats_paths = os.path.join(f_name, "cats", "*.jpg")
        cats = glob.glob(cats_paths)
        dog_paths = os.path.join(f_name, "dogs", "*.jpg")
        dogs = glob.glob(dog_paths)
        ## 0 = dogs
        ## 1 = cats
        dog_constant = torch.zeros(1)
        cat_constant = torch.ones(1)

        if torch.cuda.is_available():
            dog_constant = dog_constant.cuda()
            cat_constant = cat_constant.cuda()

        for path in dogs:
            item = (dog_constant, path)
            self.dogcat_list.append(item)

        for path in cats:
            item = (cat_constant, path)
            self.dogcat_list.append(item)

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

    def __getitem__(self, idx):
        filename = self.dogcat_list[idx][1]
        classCategory = self.dogcat_list[idx][0]
        im = Image.open(filename)
        if self.transform:
            im = self.transform(im)
        return im.view(-1), classCategory, filename

class CatsAndDogsModel(nn.Module):
    def __init__(self, image_size, out_dim):
        super(CatsAndDogsModel, self).__init__()
        in_dim = image_size[0] * image_size[1]

        self.layer = nn.Sequential(
            nn.Linear(in_dim, 20000),
            nn.Linear(20000, out_dim),
            nn.Sigmoid(),
        )

    def forward(self, x):
        return self.layer(x)

def serialize_model(model, epoch, loss, validate_loss):
    torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'loss': loss,
        'validate_loss': validate_loss,
    }, 'model.{}.pt'.format(epoch))

def load_model_from_file(model, path):
    "Returns the saved epoch of the model"
    checkpoint = torch.load(path)
    model.load_state_dict(checkpoint['model_state_dict'])
    return checkpoint['epoch']

def train_model(model, epochs, dataset, test_dataset, save_every=10, start_epoch=0):
    dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

    print(f"Max mem: {torch.cuda.max_memory_allocated()}, allocated: {torch.cuda.memory_allocated()}")

    model.train(True)

    learning_rate = 0.001
    optimiser = torch.optim.SGD(model.parameters(), lr=learning_rate)
    criterion = nn.MSELoss()

    try:
        inter_epoch_loss = 0
        for epoch in range(epochs):
            print("epoch #{}".format(epoch+start_epoch+1))
            print("Herro people")
            running_loss = 0
            for images, labels, path in dataloader:
                optimiser.zero_grad()

                if torch.cuda.is_available():
                    images = images.cuda()
                    labels = labels.cuda()
                    #print(f"device: {torch.cuda.get_device_name(images.get_device())}")

                output = model.forward(images)
                loss = criterion(output, labels)
                loss.backward()
                optimiser.step()

                running_loss += loss.item()
                inter_epoch_loss += loss.item()
            else:
                print(f"Total epoch loss: {running_loss/len(dataloader)}")

            print(f"Max mem: {torch.cuda.max_memory_allocated()}, allocated: {torch.cuda.memory_allocated()}")

            if epoch % save_every == 0:
                validate_loss = validate_model(model, test_dataset)
                serialize_model(model, epoch+start_epoch, inter_epoch_loss, validate_loss)
                inter_epoch_loss = 0
    except KeyboardInterrupt:
        pass

    model.train(False)

def validate_model(model, dataset):
    "Returns the loss of a single validation epoch"
    dataloader = DataLoader(dataset, batch_size=32, shuffle=True)

    model.train(False)

    criterion = nn.MSELoss()

    total = 0

    cats_total = 0
    cats_total_tp = 0
    cats_total_fp = 0

    dogs_total = 0
    dogs_total_tp = 0
    dogs_total_fp = 0

    running_loss = 0
    for images, labels, _ in dataloader:

        if torch.cuda.is_available():
            images = images.cuda()
            labels = labels.cuda()

        output = model.forward(images)
        loss = criterion(output, labels)
        loss.backward()

        results = output > 0.5
        results = list(zip(results, labels))

        for c in results:
            tp = 0
            fp = 0

            if c[0] == c[1].byte():
                tp += 1
            elif c[0] != c[1].byte():
                fp += 1

            if c[0] == 0:
                dogs_total += 1
                dogs_total_tp += tp
                dogs_total_tp += fp
            elif c[0] == 1:
                cats_total += 1
                cats_total_tp += tp
                cats_total_fp += fp

        total += len(results)

        running_loss += loss.item()

    # test_model is called from withing train_model, as such we should return to training mode

    model.train(True)

    cats_precision = cats_total_tp / (cats_total_tp + cats_total_fp)
    dogs_precision = dogs_total_tp / (dogs_total_tp + dogs_total_fp)

    cats_recall = cats_total_tp / (cats_total)
    dogs_recall = dogs_total_tp / (dogs_total)

    print("cats: ", cats_precision, ", dogs: ", dogs_precision)
    print("cats: ", cats_recall, ", dogs:", dogs_recall)

    return running_loss

if __name__ == "__main__":
    torch.manual_seed(69)
    np.random.seed(69)

    print(f"Using cuda: {torch.cuda.is_available()}")

    image_size = (100, 100)

    transform = transforms.Compose([
        transforms.Resize(image_size),
        transforms.Grayscale(),
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])

    training_dataset = CatsAndDogsDataset('dataset/training_set/', transform)
    test_dataset = CatsAndDogsDataset('dataset/test_set/', transform)

    model = CatsAndDogsModel(image_size, 1)
    if torch.cuda.is_available():
        model = model.cuda()
        model = nn.DataParallel(model)

#    start_epoch = load_model_from_file(model, 'first_model/model.2300.pt')
    start_epoch = 0
    train_model(model, 1, training_dataset, test_dataset, save_every=5, start_epoch=start_epoch)
    #validate_model(model, test_dataset, device)

    dataloader = DataLoader(test_dataset, batch_size=1, shuffle=True)
    total_tested = 0
    total_correct = 0

    for img, label, path in dataloader:
        output = model(img.cuda())
        cv_img = cv2.imread(path[0])
        #cv_img = img.detach().reshape((100, 100)).numpy()

        cv_img = cv2.resize(cv_img, (400, 400))
#        cv_img = cv2.cvtColor(cv_img, cv2.COLOR_GRAY2RGBA)
        cv2.putText(cv_img, f"truth: {'cat' if label > 0.5 else 'dog'}, {label.item()}", (0, 30), cv2.FONT_HERSHEY_DUPLEX, 1, (0, 255, 255))

        correct = bool(output.item() > 0.5) == bool(label.item() > 0.5)

        total_tested += 1
        total_correct += 1 if correct else 0

        if correct:
            color = (0, 255, 0)
        else:
            color = (0, 0, 255)

        cv2.putText(cv_img, f"guess: {'cat' if output.item() > 0.5 else 'dog'}, {output.item():.5f}", (0, 60), cv2.FONT_HERSHEY_DUPLEX, 1, color)
        cv2.putText(cv_img, f"{total_correct}/{total_tested}, {float(total_correct)/float(total_tested)*100.0:.2f}%", (0, 90), cv2.FONT_HERSHEY_DUPLEX, 1, color)
        cv2.imshow("random", cv_img)
        cv2.waitKey(400)

    print(f"{total_correct}/{total_tested}, {float(total_correct)/float(total_tested)*100.0:.2f}%")

    # Find Learning rate - 0.001
    # Find optmiser      - SGD
    # Find loss function - MSE(Mean squared error), BCE(binary cross entropy)

    # for (images, cats) in dataloader:
    #     for i in range(len(cats)):
    #         out = model.forward(images[i])
    #         print("model out: {}, is_cat: {}".format(float(out), float(cats[i])))


from asyncore import read
import cv2
import numpy as np

def stackImages(scale,imgArray,lables=[]):
    sizeW= imgArray[0][0].shape[1]
    sizeH = imgArray[0][0].shape[0]
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                imgArray[x][y] = cv2.resize(imgArray[x][y], (sizeW, sizeH), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
            hor_con[x] = np.concatenate(imgArray[x])
        ver = np.vstack(hor)
        ver_con = np.concatenate(hor)
    else:
        for x in range(0, rows):
            imgArray[x] = cv2.resize(imgArray[x], (sizeW, sizeH), None, scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        hor_con= np.concatenate(imgArray)
        ver = hor
    if len(lables) != 0:
        eachImgWidth= int(ver.shape[1] / cols)
        eachImgHeight = int(ver.shape[0] / rows)
        print(eachImgHeight)
        for d in range(0, rows):
            for c in range (0,cols):
                cv2.rectangle(ver,(c*eachImgWidth,eachImgHeight*d),(c*eachImgWidth+len(lables[d][c])*13+27,30+eachImgHeight*d),(255,255,255),cv2.FILLED)
                cv2.putText(ver,lables[d][c],(eachImgWidth*c+10,eachImgHeight*d+20),cv2.FONT_HERSHEY_COMPLEX,0.7,(255,0,255),2)
    return ver

#alternative to cv2 trackbar. Basically allows you to change certain values of any array
def showValues(img,valNames, valRanges,vals,option):
    i=0
    cv2.putText(img, str(option[0]), (20,100),cv2.FONT_HERSHEY_COMPLEX, 0.7, (0,255,0), 2)
    for x in valNames:
        isOption=" "
        if(i==option[0]):
            isOption="#"
            k = cv2.waitKey(1) & 0xff
            if k == ord('w') and option[0]>0:
                option[0]-=1
            elif k == ord('s') and option[0]<len(valNames)-1:
                option[0]+=1
            elif k == ord('a') and vals[i]>valRanges[i][0]:
                vals[i]-=1
            elif k == ord('d') and vals[i]<valRanges[i][1]:
                vals[i]+=1
        a=valRanges[i][0]
        b=valRanges[i][1]
        cv2.putText(img, isOption+x+" "+str(a)+" - "+str(vals[i])+" - "+str(b), (20, (i+1)*20 + 100), cv2.FONT_HERSHEY_COMPLEX, 0.7, (0,255,0), 2)
        i+=1

# def mss_screencap():
#     with mss.mss() as sct:#starts mss
#         while 'Screen capturing':
#             monitor_1 = sct.monitors[1]#monitor_1 represents screen monitor
#             sct_img = np.array(sct.grab(monitor_1))#grabs input from screen
#             img = cv2.cvtColor(np.array(sct_img), cv2.COLOR_BGRA2BGR)#converts screen input to BGR format
#             h = img.shape[0] #get height of image
#             w = img.shape[1] #get width of image
#             img=cv2.resize(img, (int(w/2),int(h/2)))#resize image so it won't take up a huge portion of the screen
#             cv2.imshow('img',img) # show img on window named 'img'
#             k=cv2.waitKey(27) & 0xff# checks for key press
#             if k==ord('q'):# if key pressed is q, exit
#                 break
#     cv2.destroyAllWindows()

def color_detect():
    cap = cv2.VideoCapture(0)

    names = ["hue1", "sat1", "value1", "hue2", "sat2", "value2"]
    values = [40, 0, 0, 50, 255, 255]
    ranges =[[0, 100], [0, 255], [0, 255], [0, 100], [0, 255], [0, 255]]
    option = [0]

    lowerbound = np.array([50, 30, 30])
    upperbound = np.array([80, 255, 255])
    # hue range is 0 -180
    # sat range is 0 -255
    # 0 is dark max is light

    # maybe values hue 7 - 21; sat 100 - 255; val 100 - 255
    names = ["hue1", "sat1", "value1", "hue2", "sat2", "value2"]
    values = [5, 100, 100, 16, 255, 255]
    ranges = [[0, 100], [0, 255], [0, 255], [0, 100], [0, 255], [0, 255]]
    option = [0]

    while cap.isOpened():

        lowerbound = np.array([values[0], values[1], values[2]])
        upperbound = np.array([values[3], values[4], values[5]])

        ret, img = cap.read()
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        # determines what pixels remain in image
        mask = cv2.inRange(hsv, lowerbound, upperbound)
        output = cv2.bitwise_and(img, img, mask=mask)
        showValues(img, names, ranges, values, option)
        imgStack = stackImages(0.3, ([output, mask],[img, img]))
        cv2.imshow('img', imgStack)
        k = cv2.waitKey(27)

        if k == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
    print("end")

if __name__ == "__main__":
    color_detect()

# show vals
# names[]
# vals[]
#ranges[]
# option = [0]


import torch
import mrcfile
import argparse
import numpy as np
import pandas as pd
from torch import nn
from tqdm import tqdm
from math import ceil
from torch import FloatTensor as FT
from torch.autograd import Variable as V

from DenseNetB import DenseNet

np.set_printoptions(threshold = np.inf)
np.set_printoptions(suppress = True)

use_gpu = torch.cuda.is_available()
if use_gpu:
    torch.cuda.empty_cache()

def get_args():
    parser = argparse.ArgumentParser(description="This script predict amino acid and secondary structure type for LDPs",
                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("--mcv", "-m", type=str, required=True,
                        help="input voxel density file")
    parser.add_argument("--ldp", "-l", type=str, required=True,
                        help="input LDP file in .pdb format")
    parser.add_argument("--bsize", "-b", type=int, default=128,
                        help="number of data points to predict in one batch")
    parser.add_argument("--model", "-M", type=str, default="../models/DenseNetB.pkl",
                        help="file name of trained model")
    args = parser.parse_args()
    return args

def read_file(file_name):
	f = open(file_name,'r')
	source = []
	for line in f.readlines():
		source.append(line.strip())
	f.close()
	return source

def main():
    vsize = 10

    args = get_args()
    mcv_file = args.mcv
    ldp_file = args.ldp
    batch_size = args.bsize
    model_file = args.model

    ldp=read_file(ldp_file)

    df = pd.read_csv(mcv_file, sep=' ', header=None)
    data = np.array(df.iloc[:,1:], dtype='float32')

    X = data.reshape(-1, vsize ** 3)

    X = V(FT(X), requires_grad=False).view(-1, 1, vsize, vsize, vsize)

    data_num = len(X)

    n_batches = ceil(data_num/batch_size)

    model = DenseNet().cuda()
    model = nn.DataParallel(model)
    model.module.load_state_dict(torch.load(model_file))

    model.eval()
    y = np.zeros((data_num,  7), dtype='float32')
    for i in tqdm(range(n_batches)):
        X_batch = X[i * batch_size : (i + 1) * batch_size].cuda()
        y_batch = model(X_batch).cpu().detach().numpy()
        y[i * batch_size : (i + 1) * batch_size] = y_batch

    i = 0
    for line in ldp:
        if line[0:4] == "ATOM":
            print("{}{:6d}{:6d}".format(line, np.argmax(y[i,:4]), np.argmax(y[i,4:])) )
            i += 1
        else:
            print(line)

if __name__ == "__main__":
    main()


from django.urls import  path
from .views import  PostDetailView, PostLike,AddPostDataset,CreatePostView, PostListView, CommentList,CommentDetail,PostCommentsView
urlpatterns = [

    path('postcreate/', CreatePostView.as_view()), #to add post data like img and content bla
    path('postcreate/<int:id>/',AddPostDataset.as_view()),#to add dataset to be predicted
    path('list/', PostListView.as_view() ), #to list all posts
    path('list/<int:id>/',  PostDetailView.as_view()), #to get post, update and delete
    path('list/like/<int:id>/',  PostLike.as_view()),

    path('comments/' , PostCommentsView.as_view()),

]


"""
This is the third script to parse the comments for rozetka themselves.
You might need to run script_to_keep_parsing before it

Also each time parsing fails you MUST change rerun_id variable (increase it) so that new
files where parsed data is stored have different name
"""

from tqdm import tqdm
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with
import time
import random
from selenium.common.exceptions import NoSuchElementException
from multiprocessing import Process

import multiprocessing, logging
#mpl = multiprocessing.log_to_stderr()
#mpl.setLevel(logging.INFO)

#NOTE: notdone_data is generated with script_to_keep_parsing in case
#parsing fails and we need to continue

prodlinks_data = pd.read_pickle("notdone_data.pkl")

random.shuffle(prodlinks_data)

comms_data = []

N_threads = 8

def chunks_gen(lst, n):
    """Yield successive n-sized chunks from lst."""
    for i in range(0, len(lst), n):
        yield lst[i:i + n]

def task(chunk, chunk_id):

    rerun_id = 0  # NOTE: increase manually after each code restart when continue parsing

    #mpl.info("Process number: " + str(chunk_id))

    try:
        test_driver = webdriver.Firefox()
        test_driver.set_window_size(2048, 1200)

        with open("comments_files/parsed_data_" + str(rerun_id) + "_" + str(chunk_id) + ".txt", "w") as f:
            f.write("\n")

        for prod in tqdm(chunk):

            try:
                #print(prod)
                test_driver.get(prod["prod_link"])
                time.sleep(4)

                xpath_all_comments_page = "/html/body/app-root/div/div/rz-product/div/rz-product-tab-main/div[1]/div[2]/div[2]/rz-product-comments-tab-main/section/a"

                more_comments_was_clicked = False
                try:
                    all_comments_button = test_driver.find_element(By.XPATH, xpath_all_comments_page)
                    all_comments_button.click()
                    time.sleep(3)
                    more_comments_was_clicked = True
                except NoSuchElementException:
                    pass

                comment_ind = 1
                xpath_comment_template = "/html/body/app-root/div/div/rz-product/div/rz-product-tab-feedback/div/div/main/rz-product-comments/section/section/rz-comment-list/ul/li[<comment_ind>]/rz-product-comment/rz-comment/div/div/div[2]"

                more_comments_exists = True
                while (more_comments_exists):
                    try:
                        xpath_comment = xpath_comment_template.replace('<comment_ind>', str(comment_ind))
                        comment_element = test_driver.find_element(By.XPATH, xpath_comment)
                        #mpl.info("comment_element")
                        num_stars = -1
                        general_comment_text = ""
                        extra_comment_text = ""

                        general_comment_element_xpath = xpath_comment + '/p'
                        #mpl.info(general_comment_element_xpath)

                        if len(test_driver.find_elements(By.XPATH, general_comment_element_xpath)) != 0:
                            #mpl.info("general_comment_element_xpath")
                            general_comment_element = comment_element.find_element(By.XPATH, general_comment_element_xpath)
                            general_comment_text = general_comment_element.text
                            #mpl.info(general_comment_text)

                        #mpl.info("mid 1")

                        extra_comment_element_xpath = xpath_comment + '/dl'
                        if len(test_driver.find_elements(By.XPATH, extra_comment_element_xpath)) != 0:
                            #mpl.info("extra_comment_element_xpath")
                            extra_comment_element = comment_element.find_element(By.XPATH, extra_comment_element_xpath)
                            extra_comment_text = extra_comment_element.text
                            #mpl.info(extra_comment_text)

                        #mpl.info("mid 2")

                        total_comment_text = general_comment_text + "\n" + extra_comment_text

                        #mpl.info(total_comment_text)

                        stars_element_xpath_v1 = xpath_comment + '/rz-comment-rating/div/ul/li[1]'
                        stars_element_xpath_v2 = xpath_comment + '/rz-comment-rating/div'

                        if len(test_driver.find_elements(By.XPATH, stars_element_xpath_v1)) != 0:
                            #mpl.info("stars_element_xpath_v1")
                            stars_element = comment_element.find_element(By.XPATH, stars_element_xpath_v1)
                            stars_element_html = stars_element.get_attribute("innerHTML")
                            num_stars = stars_element_html.count('#ffa900')

                        elif len(test_driver.find_elements(By.XPATH, stars_element_xpath_v2)) != 0:
                            #mpl.info("stars_element_xpath_v2")
                            stars_element = comment_element.find_element(By.XPATH, stars_element_xpath_v2)
                            stars_element_html = stars_element.get_attribute("innerHTML")
                            num_stars = stars_element_html.count('#ffa900')

                        #full_html = comment_element.get_attribute("innerHTML")

                        #num_stars = full_html.count('#ffa900')

                        # print("NUM STARS: " + str(num_stars))
                        # print(comment_element.text)

                        #mpl.info("NUM STARS: " + str(num_stars))
                        #mpl.info(total_comment_text)

                        doc = prod.copy()
                        doc["comment"] = total_comment_text
                        doc["rating"] = str(num_stars)

                        #print(doc)

                        with open("comments_files/parsed_data_" + str(rerun_id) + "_" + str(chunk_id) + ".txt", "a") as f:
                            f.write(str(doc) + "\n")

                        comment_ind += 1

                    except NoSuchElementException:
                        try:
                            xpath_more_comments = "/html/body/app-root/div/div/rz-product/div/rz-product-tab-feedback/div/div/main/rz-product-comments/section/section/button"
                            more_comments_button = test_driver.find_element(By.XPATH, xpath_more_comments)
                            more_comments_button.click()
                        except NoSuchElementException:
                            more_comments_exists = False
                            break
            except:
                pass
    except:
        print("Chunk " + chunk_id + " is broken")

prodlinks_chunks = list(chunks_gen(prodlinks_data, len(prodlinks_data) // N_threads))

print("prodlinks_chunks")
print(len(prodlinks_chunks))
print(prodlinks_chunks[0][:10])
time.sleep(10)

for ind, c in enumerate(prodlinks_chunks):
    print("Length of chunk " + str(ind))
    print(len(c))

processes = []
for ind, chunk in enumerate(prodlinks_chunks):
    t = Process(target=task, args=(chunk, ind))
    processes.append(t)
    t.start()

print("Join called")
for t in processes:
    t.join()

print("After join")


# -*- coding: utf-8 -*-
#!/usr/bin/env python
"""Unit tests for Rake.py"""

from collections import defaultdict

import nltk

from rake_nltk import Metric, Rake

###########################################################

text = """Compatibility of systems of linear constraints
over the set of natural numbers. Criteria of compatibility of a system
of linear Diophantine equations, strict inequations, and nonstrict
inequations are considered. Upper bounds for components of a minimal
set of solutions and algorithms of construction of minimal generating
sets of solutions for all types of systems are given. These criteria
and the corresponding algorithms for constructing a minimal supporting
set of solutions can be used in solving all the considered types of
systems and systems of mixed types."""

def test_build_frequency_dist():
    r = Rake()

    phrase_list = [['red', 'apples'], ['good'], ['red'], ['flavour']]
    freq = defaultdict(lambda: 0)
    freq['apples'] = 1
    freq['good'] = 1
    freq['flavour'] = 1
    freq['red'] = 2
    r._build_frequency_dist(phrase_list)
    assert r.get_word_frequency_distribution() == freq

def test_build_word_co_occurance_graph():
    r = Rake()

    phrase_list = [['red', 'apples'], ['good'], ['red'], ['flavour']]
    degree = defaultdict(lambda: 0)
    degree['apples'] = 2
    degree['good'] = 1
    degree['flavour'] = 1
    degree['red'] = 3
    r._build_word_co_occurance_graph(phrase_list)
    assert r.get_word_degrees() == degree

def test_generate_phrases():
    r = Rake()

    sentences = [
        'Red apples, are good in flavour.',
        'Keywords, which we define as a sequence of one or more words, '
        + "provide a compact representation of a document's content",
        'Criteria of compatibility of a system of linear Diophantine ' + 'equations',
        'whose gloomy beams transfigured the village into a lunar '
        + 'encampment of glowing houses and streets of volcanic deserts '
        + 'every fifteen seconds ',
    ]
    phrase_list = [
        ('red', 'apples'),
        ('good',),
        ('flavour',),
        ('keywords',),
        ('define',),
        ('sequence',),
        ('one',),
        ('words',),
        ('provide',),
        ('compact', 'representation'),
        ('document',),
        ('content',),
        ('criteria',),
        ('compatibility',),
        ('system',),
        ('linear', 'diophantine', 'equations'),
        ('whose', 'gloomy', 'beams', 'transfigured'),
        ('village',),
        ('lunar', 'encampment'),
        ('glowing', 'houses'),
        ('streets',),
        ('volcanic', 'deserts', 'every', 'fifteen', 'seconds'),
    ]
    assert r._generate_phrases(sentences) == phrase_list

def test_generate_phrases_with_length_limit():
    sentences = [
        'Red apples, are good in flavour.',
        'Keywords, which we define as a sequence of one or more words, '
        + "provide a compact representation of a document's content",
        'Criteria of compatibility of a system of linear Diophantine ' + 'equations',
        'whose gloomy beams transfigured the village into a lunar '
        + 'encampment of glowing houses and streets of volcanic deserts '
        + 'every fifteen seconds ',
    ]

    # Consider phrases which have minimum of 2 words and max of 4
    r = Rake(min_length=2, max_length=4)
    phrase_list = [
        ('red', 'apples'),
        ('compact', 'representation'),
        ('linear', 'diophantine', 'equations'),
        ('whose', 'gloomy', 'beams', 'transfigured'),
        ('lunar', 'encampment'),
        ('glowing', 'houses'),
    ]
    assert r._generate_phrases(sentences) == phrase_list

    # Consider phrases which have minimum of 5 words and max of 5
    r = Rake(min_length=5, max_length=5)
    phrase_list = [('volcanic', 'deserts', 'every', 'fifteen', 'seconds')]
    assert r._generate_phrases(sentences) == phrase_list

def test_get_phrase_list_from_words():
    r = Rake()

    word_list = ['red', 'apples', ',', 'are', 'good', 'in', 'flavour']
    phrase_list = [('red', 'apples'), ('good',), ('flavour',)]
    assert r._get_phrase_list_from_words(word_list) == phrase_list

    word_list = [
        'keywords',
        ',',
        'which',
        'we',
        'define',
        'as',
        'a',
        'sequence',
        'of',
        'one',
        'or',
        'more',
        'words',
        ',',
        'provide',
        'a',
        'compact',
        'representation',
        'of',
        'a',
        'document',
        "'",
        's',
        'content',
    ]
    phrase_list = [
        ('keywords',),
        ('define',),
        ('sequence',),
        ('one',),
        ('words',),
        ('provide',),
        ('compact', 'representation'),
        ('document',),
        ('content',),
    ]
    assert r._get_phrase_list_from_words(word_list) == phrase_list

def test_extract_keywords_from_text_degree_to_frequency_metric():
    r = Rake()
    r.extract_keywords_from_text(text)
    ranked_phrases = [
        'minimal generating sets',
        'linear diophantine equations',
        'minimal supporting set',
        'minimal set',
        'linear constraints',
        'upper bounds',
        'strict inequations',
        'nonstrict inequations',
        'natural numbers',
        'mixed types',
        'corresponding algorithms',
        'considered types',
        'set',
        'types',
        'considered',
        'algorithms',
        'used',
        'systems',
        'systems',
        'systems',
        'systems',
        'system',
        'solving',
        'solutions',
        'solutions',
        'solutions',
        'given',
        'criteria',
        'criteria',
        'construction',
        'constructing',
        'components',
        'compatibility',
        'compatibility',
    ]
    assert r.get_ranked_phrases() == ranked_phrases
    assert [phrase for _, phrase in r.get_ranked_phrases_with_scores()] == ranked_phrases

def test_extract_keywords_from_text_word_degree_metric():
    r = Rake(ranking_metric=Metric.WORD_DEGREE)
    r.extract_keywords_from_text(text)
    ranked_phrases = [
        'minimal supporting set',
        'minimal set',
        'minimal generating sets',
        'linear diophantine equations',
        'considered types',
        'mixed types',
        'linear constraints',
        'strict inequations',
        'set',
        'nonstrict inequations',
        'types',
        'corresponding algorithms',
        'upper bounds',
        'systems',
        'systems',
        'systems',
        'systems',
        'natural numbers',
        'solutions',
        'solutions',
        'solutions',
        'considered',
        'algorithms',
        'criteria',
        'criteria',
        'compatibility',
        'compatibility',
        'used',
        'system',
        'solving',
        'given',
        'construction',
        'constructing',
        'components',
    ]
    assert r.get_ranked_phrases() == ranked_phrases
    assert [phrase for _, phrase in r.get_ranked_phrases_with_scores()] == ranked_phrases

def test_extract_keywords_from_text_word_frequency_metric():
    r = Rake(ranking_metric=Metric.WORD_FREQUENCY)
    r.extract_keywords_from_text(text)
    ranked_phrases = [
        'minimal supporting set',
        'minimal set',
        'minimal generating sets',
        'considered types',
        'systems',
        'systems',
        'systems',
        'systems',
        'mixed types',
        'linear diophantine equations',
        'types',
        'strict inequations',
        'solutions',
        'solutions',
        'solutions',
        'set',
        'nonstrict inequations',
        'linear constraints',
        'corresponding algorithms',
        'upper bounds',
        'natural numbers',
        'criteria',
        'criteria',
        'considered',
        'compatibility',
        'compatibility',
        'algorithms',
        'used',
        'system',
        'solving',
        'given',
        'construction',
        'constructing',
        'components',
    ]

    assert r.get_ranked_phrases() == ranked_phrases
    assert [phrase for _, phrase in r.get_ranked_phrases_with_scores()] == ranked_phrases

def test_load_portuguese_stopwords():
    r = Rake(language='portuguese')
    assert r.stopwords is not None

def test_rake_default_metric():
    r = Rake(ranking_metric=1)
    assert r.metric == Metric.DEGREE_TO_FREQUENCY_RATIO

def test_allow_repeated_phrases():
    sentences = ['Magic systems is a company.', 'Magic systems was built in a garage']
    expected_phrase_list_with_repetitions = [
        (
            'magic',
            'systems',
        ),
        ('company',),
        ('magic', 'systems'),
        ('built',),
        ('garage',),
    ]
    expected_phrase_list_without_repetitions = [
        (
            'magic',
            'systems',
        ),
        ('company',),
        ('built',),
        ('garage',),
    ]

    r = Rake()
    assert r._generate_phrases(sentences) == expected_phrase_list_with_repetitions

    r = Rake(include_repeated_phrases=True)
    assert r._generate_phrases(sentences) == expected_phrase_list_with_repetitions

    r = Rake(include_repeated_phrases=False)
    assert r._generate_phrases(sentences) == expected_phrase_list_without_repetitions

def test_sent_tokenizer_config():
    text = 'This is a sentence with a #sent hashtag. This is another sentence with a a@rake.com email address.'

    punct_tokenized_sentences = [
        'This is a sentence with a #sent hashtag.',
        'This is another sentence with a a@rake.com email address.',
    ]

    # Default.
    r = Rake()
    assert punct_tokenized_sentences == r._tokenize_text_to_sentences(text)

    # Punct tokenize.
    r = Rake(sentence_tokenizer=nltk.tokenize.sent_tokenize)
    assert punct_tokenized_sentences == r._tokenize_text_to_sentences(text)

    # Custom tokenizer.
    def custom_tokenizer(text):
        return text.split('with')

    r = Rake(sentence_tokenizer=custom_tokenizer)
    assert [
        'This is a sentence ',
        ' a #sent hashtag. This is another sentence ',
        ' a a@rake.com email address.',
    ] == r._tokenize_text_to_sentences(text)

def test_word_tokenizer_config():
    sentence = 'This is a cooool #dummysmiley: :-) :-P <3 and some arrows < > -> <--'

    punct_tokenized_words = [
        'This',
        'is',
        'a',
        'cooool',
        '#',
        'dummysmiley',
        ':',
        ':-)',
        ':-',
        'P',
        '<',
        '3',
        'and',
        'some',
        'arrows',
        '<',
        '>',
        '->',
        '<--',
    ]

    # Default
    r = Rake()
    assert punct_tokenized_words == r._tokenize_sentence_to_words(sentence)

    # Punct tokenize.
    r = Rake(word_tokenizer=nltk.tokenize.wordpunct_tokenize)
    assert punct_tokenized_words == r._tokenize_sentence_to_words(sentence)

    # Custom tokenizer. (Tweet)
    r = Rake(word_tokenizer=nltk.tokenize.TweetTokenizer().tokenize)
    assert [
        'This',
        'is',
        'a',
        'cooool',
        '#dummysmiley',
        ':',
        ':-)',
        ':-P',
        '<3',
        'and',
        'some',
        'arrows',
        '<',
        '>',
        '->',
        '<--',
    ] == r._tokenize_sentence_to_words(sentence)


from AlgorithmImports import *

class SellOnProfit(QCAlgorithm):
    """
    This algoritm buys AAPL and sells it when it reaches a 100% profit.
    """

    def Initialize(self):
        self.SetStartDate(2010, 1, 1)  # Set Start Date
        self.SetEndDate(2015, 1, 1)  # Set End Date
        self.SetCash(10000)  # Set Strategy Cash
        self.AddEquity("AAPL", Resolution.Daily)

        # Set to negative for target loss
        # e.g. -0.5 means 50% loss
        self.profit_percent_target = 1.0
        self.invest = True  # avoids keep buying and selling

    def OnData(self, data):
        """OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        Arguments:
            data: Slice object keyed by symbol containing the stock data
        """
        if not self.Portfolio.Invested and self.invest:
            self.SetHoldings("AAPL", 1)
            self.Debug("Purchased Stock")

        # UnrealizedProfitPercent is the percent of profit/loss ranges from -1 to infinity
        profit_percent = self.Portfolio["AAPL"].UnrealizedProfitPercent

        if profit_percent >= self.profit_percent_target:
            self.Liquidate("AAPL")
            self.invest = False
            self.Debug("Sold Stock")


import sqlite3
from tabulate import tabulate
from customer import Customer
from service import Service
from service_type import ServiceType
from appointment import Appointment

connection = None
cursor = None

def initialise_database():
    global connection, cursor
    connection = sqlite3.connect("OMG_DB.db")
    cursor = connection.cursor()

    CREATE_CUSTOMER_TABLE_QUERY = """
    CREATE TABLE IF NOT EXISTS customer (
        customerID INTEGER PRIMARY KEY AUTOINCREMENT,
        customerFirstName TEXT NOT NULL,
        customerLastName TEXT NOT NULL,
        customerPhoneNumber TEXT NOT NULL,
        customerEmail TEXT NOT NULL,
        customerAddress TEXT NOT NULL
    )"""

    CREATE_USER_TABLE_QUERY = """
    CREATE TABLE IF NOT EXISTS users (
        userID INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT UNIQUE NOT NULL,
        password TEXT  NOT NULL
    )"""

    CREATE_SERVICE_TYPE_TABLE_QUERY = """
    CREATE TABLE IF NOT EXISTS serviceType(
        serviceTypeID INTEGER PRIMARY KEY AUTOINCREMENT,
        serviceTypeName TEXT NOT NULL
    )"""

    CREATE_SERVICE_TABLE_QUERY = """
    CREATE TABLE IF NOT EXISTS service(
        serviceID INTEGER PRIMARY KEY AUTOINCREMENT,
        serviceName TEXT NOT NULL,
        servicePrice TEXT NOT NULL,
        serviceDescription TEXT DEFAULT 'No description provided',
        serviceTypeID INTEGER,
        FOREIGN KEY(serviceTypeID) REFERENCES serviceType(serviceTypeID)
    )"""

    CREATE_APPOINTMENT_TABLE_QUERY = """
    CREATE TABLE IF NOT EXISTS appointment (
        appointmentID INTEGER PRIMARY KEY AUTOINCREMENT,
        appointmentDate DATE,
        appointmentTime TIME,
        appointmentStatus TEXT NOT NULL,
        customerID INTEGER,
        serviceNumber INTEGER,
        FOREIGN KEY (customerID) REFERENCES customer(customerID),
        FOREIGN KEY (serviceNumber) REFERENCES service(serviceNumber)
        )"""

    cursor.execute(CREATE_CUSTOMER_TABLE_QUERY)
    cursor.execute(CREATE_USER_TABLE_QUERY)
    cursor.execute(CREATE_SERVICE_TYPE_TABLE_QUERY)
    cursor.execute(CREATE_SERVICE_TABLE_QUERY)
    cursor.execute(CREATE_APPOINTMENT_TABLE_QUERY)
    connection.commit()

def AddCustomer(fname, lname, phoneNum, email, address):
    try:
        initialise_database()
        cursor.execute("""
            INSERT INTO customer (
                customerFirstName, customerLastName, customerPhoneNumber, customerEmail, customerAddress
            ) VALUES (?, ?, ?, ?, ?)
        """, (fname, lname, phoneNum, email, address))
        connection.commit()
        CloseDatabase()
    except Exception as e:
        print(e)
        raise e

def AddUser(username, password):
    try:
        initialise_database()
        cursor.execute("""
            INSERT INTO users (username, password) VALUES (?, ?)
        """, (username, password))
        connection.commit()
        CloseDatabase()
    except Exception as e:
        print(e)
        raise e

def Login(username, password):
    try:
        initialise_database()
        cursor.execute("""
            SELECT userID FROM users WHERE username=? AND password=?
        """, (username, password))
        user_id = cursor.fetchone()

        if user_id:
            cursor.execute("""
                SELECT * FROM customer WHERE customerID=?
            """, (user_id[0],))
            record = cursor.fetchone()

            if record:
                num, fname, lname, cell, email, addr = record
                User = Customer(fname, lname, email, cell, addr)
                CloseDatabase()
                return User
        CloseDatabase()
        return None
    except Exception as e:
        print(e)
        raise e

def getCustomerNumber(customer):
    initialise_database()
    fname, lname, phone, email = customer.first_name, customer.last_name, customer.phoneNum, customer.email
    cursor.execute("""SELECT customerID FROM customer
        WHERE customerFirstName=? AND customerLastName=?
        AND customerPhoneNumber=? AND customerEmail=?""",
        (fname,lname,phone,email))
    id = cursor.fetchone()
    CloseDatabase()
    return id

def CloseDatabase(): connection.close()

initialise_database()
CloseDatabase()

# How to do services: they will be saved manually by admin.
# 1. Fade Cut

def AddService(service: Service):
    try:
        id, name, price, descr, type_id = service.serviceID, service.serviceName, service.servicePrice, service.serviceDescription, service.serviceTypeID
        cursor.execute(""""INSERT INTO service VALUES(?, ?, ?, ?, ?)""",
        (id, name, price, descr, type_id))
        connection.commit()
    except Exception as e:
        print(e)
        raise e

def AddAppointmentRequest(appointment: Appointment, cust_id):
    try:
        initialise_database()
        sched, cust_num, serv_num = appointment.schedule, appointment.customer_num, appointment.service_num
        date, time, status = appointment.appointmentDate, appointment.appointmentTime, str(appointment.appointmentStatus)
        print(date, time, status, cust_num, serv_num)
        cursor.execute("INSERT INTO appointment (appointmentDate, appointmentTime, appointmentStatus, customerID, serviceNumber) VALUES(?, ?, ?, ?, ?)", (date, time, status, cust_id, serv_num))
        connection.commit()
        CloseDatabase()
    except Exception as e:
        print(e)
        raise e

def getServiceNumber(service_name: str):
    try:
        initialise_database()
        cursor.execute('SELECT serviceID FROM service WHERE serviceName=?', service_name)
        record = cursor.fetchone()[0]
    except Exception as e:
        raise e

initialise_database()
cursor.execute("SELECT * FROM appointment")
res = cursor.fetchall()
headers = ['App_ID', 'App_date', 'App_time', 'App_status', 'Cust_ID', 'Serv_num']
print(tabulate(res, headers, "fancy_grid"))


from DB_Operations.database_connection import db_connection
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.impute import KNNImputer
from Log.Log import App_Logger

class preprocessing:
    def __init__(self):
        self.connection = db_connection()
        self.file = open("Log/File_Logs/Db_error.txt", 'a+')
        self.logger = App_Logger()

    def remove_comma_from_cost(self, session, useful_rating_data):
        """
        Cost column value is given as 1,500 type. Conversion into float and removing the comma is done in this method
        :param session: database connectivity
        :param useful_rating_data: training data

        Written by : Priya Ganesan
        Version : 1.0

        """
        try:
            self.connection.log_insert_into_db(session, 'DebugLog', 'Trying to do preprocessing step in cost column')
            #comma string is replaced by empty. After executing the following statement, 1,000 is converted to 1000
            useful_rating_data['approx_cost(for two people)'] = useful_rating_data[
                'approx_cost(for two people)'].str.replace(",", "")
            #converting the column to float since it will be easy for computation while creating model
            useful_rating_data['approx_cost(for two people)'] = useful_rating_data[
                'approx_cost(for two people)'].astype(float)
            useful_rating_data = useful_rating_data.reset_index(drop=True)
            self.connection.log_insert_into_db(session, 'InfoLog', 'Preprocessing step in cost column completed')
            return useful_rating_data

        except Exception as e:
            self.connection.log_insert_into_db(session, 'ErrorLog', str(e))

    def train_test_split(self, session, useful_rating_data):
        """
        This method is used to split the data into train and test. This will be useful in calculating the accuracy and test the model
        :param session: database connectivity
        :param useful_rating_data: training data

        Written by : Priya Ganesan
        Version : 1.0

        """
        try:
            self.connection.log_insert_into_db(session, 'DebugLog', 'Trying to split train and test data')
            X = useful_rating_data.drop(columns=['rate'])
            y = useful_rating_data['rate']
            #80% of the data is taken for training and 20% for testing
            X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=200)
            self.connection.log_insert_into_db(session, 'InfoLog', 'Train , Test split completed successfully')
            return X_train, X_test, y_train, y_test

        except Exception as e:
            self.connection.log_insert_into_db(session, 'ErrorLog', str(e))

    def one_hot_encoding(self, session, X_train, X_test):
        """
        There are number of categorical columns in this dataset. Conversion of categorical columns into numerical values is necessary
        :param session: database connectivity
        :param X_train: Training features
        :param X_test: Testing features
        :param y_train: Training target
        :param y_test: Testing target
        """

        try:
            self.connection.log_insert_into_db(session, 'DebugLog', 'One hot encoding part started')
            #List of columns which are categorical are passed
            column_list = ['location', 'rest_type', 'cuisines', 'listed_in(type)']
            X_train,X_test = self.one_hot_encoding_conversion(session, X_train, X_test,column_list)
            self.connection.log_insert_into_db(session, 'InfoLog', 'One hot encoding part completed successfully')
            return X_train,X_test

        except Exception as e:
            self.connection.log_insert_into_db(session, 'ErrorLog', str(e))

    def one_hot_encoding_conversion(self, session, X_train, X_test, column_list):

        try:
            self.connection.log_insert_into_db(session, 'DebugLog', 'One hot encoding conversion started')
            for column in column_list:
                #pandas get dummies method is used to create dummies for the data. Number of columns increase while doing this method
                X_train = pd.concat([X_train.drop(column, 1), X_train[column].str.get_dummies(sep=",")], 1)
                X_test = pd.concat([X_test.drop(column, 1), X_test[column].str.get_dummies(sep=",")], 1)
            self.connection.log_insert_into_db(session, 'InfoLog', 'One hot encoding conversion completed successfully')
            return X_train,X_test

        except Exception as e:

            self.connection.log_insert_into_db(session, 'ErrorLog', str(e))

    def creating_same_number_of_columns_in_train_test(self,session,X_train,X_test):
        """
        Since we are doing one hot encoding there might be mismatch in the train and test data.
        So we are performing some operations to make sure there is same number of columns in train and test data

        Written by : Priya Ganesan
        Version : 1.0

        """
        try :
            self.connection.log_insert_into_db(session, 'DebugLog', 'Matching equal number of train and test columns started')
            #removing extra space present in the train data column name
            X_train.columns = X_train.columns.str.strip()
            #removing extra space present in the test data column name
            X_test.columns = X_test.columns.str.strip()
            #Sometimes columns can be duplicated. So duplicate columns are removed in this step
            X_train = X_train.loc[:, ~X_train.columns.duplicated()]
            X_test = X_test.loc[:, ~X_test.columns.duplicated()]
            #If the column present only in the train and not in the test, then that columns are mapped to zero in the test
            missing_cols = set(X_train.columns) - set(X_test.columns)
            for c in missing_cols:
                X_test[c] = 0
            #If the column present only in the test, then that columns are removed to match the number of columns in the train data and test data
            missing_cols_train = set(X_test.columns) - set(X_train.columns)

            if len(missing_cols_train) > 0:
                for value in missing_cols_train:
                    X_test = X_test.drop(columns=[value])
            #to arrange train data and test data in the same order
            X_test = X_test[X_train.columns]
            #train data is stored to act as a reference to the input data from prediction
            X_train.to_csv('X_train.csv',index=False)
            self.connection.log_insert_into_db(session, 'InfoLog','Matching equal number of train and test columns completed')

            return X_train, X_test

        except Exception as e:
            self.connection.log_insert_into_db(session, 'ErrorLog', str(e))

    def mapping_encoding(self, session, useful_rating_data):
        """
        For few columns encoding can be done directly by mapping values. Those type of encoding is done in this method
        :param X_train: Training data
        :param X_test: Testing data

        """
        try :
            self.connection.log_insert_into_db(session, 'DebugLog','Trying to start mapping_encoding')
            #rate is present as 4.1/5. After executing the below statement it will be stored as 4.1
            useful_rating_data['rate'] = useful_rating_data['rate'].str[0:3]
            #online_order is mapped to numerical number
            useful_rating_data['online_order'] = useful_rating_data['online_order'].map({'Yes': 1, 'No': 0})
            #book_table column is mapped to numeric value
            useful_rating_data['book_table'] = useful_rating_data['book_table'].map({'Yes': 1, 'No': 0})
            useful_rating_data['phone'] = useful_rating_data['phone'].fillna(0)
            #if phone number is present then it is mapped to 1, or else it is mapped to 0
            useful_rating_data['phone'] = useful_rating_data['phone'].apply(lambda x: 1 if x != 0 else x)
            self.creating_dish_liked_list(session,useful_rating_data)
            useful_rating_data['dish_liked'] = useful_rating_data['dish_liked'].fillna(0)
            useful_rating_data['dish_liked'] = useful_rating_data['dish_liked'].apply(lambda x: 1 if x != 0 else x)
            self.connection.log_insert_into_db(session, 'InfoLog', 'Mapping encoding completed successfully')
            return useful_rating_data
        except Exception as e :
            self.connection.log_insert_into_db(session, 'ErrorLog', str(e))

    def creating_dish_liked_list(self,session,useful_rating_data):
        try :
            """
            User gives input for recommended dish for their restaurant. We are taking some of the top liked dishes from the
            training data. If the recommended dish is present in the data, we are mapping it to 1 or else we will map to 0.
            This information is useful while choosing the restaurant. For example if we are ordering food from a particular restaurant,
            the first thing which we see is recommended dish. If we have our liked dish, then we will go ahead and order the food in that
            particular restaurant. So this information is important in rating.

            Written by: Priya Ganesan
            Version : 1.0
            """
            self.connection.log_insert_into_db(session, 'DebugLog', 'Trying to create dish liked file')
            #since dish_liked column is comma seperated, we are trying to take individual dishes
            useful_rating_data = useful_rating_data.assign(dish_liked=useful_rating_data['dish_liked'].str.split(',')).explode('dish_liked')
            #removing the extra space present in the dish
            useful_rating_data['dish_liked'] = useful_rating_data['dish_liked'].str.strip()
            #converting to upper case as it will be easy to compare the user input to the list of the dish liked
            useful_rating_data['dish_liked'] = useful_rating_data['dish_liked'].str.upper()
            dish_liked_counts = useful_rating_data['dish_liked'].value_counts().rename('liked_dish_count')
            df1 = pd.DataFrame(dish_liked_counts)
            #taking the top dish liked and the value counts. Dishes whose value count > 0 is chosen in the list
            df2 = df1[df1['liked_dish_count'] > 50]
            dish_liked_list = list(df2.index)
            dish_liked_file = open("Training_data_information/dish_liked.txt", 'w+')
            for item in dish_liked_list:
                    # write each item on a new line
                    dish_liked_file.write("%s\n" % item)
            dish_liked_file.close()

            self.connection.log_insert_into_db(session, 'InfoLog', 'dish liked file successfully created')

        except Exception as ex:
            self.connection.log_insert_into_db(session, 'ErrorLog', str(ex))

    def KNNImputer(self,session,X_train,X_test):
        """
        The dataset is having null values. This method imputes null values
        Written by : Priya Ganesan
        Version : 1.0
        """
        try :
            self.connection.log_insert_into_db(session, 'DebugLog','Trying to start imputation')
            #giving the value of k =2 for performing knn
            imputer = KNNImputer(n_neighbors=2)
            impute = imputer.fit(X_train)
            #the imputation done for train is also followed for the test data
            X_train = impute.transform(X_train)
            X_test = impute.transform(X_test)
            return X_train,X_test

        except Exception as e :
            self.connection.log_insert_into_db(session, 'ErrorLog', str(e))


import numpy as np

def find_local_maxima(src, ksize):
    (h, w) = src.shape
    pad_img = np.zeros((h+ksize, w+ksize))
    pad_img[ksize//2:h+ksize//2, ksize//2:w+ksize//2] = src
    dst = np.zeros((h, w))

    for row in range(h):
        for col in range(w):
            max_val = np.max(pad_img[row : row+ksize, col:col+ksize])
            if max_val == 0:
                continue
            if src[row, col] == max_val:
                dst[row, col] = src[row, col]

    return dst


#!/usr/bin/python

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import logging
import random

import spqr_defines as SPQR
import spqr_gui as SGFX
import spqr_events as SEVENTS
import spqr_widgets as SWIDGET
import spqr_window as SWINDOW
import spqr_ybuild as SYAML
import spqr_data as SDATA

# Setup logging
logger = logging.getLogger('spqr.battle')

# module to handle all of the battle display window code

attack_good	=	["Good auspices", "Position good", "Sun behind troops"]
attack_bad	=	["Fighting uphill", "Against the wind", "Troops tired"]
defend_good	=	["Good auspices", "Hard to retreat", "Troops rested"]
defend_bad	=	["Defense stretched", "Troops tired", "Low morale"]

attack_options	=	["Brutal", "Aggressive", "Neutral", "Cautious"]
retreat_options =	["Never", "30% loss", "20% loss", "10% loss", "Under attack"]

class BattleScreen(object):
	def __init__(self, attacker, region):
		self.result = None
		# get the defending units (only the first for now)
		# must be some units, we checked earlier
		defender = region.units[0]
		region = region
		# now we have all we need to build the base window
		window = SWINDOW.CWindow(-1, -1, 390, 300, "Battle Screen", False)
		window.modal = True
		ystart = SGFX.gui.iHeight("win_tl")
		# we need widgets for the unit names
		attack_unit_label = SWIDGET.buildLabel(str(attacker), SPQR.FONT_VERA_BOLD)
		attack_unit_label.rect.x = int((180 - attack_unit_label.rect.width) / 2) + 10
		attack_unit_label.rect.y = 60 + ystart
		defend_unit_label = SWIDGET.buildLabel(str(defender), SPQR.FONT_VERA_BOLD)
		defend_unit_label.rect.x = int((180 - defend_unit_label.rect.width) / 2) + 200
		defend_unit_label.rect.y = 60 + ystart
		# pictures of the units
		attack_image = SWIDGET.buildImageAlpha(attacker.image)
		attack_image.rect.x = int((180 - SPQR.UNIT_WIDTH) / 2) + 10
		attack_image.rect.y = 15 + ystart
		defend_image = SWIDGET.buildImageAlpha(defender.image)
		defend_image.rect.x = int((180 - SPQR.UNIT_WIDTH) / 2) + 200
		defend_image.rect.y = 15 + ystart
		for widget in [attack_unit_label, defend_unit_label, attack_image,	defend_image]:
			window.addWidget(widget)
		# get the random elements and add them
		xpos = 20
		ypos1 = 85 + ystart
		for event in self.getAttackEvents():
			label = SWIDGET.buildLabel(event)
			label.rect.x = xpos
			label.rect.y = ypos1
			window.addWidget(label)
			ypos1 += 20
		xpos = 220
		ypos2 = 85 + ystart
		for event in self.getDefendEvents():
			label = SWIDGET.buildLabel(event)
			label.rect.x = xpos
			label.rect.y = ypos2
			window.addWidget(label)
			ypos2 += 20
		# how far?
		if ypos2 > ypos1:
			ypos1 = ypos2
		ypos1 += 12
		# build in the options
		attack_text = SWIDGET.buildLabel("Attack style:", SPQR.FONT_VERA_ITALIC)
		attack_text.rect.x = 20
		attack_text.rect.y = ypos1
		defend_text = SWIDGET.buildLabel("Retreat:", SPQR.FONT_VERA_ITALIC)
		defend_text.rect.x = 220
		defend_text.rect.y = ypos1
		window.addWidget(attack_text)
		window.addWidget(defend_text)
		ypos1 += 20
		opt1 = SWIDGET.COptionMenu(20, ypos1, attack_options)
		opt2 = SWIDGET.COptionMenu(220, ypos1, retreat_options)
		opt1.active = True
		opt2.active = True
		window.addWidget(opt1)
		window.addWidget(opt2)
		ypos1 += 40
		window.addWidget(SWIDGET.CSeperator(10, ypos1, 370))
		ypos1 += 15
		# add withdraw and attack buttons
		btn_attack = SWIDGET.CButton(297, ypos1, "Attack")
		btn_attack.callbacks.mouse_lclk = self.doBattle
		btn_attack.active = True
		btn_withdraw = SWIDGET.CButton(200, ypos1, "Withdraw")
		btn_withdraw.callbacks.mouse_lclk = self.retreatBattle
		btn_withdraw.active = True
		window.addWidget(btn_attack)
		window.addWidget(btn_withdraw)
		window.rect.height = ypos1 + 50
		window.renderWindowBackdrop()
		SGFX.gui.addWindow(window)
		SGFX.gui.pauseFlashing()
		# setup dirty rect stuff
		SGFX.gui.addDirtyRect(window.drawWindow(), window.rect)

	def run(self):
		self.result = None
		while self.result == None:
			SGFX.gui.mainLoopSolo()
		return self.result

	def getAttackEvents(self):
		return self.getEvents(attack_good, attack_bad)

	def getDefendEvents(self):
		return self.getEvents(defend_good, defend_bad)

	def getEvents(self, good, bad):
		# events: 0 to 2 good, 0 to 2 bad, shuffle and pick the first 3
		events = []
		events.extend(random.sample(good, random.randrange(0, 3, 1)))
		events.extend(random.sample(bad, random.randrange(0, 3, 1)))
		random.shuffle(events)
		if len(events) < 3:
			return events
		else:
			return events[0:2]

	def ymlShowBattleScreen(self, attacker, region):
		index = SYAML.createWindow("./data/layouts/battle.yml")[0]
		# turn off unit animations
		SGFX.gui.pauseFlashing()
		# setup dirty rect stuff
		SGFX.gui.addDirtyRect(SGFX.gui.windows[index].drawWindow(),
			SGFX.gui.windows[index].rect)
		return True

	def doBattle(self, handle, xpos, ypos):
		"""Do the battle"""
		self.result = True
		SEVENTS.killModalWindow(handle, xpos, ypos)

	def retreatBattle(self, handle, xpos, ypos):
		"""Don't do the battle"""
		self.result = False
		SEVENTS.killModalWindow(handle, xpos, ypos)

def computeBattle(attackers, defenders):
	"""Run a battle, set the results, show the player and finish"""
	attack_strength = 0
	for i in attackers:
		attack_strength += i.getMilitaryStrength()
	defend_strength = 0
	for i in defenders:
		defend_strength += i.getMilitaryStrength()

	logger.debug("A: %d" % attack_strength)
	logger.debug("D: %d" % defend_strength)

	# from the ratio, we can get the chance of success for the attacker
	if random.randrange(attack_strength + defend_strength) <= attack_strength:
		# do fancy maths later
		al, dl = attackWin(attack_strength, defend_strength)
		result = True
	else:
		al, dl = attackLose(attack_strength, defend_strength)
		result = False
	# spread the results
	for i in attackers:
		i.setLoss(int(al / len(attackers)))
	for i in defenders:
		i.setLoss(int(al / len(attackers)))
	return result

def attackWin(defend, attack):
	attack_loss = defend * (random.randrange(60, 80))
	defend_loss = attack * (random.randrange(130, 180))
	message = "You won, at a loss of " + str(attack_loss) + " soldiers."
	SGFX.gui.messagebox(SPQR.BUTTON_OK, message, "Results")
	return attack_loss, defend_loss

def attackLose(defend, attack):
	attack_loss = defend * (random.randrange(130, 180))
	defend_loss = attack * (random.randrange(60, 80))
	message = "You lost, and it cost you " + str(attack_loss) + " soldiers."
	SGFX.gui.messagebox(SPQR.BUTTON_OK, message, "Results")
	return attack_loss, defend_loss


# -*- coding: utf-8 -*-
"""
Created on Thu Oct 29 06:34:32 2020

@author: Vipul
"""

import sys
"""import pandas as pd

inp = pd.read_csv(sys.argv[1],names=["feature_1","feature_2","label"])

op=inp.tail()

op.to_csv(sys.argv[2],index=False)"""

import pandas as pd
import csv

#inp = pd.read_csv("input1.csv",names=["feature_1","feature_2","label"])
inp = pd.read_csv(sys.argv[1],names=["feature_1","feature_2","label"])
#weights=[1,0.1,0.1]

weights=[0,0,0]

#weights=[59,-6,-12]

inp_lst=inp.values.tolist()

#act0=[weights[0]+weights[1]*inp_lst[i][0]+weights[2]*inp_lst[i][1] for i in range(len(inp_lst))]
#activation=[1 if (weights[0]+weights[1]*inp_lst[i][0]+weights[2]*inp_lst[i][1]) >0  else -1 for i in range(len(inp_lst))]

def predict(wt,row):
    if (wt[0]+wt[1]*row[0]+wt[2]*row[1]) >0:
        return 1
    else:
        return -1

#pred0=[predict(weights,rw) for rw in inp_lst]
weight_order=[]
def pla(lr):
    itr=0

    while True:
        itr+=1
        sq_err=0
        labels=[]
        accuracy=0
        weights_bkp=list(weights)

        for rw in inp_lst:
            pred=predict(weights,rw)
            labels.append(pred)
            if rw[-1]==pred:
                accuracy+=1
            error= rw[-1]-pred
            #error= pred-rw[-1]
            #sq_err+=error**2
            sq_err+=error
            """weights[0]=weights[0]+sq_err*lr
            weights[1]=weights[1]+sq_err*lr*rw[0]
            weights[2]=weights[2]+sq_err*lr*rw[1]"""

            """weights[0]=weights[0]+error
            weights[1]=weights[1]+error*rw[0]
            weights[2]=weights[2]+error*rw[1]"""

            """weights[0]=weights[0]+error*lr
            weights[1]=weights[1]+error*lr*rw[0]
            weights[2]=weights[2]+error*lr*rw[1]"""
            if error !=0:
                weights[0]=weights[0]+rw[-1]
                weights[1]=weights[1]+rw[-1]*rw[0]
                weights[2]=weights[2]+rw[-1]*rw[1]

        #print("Weight: ")
        """print(itr)
        print(accuracy)
        print(weights)
        print(labels)"""
        weight_order.append([weights[1],weights[2],weights[0]])

        with open(sys.argv[2], 'a', newline='') as csvfile:
            fieldnames = ['w1', 'w2', 'w0']
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            writer.writerow({'w1': weights[1], 'w2': weights[2], 'w0': weights[0]})
        if weights_bkp==weights:
            csvfile.close()
            break
            #pass

#pla(30,.02)
#pla(.01)
pla(1)
df_out=pd.DataFrame(weight_order)
#df_out.to_csv("output1.csv",index=False, header=False)
#df_out.to_csv(sys.argv[2],index=False, header=False)


import logging

from pytest import raises

from game import Game, human, computer, Minimax, Move, InvalidMoveException, MoveCompleted, noone, Choice

LOGGER = logging.getLogger(__name__)

def test_blank_board():
    b = Game()
    assert ''.join(b.board) == '_________'

def test_outside_of_range_move():
    b = Game()
    m = Move(computer, 10)
    with raises(InvalidMoveException):
        b.move(m)

def test_below_of_range_move():
    b = Game()
    m = Move(computer, -1)
    with raises(InvalidMoveException):
        b.move(m)

def test_override_move_not_allowed():
    b = Game()
    m = Move(computer, 5)
    b.move(m)
    with raises(InvalidMoveException):
        b.move(m)

def test_valid_move():
    b = Game()
    m = Move(computer, 5)
    assert b.move(m) == MoveCompleted(noone, m)

def test_Minimax_next_move():
    b = Game()
    m = Minimax(b, human)
    validMoves = set(map(lambda x: ''.join(x.game.board), m.next_moves(b, computer)))
    expectedMoves = {"X________", "_X_______", "__X______", "___X_____", "____X____", "_____X___", "______X__",
                     "_______X_", "________X"}
    assert expectedMoves == validMoves

def test_Game_determine_winner_comp():
    computer_winner = [
        list("XXX______"), list("___XXX___"), list("______XXX"),
        list("X__X__X__"), list("_X__X__X_"), list("__X__X__X"),
        list("X___X___X"), list("__X_X_X__")
    ]

    for case in computer_winner:
        game = Game(case)
        assert game.determine_winner() == computer

def test_Game_determine_winner_hum():
    human_winner = [
        list("OOO______"), list("___OOO___"), list("______OOO"),
        list("O__O__O__"), list("_O__O__O_"), list("__O__O__O"),
        list("O___O___O"), list("__O_O_O__")
    ]

    for case in human_winner:
        game = Game(case)
        assert game.determine_winner() == human

def test_Game_determine_winner_none():
    noone_winner = [
        list("OXO______"), list("___OXO___"), list("______XOO"),
        list("O__X__O__"), list("_O__O__X_"), list("__O__X__O"),
        list("X___O___O"), list("__O_O_X__")
    ]

    for case in noone_winner:
        game = Game(case)
        assert game.determine_winner() == noone

def test_Minimax_game_almost_complete():
    game = Game(list("OX_"
                     "OXO"
                     "XOX"))
    print("initial game = ", game)
    minimax = Minimax(game, computer)
    choice = minimax.get_best_choice()
    print(choice)
    assert choice.move == MoveCompleted(computer, Move(computer, 2))

def test_Choice_ordering():
    computer_choice = Choice(MoveCompleted(computer, Move(computer, 5)), Game())
    human_choice = Choice(MoveCompleted(human, Move(human, 5)), Game())
    noone_choice = Choice(MoveCompleted(noone, Move(computer, 5)), Game())
    choices = [computer_choice, human_choice, noone_choice]

    assert max(choices) == computer_choice
    assert min(choices) == human_choice

def test_Minimax_game_incomplete():
    """
        This case should be complete in one step by the machine
    """
    game = Game(list("_O_"
                     "OX_"
                     "XOX"))
    # computer
    minimax = Minimax(game, computer)
    choice = minimax.get_best_choice()
    game.move(choice.move.move_initiated)
    # human
    h_move = game.get_available_slots()[0]
    game.move(Move(human, h_move))

    assert game.is_done()
    assert game.determine_winner() == computer

def test_Minimax_game_from_zero_human_starts():
    game = Game(list("_________"))

    player = computer
    while not game.is_done():
        if player == computer:
            minimax = Minimax(game, computer)
            choice = minimax.get_best_choice()
            game.move(choice.move.move_initiated)
            player = human
        else:
            slots = game.get_available_slots()
            if not slots: break
            h_move = slots[0]
            game.move(Move(human, h_move))
            player = computer

        LOGGER.info(game)

    assert game.is_done()
    assert game.determine_winner() == computer

def test_Minimax_game_from_zero_smart_human():
    game = Game(list("_________"))
    human_moves = [6, 2]
    player = human
    while human_moves:
        if player == computer:
            minimax = Minimax(game, computer)
            choice = minimax.get_best_choice()
            game.move(choice.move.move_initiated)
            player = human
        else:
            h_move = human_moves.pop()
            game.move(Move(human, h_move))
            player = computer

        LOGGER.info(game)

    assert game.is_done() == False
    assert game.determine_winner() == noone
    assert str(game) == '__O_X_O__'


import lsst.pex.config as pexConfig

__all__ = ["OpticsLoopCorr"]

class OpticsLoopCorr(pexConfig.Config):
    """Configuration of the LSST Optics Loop Corrections.
    """

    tel_optics_ol_slope = pexConfig.Field('Delay factor for Open Loop optics correction '
                                          '(units=seconds/degrees in ALT slew)', float)

    # Table of delay factors for Closed Loop optics correction according to the ALT slew range.
    tel_optics_cl_alt_limit = pexConfig.ListField('Altitude (units=degrees) limits for the delay ranges.',
                                                  float)

    tel_optics_cl_delay = pexConfig.ListField('Time delay (units=seconds) for the corresponding ALT slew '
                                              'range in the Closed Loop optics correction.', float)

    def setDefaults(self):
        """Set defaults for the LSST Optics Loop Corrections.
        """
        self.tel_optics_ol_slope = 1.0 / 3.5
        self.tel_optics_cl_alt_limit = [0.0, 9.0, 90.0]
        self.tel_optics_cl_delay = [0.0, 20.0]

    def set_array(self, conf, param):
        """Set a DDS topic array parameter.

        Parameters
        ----------
        conf : SALPY_scheduler.scheduler_opticsLoopCorrConfigC
            The optics loop corrections configuration instance.
        param : str
            The name of the topic parameter to fill.
        """
        array = getattr(conf, param)
        local_param = getattr(self, param)
        for i, v in enumerate(local_param):
            array[i] = v


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
"""
import random as rd
from collections import Counter

def shuffle(nums):
    n = len(nums)
    for i in range(n):
        idx = rd.randint(i, n - 1)  # 包含左右端点
        nums[i], nums[idx] = nums[idx], nums[i]
    return nums

def weighted_random(nums, weight):
    def binary_search(nums, target):
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = (l + r) // 2
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                l = mid + 1
            else:
                r = mid - 1
        return r

    total_weight = 0
    weights = [0]
    for w in weight:
        total_weight += w
        weights.append(total_weight)
    rdw = rd.random() * total_weight
    idx = binary_search(weights, rdw)
    return nums[idx]

def reservoir_sampling(nums, m):
    res = [0] * m
    for i, value in enumerate(nums):
        # 保存前n个数，保证至少有n个数
        if i < m:
            res[i] = value
        else:
            if rd.randint(1, i + 1) <= m:  # 第i个数被选中概率为 m/i i start from 1!!!
                idx = rd.randint(0, m - 1)
                res[idx] = value
    return res

# 随机返回数组中等于target的索引
def pick(nums, target):
    n = 1
    res = None
    for i, v in enumerate(nums):
        if v == target:
            if rd.randint(1, n) == 1:  # 第i元素被选中的概率为 1/i  m = 1的特殊场景
                res = i
            n += 1
    return res

# 根据生成1, 2随机数的发生器 生成1-5随机发生器
def rand2to5():
    while True:
        value = rd.randint(0, 1) * 2 ** 2 + rd.randint(0, 1) * 2 + rd.randint(0, 1)
        if value < 5:
            return value + 1

# 均匀分布生成正态分布 中心极限定理
def uniform_2_normal():
    n = 100
    total = 0
    for j in range(n):
        total += rd.uniform(0, 1)
    mean = n * 0.5
    rmse = (n * (1 / 12)) ** 0.5
    return (total - mean) / rmse

# 把n个骰子扔在地上，所有骰子朝上一面的点数之和为S
# 输入n，打印出S的所有可能的值出现的概率
def probability(n):
    dic = dict()
    dic[1] = dict()
    for i in range(1, 7):
        dic[1][i] = round(1 / 6, 5)

    def helper(n):
        if n in dic:
            return dic[n]
        dic.setdefault(n, dict())
        for i in range(1, 7):
            last_dic = helper(n - 1)
            for v, p in last_dic.items():
                dic[n].setdefault(i + v, 0)
                dic[n][i + v] += round(1 / 6 * p, 5)
        return dic[n]

    return helper(n)

if __name__ == '__main__':
    print('\nshuffle')
    data = [rd.randint(0, 100) for _ in range(10)]
    print(shuffle(data))

    print('\n蓄水池')
    data = list(range(100))
    print(reservoir_sampling(data, m=10))

    print('\n加权抽样')
    res = []
    for i in range(30):
        res.append(weighted_random(list(range(3)), [2, 2, 4]))
    print(Counter(res))

    print('\nrand2构造rand5')
    res = []
    for i in range(500):
        res.append(rand2to5())
    print(Counter(res))

    print('\n均匀分布生成正太分布')
    res = []
    n = 10000
    for i in range(n):
        res.append(uniform_2_normal())
    mean = sum(res) / n
    mse = sum([(mean - i) ** 2 for i in res]) / n
    print('mean:%f, mse:%f' % (mean, mse))

    print('\nn个色子的和的概率')
    print(probability(2))


def calc_area(height, width):
    """Function to calculate the area of the rectangle"""
    print(f"The height is {height}")
    print(f"The width is {width}")

    area = height * width
    area = round(area, 2)

    return area

# specify the height and width
h = 78
w = 8.765

area = calc_area(h, w)
print(f"The area of the rectangle is {area} cm2")


from torch import nn
import torch
import torch.nn.functional as F

CHANNEL = 21

class BasicConv2d(nn.Module):
    def __init__(self, input_dim, output_dim, kernel_size, bn):
        super().__init__()
        self.conv = nn.Conv2d(
            input_dim, output_dim,
            kernel_size=kernel_size,
            padding=(kernel_size[0] // 2, kernel_size[1] // 2)
        )
        self.bn = nn.BatchNorm2d(output_dim) if bn else None

    def forward(self, x):
        h = self.conv(x)
        h = self.bn(h) if self.bn is not None else h
        return h

class LuxNet(nn.Module):
    def __init__(self):
        super().__init__()
        layers, filters = 12, 32
        self.conv0 = BasicConv2d(CHANNEL, filters, (3, 3), True)
        self.blocks = nn.ModuleList([BasicConv2d(filters, filters, (3, 3), True) for _ in range(layers)])
        self.head_p = nn.Linear(filters, 5, bias=False)

    def forward(self, x):
        h = F.relu_(self.conv0(x))
        for block in self.blocks:
            h = F.relu_(h + block(h)) # skip path
        # x[:,:1] is the mask, positions of target unit
        h_head = (h * x[:,:1]).view(h.size(0), h.size(1), -1).sum(-1)
        p = self.head_p(h_head)
        return p

class BasicConvBlock(nn.Module):
    def __init__(self, in_channel, out_channel, kernel_size, stride, padding):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_channel, out_channel, kernel_size=kernel_size, stride=stride, padding=padding),
            nn.ReLU(),
            nn.Conv2d(out_channel, out_channel, kernel_size=kernel_size, stride=1, padding=padding)
        )
        #self.bn = nn.BatchNorm2d(out_channel) if bn else None

    def forward(self, x):
        return self.conv(x)

class BasicDeconvBlock(nn.Module):
    def __init__(self, in_channel, out_channel, kernel_size, stride, padding):
        super().__init__()
        self.deconv = nn.Sequential(
            nn.ConvTranspose2d(in_channel, out_channel, kernel_size, stride, padding=padding, output_padding=1),
            nn.ReLU(),
            nn.Conv2d(out_channel, out_channel, kernel_size=kernel_size, stride=1, padding=1)
        )

    def forward(self, x):
        return self.deconv(x)

def make_layers(in_shape, layers):
    skips = []
    convs = []
    c, w, _ = in_shape
    for layer in layers:
        in_channel, out_channel, kernel, stride, padding = layer

        w, old_w = (w - kernel + 2*padding) // stride + 1, w
        c, old_c = out_channel, c

        if in_channel > out_channel:
            skips.append(nn.ConvTranspose2d(in_channel,out_channel,1,2,padding=0,output_padding=1,bias=False))
        elif in_channel == out_channel and w == old_w:
            skips.append(nn.Identity())
        else:
            skips.append(nn.Conv2d(in_channel, out_channel, kernel_size=1, stride=stride))

        convs.append(BasicConvBlock(in_channel, out_channel, kernel, stride, padding) if in_channel <= out_channel \
            else BasicDeconvBlock(in_channel, out_channel, kernel, stride, padding))

    return nn.ModuleList(skips), nn.ModuleList(convs), c*w*w

opt = {
    0: {'conv_layers': [[CHANNEL,64,3,1,1]] + [[64,64,3,1,1] for _ in range(4)],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.ReLU()
    },
    1: {'conv_layers': [[CHANNEL,64,3,1,1]] + [[64,64,3,1,1] for _ in range(5)],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    2: {'conv_layers': [[CHANNEL,64,3,1,1]] + [[64,64,3,1,1] for _ in range(6)],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.ReLU()
    },
    3: {'conv_layers': [[CHANNEL,64,3,1,1],[64,64,3,1,1],[64,128,3,1,1],\
        [128,128,3,1,1],[128,256,3,1,1],[256,256,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    }, # best
    4: {'conv_layers': [[CHANNEL,64,3,1,1],[64,64,3,1,1],[64,128,3,1,1],\
        [128,128,3,1,1],[128,256,3,1,1],[256,256,3,1,1],[256,512,3,1,1],[512,512,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    5: {'conv_layers': [[CHANNEL,32,3,1,1],[32,64,3,1,1],[64,128,3,1,1],\
        [128,256,3,1,1],[256,512,3,1,1],[512,1024,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    6: {'conv_layers': [[CHANNEL,64,3,1,1],[64,128,3,1,1],[128,256,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    7: {'conv_layers': [[CHANNEL,32,3,1,1],[32,64,3,1,1],[64,128,3,1,1],[128,256,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    8: {'conv_layers': [[CHANNEL,64,3,1,1],[64,64,3,1,1],[64,128,3,1,1],[128,256,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    9: {'conv_layers': [[CHANNEL,64,3,1,1],[64,128,3,1,1],[128,128,3,1,1],[128,256,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    10: {'conv_layers': [[CHANNEL,64,3,1,1],[64,128,3,1,1],[128,256,3,1,1],[256,256,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    },
    11: {'conv_layers': [[CHANNEL,64,3,1,1],[64,64,3,1,1],[64,128,3,1,1],[128,128,3,1,1]],
        'conv_1': nn.Conv2d(64,128,3,2,1),
        'avg_pool': nn.AvgPool2d(kernel_size=3,stride=2,padding=1),
        'dem': 8,
        'nonlinearity': nn.LeakyReLU()
    }

}

class Autoencoder(nn.Module):
    def __init__(self, input_shape=(CHANNEL,24,24), hidden_shape=512, num_action=5, option=0):
        super().__init__()
        self.in_channel, self.in_w, self.in_h = input_shape
        self.conv_layers = opt[option]['conv_layers']
        self.hidden_shape = opt[option]['conv_layers'][-1][1]
        self.conv_skips, self.conv_blocks, self.in_feature = make_layers(input_shape, self.conv_layers)
        #self.conv0 = nn.Conv2d(self.in_channel,64,3,1,1)
        #self.conv1 = opt[option]['conv_1']
        #self.avg_pool = opt[option]['avg_pool']
        #self.linear1 = nn.Linear(self.in_feature//opt[option]['dem'], hidden_shape)
        #self.linear2 = nn.Linear(hidden_shape, self.in_feature)
        self.dropout1 = nn.Dropout(p=0.5)
        #self.dropout2 = nn.Dropout(p=0.3)
        self.linear_head = nn.Linear(self.hidden_shape, num_action)
        #self.flatten = nn.Flatten()
        self.relu = opt[option]['nonlinearity']

    def encode(self, input):
        #x, distance_m, map_m = input[:,:22], input[:,22], input[:,21]
        #distance_m = distance_m.unsqueeze(1)
        #map_m = map_m.unsqueeze(1)
        #x = self.relu(self.conv0(x))
        x = input
        for i in range(len(self.conv_layers)):
            x = self.relu(self.conv_skips[i](x) + self.conv_blocks[i](x))

        x = (x * input[:,:1]).view(x.size(0), x.size(1), -1).sum(-1)
        #x = x * distance_m * map_m
        #x = self.relu(self.conv1(x))
        #x = self.avg_pool(x)
        #x = self.flatten(x)
        #x = self.dropout2(x)
        #x = self.linear1(x)
        return x

    #def decode(self, x):
    #    x = self.relu(x)
    #    x = self.relu(self.linear2(x))
    #    x = x.view(x.size(0),512,2,2)
    #    for i in range(len(self.deconv_layers)-1):
    #        x = self.relu(self.deconv_skips[i](x) + self.deconv_blocks[i](x))
    #    x = self.deconv_skips[-1](x) + self.deconv_blocks[-1](x)
    #    return x

    def forward(self,input):
        #x = self.relu(self.encode(input))
        x = self.encode(input)
        x = self.dropout1(x)
        x = self.linear_head(x)
        return x

def init_weights(net, init_type='normal', gain=0.02):
    def init_func(m):
        classname = m.__class__.__name__
        if hasattr(m, 'weight') and (classname.find('Conv') != -1 or classname.find('Linear') != -1):
            if init_type == 'normal':
                init.normal_(m.weight.data, 0.0, gain)
            elif init_type == 'xavier':
                init.xavier_normal_(m.weight.data, gain=gain)
            elif init_type == 'kaiming':
                init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
            elif init_type == 'orthogonal':
                init.orthogonal_(m.weight.data, gain=gain)
            else:
                raise NotImplementedError('initialization method [%s] is not implemented' % init_type)
            if hasattr(m, 'bias') and m.bias is not None:
                init.constant_(m.bias.data, 0.0)
        elif classname.find('BatchNorm2d') != -1:
            init.normal_(m.weight.data, 1.0, gain)
            init.constant_(m.bias.data, 0.0)

    print('initialize network with %s' % init_type)
    net.apply(init_func)

class conv_block(nn.Module):
    def __init__(self,ch_in,ch_out):
        super(conv_block,self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(ch_in, ch_out, kernel_size=3,stride=1,padding=1,bias=True),
            nn.BatchNorm2d(ch_out),
            nn.ReLU(inplace=True),
            nn.Conv2d(ch_out, ch_out, kernel_size=3,stride=1,padding=1,bias=True),
            nn.BatchNorm2d(ch_out),
            nn.ReLU(inplace=True)
        )

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

class up_conv(nn.Module):
    def __init__(self,ch_in,ch_out):
        super(up_conv,self).__init__()
        self.up = nn.Sequential(
            nn.Upsample(scale_factor=2),
            nn.Conv2d(ch_in,ch_out,kernel_size=3,stride=1,padding=1,bias=True),
		    nn.BatchNorm2d(ch_out),
			nn.ReLU(inplace=True)
        )

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

class U_Net(nn.Module):
    def __init__(self,img_ch=CHANNEL, num_action=5, dim=64, map_size=12):
        super(U_Net,self).__init__()

        self.map_size = map_size

        self.Maxpool = nn.MaxPool2d(kernel_size=2,stride=2)

        self.Conv1 = conv_block(ch_in=img_ch,ch_out=dim)
        self.Conv2 = conv_block(ch_in=dim,ch_out=dim*2)
        self.Conv3 = conv_block(ch_in=dim*2,ch_out=dim*4)

        if map_size >=24:
            self.Conv4 = conv_block(ch_in=dim*4,ch_out=dim*4)
        # self.Conv5 = conv_block(ch_in=512,ch_out=1024)

        # self.Up5 = up_conv(ch_in=1024,ch_out=512)
        # self.Up_conv5 = conv_block(ch_in=1024, ch_out=512)

            self.Up4 = up_conv(ch_in=dim*4,ch_out=dim*4)
            self.Up_conv4 = conv_block(ch_in=dim*8, ch_out=dim*4)

        self.Up3 = up_conv(ch_in=dim*4,ch_out=dim*2)
        self.Up_conv3 = conv_block(ch_in=dim*4, ch_out=dim*2)

        self.Up2 = up_conv(ch_in=dim*2,ch_out=dim)
        self.Up_conv2 = conv_block(ch_in=dim*2, ch_out=dim)

        # self.Conv_1x1 = nn.Conv2d(64,output_ch,kernel_size=1,stride=1,padding=0)

        self.linear_head = nn.Sequential(
                                    nn.Dropout(0.5),
                                    nn.Linear(dim, dim),
                                    nn.BatchNorm1d(dim),
                                    nn.ReLU(),
                                    nn.Dropout(p=0.5),
                                    nn.Linear(dim, num_action)
                                    )
    def encode(self, x):
        # encoding path
        x1 = self.Conv1(x)

        x2 = self.Maxpool(x1)
        x2 = self.Conv2(x2)

        x3 = self.Maxpool(x2)
        x3 = self.Conv3(x3)

        # x5 = self.Maxpool(x4)
        # x5 = self.Conv5(x5)

        # decoding + concat path
        # d5 = self.Up5(x5)
        # d5 = torch.cat((x4,d5),dim=1)

        # d5 = self.Up_conv5(d5)

        if self.map_size >= 24:
            x4 = self.Maxpool(x3)
            x4 = self.Conv4(x4)
            d4 = self.Up4(x4)
            d4 = torch.cat((x3,d4),dim=1)
            x3 = self.Up_conv4(d4)

        d3 = self.Up3(x3)
        d3 = torch.cat((x2,d3),dim=1)
        d3 = self.Up_conv3(d3)

        d2 = self.Up2(d3)
        d2 = torch.cat((x1,d2),dim=1)
        d2 = self.Up_conv2(d2)

        d2 = (d2 * x[:,:1]).view(d2.size(0), d2.size(1), -1).sum(-1)
        return d2

    def forward(self,x):

        d2 = self.encode(x)
        d2 = self.linear_head(d2)

        # d1 = self.Conv_1x1(d2)

        return d2


"""
Программа: Предобработка числовых и категориальных данных
Версия: 1.0
"""

import pickle
import warnings

import pandas as pd
from sklearn.preprocessing import LabelEncoder
import yaml
import json

warnings.filterwarnings("ignore")

def columns_omissions(data: pd.DataFrame, file_name: str, num_passes: float = 0.5) -> None:
    """
    Сохранение списка названия столбцов с большим количеством пропусков.
    Если относительное количеством пропусков превышает значение
    num_passes, то столбец попадает в список на удаление.

    :param data: датасет
    :param file_name: путь до файла для сохранения названия удаляемых столбцов
    :param num_passes: значение относительного кол-ва пропусков
    :return: None
    """

    many_passes_col = ['D_66']
    for i, j in zip(data.columns.to_list(), data.isnull().mean()):
        if j >= num_passes:
            many_passes_col.append(i)
    # Запись удаляемых столбцов в файл
    with open(file_name, 'w') as f:
        f.write(' '.join(many_passes_col))

def lable_coding(data: pd.DataFrame, categr_columns: list, path_name: str) -> None:
    """
    Обучение и сохранение кодировщиков для категориальных данных.

    :param data: датасет
    :param categr_columns: список названий категориальных столбцов
    :param path_name: путь до папки для сохранения кодировщиков
    :return: None
    """

    for categ in categr_columns:
        enc = LabelEncoder().fit(data[categ])
        with open(f'{path_name}/{categ}.pkl', 'wb') as f:
            pickle.dump(enc, f)

def lable_encoding(categ: str, path_name: str) -> LabelEncoder:
    """
    Возвращает обученный кодировщик для принятого названия категориального столбца.

    :param categ: название категориального столбца
    :param path_name: путь до папки с обученными кодировщиками
    :return: обученный кодировщик
    """

    with open(f'{path_name}/{categ}.pkl', 'rb') as f:
        enc = pickle.load(f)
    return enc

class PreprocessData:
    """
    Создание новых признаков для категориальных и числовых колонок. Для
    категориальных признаков: 'count', 'last', 'nunique'. Для числовых
    признаков: 'mean', 'std', 'min', 'max', 'last', 'quantile25', 'quantile50',
    'quantile75', '_diff'.
    """

    def __init__(self, categorical_col: list, numeric_col: list, encod_path_name: str):
        """
        :param categorical_col: список категориальных столбцов
        :param numeric_col: список числовых столбцов
        :param encod_path_name: путь до папки с обученными кодировщиками
        """
        self.categorical_col = categorical_col
        self.numeric_col = numeric_col
        self.encod_path_name = encod_path_name

    def __call__(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        Объединение признаков.

        :param data: датасет
        :return: датасет с новыми признаками
        """

        result = pd.concat(
            [self.preproc_cat(data), self.preproc_num(data), self.diff_data(data)],
            axis=1)
        result.columns = [
            f'{i[0]}_{i[1]}' if len(i) == 2 else i for i in result.columns
        ]
        return result

    def preproc_cat(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        Обработка категориальных данных.
        :param data: датасет
        :return: датасет с новыми признаками
        """

        # Применение трансформирования LabelEncoder к категориальным данным
        data[self.categorical_col] = data[self.categorical_col].apply(
            lambda col: lable_encoding(col.name, self.encod_path_name).transform(col))

        # Признаки для категориальных свойств
        data_cat = data.groupby("customer_ID")[self.categorical_col].agg(
            ['count', 'last', 'nunique']).astype('category')
        return data_cat

    def preproc_num(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        Признаки для числовых свойств.
        :param data: датасет
        :return: датасет с новыми признаками
        """

        digt_group = data.groupby("customer_ID")[self.numeric_col]
        data_num_1 = digt_group.agg(['mean', 'std', 'min', 'max', 'last']) \
            .astype('float16')
        data_num_2 = digt_group.quantile([.25, .5, 0.75]).unstack() \
            .astype('float16')
        return pd.concat([data_num_1, data_num_2], axis=1)

    def diff_data(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        Вычисление относительной разницы между последней и предпоследней
        датой для каждого признака.
        :param data: датасет
        :return: датасет с новыми признаками
        """
        digt_group = data.groupby("customer_ID")[self.numeric_col]
        data_num = digt_group.diff(1) / digt_group.shift(periods=1)
        data_num = data_num.add_suffix('_diff').astype('float16')
        data_num = pd.concat([data['customer_ID'], data_num], axis=1)
        data_num = data_num.groupby(['customer_ID']).last().astype('float16')
        return data_num

def feature_selection_corr(data: pd.DataFrame, path_name: str, corr_value: float = 0.9) -> None:
    """
    Сохранение названия столбцов в path_name со значением корреляции
    выше установленного в параметре corr_value.

    :param data: датасет
    :param path_name: путь до папки с обученными кодировщиками
    :param corr_value: значение корреляции выше которого признаки удаляются
    :return: None
    """

    deleted_colm = []
    left_colm = []

    corr_df = data.corr()
    for col in corr_df.columns:
        corr_list = corr_df[
            (corr_df[col].abs() > corr_value) & (corr_df[col].abs() != 1.0)
            ][col].index.to_list()
        if col not in deleted_colm:
            left_colm.append(col)
        deleted_colm.extend(corr_list)

    result = left_colm + data.select_dtypes('category').columns.to_list()
    with open(path_name, 'w') as f:
        f.write(' '.join(result))

def drop_columns(data: pd.DataFrame, file_name: str) -> pd.DataFrame:
    """
    Возвращает новый датасет с удаленными столбцами, названия
    которых сохраненны в file_name.

    :param data: датасет
    :param file_name: путь до файла
    :return: датасет с удаленными столбцами
    """

    with open(file_name, 'r') as f:
        drop_cols = f.read().split()
    return data.drop(columns=drop_cols)

def replacing_missing_values(data: pd.DataFrame,
                             change_to: float = -1000.) -> pd.DataFrame:
    """
    Замена пропущенных данных в числовых признаках.

    :param data: датасет
    :param change_to: значение, на которое заменяется пропущенные значения
    :return: датасет без пропущенными данными
    """

    float_data = data.select_dtypes('float16').columns.to_list()
    not_float = [i for i in data.columns.to_list() if i not in float_data]
    return pd.concat([
        data[not_float], data[float_data].fillna(change_to).astype('float16')
    ],
        axis=1)

def processing_target(data: pd.DataFrame, target_col: str) -> pd.Series:
    """
    Получение целевой переменной из датасета и присваивание каждому клиенту целевой переменной.

    :param data: датасет
    :param target_col: целевая переменная
    :return: датасет
    """

    return data.groupby('customer_ID')[target_col].last()

def pipeline_preprocess(data: pd.DataFrame, flg_evaluate: bool = True, **kwargs) -> pd.DataFrame:
    """
    Пайплайн по предобработке данных

    :param data: датасет
    :param flg_evaluate: флаг для evaluate
    :return: предобработанный датасет
    """

    data.sort_values(by=['customer_ID', 'S_2'], inplace=True)
    target_data = None
    if kwargs["target_column"] in data.columns:
        target_data = processing_target(data, kwargs["target_column"])
        data.drop(columns=kwargs["target_column"], inplace=True)

    # Получения столбцов с большим кол-ом пропусков
    if not flg_evaluate:
        columns_omissions(data, kwargs["drop_columns"])

    # Новый датафрейм с удаленными столбцали с большим кол-ом пропусков
    data = drop_columns(data, kwargs["drop_columns"])

    # Категориальные и цифровые колонки датасета
    cat_col = data.select_dtypes(include=['category']).columns.to_list()
    dig_col = [i for i in data.columns if i not in cat_col + ['S_2', 'customer_ID']]

    if not flg_evaluate:
        # Кодирование категориальных данных
        lable_coding(data, cat_col, kwargs["lable_encod_dir"])

    # Датасет с новыми признаками
    data = PreprocessData(cat_col, dig_col, kwargs["lable_encod_dir"])(data)

    if not flg_evaluate:
        # Сохранение списка столбцов с высокой корреляцией
        feature_selection_corr(data, kwargs["new_columns"])

    # Новый датафрейм с отобранными столбцами
    with open(kwargs["new_columns"], 'r') as f:
        new_colum = f.read().split()
    data = data[new_colum]

    # Замена пропущеных числовых значений
    data = replacing_missing_values(data)

    if target_data is not None:
        # Соединение датасета с целевым значением
        data = pd.concat([data, target_data], axis=1)

    return data

def make_dataframe(colum: list, features: list, config_path: str) -> pd.DataFrame:
    """
    Возвращает датасет полученный из переданных признаков, в датасете установлены категориальные и
    числовые колонки.

    :param colum: название колонок датасета
    :param features: признаки для датасета
    :param config_path: путь к конфигурационному файлу
    :return: предобработанный датасет
    """

    data = pd.DataFrame(data={col: feat for col, feat in zip(colum, features)}, index=[0])

    with open(config_path) as file:
        config = yaml.load(file, Loader=yaml.FullLoader)

    cat_col = config["preprocessing"]['categorical_input_data']
    dig_col = [i for i in data.columns if i not in cat_col + ['S_2', 'customer_ID']]

    data[cat_col] = data[cat_col].astype('category')
    data[dig_col] = data[dig_col].astype('float16')

    return data

def unique_features(data: pd.DataFrame, config_path: str) -> None:
    """
    Получение уникальных данных для категориальных столбцов, и максимольное и
    минимальное значение по числовым столбцам. Полученные данные сохраняются
    в json файле.

    :param data: датасет
    :param config_path: путь к конфигурационному файлу
    :return: None
    """

    result_cat = {i: data[i].unique().to_list() for i in
                  data.select_dtypes('category')}
    result_num = data.select_dtypes('float16').agg(['min', 'max']) \
        .to_dict('list')

    unique_data = {'categorical': result_cat, 'numeric': result_num}

    with open(config_path['unique_values_path'], 'w') as file:
        json.dump(unique_data, file)


class Solution:
    def kidsWithCandies(self, candies: List[int], extraCandies: int) -> List[bool]:
        result = []
        globalMax = max(candies)

        for i in range(len(candies)):
            if (candies[i]+extraCandies) >= globalMax:
                result.append(True)
            else:
                result.append(False)

        return result

Kids With the Greatest Number of Candies.py


def solution1(nums):
    tmp=[0,0,0]
    idx=0
    for i in nums:
        tmp[i]+=1
    for i in range(len(tmp)):
        for j in range(tmp[i]):
            nums[idx]=i
            idx+=1
    print(nums)


import sys
import os
from cx_Freeze import setup, Executable

# TARGET
target = Executable(
    script="main.py",
    base="Win32GUI",
    icon="icon.ico"
)

# SETUP CX FREEZE
setup(
    name="Right Posture",
    version="1.0",
    description="Right Posture",
    author="Yuul B. Alwright",
    executables=[target]
)

options = {
    'build_exe': {
        'build_exe': './/build'
    }
}
# Type python setup.py build to build.exe