# -*- coding: utf-8 -*-

# Roger - Facial detection
# Joseph - Canny
# Lyndon - Canny line -> smoothing/thickness modifier along lines
# Sabrina - Textures
# Kelsey - Quantizing RGB/HSV

"""CS4476Prj.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1WGs55cY6plbmUJFE-gipBV8MQNJsHIBL

CS  4476: Fall 2020

Final Project

Sabrina Chua, Kelsey Henson, Joseph Lee, Roger Nhan, Lyndon Puzon

"""

#export
from matplotlib import use
import numpy as np

np.set_printoptions(threshold=np.inf)
from sklearn.cluster import KMeans
from skimage.color import rgb2hsv, hsv2rgb, rgb2gray, rgba2rgb
from skimage import feature, color, draw
from imageio import imread, imsave
from scipy import ndimage
from typing import Tuple, overload
from PIL import Image
from edgeDetection import edgeDetection, edgeDetailDetection
from matplotlib import pyplot as plt
from texture import median_filter, FillColors
from binary_skin import binary_skin_erosion_dilation

#export
def quantize_hsv(img: np.ndarray, k: int):
    """
    Compute the k-means clusters for the input image in the hue dimension of the
    HSV space. Replace the hue values with the nearest cluster's hue value. Finally,
    convert the image back to RGB.

    Inputs:
        img: Input RGB image with shape H x W x 3 and dtype "uint8"
        k: The number of clusters to use

    Output:
        An RGB image with shape H x W x 3 and dtype "uint8"
    """
    quantized_img = np.zeros_like(img)

    ##########################################################################
    # TODO: Convert the image to HSV. Perform k-means clustering in hue      #
    # space. Replace the hue values in the image with the cluster centers.   #
    # Convert the image back to RGB.                                         #
    ##########################################################################

    #Converting image to HSV and retrieving H channels
    image = rgb2hsv(img)
    h,w,_ = image.shape
    hue = image[:,:,0]
    hue = hue.reshape(h*w,1)

    clusters = KMeans(n_clusters=k, random_state=101)
    kmeans = clusters.fit(hue)
    labels = kmeans.predict(hue)

    colors = np.array(kmeans.cluster_centers_)

    for row in range(0,len(hue)):
        hue[row] = colors[labels[row]]

    hue = hue.reshape(image[:,:,0].shape)

    quantized_img = np.copy(image)
    quantized_img[:,:,0] = hue

    quantized_img = hsv2rgb(quantized_img)
    quantized_img = quantized_img * 255
    quantized_img = quantized_img.astype(np.uint8)

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

    return quantized_img

# Quantize RGB
#export
def quantize_rgb(img: np.ndarray, k: int):
    """
    Compute the k-means clusters for the input image in RGB space, and return
    an image where each pixel is replaced by the nearest cluster's average RGB
    value.

    Inputs:
        img: Input RGB image with shape H x W x 3 and dtype "uint8"
        k: The number of clusters to use

    Output:
        An RGB image with shape H x W x 3 and dtype "uint8"
    """
    quantized_img = np.zeros_like(img)

    ##########################################################################
    # TODO: Perform k-means clustering and return an image where each pixel  #
    # is assigned the value of the nearest clusters RGB values.              #
    ##########################################################################

    x, y, z = img.shape
    listImg = img.reshape(x*y, z)

    kmeans = KMeans(n_clusters=k, random_state=101).fit(listImg)

    # centers = kmeans.cluster_centers_.astype(int)
    print(kmeans.cluster_centers_.shape)
    # kmeans.cluster_centers_ = np.vstack((kmeans.cluster_centers_, np.array([[0, 0, 0]])))
    labels = kmeans.predict(listImg)
    print(kmeans.cluster_centers_.shape)
    return kmeans.cluster_centers_.astype(int)[labels].reshape(x, y, z)

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

    return quantized_img

original = imread("../res/images/person2.jpg")

if original.shape[2] == 4:
    original = rgba2rgb(original).astype(np.uint8)

# img_quantize = quantize_rgb(original, k=8)
face_mask = binary_skin_erosion_dilation(original)
original_hsv = rgb2hsv(original)
if np.max(face_mask) != 0:
    skin_avgR = np.average(original_hsv[:,:,0], weights=face_mask)
    skin_avgG = np.average(original_hsv[:,:,1], weights=face_mask)
    skin_avgB = np.average(original_hsv[:,:,2], weights=face_mask)
    hsvArr = np.array([skin_avgR, skin_avgG, skin_avgB])
    rgbArr = (hsv2rgb(hsvArr) * 255).astype(np.uint8)
    print(rgbArr)

# face_mask = np.zeros_like(original[:, :, 0])
img_quantize = median_filter(FillColors(np.copy(original), 15, face_mask).get_img())
# img_quantize = original
img_quantize_face = quantize_rgb(original, k=3)

edges = edgeDetection(img_quantize)
edgesDetail = edgeDetailDetection(original)
edges_face = edgeDetection(img_quantize_face, 2)

overlaid_img = np.copy(img_quantize).astype(np.float32)
if np.max(face_mask) != 0:
    overlaid_img[face_mask == 1] = rgbArr
overlaid_img[np.logical_and(edges, np.logical_not(face_mask))] = 0
overlaid_img[np.logical_and(edgesDetail, np.logical_not(face_mask))] *= 0.5
overlaid_img[np.logical_and(edges_face, face_mask)] *= 0.9
overlaid_img = overlaid_img.astype(np.uint8)
# overlaid_img[edges] = 0

# fig, axs = plt.subplots(2, 3, figsize=(15,15))

# axs[0, 0].imshow(original)
# axs[0, 1].imshow(face_mask, cmap="gray")
# axs[0, 2].imshow(edges, cmap="gray")
# axs[1, 0].imshow(edges_face, cmap="gray")
# axs[1, 1].imshow(overlaid_img)

fig, axs = plt.subplots(1, 2)

axs[0].imshow(original)
axs[1].imshow(overlaid_img)

plt.show()
# Smooth/reinforce lines

# Textures
# img_array = imread('hill.jpg')

# fig = plt.figure()
# axes = plt.axes()

# temp = texture.FillColors(img_array, 15)
# image = temp.get_img()
# fitered = texture.median_filter(img_array)

# axes.imshow(fitered)
# plt.show()

#test2

# Blob detection


from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _

from Nectar.models import  BaseModelNative, BaseModelSVG
from Language.models import Language
from Payment.models import Currency

# Create your models here.

class Country(BaseModelNative, BaseModelSVG):
    ## https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes
    class Continents(models.TextChoices):
        AF= "AF", _("Africa")
        AS= "AS", _("Asia")
        EU= "EU", _("Europe")
        NA= "NA", _("North America")
        OC= "OC", _("Oceania")
        SA= "SA", _("South America")
        AN= "AN", _("Antarctica")

    continent= models.CharField(
        max_length= 2,
        choices= Continents.choices,
        verbose_name= _("Continent Name"),
    )
    capital= models.OneToOneField(
        to="City",
        null= True,
        blank= True,
        on_delete= models.CASCADE,
        related_name= _("Capital To +"),
        verbose_name= _("Capital"),
    )
    flag_emoji= models.CharField(
        max_length= 5,
        null= True,
        blank= True,
        verbose_name= _("Flag Emoji"),
    )
    currency= models.ForeignKey(
        Currency,
        null= True,
        blank= True,
        on_delete= models.CASCADE,
        related_name= _("Countries"),
        verbose_name= _("Currency"),
    )
    language= models.ForeignKey(
        Language,
        null= True,
        blank= True,
        on_delete= models.CASCADE,
        related_name= _("Countries"),
        verbose_name= _("languages"),
    )
    tel_code= models.CharField(
        max_length= 3,
        null= True,
        blank= True,
        verbose_name= _("Telphone Code"),
    )

    class Meta:
        verbose_name= _("Country")
        verbose_name_plural= _("Countries")

        # def get_absolute_url(self):
        #     return reverse("_detail", kwargs={"pk": self.pk})

class Governorate(BaseModelNative):  # المحافظه
    ## https://en.wikipedia.org/wiki/ISO_3166-2:EG
    tel_code= models.CharField(
        max_length= 3,
        blank= True,
        null= True,
        unique= True,
        verbose_name= _("Telephone Code"),
    )
    country= models.ForeignKey(
        Country,
        on_delete= models.CASCADE,
        related_name= _("Governorates"),
        verbose_name= _("Country"),
    )

    class Meta:
        verbose_name= _("Governorate")
        verbose_name_plural= _("Governorates")

class City(BaseModelNative):
    country= models.ForeignKey(
        Country,
        on_delete= models.CASCADE,
        related_name= _("Cities"),
        verbose_name= _("Country"),
    )
    governorate= models.ForeignKey(
        Governorate,
        on_delete= models.CASCADE,
        related_name= _("Cities"),
        verbose_name= _("Governorate"),
    )

    class Meta:
        verbose_name= _("City")
        verbose_name_plural= _("Cities")

class Region(BaseModelNative):
    city= models.ForeignKey(
        City,
        on_delete= models.CASCADE,
        related_name= _("Regions"),
        verbose_name= _("City"),
    )

    class Meta:
        verbose_name= _("Region")
        verbose_name_plural= _("Regions")

class Street(BaseModelNative):
    region= models.ForeignKey(
        Region,
        on_delete=models.CASCADE,
        related_name= _("Streets"),
        verbose_name= _("Region"),
    )

    class Meta:
        verbose_name= _("Street")
        verbose_name_plural= _("Streets")

class Geo(models.Model) :
    lat= models.FloatField(
        verbose_name= _("Lat"),
    )
    lang= models.FloatField(
        verbose_name= _("Lang"),
    )

    class Meta:
        verbose_name= _("Geo")
        verbose_name_plural= _("Geo")

class Address(BaseModelNative):
    street= models.ForeignKey(
        Street,
        null= True,
        blank= True,
        on_delete= models.CASCADE,
        related_name= _("Address"),
        verbose_name= _("Street"),
    )
    geo= models.ForeignKey(
        Geo,
        null= True,
        blank= True,
        on_delete=models.CASCADE,
        related_name= _("Address"),
        verbose_name= _("Location"),
    )

    class Meta:
        verbose_name= _("Address")
        verbose_name_plural= _("Address")

