import os, sys, logging
from configparser import ConfigParser, DEFAULTSECT
from empbase.attach.attachments import EmpAlarm
from empbase.config.defaults import ATTACHMENT_DIRS, DEFAULT_CONFIGS, \
                                    DEFAULT_CFG_FILES, SAVE_CFG_FILE

CATEGORY_MAP = {"Loops"   : "plug_",
                "Signals" : "plug_",
                "Alarms"  : "alarm_"}

def isCommentBlank(line, comments="#;"):
    l = line.strip()
    if l == '': return True
    if l[0] in comments: return True
    if l.split(None,1)[0].lower() == 'rem' and l[0] in 'rR': return True
    return False

class EmpConfigParser(ConfigParser):
    """At its heart, this config parser is a SafeConfigParser. The
    only added functionality is the default configurations automatically
    added and automatic config file validation. Oh, and there are some
    functions for getting certain values quicker.

    EmpConfigParser also is given all the default config variables for
    all the attachments on EMP. This means they can retrieve their
    variables and they can be adjusted by the user at run time.
    """
    def __init__(self, configfile=None):
        """ Check the config file and include the defaults. """
        self.CONFIG_FILES = DEFAULT_CFG_FILES

        if configfile is not None:
            if not os.path.exists(configfile):
                raise IOError("Configuration File does not exist.")

            self.CONFIG_FILES.append(configfile)

        ## now set up the parent class using defaults ##
        ConfigParser.__init__(self)
        #reset internal configparser variable...
        if sys.version_info[0]==3 and sys.version_info[1]<2:
            # i know thats bad form, but this is what happens when
            # you dont think ahead
            self._sections=DEFAULT_CONFIGS
        else:
            #this is in python3.2+ only
            self.read_dict(DEFAULT_CONFIGS)

    def validateInternals(self):
        """ Check all the values you are overwriting from the config
        file.
        """
        self.read(self.CONFIG_FILES)

        ### ### VALIDATION ### ###
        #then check if the update speed is valid, must be >= 1 minute
        if self.getfloat("Daemon","update-speed") < 1.0:
            self.set("Daemon","update-speed", 1.0)

        #first check logging capabilities.
        if self.getboolean("Logging","logging-on"):
            self.__try_setup_path(self.get("Logging","log-file"))

    def __try_setup_path(self,path):
        if os.path.exists(path):
            return os.access(path, os.W_OK)
        else:
            try:
                dirs, _ = os.path.split(path)
                if not os.path.exists(dirs):
                    os.makedirs(os.path.abspath(dirs))
            except:
                return False
            return True

    def getAttachmentVars(self, module):
        """Returns a TinyCfgPrsr of the attachment's variables that were in
        saved to smtg's config file. TinyCfgPrsr provides some utility functions
        for retrieving the types of variable that were stored there.
        """
        if type(module) is not str:
            raise TypeError("Plugin Name must be a string")

        savedir = self.get("Daemon", "save-dir")
        attach_name="plug_"+module
        try: return TinyCfgPrsr(dict(self.items(attach_name)))
        except:
            attach_name="alarm_"+module
            try: return TinyCfgPrsr(dict(self.items(attach_name)),savedir)
            except: return TinyCfgPrsr({},savedir)

    def getAttachmentDirs(self):
        """ Gets the directories that attachments can be found in."""
        #TODO: ?? allow to be changable via cfg file ??
        return ATTACHMENT_DIRS

    def getRegistryFile(self):
        """ The registry file to be read in by the Registry object. """
        return self.get("Daemon","registry-file")

    def defaultAttachmentVars(self, module, defaults, category):
        """Called by SmtgPluginManager and SmtgAlertManager to load the default
        configurations into the database for use later.
        """
        section = CATEGORY_MAP[category]+module
        if not self.has_section(section):
            self.add_section(section)

        for option in defaults.keys():
            if not self.has_option(section, option):
                self.set(section, option, defaults[option])

    def getlist(self, section, option, default=[]):
        """ Utility function for getting a list from the config file.
        The format for saving them is easy too. """
        try:
            val = self.get(section, option)
            return str(val).split(",")
        except:
            return default

    def save(self, attachments):
        """ Save the configurations to the local user's configuration. """
        if SAVE_CFG_FILE is not None:
            # update the plug-in variables before saving.
            for attach in attachments:
                try:
                    attach.plugin_object.save() #make the plugin save before pulling the configs

                    if isinstance(attach.plugin_object, EmpAlarm):
                        for key in attach.plugin_object.config.keys():
                            self.set("alarm_"+attach.module, str(key), str(attach.plugin_object.config[key]))
                    else:
                        for key in attach.plugin_object.config.keys():
                            self.set("plug_"+attach.module,key,str(attach.plugin_object.config[key]))
                        #else, it doesn't matter
                except Exception as e:
                    logging.exception(e)

            # make sure it exists and can be written to.
            logging.debug("Trying to save cfg to: %s"%SAVE_CFG_FILE)
            if self.__try_setup_path(SAVE_CFG_FILE):
                fp=None
                try: fp = open(SAVE_CFG_FILE, mode="r+")
                except:# new file
                    fp = open(SAVE_CFG_FILE, mode="w+")
                    fp.write("#\n# EMP CONFIGS\n#")
                self.update_myfile(fp)
                logging.debug("Saved to cfg file!")
            else:
                logging.error("Couldn't write to cfg file, it cant be created.")

    def update_myfile(self, fp, add_missing=True):
        """ This function was suppose to be released as a standard in
        python3.2 when they overhauled the configparser module, but they
        didn't. See:
                     http://bugs.python.org/issue1410680
        I included it as a different name, in case they do end up adding it
        later... sigh... I would have thought this would be a more important
        feature request. Obviously the python gods thought otherwise.

        Oh, I changed a lot since it was messing with variable order and adding
        random newlines and spacing. I also pushed a couple checks into new
        functions so I could adjust things later.
        """
        from io import StringIO
        sections = {}
        current = StringIO()
        replacement = [current]
        sect = None
        opt = None
        written = []
        # Default to " = " to match write(), but use the most recent
        # separator found if the file has any options.
        vi = " = "
        while True:
            line = fp.readline()
            if not line:
                break
            # Comment or blank line?
            if isCommentBlank(line):
                current.write(line)
                continue
            # Continuation line?
            if line[0].isspace() and sect is not None and opt:
                if ';' in line:
                    # ';' is a comment delimiter only if it follows
                    # a spacing character
                    pos = line.find(';')
                    if line[pos-1].isspace():
                        comment = line[pos-1:]
                        # Get rid of the newline, and put in the comment.
                        current.seek(-1, 1)
                        current.write(comment + "\n")
                continue
            # A section header or option header?
            else:
                # Is it a section header?
                mo = self.SECTCRE.match(line)
                if mo:
                    # Remember the most recent section with this name,
                    # so that any missing options can be added to it.
                    if sect:
                        sections[sect] = current
                    sect = mo.group('header')
                    current = StringIO()
                    replacement.append(current)
                    if sect in self.sections():
                        current.write(line)
                    # So sections can't start with a continuation line:
                    opt = None
                # An option line?
                else:
                    mo = self.OPTCRE.match(line)
                    if mo:
                        opt, vi, value = mo.group('option', 'vi', 'value')
                        comment = ""
                        if vi in ('=', ':') and ';' in value:
                            # ';' is a comment delimiter only if it follows
                            # a spacing character
                            pos = value.find(';')
                            if value[pos-1].isspace():
                                comment = value[pos-1:]
                        opt = opt.rstrip().lower()
                        if self.has_option(sect, opt):
                            value = self.get(sect, opt)
                            # Fix continuations.
                            value = value.replace("\n", "\n\t")
                            current.write("%s%s%s %s\n" % (opt, vi, value,
                                                          comment))
                            written.append((sect, opt))
        if sect:
            sections[sect] = current
        if add_missing:
            # Add any new sections.
            sects = [DEFAULTSECT]
            sects.extend(self.sections())
            sects.sort()
            for sect in sects:
                if sect == DEFAULTSECT:
                    opts = self._defaults.keys()
                else:
                    # Must use _section here to avoid defaults.
                    opts = self._sections[sect].keys()
                #opts.sort() <-- dont sort my keys
                if sect in sections:
                    output = sections[sect] or current
                else:
                    output = current
                    #only write the non default section headers.
                    if sect is not DEFAULTSECT:
                        output.write("\n[%s]\n" % (sect,))
                    sections[sect] = None
                for opt in opts:
                    if opt != "__name__" and not (sect, opt) in written:
                        value = self.get(sect, opt)
                        # Fix continuations.
                        value = value.replace("\n", "\n\t")
                        output.write("%s%s%s\n" % (opt, vi, value))
                        written.append((sect, opt))
                #output.write("\n")
        # Copy across the new file.
        fp.seek(0)
        fp.truncate()
        for sect in replacement:
            if sect is not None:
                fp.write(sect.getvalue())
        # fp.write("\n")
        fp.close()