# TODO API FOR COUNTRIES
# https://restcountries.com/#api-endpoints-v3
"""
    {
        "name": {
            "common": "Egypt",
            "official": "Arab Republic of Egypt",
            "nativeName": {
                "ara": {
                    "official": "جمهورية مصر العربية",
                    "common": "مصر"
                }
            }
        },
        "tld": [
            ".eg",
            ".مصر"
        ],
        "cca2": "EG",
        "ccn3": "818",
        "cca3": "EGY",
        "cioc": "EGY",
        "independent": true,
        "status": "officially-assigned",
        "unMember": true,
        "currencies": {
            "EGP": {
                "name": "Egyptian pound",
                "symbol": "£"
            }
        },
        "idd": {
            "root": "+2",
            "suffixes": [
                "0"
            ]
        },
        "capital": [
            "Cairo"
        ],
        "altSpellings": [
            "EG",
            "Arab Republic of Egypt"
        ],
        "region": "Africa",
        "subregion": "Northern Africa",
        "languages": {
            "ara": "Arabic"
        },
        "translations": {
            "ara": {
                "official": "جمهورية مصر العربية",
                "common": "مصر"
            },
            "ces": {
                "official": "Egyptská arabská republika",
                "common": "Egypt"
            },
            "cym": {
                "official": "Gweriniaeth Arabaidd yr Aifft",
                "common": "Yr Aifft"
            },
            "deu": {
                "official": "Arabische Republik Ägypten",
                "common": "Ägypten"
            },
            "est": {
                "official": "Egiptuse Araabia Vabariik",
                "common": "Egiptus"
            },
            "fin": {
                "official": "Egyptin arabitasavalta",
                "common": "Egypti"
            },
            "fra": {
                "official": "République arabe d'Égypte",
                "common": "Égypte"
            },
            "hrv": {
                "official": "Arapska Republika Egipat",
                "common": "Egipat"
            },
            "hun": {
                "official": "Egyiptomi Arab Köztársaság",
                "common": "Egyiptom"
            },
            "ita": {
                "official": "Repubblica araba d'Egitto",
                "common": "Egitto"
            },
            "jpn": {
                "official": "エジプト·アラブ共和国",
                "common": "エジプト"
            },
            "kor": {
                "official": "이집트 아랍 공화국",
                "common": "이집트"
            },
            "nld": {
                "official": "Arabische Republiek Egypte",
                "common": "Egypte"
            },
            "per": {
                "official": "جمهوری عربی مصر",
                "common": "مصر"
            },
            "pol": {
                "official": "Arabska Republika Egiptu",
                "common": "Egipt"
            },
            "por": {
                "official": "República Árabe do Egipto",
                "common": "Egito"
            },
            "rus": {
                "official": "Арабская Республика Египет",
                "common": "Египет"
            },
            "slk": {
                "official": "Egyptská arabská republika",
                "common": "Egypt"
            },
            "spa": {
                "official": "República Árabe de Egipto",
                "common": "Egipto"
            },
            "swe": {
                "official": "Arabrepubliken Egypten",
                "common": "Egypten"
            },
            "urd": {
                "official": "مصری عرب جمہوریہ",
                "common": "مصر"
            },
            "zho": {
                "official": "阿拉伯埃及共和国",
                "common": "埃及"
            }
        },
        "latlng": [
            27,
            30
        ],
        "landlocked": false,
        "borders": [
            "ISR",
            "LBY",
            "PSE",
            "SDN"
        ],
        "area": 1002450,
        "demonyms": {
            "eng": {
                "f": "Egyptian",
                "m": "Egyptian"
            },
            "fra": {
                "f": "Égyptienne",
                "m": "Égyptien"
            }
        },
        "flag": "🇪🇬",
        "maps": {
            "googleMaps": "https://goo.gl/maps/uoDRhXbsqjG6L7VG7",
            "openStreetMaps": "https://www.openstreetmap.org/relation/1473947"
        },
        "population": 102334403,
        "gini": {
            "2017": 31.5
        },
        "fifa": "EGY",
        "car": {
            "signs": [
                "ET"
            ],
            "side": "right"
        },
        "timezones": [
            "UTC+02:00"
        ],
        "continents": [
            "Africa"
        ],
        "flags": {
            "png": "https://flagcdn.com/w320/eg.png",
            "svg": "https://flagcdn.com/eg.svg"
        },
        "coatOfArms": {
            "png": "https://mainfacts.com/media/images/coats_of_arms/eg.png",
            "svg": "https://mainfacts.com/media/images/coats_of_arms/eg.svg"
        },
        "startOfWeek": "sunday",
        "capitalInfo": {
            "latlng": [
                30.05,
                31.25
            ]
        },
        "postalCode": {
            "format": "#####",
            "regex": "^(\\d{5})$"
        }
    }
"""


import numpy as np
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import KFold
import sqlite3
from sqlite3 import Error
import sys
def create_connection(db_file):
    """ create a database connection to the SQLite database
        specified by the db_file
    :param db_file: database file
    :return: Connection object or None
    """
    conn = None
    try:
        conn = sqlite3.connect(db_file)
    except Error as e:
        print(e)

    return conn

def makeDataset(conn):
    """
    Query all odds for every match from Match table an the attributes of the
    teams of the match
    :param conn: the Connection object
    :return:
    """
    cur = conn.cursor()
    cur.execute("SELECT t.home_team_goal ,t.away_team_goal,t1.buildUpPlaySpeed, t1.buildUpPlayPassing, t1.chanceCreationPassing,  t1.chanceCreationCrossing,  t1.chanceCreationShooting,  t1.defencePressure,"+
    "t1.defenceAggression,  t1.defenceTeamWidth, t2.buildUpPlaySpeed, t2.buildUpPlayPassing, t2.chanceCreationPassing,  t2.chanceCreationCrossing,  t2.chanceCreationShooting,  t2.defencePressure,  t2.defenceAggression,"+
    "t2.defenceTeamWidth,t.B365H, t.B365D, t.B365A, t.BWH, t.BWD,  t.BWA, t.IWH, t.IWD,  t.IWA,  t.LBH, t.LBD,  t.LBA  FROM [Match] t INNER JOIN "+
"(SELECT *FROM Team_Attributes ta INNER JOIN (SELECT team_api_id , MAX(date) AS MaxDateTime FROM Team_Attributes GROUP BY team_api_id) groupedtt ON ta.team_api_id = groupedtt.team_api_id AND ta.date = groupedtt.MaxDateTime ) t1 "+
 " ON t1.team_api_id=t.home_team_api_id  INNER JOIN  (SELECT *FROM Team_Attributes ta INNER JOIN (SELECT team_api_id , MAX(date) AS MaxDateTime FROM Team_Attributes GROUP BY team_api_id) groupedtt "+
"ON ta.team_api_id = groupedtt.team_api_id AND ta.date = groupedtt.MaxDateTime ) t2  ON t2.team_api_id=t.away_team_api_id "
"WHERE home_team_goal IS NOT NULL AND away_team_goal IS NOT NULL AND B365H IS NOT NULL AND B365D IS NOT NULL AND B365A IS NOT NULL AND IWH IS NOT NULL AND IWD IS NOT NULL AND IWA "+
"IS NOT NULL AND BWH IS NOT NULL AND BWD IS NOT NULL AND BWA IS NOT NULL AND LBH IS NOT NULL AND LBD IS NOT NULL AND LBA IS NOT NULL  group by t.id ")
    data = cur.fetchall()

    data=np.array(data)
    x=data[:,2:len(data[0])]
    y=data[:,0:2]
    return x,y

def multilayer_perceptron(x,goals):
    x=np.array(x)
    goals=np.array(goals)
    mean_taining_score=0
    mean_success_rate=0
    kfold = KFold(10)
    i=1
    #10-fold cross validation
    for train_index, test_index in kfold.split(x):
        x_train, x_test=x[train_index],x[test_index]
        goals_train, goals_test=goals[train_index],goals[test_index]
        d_train=[]
        #calculate the result from the score for training and testing data
        for goal in goals_train:
            if goal[0]>goal[1]:
                d_train.append('H')
            elif goal[0]<goal[1]:
                d_train.append('A')
            else :
                  d_train.append('D')

        d_test=[]
        for goal in goals_test:
            if goal[0]>goal[1]:
                d_test.append('H')
            elif goal[0]<goal[1]:
                d_test.append('A')
            else :
                d_test.append('D')

        #trasform the desired output to binary vector
        y_dense = LabelBinarizer().fit_transform(d_train)
        y_dense_test = LabelBinarizer().fit_transform(d_test)
        #train mlp
        clf = MLPClassifier(solver='sgd', alpha=1e-5,max_iter=1000,hidden_layer_sizes=(80, 40, 20), random_state=1)
        clf.fit(x_train, y_dense)
        #add the result of training score
        mean_taining_score+=clf.score(x_train, y_dense)
        #test the mlp
        y_predict=clf.predict(x_test)
        #print(y_predict)
        #print(len(x_test)," ",len(y_dense_test))
        print(i,")Successfull predictions rate",clf.score(x_test, y_dense_test))
        mean_success_rate+=clf.score(x_test, y_dense_test)
        i+=1
    mean_taining_score/=10
    mean_success_rate/=10
    mean_success_rate *=100
    print("Mean training score:", mean_taining_score)
    print("Successfull predictions mean rate", mean_success_rate,"% \n")

def main():
    np.set_printoptions(threshold=sys.maxsize)
    database = "database.sqlite"

    # create a database connection
    conn = create_connection(database)
    if conn:
        print(" making Dataset...")
        x,goals=makeDataset(conn)
        print(" training and testing multilayer perceptron...")
        multilayer_perceptron(x,goals)

if __name__ == '__main__':
    main()


#Mac setup,
# First install matplotlib and networkx
# then install graphviz using brew install graphviz
# then install pygraphviz using pip install pygraphviz

import networkx as nx
import matplotlib.pyplot as plt
from math import cos, sin, pi

class mGraph:
    def __init__(self, path=None):
        self.curr_id = 0
        self.g = nx.DiGraph()
        self.path = path
        if path is None:
            self.g.add_node(0, type='start', color='k', text='START')
        else:
            self.load_graph(path)

    def __insert_node(self, from_ids, to_ids):
        from_ids = from_ids if type(from_ids) is list else [from_ids]
        for f_id in from_ids:
            self.g.add_edge(f_id, self.curr_id)
            for t_id in to_ids:
                if t_id in self.g[f_id]:
                        self.g.remove_edge(f_id, t_id)
                        self.g.add_edge(self.curr_id, t_id)

    # manage nodes

    def remove_node(self, id):
        for pre in self.g.predecessors(id):
            for suc in self.g.successors(id):
                self.g.add_edge(pre, suc)
        self.g.remove_node(id)

    def edit_node(self, id, type=None, text=None, color=None, positive=None):
        node = self.g.nodes[id]
        text = node['text'] if text is None else text
        type = node['type'] if type is None else type
        if color is None:
            if type == 'question':
                color = 'b'
            elif type == 'answer':
                color = 'g' if positive else 'r'
            elif type == 'todo':
                color = 'xkcd:pale orange' if positive else 'xkcd:brownish red'
            elif type == 'branch':
                color = 'xkcd:dark grey'
            else:
                print("Type not allowed")
                return
        if 'positive' in node:
            self.g.add_node(id, type=type, color=color, text=text, positive=positive)
        else:
            self.g.add_node(id, type=type, color=color, text=text)

    def add_question(self, from_ids, question, to_ids=[]):
        self.curr_id += 1
        self.g.add_node(self.curr_id, type='question', color='b', text=question)
        self.__insert_node(from_ids, to_ids)

    def add_answer(self, from_ids, answer, positive, to_ids=[]):
        self.curr_id += 1
        self.g.add_node(self.curr_id, type='answer', color='g' if positive else 'r', text=answer, positive=positive)
        self.__insert_node(from_ids, to_ids)

    def add_todo(self, from_ids, todo, finished=False, to_ids=[]):
        self.curr_id += 1
        self.g.add_node(self.curr_id, type='todo', color='xkcd:pale orange' if finished else 'xkcd:brownish red',
                        text=todo, positive=finished)
        self.__insert_node(from_ids, to_ids)

    def add_branch(self, from_ids, title, to_ids=[]):
        self.curr_id += 1
        self.g.add_node(self.curr_id, type='branch', color='xkcd:dark grey', text=title)
        self.__insert_node(from_ids, to_ids)

    def todo_done(self, ids, done=True):
        if type(ids) is not list:
            print('isd must be list, otherwise use edit_node')
            return
        for id in ids:
            self.edit_node(id, positive=done)

    # visualize
    def __print(self, from_id, depth, num_spaces, curr_indent):
        print(' ' * curr_indent * num_spaces, end='')
        self.get_node(from_id)
        if curr_indent < depth - 1:
            for node in self.g.successors(from_id):
                self.__print(node, depth, num_spaces, curr_indent + 1)

    def print(self, from_id=0, depth=10, num_spaces=1):
        self.__print(from_id, depth, num_spaces, 0)

    def get_open_questions(self, only_positive=False):
        for node in self.g.nodes:
            if self.g.nodes[node]['type'] == 'question':
                has_answer = False
                for s in self.g.successors(node):
                    if self.g.nodes[s]['type'] == 'answer':
                        if not only_positive or (only_positive and self.g.nodes[s]['positive']):
                            has_answer = True
                            break
                if not has_answer:
                    print(str(node) + ': ' + self.g.nodes[node]['text'])

    def get_todo(self):
        for nod in self.g.nodes:
            if self.g.nodes[nod]['type'] == 'todo' and not self.g.nodes[nod]['positive']:
                print(str(nod) + ': ' + self.g.nodes[nod]['text'])

    def get_node(self, id):
        node = self.g.nodes[id]
        type_dict = {'start': 'S', 'branch': 'B', 'question': 'Q', 'answer': 'A', 'todo': 'T'}
        prefix = ('Y - ' if node['positive'] else 'N - ') if 'positive' in node else None
        print("{}, nc={}, t={}: {}".format(
            str(id),
            str(len(self.g[id])),
            type_dict[node['type']],
            node['text'] if prefix is None else prefix + node['text']))

    def get_children(self, id):
        for ch in self.g[id]:
            self.get_node(ch)

    def draw_graph(self):
        self.save_graph()
        nod = self.g.nodes
        pos = nx.drawing.nx_agraph.graphviz_layout(self.g, prog='dot')
        plt.clf()

        ang = pi*0.4
        ct = cos(ang)
        st = sin(ang)

        for i in pos:
            p = pos[i]
            temp = (p[0]*ct - p[1]*st, p[0]*st + p[1]*ct)
            pos[i] = temp

        nx.draw_networkx(self.g, node_color=[nod[n]['color'] for n in nod],
                         labels={i: str(i) + ': ' + nod[i]['text'] for i in nod}, alpha=0.5, pos=pos)
        plt.show()
        self.save_graph()

    # manage connections

    def reconnect(self, from_id_start, from_id_goal, to_ids):
        for to_id in to_ids:
            self.g.add_edge(from_id_goal, to_id)
            self.g.remove_edge(from_id_start, to_id)

    def connect(self, from_node, to_node):
        self.g.add_edge(from_node, to_node)

    def disconnect(self, from_node, to_node):
        self.g.remove_edge(from_node, to_node)

    # load - save

    def save_graph(self, path=None):
        path = self.path if path is None else path
        if path is None:
            print('Path not specified')
            return
        else:
            self.path = path
        try:
            nx.write_gexf(self.g, path+'_tmp')
        except:
            print('Save failed, _tmp broken, regular file not broken')
            return

        nx.write_gexf(self.g, path)

    def load_graph(self, path=None):
        path = self.path if path is None else path
        if path is None:
            print('Specify path')
            return
        self.g = nx.read_gexf(path, node_type=int)
        self.curr_id = self.g.number_of_nodes() - 1


from net import AlphaZeroResNet
import torch
import chess
from input_representation import board_to_planes
from output_representation import legal_moves_to_flat_planes
from MCTS_search import MCTS
import numpy as np
import time
import pandas as pd

def get_priors(visits, legal_moves, color):
    '''
    Helper function for getting the priors which are used for training the neural network.

    Arguments:
        visits (np.array): Contains the visit counts for the children correspondig to the legal moves.
        legal_moves (list(chess.MOVE)): A list of all possible legal moves.
        color (Optional[chess.COLOR]): Either chess.WHITE or chess.BLACK.

    Return:
        (np.array): A vetor of with 4096 entries containing the probabilities according to the visit count for all legal moves.
                    See alphazero.output_representation for further explanation on this representation.
    '''
    probs = visits / np.sum(visits)
    return legal_moves_to_flat_planes(legal_moves, probs, color)

def self_play(model, expansions_per_move, device):
    '''
    This plays a game in selfplay move, using the given model and device.

    Arguments:
        model (AlphaZeroResNet): The model with which the neural network evaluation should be peformed.
        expansions_per_move (int): The number of nodes that should be expanded before the MCTS decides on a move to play.
        device (torch.device()): The device on which the neural network evaluation should be performed.

    Returns:
        states (list()): All states that were chosen by the search.
        values (np.array): The values correspondig to the states.
                            Obtained by making a list of the outcome of the game containing the values from the perspective from the player at time step t.
        priors (np.array): The priors correspondig to the states. Entries are obtained by the function get_priors().
        outcome (chess.Outcome): The outcome of the self play game.
        move_count (int): The full move count after which the game ended.
    '''
    priors = list()
    states = list()

    board = chess.Board()
    mcts = MCTS(model, expansions_per_move, device)

    # Initialization run
    chosen_child = mcts.search(board)
    state = board_to_planes(chosen_child.parent.board, chosen_child.parent.last_moves)
    states.append(state)
    priors.append(get_priors(chosen_child.parent.child_visits, chosen_child.parent.legal_moves, chosen_child.parent.color))

    for i in range(239):
        if chosen_child.board.is_game_over():
            break
        chosen_child = mcts.search(use_exisitng_node=chosen_child)
        state = board_to_planes(chosen_child.parent.board, chosen_child.parent.last_moves)
        states.append(state)
        priors.append(get_priors(chosen_child.parent.child_visits, chosen_child.parent.legal_moves, chosen_child.parent.color))

    outcome = chosen_child.board.outcome()
    print(outcome)
    if outcome is not None:
        value = 0 if outcome.winner is None else (1 if outcome.winner else -1)
    else:
        value = 0

    print(chosen_child.board)
    print(chosen_child.board.fullmove_number)

    values = np.empty((len(states),), dtype=np.float32)
    values[::2] = value
    values[1::2] = -value

    return states, np.array(values, dtype=np.float32), np.array(priors, dtype=np.float32), outcome, chosen_child.board.fullmove_number

def update_model(states, values, priors, model, optimizer, device):
    '''
    This function updates the given model, using the given optimizer and device.
    Updates are performed using the training data obtained from one self play game.

    Arguments:
        states (list()): The list of states chosen in self play.
        values (np.array): The correspondig values.
        priors (np.array): The correspondig priors.
        model (AlphaZeroResNet): The model that should be trained.
        device (torch.device()): The device the model should be trained on.
    '''
    for state, value, prior in zip(states, values, priors):
        value_prediction, prior_prediction = model(state.to(device))
        value = torch.FloatTensor([value]).to(device)
        prior = torch.FloatTensor(prior).to(device)

        value_loss = torch.pow(value_prediction - value, 2)
        policy_loss = torch.dot(prior, torch.log(prior_prediction[0]))
        loss = 0.2 * value_loss - 0.8 * policy_loss

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

for i in range(50):
    MODEL_NAME = '44f_256c_18b_trained'
    EXPANSIONS_PER_MOVE = 800
    device = torch.device('cuda:0')

    model = AlphaZeroResNet(44, 256, num_res_blocks=18)
    model.load_state_dict(torch.load('./trained_models/' + MODEL_NAME))
    model.to(device)
    optimizer = torch.optim.SGD(model.parameters(), lr=0.02, weight_decay=0.0001, momentum=0.9)

    outcomes = list()
    times = list()
    move_counts = list()

    t0 = time.time()
    states, values, priors, outcome, move_count = self_play(model, EXPANSIONS_PER_MOVE, device)
    t1 = time.time()

    outcomes.append(outcome)
    times.append(t1-t0)
    move_counts.append(move_count)

    print(f'Time: {t1-t0}')

    update_model(states, values, priors, model, optimizer, device)

    df_old = pd.read_csv('./trained_models/training_statistics.csv')
    df_new = pd.DataFrame.from_dict({'outcome': outcomes, 'time': times, 'move_count': move_counts})
    df = pd.concat([df_old, df_new])
    df.to_csv('./trained_models/training_statistics.csv', header=True, index=False)

    torch.save(model.state_dict(), './trained_models/' + MODEL_NAME)

    print(f'No. Games played: {i + 1}')


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patheffects as path_effects
import imageio
import os
import random as rnd
import time
import matplotlib.colors as colors
import matplotlib.lines as lines
from matplotlib import cm
from matplotlib.ticker import LinearLocator
from mpl_toolkits.mplot3d import Axes3D

def der(f, x_i):
    derf = np.zeros_like(f)
    if x_i == 'r':
        for k in range(len(f)):
            for i in range(len(f[0])):
                if i>1 and i<len(f[0])-2:
                    derf[k][i] = (f[k][i-2]-8*f[k][i-1]+8*f[k][i+1]-f[k][i+2])/(12*delta_r)
                elif i==1 or i==len(f[0])-2:
                    if i==1:
                        a = 1
                    else:
                        a = -1
                    derf[k][i] = a*(-3*f[k][i-1*a]-10*f[k][i]+18*f[k][i+1*a]-6*f[k][i+2*a]+f[k][i+3*a])/(12*delta_r)
                else:
                    if i==0:
                        a = 1
                    else:
                        a = -1
                    derf[k][i] = a*(-25*f[k][i]+48*f[k][i+1*a]-36*f[k][i+2*a]+16*f[k][i+3*a]-3*f[k][i+4*a])/(12*delta_r)
    elif x_i == 'z':
        for k in range(len(f)):
            for i in range(len(f[0])):
                if k>1 and k<len(f)-2:
                    derf[k][i] = (f[k-2][i]-8*f[k-1][i]+8*f[k+1][i]-f[k+2][i])/(12*delta_z)
                elif k==1 or k==len(f)-2:
                    if k==1:
                        a = 1
                    else:
                        a = -1
                    derf[k][i] = a*(-3*f[k-1*a][i]-10*f[k][i]+18*f[k+1*a][i]-6*f[k+2*a][i]+f[k+3*a][i])/(12*delta_z)
                else:
                    if k==0:
                        a = 1
                    else:
                        a = -1
                    derf[k][i] = a*(-25*f[k][i]+48*f[k+1*a][i]-36*f[k+2*a][i]+16*f[k+3*a][i]-3*f[k+4*a][i])/(12*delta_z)
    else:
        print('ERROR')
        print('Por favor introduzca una direccion valida')
        input()
        exit()

    return derf

x,y = np.meshgrid(np.arange(-3,3, step=0.1),np.arange(-3,3, step=0.1))
f = np.zeros_like(x)
df = np.zeros_like(x)
delta_r=0.1
delta_z=0.1
for i in range(len(f)):
    for k in range(len(f[0])):
        f[k][i] = 2*np.exp(-x[k][i]**2-y[k][i]**2)+0.6*np.sqrt(x[k][i]**2+y[k][i]**2)

#df = der(f,'z')
df = der(f,'r')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(x,y,f)
plt.show()

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(x,y,df)
plt.show()