class TinyCfgPrsr():
    """ A Utility class to make handling configuration variables easier for
    attachment construction. They mimic the functionality of a standard
    config parser, but minus a lot of un-needed functions and variables. It
    also just holds one section as a dictionary.
    """

    BOOL_CHOICES = {"0":False,"1":True,"no":False,"yes":True,"true":True,
                "false":False,"on":True,"off":False, "":False}

    def __init__(self, dictionary, savedir=""):
        self._savedir = savedir
        self._value = dictionary

    def keys(self):
        """ Returns a list of the variable names."""
        return list(self._value.keys())

    def __getitem__(self, i):
        """ Runs TinyCfgPrsr.get(i, None) to get the string of whatever
        the variable is holding.
        """
        return self.get(i,None)

    def get(self, key, default):
        """ Values are held as strings, so this will return the value
        as a string.
        """
        if key in self._value:
            return self._value[key]
        else: return default

    def getint(self, key, default):
        """ Gets the value held and casts it as an integer, may throw a
        ValueError if there is a problem casting the value.
        """
        if key in self._value:
            return int(self._value[key])
        else: return default

    def getfloat(self, key, default):
        """ Gets the value held and casts it as a float, may throw a
        ValueError if there is a problem casting the value.
        """
        if key in self._value:
            return float(self._value[key])
        else: return default

    def getlist(self, key, default):
        """ Gets the value held and parses it as a list. In the emp.cfg files
        lists are held like this:
            [section]
            islist = value1,value2,value3
            notlist = value
        This means that any list given to TinyCfgPrsr will turn it into this
        string.
        """
        if key in self._value and self._value[key] != '':
            return self._value[key].split(',')
        else: return default

    def getboolean(self, key, default):
        """ Gets the value held and casts it as a boolean, may throw a
        ValueError if there is a problem casting the value.
        """
        if key in self._value:
            res=self._value[key].lower()
            if res in TinyCfgPrsr.BOOL_CHOICES:
                return TinyCfgPrsr.BOOL_CHOICES[res]
            else: return False
        else: return default

    def getgroups(self, grouptag="_g*"):
        """If you want a group of variables TinyCfgPrsr can help you get
        them quickly. Heres an example of what groups are:
            [mysection]
            myinfo = 3843.398
            name_g*1 = bob
            address_g*1 = 123 mystreet rd
            address_2_g*1 = 12345, New Port, State
            name_g*2 = mary
            phone_g*2 = 128739174
        When you call getgroups() you will get back a TinyCfgPrsr with the
        value 'myinfo' since it doesnt belong to a group, and a dictionary
        with two values '1' and '2' (these can be different strings, just
        using numbers for demonstration). These values map to two
        TinyCfgPrsrs with the values on the other side of _g*.
            (eg. name, address, address_2 are the keys in the first
            TinyCfgPrsr and name, phone are the keys in the other.)
        """
        defaults = {}
        groups = {}
        for key in self._value.keys():
            if grouptag in key:
                try:
                    name,group = self.__parsekey(key, grouptag)
                    if group in groups:
                        groups[group].update({name:self._value[key]})
                    else: groups[group] = {name:self._value[key]}
                except: defaults[key] = self._value[key]

        tinygroups = {}
        for key in groups.keys():
            tinygroups[key] = TinyCfgPrsr(groups[key])

        return TinyCfgPrsr(defaults), tinygroups

    def __parsekey(self, key, tag):
        lst = key.split(tag)
        if len(lst) != 2: raise Exception("doesn't have tag")
        else: return lst[0], lst[1]

    def __cvrtList(self, val):
        return ",".join(str(n) for n in val)

    def set(self, key, value):
        """ Converts the value into a string and then saves it in the
        internal configuration index. Can be retrieved by using the
        get methods. Can only save integers, floats, booleans, strings,
        and lists of any of the above. Objects and dictionaries are
        expressly prohibited. (for now)
        """
        if type(value) is list:
            value = self.__cvrtList(value)
        elif type(value) is dict:
            raise Exception("Can't save dictionaries in the config file.")
        elif type(value) is object:
            raise Exception("Can't save objects in the config file.")
        else: value = str(value)
        self._value[key] = value

    def setgroup(self, cfgs, groupname, grouptag="_g*"):
        """ Saves a group of variables as a 'group'. Make sure the
        group name you give is unique from the others, as TinyCfgPrsr
        will not do it for you. If you want a different separator between
        the variable name and the group-name than'_g*' you can, but make
        sure you 'getgroups' with the same separator.

        cfgs can be a dictionary that you make of variable names to values
        (of any valid value), or another TinyCfgParser (as retrieved from
        'getgroups').
        """
        val = {}
        if type(cfgs) is dict: val = cfgs
        elif type(cfgs) is TinyCfgPrsr: val = cfgs._value
        else: raise Exception("invalid value, must be dictionary or TinyCfgPrsr")

        for key in val.keys():
            newkey = key+grouptag+groupname
            self.set(newkey, val[key])

    def getMyEmpSaveDir(self, id):
        """ All attachments should save their information in the save directory
        on the local machine and should only work in their own directory.
        An example would be on linux:
                                    ~/.emp/save/2ejqo2/...
        Where '2ejqo2' is the id of the Attachment.
        """
        return self._savedir+"/"+id+"/"


from itertools import product
from .text import lowers
from .modifier import Result

keypad = {
    2:'abc',
    3:'def',
    4:'ghi',
    5:'jkl',
    6:'mno',
    7:'pqrs',
    8:'tuv',
    9:'wxyz',
}
padback = dict()
for (k, letters) in keypad.items():
    for l in letters:
        padback[l] = k

def to_phone(word):
    return [padback[c.lower()]  if c.lower() in lowers else c for c in word]

def from_phone(sequence):
    strings = [keypad[i] for i in sequence]
    for combo in product(*strings):
        yield Result(''.join(combo), sequence)

def from_word(word):
    return from_phone(to_phone(word))


import os, sys
import chainer
from matplotlib import pylab as plt
import numpy as np
np.random.seed(555)
from image_normalizer import ImageNormalizer
from skimage import io, transform
import numbers
import pandas as pd