plt.plot(x[len(f[0])//2], f[len(f[0])//2],x[len(f[0])//2],df[len(f[0])//2],'--g')
plt.show()


from tkinter import *
from tkinter.ttk import *
import time
import serial
import io

#
# Runs with python 3
# works for microlab 500
#
root = Tk()
master = Frame(root, name='master')
master.pack(fill=BOTH)  # fill both sides of the parent
root.title('Syringe Control')  # title for top-level window
root.protocol("WM_DELETE_WINDOW", master.quit)  #quit if the window is deleted

# This is to add a second window
'''
syrStat = Toplevel()
syrStat.title("Syringe Status")
msg = Message(syrStat, text='test    fre          fre')
msg.pack()
button = Button(syrStat, text="Dismiss", command=syrStat.destroy)
button.pack()
'''

syrCtrl = Notebook(master, name='syrCtrl')  # create Notebook in "master"
syrCtrl.pack(fill=BOTH, padx=2, pady=3)  # fill "master" but pad sides -> frame appears
syrCtrlMan = Frame(syrCtrl, name='syrCtrlMan') # create foo tab in Notebook
syrCtrlMan.pack(fill=BOTH)

# Create Init
syrCtrlManInit = LabelFrame(syrCtrlMan, text='Init', name='syrCtrlManLeftInit', relief=GROOVE, borderwidth=2, labelanchor=N)
syrCtrlManInit.grid(row = 0, column = 0, columnspan = 2)
InitBut = Button(syrCtrlManInit, text="Init", command=lambda: syrCtrl().sendCmd('aXS30R'))
InitBut.grid(row = 0, column = 0, rowspan = 2, padx=2, pady=3)
Label(syrCtrlManInit, text="Fine Speed").grid(row = 0, column = 1)
ManFineSpeed = Entry(syrCtrlManInit, width=11)
ManFineSpeed.insert(END, 250)
ManFineSpeed.grid(row = 0, column = 2)
Label(syrCtrlManInit, text="Coarse Speed").grid(row = 1, column = 1)
ManCoarseSpeed = Entry(syrCtrlManInit, width=11)
ManCoarseSpeed.insert(END, 50)
ManCoarseSpeed.grid(row = 1, column = 2)

# Create 'Left Syringe' frame
syrCtrlManLeft = LabelFrame(syrCtrlMan, text='Left Syringe', name='syrCtrlManLeft', relief=GROOVE, borderwidth=2)
syrCtrlManLeft.grid(row = 1, column = 0, padx=2, pady=3)

# Create 'Pick Up' frame in 'Left Syringe' frame
syrCtrlManLeftPickUp = LabelFrame(syrCtrlManLeft, text='Pick-Up (Fine Speed)', name='syrCtrlManLeftPickUp', relief=GROOVE, borderwidth=2, labelanchor=N)
syrCtrlManLeftPickUp.grid(row = 0, column = 0)
PickUp1 = Button(syrCtrlManLeftPickUp, text="PickUp\n1 step", command=lambda: syrCtrl().singleSyrMove('B', 'I', 'P', 1, ManFineSpeed.get()))
PickUp1.grid(row = 0, column = 0, rowspan = 2)
PickUp2 = Button(syrCtrlManLeftPickUp, text="PickUp\n5 steps", command=lambda: syrCtrl().singleSyrMove('B', 'I', 'P', 5, ManFineSpeed.get()))
PickUp2.grid(row = 0, column = 1, rowspan = 2)
PickUp3 = Button(syrCtrlManLeftPickUp, text="PickUp\nSpecified", command=lambda: syrCtrl().singleSyrMove('B', 'I', 'P', int(ManPickUpStep.get()), ManFineSpeed.get()))
PickUp3.grid(row = 0, column = 2, rowspan = 2)
Label(syrCtrlManLeftPickUp, text="<-Steps", ).grid(row = 0, column = 4)
ManPickUpStep = Entry(syrCtrlManLeftPickUp, width=11)
ManPickUpStep.insert(END, 50)
ManPickUpStep.grid(row = 1, column = 4)

# Create 'other' frame in 'Left Syringe' frame
syrCtrlManLeftOther = LabelFrame(syrCtrlManLeft, text='Other (Coarse Speed)', name='syrCtrlManLeftOther', relief=GROOVE, borderwidth=2, labelanchor=N)
syrCtrlManLeftOther.grid(row = 1, column = 0)
LeftOther1 = Button(syrCtrlManLeftOther, text="Empty\nto\nwaste", command=lambda: syrCtrl().singleSyrMove('B', 'O', 'M', 0, ManCoarseSpeed.get()))
LeftOther1.grid(row = 0, column = 0)
LeftOther2 = Button(syrCtrlManLeftOther, text="Empty\nto\nmylar", command=lambda: syrCtrl().singleSyrMove('B', 'I', 'M', 0, ManCoarseSpeed.get()))
LeftOther2.grid(row = 0, column = 1)
LeftOther3 = Button(syrCtrlManLeftOther, text="Fill\nfrom\nwaste", command=lambda: syrCtrl().singleSyrMove('B', 'O', 'M', 2000, ManCoarseSpeed.get()))
LeftOther3.grid(row = 0, column = 2)
LeftOther4 = Button(syrCtrlManLeftOther, text="Fill\nfrom\nmylar", command=lambda: syrCtrl().singleSyrMove('B', 'I', 'M', 2000, ManCoarseSpeed.get()))
LeftOther4.grid(row = 0, column = 4)

# Create 'Right Syringe' frame
syrCtrlManRight = LabelFrame(syrCtrlMan, text='Right Syringe', name='syrCtrlManRight', relief=GROOVE, borderwidth=2)
syrCtrlManRight.grid(row = 1, column = 1, padx=2, pady=3)
# Create 'Dispence' frame in 'Right Syringe' frame
syrCtrlManRightDispence = LabelFrame(syrCtrlManRight, text='Dispence (Fine Speed)', name='syrCtrlManRightDispence', relief=GROOVE, borderwidth=2, labelanchor=N)
syrCtrlManRightDispence.grid(row = 0, column = 0)
Dispence1 = Button(syrCtrlManRightDispence, text="Dispence\n1 step", command=lambda: syrCtrl().singleSyrMove('C', 'O', 'D', 1, ManFineSpeed.get()))
Dispence1.grid(row = 0, column = 0, rowspan = 2)
Dispence2 = Button(syrCtrlManRightDispence, text="Dispence\n5 steps", command=lambda: syrCtrl().singleSyrMove('C', 'O', 'D', 5, ManFineSpeed.get()))
Dispence2.grid(row = 0, column = 1, rowspan = 2)
Dispence3 = Button(syrCtrlManRightDispence, text="Dispence\nSpecified", command=lambda: syrCtrl().singleSyrMove('C', 'O', 'D', int(ManDispStep.get()), ManFineSpeed.get()))
Dispence3.grid(row = 0, column = 2, rowspan = 2)
Label(syrCtrlManRightDispence, text="<-Steps", ).grid(row = 0, column = 4)
ManDispStep = Entry(syrCtrlManRightDispence, width=11)
ManDispStep.insert(END, 50)
ManDispStep.grid(row = 1, column = 4)

# Create 'other' frame in 'Right Syringe' frame
syrCtrlManRightOther = LabelFrame(syrCtrlManRight, text='Other (Coarse Speed)', name='syrCtrlManRightOther', relief=GROOVE, borderwidth=2, labelanchor=N)
syrCtrlManRightOther.grid(row = 1, column = 0)
RightOther1 = Button(syrCtrlManRightOther, text="Empty\nto\nsupply", command=lambda: syrCtrl().singleSyrMove('C', 'I', 'M', 0, ManCoarseSpeed.get()))
RightOther1.grid(row = 0, column = 0)
RightOther2 = Button(syrCtrlManRightOther, text="Empty\nto\nmylar", command=lambda: syrCtrl().singleSyrMove('C', 'O', 'M', 0, ManCoarseSpeed.get()))
RightOther2.grid(row = 0, column = 1)
RightOther3 = Button(syrCtrlManRightOther, text="Fill\nfrom\nsupply", command=lambda: syrCtrl().singleSyrMove('C', 'I', 'M', 2000, ManCoarseSpeed.get()))
RightOther3.grid(row = 0, column = 2)
RightOther4 = Button(syrCtrlManRightOther, text="Fill\nfrom\nmylar", command=lambda: syrCtrl().singleSyrMove('C', 'O', 'M', 2000, ManCoarseSpeed.get()))
RightOther4.grid(row = 0, column = 4)

# Create Stop
syrCtrlManStop = LabelFrame(syrCtrlMan, text='Stop', name='syrCtrlManLeftStop', relief=GROOVE, borderwidth=2, labelanchor=N)
syrCtrlManStop.grid(row = 2, column = 0, columnspan = 2, padx=2, pady=3)
Stop = Button(syrCtrlManStop, text="STOP", command=lambda: syrCtrl().sendCmd('aK'))
Stop.grid(row = 0, column = 0, rowspan = 2)

# add 'Manual tab' tab to Notebook
syrCtrl.add(syrCtrlMan, text="Manual Mode")

# repeat for each tab
# line 1
syrCtrlAuto = Frame(master, name='syrCtrlAuto')
Label(syrCtrlAuto, text="Bottle Speed").grid(row = 0, column = 0)
bottleSpeed = Entry(syrCtrlAuto, width=11)
bottleSpeed.insert(END, 50)
bottleSpeed.grid(row = 0, column = 1)
Label(syrCtrlAuto, text="Syr Size (mL)").grid(row = 0, column = 2)
syrSize = Entry(syrCtrlAuto, width=11)
syrSize.insert(END, 25)
syrSize.grid(row = 0, column = 3)
btn6 = Button(syrCtrlAuto,
				text="Check Time",
				command=lambda : syrCtrl().checkTime(int(cycleNumberFlow.get())))
btn6.grid(row = 0, column = 4)

Label(syrCtrlAuto, text="Flow Speed").grid(row = 1, column = 0)
flowSpeed = Entry(syrCtrlAuto, width=11)
flowSpeed.insert(END, 250)
flowSpeed.grid(row = 1, column = 1)
Label(syrCtrlAuto, text="N cycle").grid(row = 1, column = 2)
cycleNumberFlow = Entry(syrCtrlAuto, width=11)
cycleNumberFlow.insert(END, 5)
cycleNumberFlow.grid(row = 1, column = 3)
btn6 = Button(syrCtrlAuto,
				text="Flow !",
				command=lambda : syrCtrl().flowCycle(int(cycleNumberFlow.get())))
btn6.grid(row = 1, column = 4)

btn5 = Button(syrCtrlAuto,
				text="getReady",
				command=lambda : syrCtrl().dualSyrMove('O', 'M', 0, 20, 'I', 'M', 2000, 20))
btn5.grid(row = 2, column = 0)

btn7 = Button(syrCtrlAuto,
				text="Flush",
				command=lambda : syrCtrl().flush(int(cycleNumberFlow.get())))
btn7.grid(row = 3, column = 0)

syrCtrl.add(syrCtrlAuto, text="Auto Mode") #end of the Auto tab

class syrCtrl():

	def setup(self):
		syrCtrl().sendSimpleCmd('1a')
		syrCtrl().sendCmd('aBYSM1R') # set full resolution -> 2000 step per strokes
		syrCtrl().sendCmd('aCYSM1R') # set full resolution -> 2000 step per strokes
		syrCtrl().sendCmd('aCYSN0R') # eliminates backlash
		syrCtrl().sendCmd('aBYSN0R') # eliminates backlash

	def sendSimpleCmd(self, cmd2send):
		# does not check the 'ack'
		sio.write(cmd2send + '\r') #??? removed unicode here
		sio.flush()
		result = sio.readline() #??? dropped '.decode('utf8')'
		response = result[1:-1]
		print('response is :', response[0:1])
		return response

	def sendCmd(self, cmd2send):
		sio.write(cmd2send + '\r') #??? removed unicode here
		sio.flush()
		result = sio.readline() #??? dropped '.decode('utf8')'
		ack = result[:1]
		#print('sould be 6 :',ord(ack[0]))
		if ord(ack[0]) != (6 or 49):
			raise Exception("bad response {}".format(ord(ack)))
	# strip off leading ack and trailin CR
		response = result[1:-1]
		#print('response is :', response[0:1])
		return response

	def moveAndWait(self, cmdMove):
		#global pl
		try:
			print('execute move', cmdMove)
			syrCtrl().sendCmd(cmdMove)
			while True:
				time.sleep(.2)
				response = syrCtrl().sendCmd('aF')
				# posLeft = getSyrPos()[0]
				# pl.config(text=getSyrPos()[0])
				if response[0:1] == 'Y':
					break
		except Exception as e:
			print('it broke')

	def singleSyrMove(self, syr, valve, type, step, speed):
		cmd = 'a'+syr+valve+type+str(step)+'S'+str(speed)+'R'
		syrCtrl().moveAndWait(cmd)

	def dualSyrMove(self, valveL, typeL, stepL, speedL, valveR, typeR, stepR, speedR):
		cmd = ('a'+
			'B'+valveL+typeL+str(stepL)+'S'+str(speedL)+
			'C'+valveR+typeR+str(stepR)+'S'+str(speedR)+'R')
		syrCtrl().moveAndWait(cmd)

	def syrFlush(self, cycleNum):
		for i in range(cycleNum):
			syrCtrl().dualSyrMove('O', 'M', 2000, 20, 'I', 'M', 2000, 20)
			syrCtrl().dualSyrMove('I', 'M', 0, ManCoarseSpeed.get(), 'O', 'M', 0, ManCoarseSpeed.get())

	def flowCycle(self, cycleNumber):
		for i in range(cycleNumber):
			time.sleep(.5)
			syrCtrl().getReady()
			time.sleep(.5)
			syrCtrl().dualSyrMove('I', 'M', 2000, flowSpeed.get(), 'O', 'M', 0, flowSpeed.get())

	def getReady(self):
		syrCtrl().dualSyrMove('O', 'M', 0, bottleSpeed.get(), 'I', 'M', 2000, bottleSpeed.get())

	def checkTime(self, cycleNumber):
		time = cycleNumber * (int(bottleSpeed.get()) + int(flowSpeed.get()))
		volume = cycleNumber * int(syrSize.get())
		print(('Will flow {} mL in {:.1f} minutes or {:.2f} hours').format(volume, time / 60, time / 3600))

	def flush(self, cycleNumber):
		for i in range(cycleNumber):
			time.sleep(.5)
			syrCtrl().dualSyrMove('I', 'M', 2000, bottleSpeed.get(), 'I', 'M', 2000, bottleSpeed.get())
			time.sleep(.5)
			syrCtrl().dualSyrMove('O', 'M', 0, flowSpeed.get(), 'O', 'M', 0, flowSpeed.get())

if __name__ == "__main__":
	# serial config
	ser = serial.Serial(
	port='\\.\COM3',
	baudrate=9600,
	parity=serial.PARITY_ODD,
	stopbits=serial.STOPBITS_ONE,
	bytesize=serial.SEVENBITS,
	timeout=.02
	)
	sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))
	#time.sleep(10)
	syrCtrl().setup()

	master.mainloop()

'''
class syrCtrl():

    def sendCmd(self, cmd2send):
        print cmd2send

    def moveAndWait(self, cmdMove):
        print cmdMove

    def singleSyrMove(self, par):
        print 'single move', par

    def dualSyrMove(self, par):
        print 'dual move', par

#syrCtrl().singleSyrMove('maybe')
'''

"""

class test():
    def printTata(self):
        # type: () -> object
        print 'tata'

    def printToto(self):
        print 'toto'

test2 = test()

test2.printTata()
"""
'''

import Tkinter as tk

class Notepad(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.text = tk.Text(self, wrap="word")
        self.vsb = tk.Scrollbar(self, orient="vertical", comman=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)
        self.vsb.pack(side="right", fill="y")
        self.text.pack(side="left", fill="both", expand=True)

def main():
    root = tk.Tk()
    Notepad(root).pack(fill="both", expand=True)
    for i in range(5):
        top = tk.Toplevel(root)
        Notepad(top).pack(fill="both", expand=True)

    root.mainloop()

if __name__ == "__main__":
    main()

'''

'''
class Demo1:
    def __init__(self, master):
        self.master = master
        self.frame = Frame(self.master)
        self.button1 = Button(self.frame, text = 'New Window', width = 25, command = self.new_window)
        self.button1.pack()
        self.frame.pack()

    def new_window(self):
        self.newWindow = Toplevel(self.master)
        self.app = Demo2(self.newWindow)

class Demo2:
    def __init__(self, master):
        self.master = master
        self.frame = Frame(self.master)
        self.quitButton = Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
        self.quitButton.pack()
        self.frame.pack()

    def close_windows(self):
        self.master.destroy()

def main():
    root = Tk()
    app = Demo1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

'''


from deap import base
from deap import creator
from deap import tools
from deap import algorithms

import random
import numpy

import matplotlib.pyplot as plt
import seaborn as sns

import knapsack
from utils import processing_str_lst

# Genetic Algorithm constants:
POPULATION_SIZE = 65
P_CROSSOVER = 0.9  # probability for crossover
P_MUTATION = 0.1   # probability for mutating an individual
MAX_GENERATIONS = 50
HALL_OF_FAME_SIZE = 2

def processing_data_genetic_algorithm(process_lst):
    lst_processed = processing_str_lst(process_lst)

    items = []
    for i in range(2, int(lst_processed[0]) + 2):
        items.append((f"{i - 2}", int(lst_processed[i].split()[0]), int(lst_processed[i].split()[1])))

    capacities = int(lst_processed[1])

    return items, capacities

def initData(items, capacities):
    knapsack_init = knapsack.Knapsack01Problem(items, capacities)
    return knapsack_init

def run(items, capacities):
    # set the random seed:
    knapsack_init = initData(items, capacities)
    RANDOM_SEED = 19522081
    random.seed(RANDOM_SEED)

    toolbox = base.Toolbox()

    # create an operator that randomly returns 0 or 1:
    toolbox.register("zeroOrOne", random.randint, 0, 1)

    # define a single objective, maximizing fitness strategy:
    creator.create("FitnessMax", base.Fitness, weights=(1.0,))

    # create the Individual class based on list:
    creator.create("Individual", list, fitness=creator.FitnessMax)

    # create the individual operator to fill up an Individual instance:
    toolbox.register("individualCreator", tools.initRepeat, creator.Individual, toolbox.zeroOrOne, len(knapsack_init))

    # create the population operator to generate a list of individuals:
    toolbox.register("populationCreator", tools.initRepeat, list, toolbox.individualCreator)

    # fitness calculation
    def knapsackValue(individual):
        return knapsack_init.getValue(individual), # return a tuple

    toolbox.register("evaluate", knapsackValue)

    # genetic operators:mutFlipBit

    # Tournament selection with tournament size of 3:
    toolbox.register("select", tools.selTournament, tournsize=3)

    # Single-point crossover:
    toolbox.register("mate", tools.cxTwoPoint)

    # Flip-bit mutation:
    # indpb: Independent probability for each attribute to be flipped
    toolbox.register("mutate", tools.mutFlipBit, indpb=1.0/len(knapsack_init))

    # create initial population (generation 0):
    population = toolbox.populationCreator(n=POPULATION_SIZE)

    # prepare the statistics object:
    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("max", numpy.max)
    stats.register("avg", numpy.mean)

    # define the hall-of-fame object:
    hof = tools.HallOfFame(HALL_OF_FAME_SIZE)

    # perform the Genetic Algorithm flow with hof feature added:
    population, logbook = algorithms.eaSimple(population, toolbox, cxpb=P_CROSSOVER, mutpb=P_MUTATION,
                                              ngen=MAX_GENERATIONS, stats=stats, halloffame=hof, verbose=True)

    # print best solution found:
    best = hof.items[0]
    print("-- Best Ever Individual = ", best)
    print("-- Best Ever Fitness = ", best.fitness.values[0])

    totalWeight, totalValue = knapsack_init.printItems(best)

    # extract statistics:
    # maxFitnessValues, meanFitnessValues = logbook.select("max", "avg")

    # plot statistics:
    # sns.set_style("whitegrid")
    # plt.plot(maxFitnessValues, color='red')
    # plt.plot(meanFitnessValues, color='green')
    # plt.xlabel('Generation')
    # plt.ylabel('Max / Average Fitness')
    # plt.title('Max and Average fitness over Generations')
    # plt.savefig(f'TestResults/Genetic/{figure_name}.png')
    # plt.close()

    return best.fitness.values[0], totalWeight, totalValue


from django.urls import path
from start import views

urlpatterns = [
    path('', views.start),
    path('candidates', views.getCandidates),
    path('add_candidate', views.addCandidate),
    path('change_candidate/<int:pk>', views.changeCandidate),
    path('change_job/<int:pk>', views.changeJob),
    path('change_jobseek/<int:pk>', views.changeJobSeek),
    path('add_jobseek', views.addJobSeek),
    path('jobs', views.getJob),
    path('jobseek', views.getJobSeek),
    path('add_job', views.addJob),
    path('cerjobseek/<int:pk>', views.getCerJobSeek, name='cerjobseek'),
    path('cercandidate/<int:pk>', views.getCerCandidate, name='cercandidate'),
    path('cerjob/<int:pk>', views.getCerJob, name='cerjob'),
    path('candidates', views.getCandidates),
    path('jobs', views.getJob),
    path('jobseek', views.getJobSeek),
    path('cercandidate/get_cv/<int:pk>',views.get_cv),
    path('parser', views.parser),
    path('parseHTML',views.parseHTML)
]


import sys
import argparse
import math
from collections import defaultdict
import itertools

reset_report = None

def print_usage(name, input_file):
    print(f"Usage: python3 {name} {input_file}")

def load_inputs(input_file):
    global reset_report
    report = []

    if reset_report is not None:
        report = reset_report.copy()
    else:
        for line in input_file:
            report.append(line[:-1]) #remove \n

        if reset_report is None:
            reset_report = report.copy()

    return report

def convert_routes(bus_routes):
    arrival = int(bus_routes[0])
    buses = bus_routes[1].replace("x,", "").split(",")
    buses = [int(bus) for bus in buses]

    return (arrival, buses)

def convert_routes_with_gaps(bus_routes):
    arrival = int(bus_routes[0])
    buses = bus_routes[1].split(",")

    for bus in buses:
        if bus.isnumeric():
            buses[buses.index(bus)] = int(bus)

    return (arrival, buses)

def find_soonest_bus(arrival, buses):
    deltas = []

    for bus in buses:
        temp = arrival//int(bus)
        deltas.append(((temp + 1) * bus) - arrival)

    bus_id = buses[deltas.index(min(deltas))]
    delta = min(deltas)
    print(f"deltas: {deltas}")
    print(f"min deltas: {delta}")
    print(f"bus id: {bus_id}")
    return (bus_id, delta)

def gcd(a, b):
    while b > 0:
        a, b = b, a%b
    return a

def lcm(a, b):
    return a * b //  gcd(a, b)

def find_soonest_series(buses):
    bus_index = []
    just_buses = []
    first_bus = None
    offset = 0
    for bus in buses:
        if type(bus) == int:
            bus_index.append(buses.index(bus))
            just_buses.append(bus)
            if first_bus is None:
                first_bus =  bus

    lcms = []
    combos = itertools.combinations(just_buses, 2)
    for combo in combos:
        lcms.append(lcm(combo[0], combo[1]))

    print(f"lcms: {lcms}")

    offset = first_bus * max(just_buses)
    t = first_bus * max(just_buses)
    print(f"starting the search at t: {t}")
    failed = False
    while not failed:
        for index in bus_index:
#            print (f"index: {index}, bus: {buses[index]}, t: {t}")
#            print(f"(t%bus) - index == {(t%buses[index])-index}")
            if 0 != ((t+index) % buses[index]):
                failed = True

        if not failed:
            break;
        t += offset
        failed = False

    print(f"t: {t}")
    return t

def part_1(input_file):
    bus_routes = load_inputs(input_file)
    arrival, buses = convert_routes(bus_routes)

    bus_id, delta = find_soonest_bus(arrival, buses)

    print(f"{bus_id} * {delta} = {bus_id * delta}")

def part_2(input_file):
    bus_routes = load_inputs(input_file)
    arrival, buses = convert_routes_with_gaps(bus_routes)

    timestamp = find_soonest_series(buses)

    print(f"buses: {buses} line up at {timestamp}")

def main():
    parser = argparse.ArgumentParser(description="Find bus routes.")
    parser.add_argument('file', type=argparse.FileType('r'))
    parser.add_argument('--part', type=int, required=True, help='Part 1 or Part 2')

    args = parser.parse_args()

    if (len(sys.argv) > 1):
        with args.file as input_file:
            if args.part == 1:
                part_1(input_file)
            elif args.part == 2:
                part_2(input_file)
    else:
        print_usage(sys.argv[0], args.file)

if __name__ == "__main__":
    main()