class DatasetPreProcessor(chainer.dataset.DatasetMixin):
    def __init__(self, args):
        self.args = args
        self.image_normalizer = ImageNormalizer()
        self.pairs = self.read_paths()
        self.counter = 0
        self.image_size_in_batch = [None, None]  # height, width

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

    def read_paths(self):
        path_label_pairs = []
        for image_path, label in self.__path_label_pair_generator():
            path_label_pairs.append((image_path, label))
        return path_label_pairs

    def __path_label_pair_generator(self):
        with open(self.args.image_pointer_path, 'r') as f_image:
            for image_file_name in f_image:
                image_file_name = image_file_name.rstrip()
                image_full_path = os.path.join(self.args.image_dir_path, image_file_name)

                label_file_name = image_file_name.replace('.png', '_L.npz')
                label_full_path = os.path.join(self.args.image_dir_path, label_file_name)
                if os.path.isfile(image_full_path) and os.path.isfile(label_full_path):
                    yield image_full_path, np.load(label_full_path)['data']
                else:
                    assert False, "error occured at path_label_pair_generator(file is not fined)."

    def __init_batch_counter(self):
        if self.args.train and self.counter==self.args.training_params.batch_size:
            self.counter = 0
            self.image_size_in_batch = [None, None]

    def __set_image_size_in_batch(self, image):
        if self.counter==1:
            resized_h, resized_w = image.shape[:2]
            self.image_size_in_batch = [resized_h, resized_w]

    def load_data(self, indices):
        xs = []
        ys = []

        for idx in indices:
            batch_inputs = self.get_example(idx)
            xs.append(batch_inputs[0])
            ys.append(batch_inputs[1])
        return np.array(xs, dtype=np.float32), np.array(ys, np.int32),

    def get_example(self, index):
        self.counter += 1
        if self.args.debug_mode:
            if self.counter>15:
                assert False, 'stop test'

        path, gt = self.pairs[index]
        image = io.imread(path)

        if image is None:
            raise RuntimeError("invalid image: {}".format(path))

        if self.args.debug_mode:
            plt.figure()
            io.imshow(image)
            plt.show()

        h, w, ch = image.shape

        image, ms, ds = self.resize_image(image)
        gt = gt[ds[0]:(gt.shape[0]-ms[0]+ds[0]),
                ds[1]:(gt.shape[1]-ms[1]+ds[1])]

        image, ms, ds = self.resize_image(image, 0.25)
        gt = gt[::4, ::4]
        gt = gt[ds[0]:(gt.shape[0]-ms[0]+ds[0]),
                ds[1]:(gt.shape[1]-ms[1]+ds[1])]

        if self.args.debug_mode:
            plt.figure()
            io.imshow(image)
            plt.show()

            color_data = pd.read_csv(self.args.label_path)
            restoration([gt], color_data, './', index, 32)

        # オーグメンテーション
        if self.args.aug_params.do_augment:
            image, gt = self.augment_image(image, gt)

        # バッチごとにデータサイズを統一する
        self.__set_image_size_in_batch(image)

        # 画像の正規化
        image = self.image_normalizer.GCN(image)

        if self.args.debug_mode:
            show_image = image.astype(np.uint8)
            plt.figure()
            io.imshow(show_image)
            plt.show()

        # Chainerの入力に合わせてメモリオーダーを変更
        image = image.transpose(2, 0, 1)
        # バッチカウンターの初期化
        self.__init_batch_counter()

        batch_inputs = image.astype(np.float32), np.array(gt, dtype=np.int32)
        return batch_inputs

    def augment_image(self, image, gt):
        orig_h, orig_w, _ = image.shape
        if self.args.aug_params.params.do_scale and self.counter==1:
            image, ms, ds = self.scaling(image)
            h, w, ch = image.shape
            inv_scale = orig_h//h, orig_w//w
            gt = gt[::inv_scale[0], ::inv_scale[1]]

        if self.args.aug_params.params.do_flip:
            image, gt = self.flip(image, gt)

        if self.args.aug_params.params.change_britghtness:
            image = self.random_brightness(image)

        if self.args.aug_params.params.change_contrast:
            image = self.random_contrast(image)

        return image, gt

    def resize_image(self, image, scale=None):
        xh, xw = image.shape[:2]

        if scale is None:
            # スケールの定義
            h_scale = (xh//chainer.config.user_multiple)*chainer.config.user_multiple/xh
            w_scale = (xw//chainer.config.user_multiple)*chainer.config.user_multiple/xw
            scale = h_scale, w_scale
        elif isinstance(scale, numbers.Number):
            scale = scale, scale
        elif isinstance(scale, tuple) and len(scale)>2:
            raise InvalidArgumentError

        new_sz = (int(xh*scale[0]), int(xw*scale[1]))
        image = transform.resize(image, new_sz, mode='constant')

        xh, xw = image.shape[:2]
        m0, m1 = xh % chainer.config.user_multiple, xw % chainer.config.user_multiple
        d0, d1 = np.random.randint(m0+1), np.random.randint(m1+1)

        image = image[d0:(image.shape[0] - m0 + d0), d1:(image.shape[1] - m1 + d1)]

        if len(image.shape)==2:
            return image.reshape((image.shape[0], image.shape[1], 1))
        else:
            return image, (m0, m1), (d0, d1)

    def flip(self, image, gt):
        do_flip_xy = np.random.randint(0, 2)
        do_flip_x = np.random.randint(0, 2)
        do_flip_y = np.random.randint(0, 2)

        if do_flip_xy: # X,Y軸の反転
            image = image[::-1, ::-1, :]
            gt = gt[::-1, ::-1]
        elif do_flip_x: # X軸の反転
            image = image[::-1, :, :]
            gt = gt[::-1, :]
        elif do_flip_y: # Y軸の反転
            image = image[:, ::-1, :]
            gt = gt[:, ::-1]
        return image, gt,

    def scaling(self, image):
        do_scale = np.random.randint(0, 2)
        if do_scale:
            scale = self.args.aug_params.params.scale[ \
                np.random.randint(0,len(self.args.aug_params.params.scale))]
            return self.resize_image(image, scale)
        else:
            return image, None, None

    def random_brightness(self, image, max_delta=63, seed=None):
        brightness_flag = np.random.randint(0, 2)
        if brightness_flag:
            delta = np.random.uniform(-max_delta, max_delta)
            return image + delta
        else:
            return image

    def random_contrast(self, image, lower=0.2, upper=1.8, seed=None):
        contrast_flag = np.random.randint(0, 2)
        if contrast_flag:
            factor = np.random.uniform(-lower, upper)
            im_mean = image.mean(axis=2)
            return ((image.transpose(2, 0, 1) - im_mean)*factor + im_mean).transpose(1,2,0).astype(np.uint8)
        else:
            return image


import io
import os
import re
from collections import namedtuple
from typing import Union, List
from urllib.parse import urljoin, urlsplit

import requests

from .file import File
from .job import Job
from .service import Service

Version = namedtuple('Version', ['client', 'server', 'API'])

class SlivkaClient:
    """
    A Client class which will connect to the specified address.
    You can provide a single argument *url* either a string or an
    instance of ``urllib3.util.url.Url`` of you can specify individual
    arguments that will be passed to the ``urllib3.util.url.Url``. This
    method does not check the validity of the URL, its up to the user to
    make sure that URL is correct and points to an existing server.
    """

    def __init__(self, url: str):
        if not re.match(r'(\w+:)?//', url):
            url = 'http://' + url
        self._url = urlsplit(url, scheme='http').geturl()
        self._services = None

    def get_url(self) -> str:
        """Get the URL the client will connect to.

        :rtype: urllib3.util.url.Url
        """
        return self._url

    url = property(get_url)

    def get_version(self) -> Version:
        from . import __version__
        response = requests.get(urljoin(self.url, 'api/version'))
        response.raise_for_status()
        resp_json = response.json()
        return Version(
            client=__version__,
            server=resp_json['slivkaVersion'],
            API=resp_json['APIVersion']
        )

    version = property(get_version)

    def get_services(self) -> List['Service']:
        """Return the list of services.

        :rtype: list[slivka_client.Service]
        """
        if self._services is None:
            self.reload_services()
        return self._services

    services = property(get_services)

    def get_service(self, name):
        try:
            return next(s for s in self.services if s.id == name)
        except StopIteration:
            raise KeyError(name)

    __getitem__ = get_service

    def reload_services(self):
        """Force reloading the services list from the server."""
        response = requests.get(urljoin(self.url, 'api/services'))
        response.raise_for_status()
        self._services = [
            Service.from_response(self.url, service)
            for service in response.json()['services']
        ]

    def upload_file(self,
                    file: Union[str, io.BufferedIOBase],
                    title: str = "") -> File:
        """Upload the file to the server and obtain its handler.

        *file* can be either a stream open for reading or a path.
        If path is provided, the file will be opened in binary mode.
        Optionally, the file title can be specified.

        :return: handler to the file on the server.
        :rtype: slivka_client.File
        """
        if isinstance(file, (str, bytes, os.PathLike)):
            file = open(file, 'rb')
        response = requests.post(
            url=urljoin(self.url, 'api/files'),
            files={'file': (title, file)}
        )
        response.raise_for_status()
        return File.from_response(self.url, response.json())

    def get_file(self, file_id: str) -> File:
        """Create a file handler from file id."""
        parts = file_id.split('/', 1)
        if len(parts) > 1:
            path = f"api/jobs/{parts[0]}/files/{parts[1]}"
        else:
            path = f"api/files/{parts[0]}"
        response = requests.get(urljoin(self.url, path))
        response.raise_for_status()
        return File.from_response(self.url, response.json())

    def get_job(self, job_id: str) -> Job:
        """Create a job handler from job id """
        response = requests.get(urljoin(self.url, f"api/jobs/{job_id}"))
        response.raise_for_status()
        return Job.from_response(self.url, response.json())

    def __repr__(self):
        return 'SlivkaClient(%s)' % self._url


import numpy as np
from scipy.stats import norm

def compute_div_pv(interest, dividends):
    div_pv = 0.
    for div in dividends:
        div_pv += div[0] * np.exp(-1*interest*div[1]/12)
    return div_pv

def black_scholes(S, K, r, sigma, tao):
    d1 = (np.log(S / K) + (r + sigma**2 / 2) * tao) / (sigma * np.sqrt(tao))
    d2 = d1 - sigma * np.sqrt(tao)
    call = S * norm.cdf(d1) - K * np.exp(-1*r*tao) * norm.cdf(d2)
    put = K * np.exp(-1*r*tao) * norm.cdf(-1*d2) - S * norm.cdf(-1*d1)
    return call, put

def main():
    spot_price = 75
    strike = 65
    interest = 6 * 10**(-2)
    tao = 6 / 12
    sigma = 0.35

    dividends = [[1,1], [1,6]]  # (cash div, paied in months)

    div_pv = compute_div_pv(interest, dividends)

    net_spot = spot_price - div_pv
    c, p = black_scholes(S=net_spot,
                         K=strike,
                         r=interest,
                         sigma=sigma,
                         tao=tao)

    print(" - Black-Scholes Option pricing Model - ")
    print("call - %.4f" % c)
    print("put  - %.4f" % p)

"""
 - Black-Scholes Option pricing Model -
call - 12.8136
put  - 2.8580
"""

if __name__ == "__main__":
    main()


from django.contrib import admin
from . models import GolfCourse, Hole

class HoleInline(admin.TabularInline):
    model = Hole
    max_num = 18
    can_delete = False
    exclude = ['hole_id']

class GolfCourseAdmin(admin.ModelAdmin):

    inlines = [HoleInline]
    fieldsets = [(None, {'fields': ['course_name']}),
                 ('Course Total Par', {'fields': ['course_total_par']}), ]
    exclude = ['course_id']
    actions_on_top = False

admin.site.register (GolfCourse, GolfCourseAdmin)


import requests
import json
import logging, time, os, datetime

from bs4 import BeautifulSoup
from django.http import JsonResponse
from fake_useragent import UserAgent
from logging import config, Formatter, getLogger
from logging.handlers import RotatingFileHandler
from selenium import webdriver
from selenium.webdriver import Firefox, Chrome, ChromeOptions
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from rest_framework.views import APIView
from rest_framework.response import Response

from .data import api_text
from .models import Product
from .serializers import ProductSerializer

def create_logger():
    logger = logging.getLogger('OZON_api')
    log_file = 'ozon_api.log'
    log_formatter = logging.Formatter('%(asctime)s %(name)s - %(levelname)s:%(message)s')
    handler = RotatingFileHandler(log_file, mode='a', maxBytes=1*1024*1024, backupCount=60)
    handler.setFormatter(log_formatter)
    logger.addHandler(handler)

    return logger

def open_browser():
    profile = webdriver.FirefoxProfile()
    """
    ПОМЕНЯТЬ ПУТЬ К РАСШИРЕНИЮ
    """
    #profile.add_extension(extension='/usr/ozon/ozon_api/doz4@hotmail.com.xpi')
    #profile.install_addon('/root/.mozilla/extensions/doz4@hotmail.com.xpi', temporary=True)

    cap = DesiredCapabilities.FIREFOX
    cap['marionette'] = True

    options = Options()
    options.headless = True
    options.add_argument("--window-size=1920,1080")
    options.add_argument("--start-maximized")

    """
    ПОМЕНЯТЬ ПУТЬ К ДРАЙВЕРУ
    """
    browser = Firefox(executable_path='/usr/ozon/ozon_api/driver', service_log_path=os.path.devnull, options=options, firefox_profile=profile, capabilities=cap)
    # browser = Firefox(executable_path='/home/element/Projects/ozon_api/ozon_api/driver', service_log_path=os.path.devnull, options=options, firefox_profile=profile, capabilities=cap)
    browser.install_addon('/root/.mozilla/extensions/doz4@hotmail.com.xpi', temporary=True)
    # browser.install_addon('/home/element/Projects/ozon_api/ozon_api/doz4@hotmail.com.xpi', temporary=True)

    browser.maximize_window()
    time.sleep(1)
    browser.get('about:addons')
    time.sleep(1)
    browser.find_element_by_xpath("//button[@title='Extensions']").click()
    time.sleep(2)
    browser.find_element_by_xpath("//div[@class='addon-name-container']").click()
    time.sleep(2)

    prefs = browser.find_element_by_xpath("//button[@class='tab-button'][text()='Preferences']")

    prefs.click()
    time.sleep(0.5)
    prefs.send_keys(Keys.TAB)
    time.sleep(0.5)
    prefs.send_keys(Keys.TAB)
    time.sleep(0.5)
    prefs.send_keys(Keys.TAB)
    time.sleep(0.5)
    prefs.send_keys(Keys.TAB)

    opts = browser.find_element_by_id('addon-inline-options')
    opts.send_keys(Keys.TAB)
    opts.send_keys('************************')
    opts.send_keys(Keys.TAB)
    opts.send_keys(Keys.TAB)
    opts.send_keys(Keys.TAB)
    opts.send_keys(Keys.SPACE)
    opts.send_keys(Keys.TAB)
    opts.send_keys(Keys.SPACE)
    opts.send_keys(Keys.TAB)
    opts.send_keys("1")
    opts.send_keys(Keys.TAB)
    opts.send_keys(Keys.SPACE)
    return browser

class GetProducts(APIView):
    def get(self, request):
        products = Product.objects.all().order_by('id_product')
        serializer = ProductSerializer(products, many=True)
        context = serializer.data
        return JsonResponse(context, safe=False)


import os
import time
from PIL import Image, ImageOps
import random
import numpy as np

import torch
import torch.optim as optim
import torch.nn as nn
import torchvision

from models.snmpnet.snmpnet import Projector
from utils.logger import AverageMeter
from utils import utils

_BASE_PATH = '/home/spaul/windows/TTT-UCDR/src/data'

class Jigsaw_Online:

	def __init__(self, te_query, te_gallery, model, checkpoint, img_transforms, args, device, jig_classes=30, bias_whole_image=0.8):

		self.permutations = self.__retrieve_permutations(jig_classes)
		self.grid_size = 3
		self.bias_whole_image = bias_whole_image # biases the training procedure to show the whole image more often

		self._image_transformer = img_transforms['train']['image']
		self._augment_tile = img_transforms['train']['tile']
		self._eval_transformer = img_transforms['eval']

		def make_grid(x):
			return torchvision.utils.make_grid(x, self.grid_size, padding=0)
		self.returnFunc = make_grid

		self.te_query = te_query
		self.te_gallery = te_gallery
		self.model = model
		self.projector = Projector(args, args.jigsaw_version, 31).to(device)
		self.checkpoint = checkpoint
		self.args = args
		self.device = device

		self.backbone_params = list(self.model.base_model.parameters())[:-2]
		self.classifier_params = self.model.base_model.last_linear.parameters()

		self.opt_net = optim.SGD(self.backbone_params, momentum=0, weight_decay=0, lr=self.args.lr_net)
		self.opt_clf = optim.SGD(list(self.classifier_params) + list(self.projector.parameters()), momentum=self.args.momentum,
								 weight_decay=5e-4, nesterov=bool(self.args.nesterov), lr=self.args.lr_clf)

		self.jig_loss = nn.CrossEntropyLoss()
		self.loss_meter = AverageMeter()

	def get_tile(self, img, n):
		w = float(img.size[0]) / self.grid_size
		y = int(n / self.grid_size)
		x = n % self.grid_size
		tile = img.crop([x * w, y * w, (x + 1) * w, (y + 1) * w])
		tile = self._augment_tile(tile)
		return tile

	def get_tiled_img(self, img):

		n_grids = self.grid_size ** 2
		tiles = [None] * n_grids
		for n in range(n_grids):
			tiles[n] = self.get_tile(img, n)

		order = np.random.randint(len(self.permutations) + 1) # added 1 for class 0: unsorted
		if self.bias_whole_image:
			if self.bias_whole_image > random.random():
				order = 0

		if order == 0:
			data = tiles
		else:
			data = [tiles[self.permutations[order - 1][t]] for t in range(n_grids)]

		data = torch.stack(data, 0)
		data = self.returnFunc(data)

		return [data, order]

	def __retrieve_permutations(self, classes):
		all_perm = np.load(os.path.join(_BASE_PATH, 'permutations_%d.npy' % (classes)))
		# from range [1,9] to [0,8]
		if all_perm.min() == 1:
			all_perm = all_perm - 1

		return all_perm

	def adapt_single_sample(self, img):

		if self.args.online=='std':
			# print('000')
			self.model.load_state_dict(self.checkpoint['model_state_dict'])
			self.projector.reset()

		self.model.train()
		self.projector.train()

		img_domain = img.split('/')[-3]
		if img_domain=='sketch' or img_domain=='quickdraw':
			sample = ImageOps.invert(Image.open(img)).convert(mode='RGB')
		else:
			sample = Image.open(img).convert(mode='RGB')

		for _ in range(self.args.num_iter):
			inputs = [self.get_tiled_img(self._image_transformer(sample)) for _ in range(self.args.batch_size_train)]
			# extract img and label from list of tuples
			inputs_batch, labels_batch = zip(*inputs)
			inputs_batch, labels_batch = torch.stack(inputs_batch).to(self.device), torch.LongTensor(list(labels_batch)).to(self.device)

			self.opt_net.zero_grad()
			self.opt_clf.zero_grad()

			_, im_feat = self.model(inputs_batch)
			if self.args.jigsaw_version==1:
				im_feat = self.model.base_model.last_linear(im_feat)

			pred_var = self.projector(im_feat)
			loss = self.jig_loss(pred_var, labels_batch)
			loss.backward()

			self.opt_net.step()
			self.opt_clf.step()

			self.loss_meter.update(loss.item(), inputs_batch.size(0))

	def test_single_sample(self, img):

		self.model.eval()

		img_domain = img.split('/')[-3]
		img_clss = img.split('/')[-2]

		if img_domain=='sketch' or img_domain=='quickdraw':
			sample = ImageOps.invert(Image.open(img)).convert(mode='RGB')
		else:
			sample = Image.open(img).convert(mode='RGB')

		with torch.no_grad():
			inputs = self._eval_transformer(sample).unsqueeze(0).to(self.device)

			_, im_feat = self.model(inputs)
			im_em = self.model.base_model.last_linear(im_feat)

		return im_em.cpu().data.numpy(), np.expand_dims(np.array(img_clss), axis=0)

	def save_model(self, path_cp, model_save_name):

		utils.save_checkpoint({
							'iter':self.args.num_iter,
							'model_state_dict':self.model.state_dict(),
							'projector_state_dict':self.projector.state_dict()
							}, directory=path_cp, save_name=model_save_name, last_chkpt='')

	def train(self):

		# Start counting time
		start = time.time()

		np.random.shuffle(self.te_query['te'])

		print('\nQuery set size: ', len(self.te_query['te']))
		for i in range(len(self.te_query['te'])):

			self.adapt_single_sample(self.te_query['te'][i])
			sk_em, cls_sk = self.test_single_sample(self.te_query['te'][i])

			# Accumulate sketch embedding
			if i == 0:
				self.acc_sk_em = sk_em
				self.acc_cls_sk = cls_sk
			else:
				self.acc_sk_em = np.concatenate((self.acc_sk_em, sk_em), axis=0)
				self.acc_cls_sk = np.concatenate((self.acc_cls_sk, cls_sk), axis=0)

			if (i+1) % self.args.log_interval == 0:
				print('[Train] [{0}/{1}]\t'
					  'jigsaw loss: {rn.val:.4f} ({rn.avg:.4f})\t'
					  .format(i+1, len(self.te_query['te']), rn=self.loss_meter))

			# if (i+1)==50:
			# 	break

		if self.args.include_gallery:
			np.random.shuffle(self.te_gallery['te_unseen_cls'])

		print('\nGallery set size: ', len(self.te_gallery['te_unseen_cls']))
		for i in range(len(self.te_gallery['te_unseen_cls'])):

			if self.args.include_gallery:
				self.adapt_single_sample(self.te_gallery['te_unseen_cls'][i])

			im_em, cls_im = self.test_single_sample(self.te_gallery['te_unseen_cls'][i])

			# Accumulate image embedding
			if i == 0:
				self.acc_im_em = im_em
				self.acc_cls_im = cls_im
			else:
				self.acc_im_em = np.concatenate((self.acc_im_em, im_em), axis=0)
				self.acc_cls_im = np.concatenate((self.acc_cls_im, cls_im), axis=0)

			if (i+1) % self.args.log_interval == 0:
				print('[Train] [{0}/{1}]\t'
					  'jigsaw loss: {rn.val:.4f} ({rn.avg:.4f})\t'
					  .format(i+1, len(self.te_gallery['te_unseen_cls']), rn=self.loss_meter))

			# if (i+1)==50:
			# 	break

		if self.args.dataset=='DomainNet':
			print('\nSeen gallery set size: ', len(self.te_gallery['te_seen_cls']))
			for i in range(len(self.te_gallery['te_seen_cls'])):

				im_seen_em, cls_seen_im = self.test_single_sample(self.te_gallery['te_seen_cls'][i])

				# Accumulate image embedding
				if i == 0:
					acc_im_seen_em = im_seen_em
					acc_cls_seen_im = cls_seen_im
				else:
					acc_im_seen_em = np.concatenate((acc_im_seen_em, im_seen_em), axis=0)
					acc_cls_seen_im = np.concatenate((acc_cls_seen_im, cls_seen_im), axis=0)

				# if (i+1)==50:
				# 	break

			self.acc_im_em_gzs = np.concatenate((self.acc_im_em, acc_im_seen_em), axis=0)
			self.acc_cls_im_gzs = np.concatenate((self.acc_cls_im, acc_cls_seen_im), axis=0)

			print('\nSeen + Unseen Gallery Emb Dim:{}'.format(self.acc_im_em_gzs.shape))

		print('\nQuery Emb Dim:{}; Gallery Emb Dim:{}.'.format(self.acc_sk_em.shape, self.acc_im_em.shape))

		end = time.time()
		elapsed = end-start
		print(f"Time Taken:{elapsed//60:.0f}m{elapsed%60:.0f}s.\n")

# Jigsaw Puzzle Loss for test time training
def jigsaw_ttt(loader, model, jig_classes, args):

	if args.jigsaw_version==1:
		jig_classifier = nn.Linear(args.semantic_emb_size, jig_classes).cuda()
		classifier_params = list(model.base_model.last_linear.parameters()) + list(jig_classifier.parameters())
	elif args.jigsaw_version==2:
		jig_classifier = nn.Linear(2048, jig_classes).cuda()
		classifier_params = list(jig_classifier.parameters())
	else:
		raise ValueError('Jigsaw version not supported')

	# get list of parameters in model.base_model except model.base_model.last_linear
	backbone_params = list(model.base_model.parameters())[:-2]
	jigen_loss = nn.CrossEntropyLoss()

	opt_net = optim.SGD(backbone_params, momentum=0, weight_decay=0, lr=args.lr_net)
	opt_clf = optim.SGD(classifier_params, momentum=0.9, nesterov=True, weight_decay=5e-4, lr=args.lr_clf)

	model.train()
	jig_loss = AverageMeter()

	for epoch in range(args.epochs):

		# Start counting time
		start = time.time()

		for i, (data, order, cl) in enumerate(loader):

			data = data.float().cuda()
			data1, data2 = torch.split(data, [3, 3], dim=1)

			order = order.long().cuda()

			opt_net.zero_grad()
			opt_clf.zero_grad()

			_, im_feat = model(data2)
			if args.jigsaw_version==1:
				im_feat = model.base_model.last_linear(im_feat)
			jig = jig_classifier(im_feat)

			loss = jigen_loss(jig, order)
			loss.backward()

			opt_net.step()
			opt_clf.step()

			jig_loss.update(loss.item(), data2.size(0))

			if (i+1) % args.log_interval == 0:
				print('[Train] Epoch: [{0}][{1}/{2}]\t'
					  'Jig loss: {jig.val:.4f} ({jig.avg:.4f})\t'
					  .format(epoch+1, i+1, len(loader), jig=jig_loss))

		end = time.time()
		elapsed = end-start
		print(f"Time Taken:{elapsed//60:.0f}m{elapsed%60:.0f}s.\n")

	return model


from game_scripts.utilities import draw_button2
import random
import pygame
pygame.init()

# COLORS
black = (0,0,0)
white = (255,255,255)
pink = (255, 153, 255)
dark_grey = (40,40,40)
grey = (60,60,60)
light_grey = (100,100,100)
yellow = (255,204,0)
green = (51,204,51)
purple = (153,0,255)
orange = (255, 153, 0)
red = (255, 57, 57)
blue = (0, 64, 255)
turquoise = (0, 255, 255)

# FONTS
font_h1 = pygame.font.Font('resources/fonts/Gameplay.ttf', 30)
font_h2 = pygame.font.Font('resources/fonts/Gameplay.ttf', 25)
font_h3 = pygame.font.Font('resources/fonts/Gameplay.ttf', 20)

tetris_panel_width = 400
tetris_panel_height = 800
tetris_panel_X = 250
tetris_panel_Y = 25
tetris_panel = pygame.Rect(tetris_panel_X, tetris_panel_Y, tetris_panel_width, tetris_panel_height)
hold_panel_width = 200
hold_panel_height = 270
hold_panel_X = 25
hold_panel_Y = 50
next_panel_width = 210
next_panel_height = 500
next_panel_X = 670
next_panel_Y = 50

BLOCKSIZE = 40
TEMPLATEWIDTH = 5
TEMPLATEHEIGHT = 5
WINDOWWIDTH = 900
WINDOWHEIGHT = 850
ROWS = 20
COLUMNS = 10
BLANK = '.'

# TETRIS UI FUNCTIONS
def draw_tetris_panels(screen, score=None, lines=None) :
	tetris_panel_border = pygame.Rect(tetris_panel_X-2, tetris_panel_Y-2, tetris_panel_width+4, tetris_panel_height+4)
	tetris_panel = pygame.Rect(tetris_panel_X, tetris_panel_Y, tetris_panel_width, tetris_panel_height)

	hold_panel_border = pygame.Rect(hold_panel_X-2, hold_panel_Y-2, hold_panel_width+4, hold_panel_height+4)
	hold_panel = pygame.Rect(hold_panel_X, hold_panel_Y, hold_panel_width, hold_panel_height)
	hold_space = pygame.Rect(hold_panel_X+10, hold_panel_Y+60, hold_panel_width-20, hold_panel_height-70)

	score_panel_width = 150
	score_panel_height = 300
	score_panel_X = 50
	score_panel_Y = 500
	score_panel_border = pygame.Rect(score_panel_X-2, score_panel_Y-2, score_panel_width+4, score_panel_height+4)
	score_panel = pygame.Rect(score_panel_X, score_panel_Y, score_panel_width, score_panel_height)
	score_space = pygame.Rect(score_panel_X+10, score_panel_Y+60, score_panel_width-20, 50)
	lines_space = pygame.Rect(score_panel_X+10, score_panel_Y+220, score_panel_width-20, 50)

	next_panel_border = pygame.Rect(next_panel_X-2, next_panel_Y-2, next_panel_width+4, next_panel_height+4)
	next_panel = pygame.Rect(next_panel_X, next_panel_Y, next_panel_width, next_panel_height)
	next_space = pygame.Rect(next_panel_X+10, next_panel_Y+60, next_panel_width-20, next_panel_height-70)

	pause_button_size = 100
	pause_button_X = 725
	pause_button_Y = 650
	pause_button_border = pygame.Rect(pause_button_X-2, pause_button_Y-2, pause_button_size+4, pause_button_size+4)
	pause_button = pygame.Rect(pause_button_X, pause_button_Y, pause_button_size, pause_button_size)
	pause_button_simbol_1 = pygame.Rect(pause_button_X+30, pause_button_Y+15, 10, 70)
	pause_button_simbol_2 = pygame.Rect(pause_button_X+60, pause_button_Y+15, 10, 70)

	# 	- TETRIS
	# Panel
	pygame.draw.rect(screen, pink, tetris_panel_border)
	pygame.draw.rect(screen, dark_grey, tetris_panel)

	# 	- HOLD
	# Panel
	pygame.draw.rect(screen, pink, hold_panel_border)
	pygame.draw.rect(screen, dark_grey, hold_panel)
	pygame.draw.rect(screen, black, hold_space, border_radius = 10)

	# Text
	hold_string = 'HOLD'
	hold_text = font_h2.render(hold_string, True, white)
	screen.blit(hold_text, (hold_panel_X+65, hold_panel_Y+15))

	# 	- SCORE / LINES
	# Panel
	pygame.draw.rect(screen, pink, score_panel_border)
	pygame.draw.rect(screen, dark_grey, score_panel)
	pygame.draw.rect(screen, black, score_space, border_radius = 10)
	pygame.draw.rect(screen, black, lines_space, border_radius = 10)

	# Text
	score_string = 'SCORE'
	lines_string = 'LINES'
	score_text = font_h2.render(score_string, True, white)
	lines_text = font_h2.render(lines_string, True, white)
	screen.blit(score_text, (score_panel_X+30, score_panel_Y+15))
	screen.blit(lines_text, (score_panel_X+35, score_panel_Y+175))

	if score != None and lines != None :
		score = font_h3.render(str(score).center(7), True, white)
		lines = font_h3.render(str(lines).center(7), True, white)
		screen.blit(score, (score_panel_X+30, score_panel_Y+70))
		screen.blit(lines, (score_panel_X+30, score_panel_Y+230))

	# 	- NEXT
	# Panel
	pygame.draw.rect(screen, pink, next_panel_border)
	pygame.draw.rect(screen, dark_grey, next_panel)
	pygame.draw.rect(screen, black, next_space, border_radius = 10)

	# Text
	next_string = 'NEXT'
	next_text = font_h2.render(next_string, True, white)
	screen.blit(next_text, (next_panel_X+70, next_panel_Y+15))

	# 	- PAUSE
		# Button
	pygame.draw.rect(screen, pink, pause_button_border, border_radius = 20)
	pygame.draw.rect(screen, black, pause_button, border_radius = 20)
	pygame.draw.rect(screen, white, pause_button_simbol_1)
	pygame.draw.rect(screen, white, pause_button_simbol_2)

def draw_tetris_board(screen) :
	cover_above_board1 = pygame.Rect(tetris_panel_X, 0, tetris_panel_width, 23)
	cover_above_board2 = pygame.Rect(tetris_panel_X, 23, tetris_panel_width, 2)
	pygame.draw.rect(screen, black, cover_above_board1)
	pygame.draw.rect(screen, pink, cover_above_board2)
	for i in range(ROWS):
			pygame.draw.line(screen, light_grey, (tetris_panel_X, tetris_panel_Y+ i*BLOCKSIZE), (tetris_panel_X + tetris_panel_width, tetris_panel_Y + i * BLOCKSIZE))
			for j in range(COLUMNS):
					pygame.draw.line(screen, light_grey, (tetris_panel_X + j * BLOCKSIZE, tetris_panel_Y), (tetris_panel_X + j * BLOCKSIZE, tetris_panel_Y + tetris_panel_height))

def draw_tetris_menu(screen, mouse, record_1_string, record_2_string, record_3_string, record_4_string, record_5_string) :
	# TETRIS LABEL
	tetris_title_string = 'TETRIS'
	tetris_label_width = 300
	tetris_label_height = 110
	tetris_label_X = 300
	tetris_label_Y = 75

	pygame.draw.rect(screen, pink, [tetris_label_X-10, tetris_label_Y-10, tetris_label_width+20, tetris_label_height+20])
	pygame.draw.rect(screen, pink, [tetris_label_X+99-10, tetris_label_Y-10, tetris_label_height+20, tetris_label_width-100+20])

	pygame.draw.rect(screen, purple, [tetris_label_X-8, tetris_label_Y-8, tetris_label_width+16, tetris_label_height+16])
	pygame.draw.rect(screen, purple, [tetris_label_X+99-8, tetris_label_Y-8, tetris_label_height+16, tetris_label_width-100+16])

	pygame.draw.rect(screen, pink, [tetris_label_X-2, tetris_label_Y-2, tetris_label_width+4, tetris_label_height+4])
	pygame.draw.rect(screen, pink, [tetris_label_X+99-2, tetris_label_Y-2, tetris_label_height+4, tetris_label_width-100+4])

	pygame.draw.rect(screen, black, [tetris_label_X, tetris_label_Y, tetris_label_width, tetris_label_height])
	pygame.draw.rect(screen, black, [tetris_label_X+99, tetris_label_Y, tetris_label_height, tetris_label_width-100])

	tetris_font = pygame.font.Font('resources/fonts/UniformBold.ttf', 100)
	tetris_text = tetris_font.render(tetris_title_string, True, white)
	screen.blit(tetris_text, (tetris_label_X+18, tetris_label_Y))

	# START BUTTON
	play_string = '    PLAY'
	play_button_X = 325
	play_button_Y = 350
	draw_button2(screen, play_button_X, play_button_Y, play_string, mouse)

	# HIGH SCORES TABLE
	highscores_string = 'HIGH SCORES'
	highscores_text = font_h1.render(highscores_string, True, white)
	highscores_panel_width = 340
	highscores_panel_height = 320
	highscores_panel_X = 280
	highscores_panel_Y = 470
	highscores_panel_border = pygame.Rect(highscores_panel_X-2, highscores_panel_Y-2, highscores_panel_width+4, highscores_panel_height+4)
	highscores_panel = pygame.Rect(highscores_panel_X, highscores_panel_Y, highscores_panel_width, highscores_panel_height)
	record_1 = pygame.Rect(highscores_panel_X+15, highscores_panel_Y+60, highscores_panel_width-30, 47)
	record_2 = pygame.Rect(highscores_panel_X+15, highscores_panel_Y+109, highscores_panel_width-30, 47)
	record_3 = pygame.Rect(highscores_panel_X+15, highscores_panel_Y+158, highscores_panel_width-30, 47)
	record_4 = pygame.Rect(highscores_panel_X+15, highscores_panel_Y+207, highscores_panel_width-30, 47)
	record_5 = pygame.Rect(highscores_panel_X+15, highscores_panel_Y+256, highscores_panel_width-30, 47)

	record1_text = font_h2.render(record_1_string, True, white)
	record2_text = font_h2.render(record_2_string, True, white)
	record3_text = font_h2.render(record_3_string, True, white)
	record4_text = font_h2.render(record_4_string, True, white)
	record5_text = font_h2.render(record_5_string, True, white)

	pygame.draw.rect(screen, pink, highscores_panel_border)
	pygame.draw.rect(screen, black, highscores_panel)

	pygame.draw.rect(screen, grey, record_1)
	pygame.draw.rect(screen, light_grey, record_2)
	pygame.draw.rect(screen, grey, record_3)
	pygame.draw.rect(screen, light_grey, record_4)
	pygame.draw.rect(screen, grey, record_5)

	screen.blit(highscores_text, (highscores_panel_X+60, highscores_panel_Y+10))
	screen.blit(record1_text, (highscores_panel_X+50, highscores_panel_Y+65,))
	screen.blit(record2_text, (highscores_panel_X+50, highscores_panel_Y+114,))
	screen.blit(record3_text, (highscores_panel_X+50, highscores_panel_Y+163))
	screen.blit(record4_text, (highscores_panel_X+50, highscores_panel_Y+212))
	screen.blit(record5_text, (highscores_panel_X+50, highscores_panel_Y+261))

def draw_tetris_pause(screen, mouse) :
	# Cover background
	pygame.draw.rect(screen, light_grey, tetris_panel)

	# Menu
	pause_string = 'PAUSE'
	pause_menu_size = 350
	pause_menu_X = 275
	pause_menu_Y = 220
	pause_menu_border = pygame.Rect(pause_menu_X-2, pause_menu_Y-2, pause_menu_size+4, pause_menu_size+4)
	pause_menu = pygame.Rect(pause_menu_X, pause_menu_Y, pause_menu_size, pause_menu_size)
	pygame.draw.rect(screen, pink, pause_menu_border)
	pygame.draw.rect(screen, black, pause_menu)
	pause_label = font_h1.render(pause_string, True, white)
	screen.blit(pause_label, (pause_menu_X+125, pause_menu_Y+20))

	# Buttons
	resume_string = '  RESUME'
	controls_string = 'CONTROLS'
	quit_string = '     QUIT'
	resume_button_X = 325
	resume_button_Y = 300
	controls_button_X = 325
	controls_button_Y = 390
	quit_button_X = 325
	quit_button_Y = 480
	draw_button2(screen, resume_button_X, resume_button_Y, resume_string, mouse)
	draw_button2(screen, controls_button_X, controls_button_Y, controls_string, mouse)
	draw_button2(screen, quit_button_X, quit_button_Y, quit_string, mouse)

	# Pause button
	pause_button_size = 100
	pause_button_X = 725
	pause_button_Y = 650
	pause_button_border = pygame.Rect(pause_button_X-2, pause_button_Y-2, pause_button_size+4, pause_button_size+4)
	pause_button = pygame.Rect(pause_button_X, pause_button_Y, pause_button_size, pause_button_size)
	pause_button_simbol_1 = pygame.Rect(pause_button_X+30, pause_button_Y+15, 10, 70)
	pause_button_simbol_2 = pygame.Rect(pause_button_X+60, pause_button_Y+15, 10, 70)
	pygame.draw.rect(screen, purple, pause_button_border, border_radius = 20)
	pygame.draw.rect(screen, black, pause_button, border_radius = 20)
	pygame.draw.rect(screen, pink, pause_button_simbol_1)
	pygame.draw.rect(screen, pink, pause_button_simbol_2)

def draw_tetris_game_over(screen, mouse, score) :
	game_over_string = 'GAME OVER'
	game_over_menu_width = 600
	game_over_menu_height = 350
	game_over_menu_X = 150
	game_over_menu_Y = 220
	game_over_menu_border = pygame.Rect(game_over_menu_X-2, game_over_menu_Y-2, game_over_menu_width+4, game_over_menu_height+4)
	game_over_menu = pygame.Rect(game_over_menu_X, game_over_menu_Y, game_over_menu_width, game_over_menu_height)

	pygame.draw.rect(screen, pink, game_over_menu_border)
	pygame.draw.rect(screen, black, game_over_menu)

	# Score
	score_string = 'SCORE : '+str(score)
	score_label = font_h1.render(score_string, True, white)
	screen.blit(score_label, (game_over_menu_X+175, game_over_menu_Y+100))

	# Buttons
	restart_string = 'RESTART'
	restart_button_X = 180
	restart_button_Y = 470
	quit_string = 'QUIT'
	quit_button_X = 470
	quit_button_Y = 470

	draw_button2(screen, restart_button_X, restart_button_Y, restart_string, mouse)
	draw_button2(screen, quit_button_X, quit_button_Y, quit_string, mouse)

# TETRIS GAME FUNCTIONS

S_SHAPE_TEMPLATE = [['.....',
                     '.....',
                     '..OO.',
                     '.OO..',
                     '.....'],
                    ['.....',
                     '..O..',
                     '..OO.',
                     '...O.',
                     '.....']]

Z_SHAPE_TEMPLATE = [['.....',
                     '.....',
                     '.OO..',
                     '..OO.',
                     '.....'],
                    ['.....',
                     '..O..',
                     '.OO..',
                     '.O...',
                     '.....']]

I_SHAPE_TEMPLATE = [['..O..',
                     '..O..',
                     '..O..',
                     '..O..',
                     '.....'],
                    ['.....',
                     '.....',
                     'OOOO.',
                     '.....',
                     '.....']]

O_SHAPE_TEMPLATE = [['.....',
                     '.....',
                     '.OO..',
                     '.OO..',
                     '.....']]

J_SHAPE_TEMPLATE = [['.....',
                     '.O...',
                     '.OOO.',
                     '.....',
                     '.....'],
                    ['.....',
                     '..OO.',
                     '..O..',
                     '..O..',
                     '.....'],
                    ['.....',
                     '.....',
                     '.OOO.',
                     '...O.',
                     '.....'],
                    ['.....',
                     '..O..',
                     '..O..',
                     '.OO..',
                     '.....']]

L_SHAPE_TEMPLATE = [['.....',
                     '...O.',
                     '.OOO.',
                     '.....',
                     '.....'],
                    ['.....',
                     '..O..',
                     '..O..',
                     '..OO.',
                     '.....'],
                    ['.....',
                     '.....',
                     '.OOO.',
                     '.O...',
                     '.....'],
                    ['.....',
                     '.OO..',
                     '..O..',
                     '..O..',
                     '.....']]

T_SHAPE_TEMPLATE = [['.....',
                     '..O..',
                     '.OOO.',
                     '.....',
                     '.....'],
                    ['.....',
                     '..O..',
                     '..OO.',
                     '..O..',
                     '.....'],
                    ['.....',
                     '.....',
                     '.OOO.',
                     '..O..',
                     '.....'],
                    ['.....',
                     '..O..',
                     '.OO..',
                     '..O..',
                     '.....']]

PIECES = {'S': S_SHAPE_TEMPLATE,
          'Z': Z_SHAPE_TEMPLATE,
          'J': J_SHAPE_TEMPLATE,
          'L': L_SHAPE_TEMPLATE,
          'I': I_SHAPE_TEMPLATE,
          'O': O_SHAPE_TEMPLATE,
          'T': T_SHAPE_TEMPLATE}

COLORS = [green, red, blue, orange, turquoise, yellow, purple]

def get_piece():
    shape = random.choice(list(PIECES.keys()))
    piece = {'shape': shape,
			'rotation': random.randint(0, len(PIECES[shape]) - 1),
			'x': int(COLUMNS / 2) - int(TEMPLATEWIDTH / 2),
			'y': -4, # start it above the board
			'color': COLORS[list(PIECES.keys()).index(shape)]}
    return piece

def get_empty_board():
	# returns a 10x20 array filled with blanks (.)
    board = []
    for i in range(COLUMNS):
        board.append([BLANK] * ROWS)
    return board

def is_valid_position(board, piece, ad_X=0, ad_Y=0):
	for x in range(TEMPLATEWIDTH):
		for y in range(TEMPLATEHEIGHT):
			above_board = y + piece['y'] + ad_Y < 0
			if (above_board and (0 <= (x + piece['x'] + ad_X) < COLUMNS)) or (PIECES[piece['shape']][piece['rotation']][y][x] == BLANK):
				continue
			if not (0 <= (x + piece['x'] + ad_X) < COLUMNS and (y + piece['y'] + ad_Y) < ROWS):
				return False
			if board[x + piece['x'] + ad_X][y + piece['y'] + ad_Y] != BLANK:
				return False
	return True

def add_piece_to_board(board, piece):
    for x in range(TEMPLATEWIDTH):
        for y in range(TEMPLATEHEIGHT):
            if PIECES[piece['shape']][piece['rotation']][y][x] != BLANK:
                board[x + piece['x']][y + piece['y']] = piece['color']

def draw_board_blocks(screen, board):
    for x in range(COLUMNS):
        for y in range(ROWS):
            draw_block(screen, x, y, board[x][y])

def draw_block(screen, blockx, blocky, color, x_axis=None, y_axis=None):
	# blockx and blocky are variables for the board pieces
	# x_axis and y_axis are variables for drawing the next and hold pieces
    if color == BLANK:
        return
    if x_axis == None and y_axis == None:
        x_axis, y_axis = tetris_panel_X + (blockx * BLOCKSIZE), tetris_panel_Y + (blocky * BLOCKSIZE)
    pygame.draw.rect(screen, color, (x_axis, y_axis, BLOCKSIZE , BLOCKSIZE))

def draw_piece(screen, piece, pixelx=None, pixely=None):
    piece_shape = PIECES[piece['shape']][piece['rotation']]
    if pixelx == None and pixely == None:
        # if pixelx & pixely are specified, use the location stored in the piece data structure
        pixelx, pixely = tetris_panel_X + (piece['x'] * BLOCKSIZE), tetris_panel_Y + (piece['y'] * BLOCKSIZE)

    # draw each of the boxes that make up the piece
    for x in range(TEMPLATEWIDTH):
        for y in range(TEMPLATEHEIGHT):
            if piece_shape[y][x] != BLANK:
                draw_block(screen, None, None, piece['color'], pixelx + (x * BLOCKSIZE), pixely + (y * BLOCKSIZE))

def draw_ui_pieces(screen, next_piece1, next_piece2, hold_piece):
	if next_piece1 != None : draw_piece(screen, next_piece1,  pixelx=next_panel_X+15, pixely=next_panel_Y+90)
	if next_piece2 != None : draw_piece(screen, next_piece2,  pixelx=next_panel_X+15, pixely=next_panel_Y+270)
	if hold_piece != None : draw_piece(screen, hold_piece,  pixelx=hold_panel_X+20, pixely=hold_panel_Y+80)

def remove_complete_lines(board):
	removed_lines = 0
	score = 0
	complete_line = True
	y = ROWS - 1
	while y >= 0:
		for x in range(COLUMNS):
			if board[x][y] == BLANK:
				complete_line = False
				break

		if complete_line:
			# Remove the line and pull blocks down
			for pull_blocks_down in range(y, 0, -1):
				for x in range(COLUMNS):
					board[x][pull_blocks_down] = board[x][pull_blocks_down-1]

			for x in range(COLUMNS):
				board[x][0] = BLANK

			removed_lines += 1
		else:
			complete_line = True
			y -= 1

	if removed_lines == 1 : score = 10
	if removed_lines == 2 : score = 50
	if removed_lines == 3 : score = 250
	if removed_lines == 4 : score = 1000

	return [score, removed_lines]


r"""Extracts import dependencies from a Jsonnet file

    > python get_jsonnet_dependencies.py
    > local thing = import "thing.jsonnet";
    thing.jsonnet
    > local amoguise = import @"C:\Users\sus\Documents\amoguise.libsonnet";
    C:\Users\sus\Documents\amoguise.libsonnet
    > local a = import "a.jsonnet"; local b = importstr "b.txt";
    a.jsonnet
    b.txt

Note: Imports spanning multiple lines won't be found by this script.

"""
import sys
import fileinput
import re
from typing import Optional

# - Unescaping escape sequences

ESCAPE_PATTERN = re.compile(
    r'''
    \\["'/\\bfnrt]  # simple escapes
    |\\u[0-9a-fA-F]{4}  # unicode escape
    ''',
    flags=re.VERBOSE,
)

_SIMPLE_ESCAPES = {
    "b": "\b",
    "f": "\f",
    "n": "\n",
    "r": "\r",
    "t": "\t",
}

def _replace_escape(match):
    string = match[0]
    if string[1] == "u":
        return chr(int(string[2:], base=16))
    return _SIMPLE_ESCAPES.get(string[1], string[1])

# - Extracting import strings

IMPORT_PATTERN = re.compile(
    r'''
        \b
        (?P<func>
            import(?:str)?  # find import or importstr
        )
        \s*
        (?P<at>@)?  # check if verbatim string
        (?P<quote>['"])
        (?P<string>
            (?(at)
                (?:
                    (?P=quote){2}  # doubled quotes get turned into one quote
                    |(?!(?P=quote)).
                )*
                |(?:
                    \\.  # escaped char
                    |(?!\\|(?P=quote)).
                )*
            )
        )
        (?P=quote)
        (?(at)
            (?!(?P=quote))  # makes sure @""" doesnt match
        )
    ''',
    flags=re.VERBOSE,
)

def extract_imports(string: str):
    """Yields all import strings found

    - string is the string to search

        >>> list(extract_imports("import 'sus'"))
        ['sus']
        >>> list(extract_imports("import 'sus' import @'s\e\t''us'"))
        ['sus', "s\\e\t'us"]

    """
    for match in IMPORT_PATTERN.finditer(string):
        string = match["string"]
        if match["at"]:  # Verbatim string
            yield string.replace(match["quote"]*2, match["quote"])
        else:
            yield ESCAPE_PATTERN.sub(_replace_escape, string)

# - Command line

def main(argv: Optional[list[str]] = None):
    """Command line entry point

    - argv => sys.argv[1:]

    """
    if argv is None:
        argv = sys.argv[1:]

    for line in fileinput.input(argv):
        # UX improvement by allowing commented imports during development
        if line.strip().startswith("#") or line.strip().startswith("//"):
            continue
        for string in extract_imports(line):
            print(string)

if __name__ == "__main__":
    main()


import pygame
import random
import math
pygame.init()

#CLASS OF VARIABLES
class DrawInformation:
	BLACK = 0, 0, 0
	WHITE = 183, 196, 208
	GREEN = 0, 255, 0
	RED = 255, 0, 0
	BACKGROUND_COLOR = WHITE

	GRADIENTS = [
		(238, 227, 203),
		(215, 192, 174),
		(150, 126, 118)
	]

	FONT = pygame.font.SysFont('arial', 30)
	LARGE_FONT = pygame.font.SysFont('arial', 40)

	SIDE_PAD = 120
	TOP_PAD = 150

	def __init__(self, width, height, lst):
		self.width = width
		self.height = height

		self.window = pygame.display.set_mode((width, height))
		pygame.display.set_caption("Xenon")
		self.set_list(lst)

	def set_list(self, lst):
		self.lst = lst
		self.min_val = min(lst)
		self.max_val = max(lst)

		self.block_width = round((self.width - self.SIDE_PAD) / len(lst))
		self.block_height = math.floor((self.height - self.TOP_PAD) / (self.max_val - self.min_val))
		self.start_x = self.SIDE_PAD // 2

def draw(draw_info, algo_name, ascending):
	draw_info.window.fill(draw_info.BACKGROUND_COLOR)

	title = draw_info.LARGE_FONT.render(f"{algo_name}", 1, draw_info.GREEN)
	draw_info.window.blit(title, (draw_info.width/2 - title.get_width()/2 , 5))

	controls = draw_info.FONT.render("R - Reset | SPACE - Start Sorting", 1, draw_info.BLACK)
	draw_info.window.blit(controls, (draw_info.width/2 - controls.get_width()/2 , 45))

	sorting = draw_info.FONT.render("I - Insertion Sort | B - Bubble Sort |S -Selection Sort", 1, draw_info.BLACK)
	draw_info.window.blit(sorting, (draw_info.width/2 - sorting.get_width()/2 , 75))

	draw_list(draw_info)
	pygame.display.update()

def draw_list(draw_info, color_positions={}, clear_bg=False):
	lst = draw_info.lst
 #clearing only the portion of screen which is being used for sorting.
	if clear_bg:
		clear_rect = (draw_info.SIDE_PAD//2, draw_info.TOP_PAD,
						draw_info.width - draw_info.SIDE_PAD, draw_info.height - draw_info.TOP_PAD)
		#redrawing
		pygame.draw.rect(draw_info.window, draw_info.BACKGROUND_COLOR, clear_rect)

 #Finding the leftTop(x,y)for each block
	for i, val in enumerate(lst):
		x = draw_info.start_x + i * draw_info.block_width
		y = draw_info.height - (val - draw_info.min_val) * draw_info.block_height

		color = draw_info.GRADIENTS[i % 3]
  #manually recoloring blocks that is being sorted.
		if i in color_positions:
			color = color_positions[i]

		pygame.draw.rect(draw_info.window, color, (x, y, draw_info.block_width, draw_info.height))

	if clear_bg:#if we have redrawn some portion make sure that we update.
		pygame.display.update()

def generate_starting_list(n, min_val, max_val):
	lst = []

	for _ in range(n):
		val = random.randint(min_val, max_val)
		lst.append(val)

	return lst

def selection_sort(draw_info,ascending=True):
  lst=draw_info.lst
  size = len(lst)
  for i in range(size-1):
      smallIndex = i
      for j in range(i, size):
          if lst[j] < lst[smallIndex]:
              smallIndex = j
      lst[i], lst[smallIndex] = lst[smallIndex], lst[i]
      draw_list(draw_info, {i: draw_info.GREEN, j: draw_info.RED}, True)
      yield True
  return lst

def bubble_sort(draw_info, ascending=True):
	lst = draw_info.lst

	for i in range(len(lst) - 1):
		for j in range(len(lst) - 1 - i):
			num1 = lst[j]
			num2 = lst[j + 1]

			if (num1 > num2 and ascending) or (num1 < num2 and not ascending):
				lst[j], lst[j + 1] = lst[j + 1], lst[j]
				#in this block itself we are going to manually draw the blocks sorted.Redraw entire blocks and color present blocks
				draw_list(draw_info, {j: draw_info.GREEN, j + 1: draw_info.RED}, True)
				yield True
				#pausing the bubble sort function everytime a swap happens.Wait for calling this next time
				#this helps to retain control over reset and exit while the program runs.

	return lst

def insertion_sort(draw_info, ascending=True):
	lst = draw_info.lst

	for i in range(1, len(lst)):
		current = lst[i]

		while True:
			ascending_sort = i > 0 and lst[i - 1] > current and ascending
			descending_sort = i > 0 and lst[i - 1] < current and not ascending

			if not ascending_sort and not descending_sort:
				break

			lst[i] = lst[i - 1]
			i = i - 1
			lst[i] = current
			draw_list(draw_info, {i - 1: draw_info.GREEN, i: draw_info.RED}, True)
			yield True

	return lst

def main():
	run = True
	clock = pygame.time.Clock()

	n = 50
	min_val = 0
	max_val = 100

	lst = generate_starting_list(n, min_val, max_val)
	draw_info = DrawInformation(1000, 800, lst)
	sorting = False
	ascending = True

	sorting_algorithm = bubble_sort
	sorting_algo_name = "Bubble Sort"
	sorting_algorithm_generator = None

	while run:
		clock.tick(60)

  #Continously calling the generatoru next method if sorting is true.
		if sorting:
			try:
				next(sorting_algorithm_generator)
			except StopIteration:
				sorting = False
		else:
			draw(draw_info, sorting_algo_name, ascending)

		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				run = False

			if event.type != pygame.KEYDOWN:
				continue

			if event.key == pygame.K_r:
				lst = generate_starting_list(n, min_val, max_val)
				draw_info.set_list(lst)
				sorting = False
			elif event.key == pygame.K_SPACE and sorting == False:
				sorting = True
				#storing the generator object when the sorting algorithm is called.
				sorting_algorithm_generator = sorting_algorithm(draw_info, ascending)
			elif event.key == pygame.K_i and not sorting:
				sorting_algorithm = insertion_sort
				sorting_algo_name = "Insertion Sort"
			elif event.key == pygame.K_b and not sorting:
				sorting_algorithm = bubble_sort
				sorting_algo_name = "Bubble Sort"
			elif event.key == pygame.K_s and not sorting:
				sorting_algorithm = selection_sort
				sorting_algo_name = "Selection Sort"

	pygame.quit()

if __name__ == "__main__":
	main()


#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import argparse
from ete3 import Tree

# 创建解析器
parser = argparse.ArgumentParser(description="Remove branch lengths from a Newick tree.")

# 添加输入文件参数
parser.add_argument("--input", "-i", required=True, help="Input tree file in Newick format")

# 添加输出文件参数
parser.add_argument("--output", "-o", required=True, help="Output tree file without branch lengths")

# 解析命令行参数
args = parser.parse_args()

# 从输入文件中读取Newick格式的树
with open(args.input, 'r') as f:
    tree_str = f.read()

# 将树解析为ete3对象
t = Tree(tree_str)

# 去掉树中的分支长度
for node in t.traverse():
    node.dist = 0

# 将结果写入输出文件
with open(args.output, 'w') as f:
    f.write(t.write())

print("分支长度已经去掉，并已写入文件:", args.output)


import paho.mqtt.client as mqtt
import requests

# MQTT broker details
broker = "test.mosquitto.org"
port = 1883
topic = "http/post"

# HTTP endpoint details
url = "https://httpbin.org/post"
headers = {"Content-Type": "application/json"}
payload = {"key": "Hello MQTT from Python! I am George! I am a student at the University of Patras! I am 23 years old!"}

# MQTT callback functions
def on_connect(client, userdata, flags, rc):
    print("Connected to MQTT broker")
    client.publish(topic, str(payload))

def on_publish(client, userdata, mid):
    print("Message published to MQTT topic")
    send_http_request()

# Send HTTP request
def send_http_request():
    response = requests.request("POST", url, headers=headers, data=str(payload))
    print("HTTP response: " + str(response.status_code))

# Create MQTT client
client = mqtt.Client()

# Set MQTT callback functions
client.on_connect = on_connect
client.on_publish = on_publish

# Connect to MQTT broker
client.connect(broker, port, 60)

# Enable network traffic handling
client.loop_forever()