import asyncio
import datetime
import os
import subprocess

import discord
import humanize
import psutil
from cogs.consts import *
from cogs.handlers import Handlers
from discord.ext import commands

class Git(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.assignees = "PineaFan"
        self.emojis = Emojis
        self.colours = Cols()
        self.handlers = Handlers(self.bot)

        self.head = str(subprocess.check_output(["git", "rev-parse", "HEAD"]))[2:-3]
        self.branch = str(subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]))[2:-3]
        self.commit = str(subprocess.check_output(["git", "show-branch", self.branch]))[(5+(len(self.branch))):-3]
        self.url = str(subprocess.check_output(["git", "config", "--get", "remote.origin.url"]))[2:-3]

    @commands.command(aliases=["v"])
    async def version(self, ctx):
        total_size = 0
        for path, _, files in os.walk("./data/guilds"):
            for f in files:
                fp = os.path.join(path, f)
                total_size += os.path.getsize(fp)

        await ctx.send(embed=discord.Embed(
            title=f"{self.bot.user.name}",
            description=f"**Repository:** {self.url.split('/')[-2]}/{self.url.split('/')[-1]}\n"
                        f"**Branch:** `{self.branch}`\n"
                        f"**HEAD:** `{self.head}`\n"
                        f"**Commit:** `{self.commit}`\n"
                        f"**Server size:** `{humanize.naturalsize(os.path.getsize(f'./data/guilds/{ctx.guild.id}.json')) if ctx.guild else 0}`"
                        f" • `{humanize.naturalsize(total_size)}`\n"
                        f"**Uptime:** `{str(datetime.datetime.now()-self.bot.uptime).split('.')[0]}`",
            colour=self.colours.red,
            url="https://discord.gg/bPaNnxe"
        ).set_footer(
            text=f"You probably don't know what most of this means - "
                 f"If you do know what this means, you can become a programmer of {self.bot.user.name} and other bots at https://discord.gg/bPaNnxe",
            icon_url=self.bot.user.avatar.url
        ))

    @commands.command()
    @commands.is_owner()
    async def git(self, ctx):
        m = await ctx.send(embed=loading_embed)
        for r in [834127343206400021, 834148997324472391, 834127343533555713, 834127343525822474, 834127343244673055, 834139266921267211]:  # 834127343576023130
            await m.add_reaction(self.bot.get_emoji(r))

        gc = {
            "commit": 834127343525822474,
            "pull": 834148997324472391,
            "merge": 834127343533555713,
            "push": 834127343244673055,
            "fetch": 834127343206400021,
            "fork": 834127343576023130,
            "reload": 834139266921267211
        }

        self.head = str(subprocess.check_output(["git", "rev-parse", "HEAD"]))[2:-3]
        self.branch = str(subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]))[2:-3]
        self.commit = str(subprocess.check_output(["git", "show-branch", self.branch]))[(5+(len(self.branch))):-3]
        self.url = str(subprocess.check_output(["git", "config", "--get", "remote.origin.url"]))[2:-3]
        while True:
            await m.edit(embed=discord.Embed(
                title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                description=f"Current version for `{self.url.split('/')[-2]}/{self.url.split('/')[-1]}`\n"
                            f"**Branch:** `{self.branch}`\n"
                            f"**HEAD:** `{self.head}`\n"
                            f"**Commit:** `{self.commit}`\n\n"
                            f"{self.bot.get_emoji(gc['fetch'])} **Fetch** latest commit\n"
                            f"{self.bot.get_emoji(gc['pull'])} **Pull** fetched version\n"
                            f"{self.bot.get_emoji(gc['merge'])} **Merge** with current version\n"
                            f"{self.bot.get_emoji(gc['commit'])} **Commit** current code\n"
                            f"{self.bot.get_emoji(gc['push'])} **Push** current commit\n\n"
                            f"{self.bot.get_emoji(gc['reload'])} **PM2 reload**",
                colour=self.colours.green
            ))
            try:
                reaction = await ctx.bot.wait_for("reaction_add", timeout=60, check=lambda _, user: user == ctx.author)
            except asyncio.TimeoutError:
                break

            try:
                await m.remove_reaction(reaction[0].emoji, ctx.author)
            except Exception as e:
                print(e)

            if reaction is None:
                break
            elif reaction[0].emoji.name == "Fetch":
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['fetch'])} Fetch\n\n>>> Fetching",
                    colour=self.colours.green
                ))
                out = subprocess.run(["git", "fetch"], stdout=subprocess.PIPE)
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['fetch'])} Fetch\n\n>>> "
                                f"{'Fetched successfully' if out.returncode == 0 else 'Exited with code `' + str(out.returncode) +'`'}",
                    colour=self.colours.green
                ))
                await asyncio.sleep(3)
            elif reaction[0].emoji.name == "Pull":
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['pull'])} Pull\n\n>>> Pulling",
                    colour=self.colours.green
                ))
                out = subprocess.run(["git", "pull"], stdout=subprocess.PIPE)
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['pull'])} Pull\n\n>>> {'Pulled successfully' if out.returncode == 0 else 'Exited with code `' + str(out.returncode) +'`'}",
                    colour=self.colours.green
                ))
                await asyncio.sleep(3)
            elif reaction[0].emoji.name == "Merge":
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['merge'])} Merge\n\n>>> Merging",
                    colour=self.colours.green
                ))
                out = subprocess.run(["git", "merge"], stdout=subprocess.PIPE)
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['merge'])} Merge\n\n>>> "
                                f"{'Merged successfully' if out.returncode == 0 else 'Exited with code `' + str(out.returncode) +'`'}",
                    colour=self.colours.green
                ))
                await asyncio.sleep(3)
            elif reaction[0].emoji.name == "Commit":
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['commit'])} Commit\n\n>>> Enter a commit message",
                    colour=self.colours.green
                ))
                try:
                    message = await ctx.bot.wait_for("message", timeout=60, check=lambda message: message.author.id == ctx.author.id)
                except asyncio.TimeoutError:
                    break

                try:
                    await message.delete()
                except discord.HTTPException:
                    pass
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['commit'])} Commit\n\n>>> Committing",
                    colour=self.colours.green
                ))
                out = subprocess.run(["git", "commit", "-am", f'"{message.content}"'], stdout=subprocess.PIPE)
                backn = "\n"
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['commit'])} Commit\n\n>>> "
                                f"{f'Committed successfully with message:{backn} {message.content}' if out.returncode == 0 else 'Exited with code `' + str(out.returncode) +'`'}",
                    colour=self.colours.green
                ))
                await asyncio.sleep(3)
            elif reaction[0].emoji.name == "Push":
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['push'])} Push\n\n>>> Pushing",
                    colour=self.colours.green
                ))
                out = subprocess.run(["git", "push"], stdout=subprocess.PIPE)
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['push'])} Push\n\n>>> "
                                f"{'Pushed successfully' if out.returncode == 0 else 'Exited with code `' + str(out.returncode) +'`'}",
                    colour=self.colours.green
                ))
                await asyncio.sleep(3)
            elif reaction[0].emoji.name == "reload":
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['reload'])} PM2 Reload\n\n>>> Reloading",
                    colour=self.colours.green
                ))
                try:
                    out = subprocess.run(["pm2", "reload", "0"], stdout=subprocess.PIPE).returncode
                except FileNotFoundError:
                    out = 1
                await m.edit(embed=discord.Embed(
                    title=f"{self.bot.get_emoji(gc['fork'])} Git Controls",
                    description=f"{self.bot.get_emoji(gc['reload'])} PM2 Reload\n\n>>> "
                                f"{'Reloaded successfully' if out == -2 else 'Exited with code `' + str(out) +'`'}",
                    colour=self.colours.green
                ))
                return

    @commands.command()
    async def usage(self, ctx):
        m = await ctx.send(embed=loading_embed)
        cpu = psutil.getloadavg()
        cpu = round(sum(cpu) / len(cpu) / psutil.cpu_count(), 2)
        mem = round((psutil.virtual_memory().used/psutil.virtual_memory().total)*100, 2)
        temp, count = 0, 0
        try:
            sensors = psutil.sensors_temperatures()
        except AttributeError:
            sensors = []
        for sensor in sensors:
            for each in sensors[sensor]:
                temp += each.current
                count += 1
        tempav = round(temp/count, 2)
        swap = round(psutil.swap_memory().percent, 2)
        disk = psutil.disk_usage('/').percent

        await m.edit(embed=discord.Embed(
            title="Usage statistics",
            description=f"**Server time:** {self.handlers.strf(datetime.datetime.now())}\n"
                        f"**CPU:** {cpu}%\n"
                        f"**Memory:** {mem}%\n"
                        f"**Swap:** {swap}%\n"
                        f"**Disk:** {disk}%\n"
                        f"**Temperature:** {tempav}°c",
            color=self.colours.green
        ))

def setup(bot):
    bot.add_cog(Git(bot))


from discord.ext import commands
import discord

class Bot(commands.Bot):

    def __init__(self, command_prefix = '!', self_bot = False):
        intents = discord.Intents.all()
        intents.messages = True
        commands.Bot.__init__(self, command_prefix = command_prefix, intents = intents, self_bot = self_bot)

    async def on_ready(self):
        print(f'{self.user} is ready and online!')

    async def on_command_error(self, ctx, exception) -> None:
        print(f'exception in command {ctx.command}: {exception}')
        if ctx.command == None:
            await ctx.channel.send(f'{exception}')
        return await super().on_command_error(ctx, exception)


from unittest import mock

import pytest
from confluent_kafka import Consumer
from streaming_data_types.fbschemas.forwarder_config_update_rf5k.UpdateType import (
    UpdateType,
)
from streaming_data_types.forwarder_config_update_rf5k import (
    Protocol,
    StreamInfo,
    serialise_rf5k,
)

from forwarder.common import Channel, EpicsProtocol, config_change_to_command_type
from forwarder.configuration_store import ConfigurationStore
from forwarder.parse_config_update import parse_config_update
from tests.kafka.fake_producer import FakeProducer

DUMMY_UPDATE_HANDLER = None

CHANNELS_TO_STORE = {
    Channel("channel1", EpicsProtocol.PVA, "topic1", "f142"): DUMMY_UPDATE_HANDLER,
    Channel("channel2", EpicsProtocol.CA, "topic2", "tdct"): DUMMY_UPDATE_HANDLER,
}

STREAMS_TO_RETRIEVE = [
    StreamInfo(
        channel.name,
        channel.schema,
        channel.output_topic,
        Protocol.Protocol.PVA
        if channel.protocol == EpicsProtocol.PVA
        else Protocol.Protocol.CA,
    )
    for channel in CHANNELS_TO_STORE.keys()
]

class FakeKafkaMessage:
    def __init__(self, message):
        self._message = message

    def value(self):
        return self._message

def assert_stored_channel_correct(outputted_channel):
    # Will only be found if key exists and as the key is the channel
    # it will only match if the values are exactly the same.
    assert outputted_channel in CHANNELS_TO_STORE

def test_when_multiple_pvs_dumped_config_contains_all_pv_details():
    producer = FakeProducer()
    store = ConfigurationStore(producer, consumer=None, topic="store_topic")

    store.save_configuration(CHANNELS_TO_STORE)

    stored_message = parse_config_update(producer.published_payloads[-1])  # type: ignore
    stored_channels = stored_message.channels

    assert_stored_channel_correct(stored_channels[0])  # type: ignore
    assert_stored_channel_correct(stored_channels[1])  # type: ignore

def test_when_no_pvs_stored_message_type_is_remove_all():
    producer = FakeProducer()
    store = ConfigurationStore(producer, consumer=None, topic="store_topic")

    store.save_configuration({})

    stored_message = parse_config_update(producer.published_payloads[-1])  # type: ignore

    assert stored_message.channels is None
    assert (
        stored_message.command_type
        == config_change_to_command_type[UpdateType.REMOVEALL]
    )

def test_retrieving_stored_info_with_no_pvs_gets_message_without_streams():
    mock_consumer = mock.create_autospec(Consumer)
    mock_consumer.get_watermark_offsets.return_value = (0, 100)
    message = serialise_rf5k(UpdateType.REMOVEALL, [])
    mock_consumer.consume.return_value = [FakeKafkaMessage(message)]
    store = ConfigurationStore(
        producer=None, consumer=mock_consumer, topic="store_topic"
    )

    config = parse_config_update(store.retrieve_configuration())
    assert config.channels is None

def test_retrieving_stored_info_with_multiple_pvs_gets_streams():
    mock_consumer = mock.create_autospec(Consumer)
    mock_consumer.get_watermark_offsets.return_value = (0, 100)
    message = serialise_rf5k(UpdateType.ADD, STREAMS_TO_RETRIEVE)
    mock_consumer.consume.return_value = [FakeKafkaMessage(message)]
    store = ConfigurationStore(
        producer=None, consumer=mock_consumer, topic="store_topic"
    )

    config = parse_config_update(store.retrieve_configuration())
    channels = config.channels

    assert_stored_channel_correct(channels[0])  # type: ignore
    assert_stored_channel_correct(channels[1])  # type: ignore

def test_retrieve_config_find_valid_message_amongst_junk():
    message = serialise_rf5k(UpdateType.ADD, STREAMS_TO_RETRIEVE)
    messages_in_storage_topic = [
        [FakeKafkaMessage(":: SOME JUNK MESSAGE 1 ::")],
        [FakeKafkaMessage(":: SOME JUNK MESSAGE 2 ::")],
        [FakeKafkaMessage(message)],
        [FakeKafkaMessage(":: SOME JUNK MESSAGE 3 ::")],
        [FakeKafkaMessage(":: SOME JUNK MESSAGE 4 ::")],
    ]  # type: ignore

    mock_consumer = mock.create_autospec(Consumer)
    mock_consumer.get_watermark_offsets.return_value = (
        0,
        len(messages_in_storage_topic),
    )

    mock_consumer.consume.side_effect = messages_in_storage_topic

    store = ConfigurationStore(
        producer=None, consumer=mock_consumer, topic="store_topic"
    )
    config = parse_config_update(store.retrieve_configuration())
    channels = config.channels
    assert_stored_channel_correct(channels[0])  # type: ignore
    assert_stored_channel_correct(channels[1])  # type: ignore

def test_retrieve_config_with_only_junk_as_message_in_storage_topic():
    messages_in_storage_topic = [
        [FakeKafkaMessage(":: SOME JUNK MESSAGE 1 ::")],
        [FakeKafkaMessage(":: SOME JUNK MESSAGE 2 ::")],
        [FakeKafkaMessage(":: SOME JUNK MESSAGE 3 ::")],
    ]  # type: ignore
    mock_consumer = mock.create_autospec(Consumer)
    mock_consumer.get_watermark_offsets.return_value = (
        0,
        len(messages_in_storage_topic),
    )
    mock_consumer.consume.side_effect = messages_in_storage_topic

    store = ConfigurationStore(
        producer=None, consumer=mock_consumer, topic="store_topic"
    )
    with pytest.raises(RuntimeError):
        store.retrieve_configuration()

def test_retrieve_config_with_empty_storage_topic():
    messages_in_storage_topic = []  # type: ignore
    mock_consumer = mock.create_autospec(Consumer)
    mock_consumer.get_watermark_offsets.return_value = (
        0,
        len(messages_in_storage_topic),
    )
    mock_consumer.consume.side_effect = messages_in_storage_topic

    store = ConfigurationStore(
        producer=None, consumer=mock_consumer, topic="store_topic"
    )
    with pytest.raises(RuntimeError):
        store.retrieve_configuration()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on Tue Apr 14 17:20:17 2020

@author: Edyta Bosacka
"""

import os
import librosa.display
import matplotlib.pyplot as plt
import numpy
import librosa

directory = 'E:/Nagrania'
resultsDirectory = directory + "/MFCCsresult"

for filename in os.listdir(directory):
    if filename.endswith('.wav'):
        y,sr = librosa.load(directory + "/" + filename)
        mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13, win_length= 1024, hop_length = 512)
        print(mfccs)
        plt.figure(figsize=(10,4))
        librosa.display.specshow(mfccs, x_axis = 'time')
        plt.colorbar()
        plt.title('MFCC')
        plt.tight_layout()
        plt.show()

        outputFile = resultsDirectory + "/" + "Mfcc" + ".csv"
        file = open(outputFile, 'a')
        file.write(filename+"\n")
        numpy.savetxt(file, mfccs, delimiter=",") #save MFCCs as .csv
        file.close() # close file


import uuid

import numpy as np

class LearningModel:
    def __init__(self, w_vector: [float], d: float, model_id=None):
        self.model_id = model_id if model_id else str(uuid.uuid4())
        self.w_vector = w_vector
        self.d = d

        self.score = 0
        self.processed = False

        self.generation = None

    def apply(self, x_vector: [float]):
        x = np.array(x_vector).reshape(1, 3)
        w = np.array([self.w_vector])

        product = x * w + self.d
        average = np.sum(product, axis=1) / x_vector.shape[1]
        return np.tan(average).ravel()

    def __hash__(self):
        return hash((str(self.w_vector), self.d))

    def __eq__(self, other):
        if not isinstance(other, type(self)):
            return NotImplemented
        return self.w_vector == other.w_vector and self.d == other.d


"""
load data from the csv & sort_values
adds days delta calc vs. failure date if available
"""
import time
import pickle
import pandas as pd
import numpy as np
from tqdm import tqdm
from hlp_analysis import xstat

def days_delta_calc(df):
  """ given data_frame returns days from the failure date  """
  return df.date.progress_apply(lambda x: (x - df.loc[df[df.failure].index[0]].date).days)

def load_parse_save(in_file_name='./predictive_maintenance.csv', save_file='', debug=False):
  """
  read in input csv file & returns pased dateframe & saves
  a save_file, if save_file name is specificed
  """
  beg = time.time()
  dt_parser = lambda x: pd.datetime.strptime(x, "%m/%d/%y")
  df = pd.read_csv(in_file_name, parse_dates=[0], date_parser=dt_parser)
  #df.date = df.date.progress_apply(lambda x: pd.to_datetime(x, format="%m/%d/%Y"))
  #sort by device & date
  pm_df = df.sort_values(['device', 'date'])
  pm_df = pm_df.reset_index(drop=True)
  df = None
  pm_df.failure = pm_df.failure.apply(lambda x: True if x > 0 else False)
  # adds following new columns
  pm_df['daysDelta'] = np.nan # date from the failure date
  # convert date to pandas datetime for calculation
  # get list of failed devices for special dateDelta processing
  dev_failed = pm_df.device[pm_df.failure].tolist()
  # loop & if device is
  for ky in dev_failed:
    pm_df.loc[pm_df.device == ky, 'daysDelta'] = days_delta_calc(pm_df[pm_df.device == ky])
    beg = time.time()
  pm_df['Fail_set'] = pm_df.daysDelta.apply(lambda x: True if x <= 0.0 else False)
  grp = pm_df.groupby(['device', 'Fail_set'])
  if debug:
    print('Processing csv at {} took {:,.2f} sec'.format(time.ctime(), time.time()-beg))
  g_stat_df = grp.apply(lambda x: xstat(x, False, False))
  # saving dict of processed_csv, group, & stat_df from group
  ret_dict = {'csv_df': pm_df, 'grp_dev_fail': grp, 'g_stat_df': g_stat_df}
  if debug:
    print('Processing g_df at {} took {:,.2f} sec'.format(time.ctime(), time.time()-beg))
    print(g_stat_df.head(15))
  if save_file != '':
    with open(save_file, 'wb') as fw:
      pickle.dump(ret_dict, fw)
  return ret_dict

if __name__ == '__main__':
  pkl_file = './parsed_dataframe.pkl'
  tqdm.pandas(desc='load & parse csv')
  pkl_dict = load_parse_save(save_file='./parsed_dataframe.pkl', debug=True)


# -*- coding: utf-8 -*-
"""
Created on Fri May  5 18:41:06 2023

@author: mustafa
"""

import pydirectinput
import time
from PIL import ImageGrab
from PIL import Image
from numpy import asarray
import pytesseract

pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract'

time.sleep(1)

while True:
    try:
        '''
        imagehp = ImageGrab.grab(bbox=(350, 250, 475,260))
        imagehp.save('hp.png')
        hp = pytesseract.image_to_string(r'hp.png')
        hp=hp.replace(" ", "")
        hp=hp.replace("\n", "")
        hp = hp[0:3]
        hp = int(hp)
        '''
        imagemp = ImageGrab.grab(bbox=(350, 60, 440,92))
        imagemp.save('mp.png')
        mp = pytesseract.image_to_string(r'mp.png')
        mp=mp.replace(" ", "")
        mp=mp.replace("\n", "")
        mp = mp[0:4]
        mp = int(mp)

        if mp < 2750:
            pydirectinput.press('2')
        '''

        if hp < 515:
            pydirectinput.press('1')
        '''
    except:
        print('hata')


from typing import List
from queue import PriorityQueue

class Solution:
    def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
        length = len(matrix) * (len(matrix[0]) if len(matrix) > 0 else 0)
        pq = PriorityQueue()
        for row in matrix:
            for n in row:
                pq.put(n)
                if pq.qsize() > length - k + 1:
                    pq.get()
        return pq.get()

if __name__ == "__main__":
    print(Solution().kthSmallest([[1,5,9],[10,11,13],[12,13,15]], 8))


import numpy as np
import pandas as pd
import matplotlib.pylab as plt
import seaborn as sns

def load_data():
    train_data_2011 = pd.read_csv('./data/gt_2011.csv').values
    train_data_2012 = pd.read_csv('./data/gt_2012.csv').values
    train_data_2013 = pd.read_csv('./data/gt_2013.csv').values
    train_data_2014 = pd.read_csv('./data/gt_2014.csv').values
    train_data_2015 = pd.read_csv('./data/gt_2015.csv').values

    data = np.vstack((train_data_2011,train_data_2012,train_data_2013,train_data_2014,train_data_2015))

    feature_name = [column for column in pd.read_csv('./data/gt_2011.csv')]

    return data,feature_name

def plot_feature_label_relation(data,feature_name):

    for a in range(-2,0):
        fig, axs = plt.subplots(3,3,figsize=(12,8))
        fig.suptitle('Relation between Feature and %s subplots'%(feature_name[a]))
        for i in range(3):
            for j in range(3):
                axs[i,j].scatter(data[:,3*i+j],data[:,a],s=0.1)
                axs[i,j].set(xlabel=feature_name[3*i+j], ylabel=feature_name[a])
        plt.tight_layout()
        plt.savefig('./result/Feature_%s_relation_subplots.png'%(feature_name[a]))
        plt.show()

if __name__ == '__main__':
    data,feature_name = load_data()
    plot_feature_label_relation(data,feature_name)


# This creates a table in a PostGIS enabled PostgreSQL database
# with SMOS points and (circular) pixels.

# table name
table = 'smos_grid_ia'

# set bounds for Iowa
ia = {
    'n':  44.0, 's':  40.0,
    'e': -90.0, 'w': -97.0,
}

# connect to the database
import psycopg2

conn = psycopg2.connect('')
cur = conn.cursor()

# drop the table (uncomment if needed)
#query = 'DROP TABLE %s' % (table)
#cur.execute(query)

# create the table
query = '''
CREATE TABLE %s (
dgg INT PRIMARY KEY,
longitude DOUBLE PRECISION,
latitude DOUBLE PRECISION)
''' % (table)
cur.execute(query)

# loop through isea4h9 grid and store the pixels inside the bounds
for line in open('isea4h9.txt'):
    col = line.split()

    # get the DGG, longitude, and latitude
    dgg = int(col[0])
    lon = float(col[1])
    lat = float(col[2])

    # skip points outside of the bounds
    if not ((lat > ia['s'] and lat < ia['n']) and
            (lon > ia['w'] and lon < ia['e'])): continue

    # store points inside bounds
    query = 'INSERT INTO ' + table + ' (dgg, longitude, latitude) VALUES (%s, %s, %s)'
    cur.execute(query, (dgg, lon, lat))

conn.commit()

# create the point geometry
query = "SELECT AddGeometryColumn('%s', 'geom', 4326, 'POINT', 2)" % (table)
cur.execute(query)

query = 'UPDATE %s SET geom = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)' % (table)
cur.execute(query)

conn.commit()

# create the pixel geometry (use UTM zone 15N, SRID 26915)
query = "SELECT AddGeometryColumn('%s', 'geom_43km', 4326, 'POLYGON', 2)" % (table)
cur.execute(query)

radius = 43000./2 # 43 km diameter
query = '''
UPDATE %s
SET geom_43km = ST_Transform(ST_Buffer(ST_Transform(geom, 26915), %f), 4326)
''' % (table, radius)
cur.execute(query)

conn.commit()


import torch
import numpy
from scipy.spatial.distance import cdist
import distance as cuda
from timeit import default_timer as Timer

def cityblock(XA, XB):

    XC = list()
    for xa in XA:
        xa = xa.unsqueeze(0).expand_as(XB)
        XC.append( (xa-XB).abs().sum(0) )
    return torch.stack(XC)

XA = torch.randn(4, 4)
XB = torch.randn(4, 4)
XC = torch.zeros((XA.size(0), XB.size(0)))

print(XA.type())
print(XB.type())
print(XC.type())

start = Timer()
XC = cuda.cdist(XA.to(torch.device('cuda')), XB.to(torch.device('cuda')), "cityblock")
stop = Timer()
print('Time: {}'.format(stop - start))

start = Timer()
XD = cdist(XA.cpu().numpy(), XB.cpu().numpy(), metric="cityblock")
stop = Timer()
print('Time: {}'.format(stop - start))

start = Timer()
XE = cityblock(XA.cpu(), XB.cpu())
stop = Timer()
print('Time: {}'.format(stop - start))

print('diff: {}'.format(numpy.mean(numpy.abs(XC.cpu().numpy() - XD))))
print('diff: {}'.format( numpy.mean( numpy.abs( XC.cpu().numpy() - XE.numpy() ) ) ))
print('diff: {}'.format( numpy.mean( numpy.abs(XD - XE.numpy()) ) ) )

print(XA.cpu().float().numpy())
print(XB.cpu().float().numpy())
print(XC.cpu().float().numpy())
print(XD.astype(numpy.float32))
print(XE.cpu().float().numpy())


import gym
import numpy as np
from gym.wrappers import Monitor

# A states consists of the last images_per_state
class CarRacingEnv(object):
    def __init__(self, vid_path, action_mode, images_per_state=4, time_diff_stack=1, num_skip=2, color="bw"):
        self.n = images_per_state
        self.t = time_diff_stack
        self.num_skip = num_skip
        env = gym.make('CarRacing-v0')
        self.env = Monitor(env, vid_path, force=True)

        self.color = color
        env_obs_shape = self.env.observation_space.shape

        self.obs_shape = (self.n, 3 if color=="rgb" else 1, env_obs_shape[0], env_obs_shape[1])

        imgs_to_store = 1+self.t*(self.n-1)
        self.last_nt_images = np.zeros((imgs_to_store, self.obs_shape[1], self.obs_shape[2], self.obs_shape[3]))

        self.index_to_action = CarRacingEnv.make_action_space(action_mode)

    def new_epsiode(self):
        self.last_nt_images[:, :, :, :] = 0

    def process_img(self, img):
        img = np.transpose(img, (2, 0, 1))

        if self.color == "rgb":
            mean = np.array([0.485, 0.456, 0.406]).reshape((3,1,1))
            std = np.array([0.229, 0.224, 0.225]).reshape((3,1,1))
            norm_img = (img - img.mean(axis=(1,2)).reshape(3,1,1))/img.std(axis=(1,2)).reshape(3,1,1)
            processed_img = norm_img*std + mean
        else:
            img = img.astype(float)

            processed_img = 0.2989 * img[0] + 0.5870 * img[1] + 0.1140 * img[2]
            processed_img /= 255.0
            processed_img = processed_img.reshape((1, 96, 96))

        return processed_img

    @staticmethod
    def make_action_space(action_mode):
        choices = [(0, -1, 1), (0, 1), (0, 0.2)]

        # One or more sub-actions
        if action_mode == "mutually_exclusive":
            actions = [np.zeros(len(choices)),]
            for i, choice in enumerate(choices):
                for val in choice:
                    if val != 0:
                        code = np.zeros(len(choices))
                        code[i] = val
                        actions.append(code)
            return np.stack(actions)
        # Any combination of sub-actions
        elif action_mode == "decoupled":
            actions = []
            code = np.zeros(len(choices))
            for choice_0 in choices[0]:
                code_0 = code.copy()
                code_0[0] = choice_0

                for choice_1 in choices[1]:
                    code_1 = code_0.copy()
                    code_1[1] = choice_1

                    for choice_2 in choices[2]:
                        code_2 = code_1.copy()
                        code_2[1] = choice_2
                        actions.append(code_2)
            return np.stack(actions)
        else:
            assert False, f"Action Mode of {action_mode} is not valid"

    def action_space_size(self):
        return len(self.index_to_action)

    def step(self, action_index, is_train=True):
        action = self.index_to_action[action_index]

        R = 0
        for _ in range(self.num_skip+1):
            self.env.render()
            next_img, r, done, info = self.env.step(action)
            R += r

            next_img = self.process_img(next_img)
            self.last_nt_images[1:, :, :, :] = self.last_nt_images[:-1, :, :, :].copy() # Numpy requires clone
            self.last_nt_images[0, :, :, :] = next_img

            if done:
                break

        output = self.last_nt_images.copy()[::self.t, :, :, :]

        if done: self.new_epsiode()

        return output, R, done, info

    def reset(self):

        img = self.env.reset()
        img = self.process_img(img)
        self.new_epsiode()

        self.last_nt_images[0, :, :, :] = img
        output = self.last_nt_images[::self.t].copy()

        return output

    def close(self):
        self.env.close()

if __name__ == "__main__":
    print( CarRacingEnv.make_action_space("decoupled") )
    print( type(CarRacingEnv.make_action_space("decoupled")) )
    print( CarRacingEnv.make_action_space("mutually_exclusive") )
    print( type(CarRacingEnv.make_action_space("mutually_exclusive")) )


import requests
import datetime
import os
import csv
import pandas as pd
import pickle

def get_time():
    date = datetime.datetime.now()
    return date.strftime('%x').replace('/', '_')

def load_obj(date, country=None):
    """
    Loads existing pickle file to obj.
    :param date: search by date string format: 'DD_MM_YY'
    :param country: If country supplied will look in the output folder for specific country dir
    :return: load pickle file to variable
    """
    # Define paths
    parent = os.path.sep.join(os.getcwd().split(os.path.sep)[:-1])  # Get parent folder
    output_path = os.path.join(os.path.join(parent, 'output'))
    history_path = os.path.join(output_path, 'all_history')
    # Load data
    if country is None:  # If country was not supplied means all history request
        for files in os.listdir(history_path):
            if files.replace('.pickle', '') == date:
                with open(os.path.join(history_path, files), 'rb') as load_file:
                    return pickle.load(load_file)
    else:
        for r, d, f in os.walk(output_path):
            print(f'root: {f}, dir: {d}, file:{f}')
            if (len(r) and country in r) and (len(f) and date + '.pickle' in f):
                with open(os.path.join(r, date + '.pickle'), 'rb') as load_file:
                    return pickle.load(load_file)
    print(f'{date}.pickle not found!')

class request:
    def __init__(self, name=get_time()):
        self.name = name
        self.base = 'https://corona.lmao.ninja/'  # API - endpoint
        self.timePeriod = None
        self.country = None
        self.URL = None
        self.response = None
        self.data = None
        self.df = None

    def create_historical_country_request(self, countryName, daysBack=30):
        """
        Creates a request for historical data for specific country
        for specific duration. Default set to 30 days
        """
        historical_country = f'v2/historical/{countryName}?lastdays={daysBack}'
        self.URL = self.base + historical_country
        self.timePeriod = daysBack
        self.country = countryName
        self.print_url()

    def create_historical_all_request(self, daysBack=30):
        """
        Creates a request for historical data for all countries for specific duration.
        Default set to 30 days
        """
        historical_all = f'v2/historical?lastdays={daysBack}'
        self.URL = self.base + historical_all
        self.timePeriod = daysBack
        self.print_url()

    def send_request(self):
        """
        Sends the request and stores the data in self.data as DICT
        """
        self.response = requests.get(url=self.URL)
        print(f'Request result: {self.response}')
        self.df = pd.read_json(self.response.text)
        self.data = self.response.json()

    def print_url(self):
        """
        Prints the url when the request is created
        """
        print(f'URL set to: {self.URL}')

    def output_data(self):
        parent = os.path.sep.join(os.getcwd().split(os.path.sep)[:-1])  # Get parent folder
        output_path_dir = os.path.join(os.path.join(parent, 'output'))  # ./data_func/output
        if not os.path.exists(output_path_dir):  # check if output folder exists
            os.mkdir(output_path_dir)  # If not create output folder
        country_dir = os.path.join(output_path_dir, self.data['country'])  # ./data_func/output/Israel
        if not os.path.exists(country_dir):  # check if country folder exists
            os.mkdir(country_dir)
        # timeline_dir = os.path.join(country_dir, 'timeline')  # ./data_func/output/Israel/timeline
        # if not os.path.exists(timeline_dir):
        #     os.mkdir(timeline_dir)

        for sir in self.data['timeline'].items():
            with open(os.path.join(country_dir, f'{sir[0]}_{self.name}.csv'), 'w') as output_file:
                header = ['date', 'value']
                dict_writer = csv.DictWriter(output_file, fieldnames=header)

                dict_writer.writeheader()
                for k, v in sir[1].items():
                    dict_writer.writerow({'date': k, 'value': v})

    def save_obj(self):
        """
        Saves the created class to pickle file named as the class name.
        The path is set to ./output/all_history as default.
        If country specified in the class the path is set ot ./output/{country_name}
        """
        parent = os.path.sep.join(os.getcwd().split(os.path.sep)[:-1])  # Get parent folder
        output_path_dir = os.path.join(os.path.join(parent, 'output'))  # ./data_func/output
        if not os.path.exists(output_path_dir):  # check if output folder exists
            os.mkdir(output_path_dir)  # If not create output folder
        history_path = os.path.join(output_path_dir, 'all_history')  # ./data_func/output/all_history
        if self.country is not None:
            history_path = os.path.join(output_path_dir, self.country)
        if not os.path.exists(history_path):
            os.mkdir(history_path)
        # Save pickle obj
        with open(os.path.join(history_path, self.name + '.pickle'), 'wb') as save_file:
            pickle.dump(self, save_file)
            print(f'Saved class: {self.name}.pickle to: {history_path}')
        # Save Data frame as csv
        with open(os.path.join(history_path, self.name + '.csv'), 'w') as save_file:
            self.export_csv(os.path.join(history_path, self.name + '.csv'))
            print(f'Saved class: {self.name}.csv to: {history_path}')

    def export_csv(self, path):
        if self.df is not None:
            self.df.to_csv(path, index=False, header=True)

# Example
# x = request()
# x.create_historical_all_request(90)
# x.send_request()
# x.save_obj()
# print(x)

# x = load_obj('04_13_20')
# print(x)