""" Implementation of Ghostnet """
from collections import namedtuple
import tensorflow as tf
# from GhostNetModule import ConvBlock
from models.decmodel_components.GhostNetModule import GhostModule as MyConv
from models.decmodel_components.GhostNetModule import MyDepthConv as DepthConv
from dec.dec_config import ACTIVATION, ATTENTION
from models.decmodel_components.convblock import ConvBatchNormRelu as CBR
from models.decmodel_components.squeeze_layers import Squeeze_excitation_layer as SElayer

kernel_initializer = tf.contrib.layers.variance_scaling_initializer(2.0)

Conv = namedtuple('Conv', ['kernel', 'stride', 'depth', 'factor', 'se'])
Bottleneck = namedtuple('Bottleneck', ['kernel', 'stride', 'depth', 'factor', 'se'])

_CONV_DEFS_0 = [
    Conv(kernel=[3, 3], stride=2, depth=16, factor=1, se=0),
    Bottleneck(kernel=[3, 3], stride=1, depth=16, factor=1, se=0),

    Bottleneck(kernel=[3, 3], stride=2, depth=24, factor=48 / 16, se=0),
    Bottleneck(kernel=[3, 3], stride=1, depth=24, factor=72 / 24, se=0),

    Bottleneck(kernel=[5, 5], stride=2, depth=40, factor=72 / 24, se=1),
    Bottleneck(kernel=[5, 5], stride=1, depth=40, factor=120 / 40, se=1),

    Bottleneck(kernel=[3, 3], stride=2, depth=80, factor=240 / 40, se=0),
    Bottleneck(kernel=[3, 3], stride=1, depth=80, factor=200 / 80, se=0),
    Bottleneck(kernel=[3, 3], stride=1, depth=80, factor=184 / 80, se=0),
    Bottleneck(kernel=[3, 3], stride=1, depth=80, factor=184 / 80, se=0),

    Bottleneck(kernel=[3, 3], stride=1, depth=112, factor=480 / 80, se=1),
    Bottleneck(kernel=[3, 3], stride=1, depth=112, factor=672 / 112, se=1),
    Bottleneck(kernel=[5, 5], stride=2, depth=160, factor=672 / 112, se=1),

    Bottleneck(kernel=[5, 5], stride=1, depth=160, factor=960 / 160, se=0),
    Bottleneck(kernel=[5, 5], stride=1, depth=160, factor=960 / 160, se=1),
    Bottleneck(kernel=[5, 5], stride=1, depth=160, factor=960 / 160, se=0),
    Bottleneck(kernel=[5, 5], stride=1, depth=160, factor=960 / 160, se=1),

]

def shape2d(a):
    """
    Ensure a 2D shape.

    Args:
        a: a int or tuple/list of length 2

    Returns:
        list: of length 2. if ``a`` is a int, return ``[a, a]``.
    """
    if type(a) == int:
        return [a, a]
    if isinstance(a, (list, tuple)):
        assert len(a) == 2
        return list(a)
    raise RuntimeError("Illegal shape: {}".format(a))

def ghostnet_base(inputs,
                  mode,
                  data_format,
                  min_depth=8,
                  depth_multiplier=1.0,
                  depth=1.0,
                  conv_defs=None,
                  output_stride=None,
                  dw_code=None,
                  ratio_code=None,
                  se=1,
                  scope=None,
                  is_training=False,
                  momentum=0.9):

    """ By adjusting depth_multiplier can change the depth of network """
    if data_format == 'channels_first':
        axis = 1
        inputs = tf.transpose(inputs, [0, 3, 1, 2])
    else:
        axis = -1

    output_layers = []

    def depth(d):
        d = max(int(d * depth_multiplier), min_depth)
        d = round(d / 4) * 4
        return d

    # Used to find thinned depths for each layer.
    if depth_multiplier <= 0:
        raise ValueError('depth_multiplier is not greater than zero.')

    if conv_defs is None:
        conv_defs = _CONV_DEFS_0

    if dw_code is None or len(dw_code) < len(conv_defs):
        dw_code = [3] * len(conv_defs)
    print('dw_code', dw_code)

    if ratio_code is None or len(ratio_code) < len(conv_defs):
        ratio_code = [2] * len(conv_defs)
    print('ratio_code', ratio_code)

    se_code = [x.se for x in conv_defs]
    print('se_code', se_code)

    if output_stride is not None and output_stride not in [8, 16, 32]:
        raise ValueError('Only allowed output_stride values are 8, 16, 32.')

    with tf.variable_scope(scope, 'MobilenetV2', [inputs]):

        """
        The current_stride variable keeps track of the output stride of the
        activations, i.e., the running product of convolution strides up to the
        current network layer. This allows us to invoke atrous convolution
        whenever applying the next convolution would result in the activations
        having output stride larger than the target output_stride.
        """
        current_stride = 1
        # The atrous convolution rate parameter.
        rate = 1
        net = inputs
        in_depth = 3
        gi = 0

        for i, conv_def in enumerate(conv_defs):
            layer_stride = conv_def.stride
            current_stride *= conv_def.stride
            if layer_stride != 1:
                output_layers.append(net)

            if isinstance(conv_def, Conv):
                # net = ConvBlock(net, depth(conv_def.depth), conv_def.kernel, stride=conv_def.stride,
                #                 name='ConvBlock_{}'.format(i), is_training=is_training, activation=ACTIVATION)
                net = CBR(net, depth(conv_def.depth), conv_def.kernel[0], strides=conv_def.stride, training=is_training,
                          momentum=momentum, mode=mode, name='ConvBlock_{}'.format(i), padding='same', data_format=data_format,
                          activation=ACTIVATION, bn=True, use_bias=False)

            # Bottleneck block.
            elif isinstance(conv_def, Bottleneck):
                # Stride > 1 or different depth: no residual part.
                if layer_stride == 1 and in_depth == conv_def.depth:
                    res = net
                else:
                    res = DepthConv(net, conv_def.kernel, stride=layer_stride, data_format=data_format, name='Bottleneck_block_{}_shortcut_dw'.format(i))
                    res = tf.layers.batch_normalization(res, training=is_training, name='Bottleneck_block_{}_shortcut_dw_BN'.format(i), axis=axis)

                    res = CBR(res, depth(conv_def.depth), 1, 1, training=is_training, momentum=momentum, mode=mode,
                              name='Bottleneck_block_{}_shortcut_1x1'.format(i), padding='same',
                              data_format=data_format, activation=ACTIVATION, bn=True, use_bias=False)

                # Increase depth with 1x1 conv.
                net = MyConv('Bottleneck_block_{}_up_pointwise'.format(i), net, depth(in_depth * conv_def.factor), 1,
                             dw_code[gi], ratio_code[gi], mode=mode, strides=1, data_format=data_format, use_bias=False, is_training=is_training, activation=ACTIVATION, momentum=momentum)

                # Depthwise conv2d.
                if layer_stride > 1:
                    net = DepthConv(net, conv_def.kernel, stride=layer_stride, data_format=data_format, name='Bottleneck_block_{}_depthwise'.format(i))
                    net = tf.layers.batch_normalization(net, training=is_training, name='Bottleneck_block_{}_depthwise_BN'.format(i), axis=axis)

                # SE
                if se_code[i] > 0 and se > 0:
                    if ATTENTION == 'se':
                        # net = SELayer(net, depth(in_depth * conv_def.factor), 4)
                        net = SElayer(net, depth(in_depth * conv_def.factor), depth(in_depth * conv_def.factor)//4, "se_{}".format(i), data_format=data_format)
                # Downscale 1x1 conv.
                net = MyConv('Bottleneck_block_{}_down_pointwise'.format(i), net, depth(conv_def.depth), 1, dw_code[gi],
                             ratio_code[gi], mode=mode, strides=1, data_format=data_format, use_bias=False, is_training=is_training, activation=ACTIVATION, momentum=momentum)

                gi += 1

                # Residual connection?
                net = tf.add(res, net, name='Bottleneck_block_{}_Add'.format(i)) if res is not None else net

            in_depth = conv_def.depth
            # Final end point?
        output_layers.pop(0)
        output_layers.append(net)
        return output_layers


from turtle import Turtle
import random
FONT_20 = ('Courier', 20, 'normal')
FONT_15 = ('Courier', 15, 'normal')

with open('words.txt') as words:
    WORD = words.read().split('\n')
WORDS = list(WORD)

# Create a HangManWords Class and inherit the Turtle Class.
class HangManWords(Turtle):
    def __init__(self):
        super().__init__()
        self.hangman_word = random.choice(WORDS)
        self.word_hint = ' '.join(len(self.hangman_word) * '_')
        self.not_in = 'is not in word :('
        self.lost_a_live = 'You loss a life, guess again!'
        self.hideturtle()
        self.penup()
        self.goto(330, 230)
        self.write(f'Word: {self.word_hint}', move=False, align='right', font=FONT_15)
        self.word_hint = list(len(self.hangman_word) * '_')

# Check the guess letter if it in the generated word
    def check_word(self, guess):
        for letter in range(len(self.hangman_word)):
            if guess == self.hangman_word[letter]:
                self.word_hint[letter] = guess
                self.clear()
                self.goto(80, 100)
                self.write(f'Nice guess mate! :D', move=False, align='right', font=FONT_20)
                self.update_board()
        if ''.join(self.word_hint) == self.hangman_word:
            return True

# Generate a new word when the user gets the letters correctly
    def generate_new_word(self):
        self.clear()
        self.hangman_word = random.choice(WORDS)
        self.word_hint = ' '.join(len(self.hangman_word) * '_')
        self.word_hint = list(len(self.hangman_word) * '_')
        self.update_board()

# Update the word text
    def update_board(self):
        self.word_hint = list(self.word_hint)
        self.goto(330, 230)
        self.write('Word: ' + ' '.join(self.word_hint), move=False, align='right', font=FONT_15)

# Display an error message when the user guess is incorrect
    def error_message(self, guess):
        if guess not in self.hangman_word:
            self.clear()
            self.goto(100, 120)
            self.write(f'letter "{guess.upper()}" ' + self.not_in, move=False, align='right', font=FONT_20)
            self.goto(100, 100)
            self.write(self.lost_a_live, move=False, align='right', font=FONT_20)
            self.update_board()
            return True

# Display the word when the user life gets to Zero
    def display_word(self):
        self.clear()
        self.goto(330, 230)
        self.write(f'Word: {self.hangman_word}', move=False, align='right', font=FONT_15)


import numpy as np
import matplotlib.pyplot as plt
from DPendulum import Pendulum

def s1(y):
    """Transform onto s1"""
    s1_y = []
    for val in y:
        v = val % (2*np.pi)
        if v > np.pi:
            v = v - 2*np.pi
        s1_y.append(v)
    return s1_y

def pi_jumps(y):
    """Return list of places where line between i -> i+1 should be removed."""
    no_line = []
    a = (y + np.pi) // (2*np.pi) / np.pi
    for i in range(len(a)-1):
        if a[i] != a[i+1]:
            no_line.append(i)
    return no_line

def plot_minus_jumps(y1, y2):
    index = [i for i in range(len(y1)-1, -1, -1)]
    discont  = set(pi_jumps(y1) + pi_jumps(y2))
    s_y1 = s1(y1)
    s_y2 = s1(y2)
    discont = list(discont)
    discont.sort()
    separated_points = []
    while index:
        run = [[], []]
        while True:
            j = index.pop()
            run[0].append(s_y1[j])
            run[1].append(s_y2[j])
            if j in discont or j == len(y1)-1:
                separated_points.append(run)
                break
    for r in range(len(separated_points)):
        plt.plot(separated_points[r][0], separated_points[r][1], color = 'b')

def twod_projection(pendulum, *, i=0, j=2):
    y = pendulum.sol()
    label = [r'$\theta_1$', 'r$\omega_1$', 'theta2', 'theta2dot']
    plt.figure(figsize=(15,5))
    a = plt.subplot(1, 3, 1)
    plt.subplots_adjust(wspace=0.5)
    plt.plot(y[i], y[j])
    plt.xlabel(label[i])
    plt.ylabel(label[j])
    b = plt.subplot(1, 3, 2)
    plt.plot(s1(y[i]), s1(y[j]))
    plt.xlabel(label[i])
    plt.ylabel(label[j])
    c = plt.subplot(1, 3, 3)
    plot_minus_jumps(y[i], y[j])
    plt.xlabel(label[i])
    plt.ylabel(label[j])
    plt.show()

def poincare(pendulum, *, var=0, varpos=0, s=True, time=0):
    label = [r'$\theta_1$', r'$\dot{\theta_1}$', r'$\theta_2$', r'$\dot{\theta_2}$']
    label.pop(var)
    y = np.array(pendulum.sol())
    y[0] = s1(y[0])
    y[2] = s1(y[2])
    indices = []
    for i in range(len(y[var]) - 1):
        if y[var][i] < varpos and y[var][i+1] > varpos:
            indices.append(i)
    y = y.T
    points = []
    if indices:
        for i in indices:
            x1, x2 = list(y[i]), list(y[i+1])
            w1, w2 = x1.pop(var), x2.pop(var)
            points.append([(x2[i]*w2 - x1[i]*w1)/(w2-w1) for i in range(3)])
        print(points)
        points = np.array(points).T

        fig = plt.figure(figsize=(15,5))
        a = plt.subplot(1, 3, 1, projection='3d')
        plt.subplots_adjust(wspace=0.5)
        a.scatter3D(points[0], points[1], points[2], s=0.3, c="#00008B")
        a.set_xlabel(label[0])
        a.set_ylabel(label[1])
        a.set_zlabel(label[2])
        b = plt.subplot(1, 3, 2)
        b.scatter(points[0], points[2], s=0.3, c="blue")
        b.set_xlabel(label[0], fontsize='12')
        b.set_ylabel(label[2], fontsize='12')
        c = plt.subplot(1, 3, 3)
        plt.scatter(points[1], points[2], s=0.5, c="#00008B")
        plt.xlabel(label[1], fontsize='12')
        plt.ylabel(label[2], fontsize='12')
        fig.tight_layout
        plt.show()
    else:
        print('No crosses')
        return y

x = 4
m2 = (1-x**2)**2 / (4*x**2)

y0 = [0, 0, np.pi/100, 0]
pendulum = Pendulum(theta1=y0[0], z1=y0[1], theta2=y0[2], z2=y0[3], tmax=300,
                    m2=m2, y0=y0)
poincare(pendulum)


from django.test import TestCase
from unittest.mock import patch

from trades.models import Currency, Trade

class TradeModelTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.unique_id = 'TR1234567'
        cls.sell_currency = Currency.objects.create(name='USD')
        cls.buy_currency = Currency.objects.create(name='EUR')
        Trade.objects.create(string_id=cls.unique_id, sell_currency=cls.sell_currency,
                             sell_amount=10, buy_currency=cls.buy_currency, buy_amount=15, rate=1.5)

    def test_id_uniqueness(self):
        available_id = '1234ASD'
        with patch('core.utils.generate_random_alphanumeric',
                   side_effect=[self.unique_id.strip('TR'), available_id]) as mock_id_randomness:
            Trade.objects.create(sell_currency=self.sell_currency, sell_amount=10,
                                 buy_currency=self.buy_currency, buy_amount=20, rate=2)
            self.assertEqual(mock_id_randomness.call_count, 2)
        self.assertEqual(Trade.objects.count(), 2)


"""Tests standard tap features using the built-in SDK tests library."""

import json
from pathlib import Path

import jsonschema
import pytest
from singer_sdk.testing import get_standard_tap_tests

from tap_atinternet.tap import TapATInternet

with open(Path(__file__).parents[2] / ".secrets/config.gn.json") as f:
    SAMPLE_CONFIG_GN = json.load(f)
with open(Path(__file__).parents[2] / ".secrets/config.sp.json") as f:
    SAMPLE_CONFIG_SP = json.load(f)
with open(Path(__file__).parent / "incremental_catalog.json") as f:
    # you can obtain this file by configuring the tap to incremental sync, and running
    # `meltano elt tap-atinternet target-jsonl --dump catalog`
    INCREMENTAL_CATALOG = json.load(f)

@pytest.fixture
def configs():
    return [SAMPLE_CONFIG_GN, SAMPLE_CONFIG_SP]

# Run standard built-in tap tests from the SDK:
def test_standard_tap_tests(configs):
    """Run standard tap tests from the SDK."""
    for config in configs:
        tests = get_standard_tap_tests(TapATInternet, config=config)
        for test in tests:
            test()

# Additional tests
def test_incremental_sync(configs):
    for config in configs:
        tap = TapATInternet(config=config, catalog=INCREMENTAL_CATALOG)
        tap.run_connection_test()

def test_record_schema(configs):
    """
    Validate the tap records against the provided schema.

    This should part of the SDK standard tests (above), but this not the case yet
    (see https://gitlab.com/meltano/sdk/-/issues/228).

    Note: During ELT pipelines, target can be configured to validate the input records against
    the schema, but this is not an obligation.
    """
    for config in configs:
        tap = TapATInternet(config=config)
        tap.run_connection_test()  # start with this to initialize stream_state

        streams = tap.discover_streams()
        for stream in streams:
            records_iterator = stream.get_records(context=None)
            first_record = next(records_iterator)
            print('Record:\n', first_record)
            print('Schema:\n', stream.schema)
            jsonschema.validate(instance=first_record, schema=stream.schema)


#!/usr/bin/python2.7

from __future__ import print_function
import Tkinter
import tkFileDialog
from collections import OrderedDict
from time import asctime
import sys

class GUIParameter(object):

    def __init__(
        self,
        name,
        widget_type,
        info=None,
        default=None
    ):
        self.name = name
        self.info = info
        self.widget_type = widget_type
        self.default = default
        self.widget = None
        self.value = None

    def __str__(self):
        return "{} = {}".format(
            self.name,
            self.value.get()
        )

class GUI(object):

    def __init__(self, title, parameters, externalRunCommand):
        sys.stderr = self
        sys.stdout = self
        self.root = Tkinter.Tk()
        self.root.winfo_toplevel().title(title)
        self.parameters = OrderedDict(
            (parameter.name, parameter) for parameter in parameters
        )
        self.externalRunCommand = externalRunCommand
        self.createForm()
        self.root.mainloop()

    def createForm(self):
        self.setCustomWidgets()
        self.setDefaultButtons()
        self.setDisplay()

    def setCustomWidgets(self):
        for i, parameter in enumerate(self.parameters.values()):
            self.setCustomWidget(i, parameter)

    def setDefaultButtons(self):
        for i, (name, command) in enumerate(
            [
                # ('Check Parameters', self.checkParameterCommand),
                ('Load Parameters', self.loadParameterCommand),
                ('Save Parameters', self.saveParameterCommand),
                ('Run', self.runCommand),
            ]
        ):
            self.setDefaultButton(name, command, len(self.parameters) + i)

    def setCustomWidget(self, row, parameter):
        Tkinter.Label(
            self.root,
            text=parameter.name
        ).grid(row=row, sticky='w')
        if parameter.widget_type == Tkinter.Entry:
            value = Tkinter.StringVar()
            widget = parameter.widget_type(
                self.root,
                textvariable=value
            )
        elif parameter.widget_type == Tkinter.Checkbutton:
            value = Tkinter.IntVar()
            widget = parameter.widget_type(
                self.root,
                variable=value
            )
        if parameter.default is not None:
            value.set(parameter.default)
        widget.grid(row=row, column=1, sticky='w', )
        info_button = Tkinter.Button(
            self.root,
            text='Info',
            command=lambda info=parameter.info: print(info)
        )
        info_button.grid(row=row, column=2)
        parameter.widget = widget
        parameter.value = value

    def setDefaultButton(self, name, command, row):
        default_button = Tkinter.Button(
            self.root,
            text=name,
            command=command
        )
        default_button.grid(
            row=row,
            column=0,
            columnspan=3,
            sticky='we'
        )

    # def checkParameterCommand(self):
    #     self.triggerActive(False)
    #     # TODO
    #     print("Not implemented")
    #     self.triggerActive(True)

    def loadParameterCommand(self):
        self.triggerActive(False)
        file_name = tkFileDialog.askopenfilename(
            parent=self.root,
            title='Select parameter file'
        )
        if file_name:
            with open(file_name, "rb") as infile:
                for line in infile:
                    if not line.startswith("#") and line.strip():
                        name, value = line.split(" = ")
                        self.parameters[name].value.set(value.rstrip())
            print(
                "Succesfully loaded parameters from {}".format(
                    file_name
                )
            )
        self.triggerActive(True)

    def saveParameterCommand(self):
        self.triggerActive(False)
        file_name = tkFileDialog.asksaveasfilename(
            parent=self.root,
            title='Select parameter file'
        )
        if file_name:
            with open(file_name, "wb") as outfile:
                for parameter in self.parameters.values():
                    outfile.write("{}\n".format(parameter))
            print(
                "Succesfully saved parameters to {}".format(
                    file_name
                )
            )
        self.triggerActive(True)

    def runCommand(self):
        self.triggerActive(False)
        self.externalRunCommand(self)
        self.triggerActive(True)

    def triggerActive(self, active):
        if active:
            state = "normal"
        else:
            state = "disabled"
        for widget in self.root.winfo_children():
            widget.config(state=state)

    def setDisplay(self):
        self.display_indent = 0
        self.display = Tkinter.Text(self.root)
        self.display.grid(
            row=0,
            column=3,
            # rowspan=len(self.parameters) + 4
            rowspan=len(self.parameters) + 3,
            sticky="ns"
        )
        self.display.config(state="disabled")

    def write(self, text):
        self.display.config(state="normal")
        # text = text.rstrip()
        # time = asctime()
        # space = 80 - len(time) - 3
        # chunks = len(text) / space + 1
        # if len(text) % space == 0:
        #     chunks -= 1
        # for i in xrange(chunks):
        #     self.display.insert(
        #         Tkinter.END,
        #         "{} > {}\n".format(
        #             time,
        #             text[space * i: space * (i + 1)]
        #         )
        #     )
        self.display.insert(Tkinter.END, text)
        self.display.update()
        self.display.config(state="disabled")
        # indent_space = "  " * self.display_indent
        # self.display.config(state="normal")
        # self.display.insert(
        #     Tkinter.END,
        #     "{} > {}{}\n".format(asctime(), indent_space, text)
        # )
        # self.display.update()
        # self.display.config(state="disabled")
        # self.display_indent += indent


import gym
from gym import error, spaces, utils
from gym.utils import seeding
import numpy as np
import pandas as pd
import torch

class BatteryEnv(gym.Env):
    def __init__(self, df, Eess=1, SOCmax=1, SOCmin=0, nu=0.9, PowStBy=0):
        self.df = df

        self.Eess = Eess #MWh
        self.SOC = SOCmin #a percentage of capacity
        self.SOCmin = SOCmin
        self.SOCmax = SOCmax
        self.steps = len(self.df)
        self.T = 1 #1 hour
        self.actions = np.zeros(self.steps) #stores historical actions that I take
        self.nu= nu #efficiency
        self.PowStBy = PowStBy
        self.alpha = 0 #apparently this needs to be updated every episodes

        self.reward_total = 0
        self.step = 0
        self.scaling_factor = 1
        # Actions of the format Buy x% of capacity, Sell x% of capacity, Hold, etc.
        self.action_space = spaces.Discrete( 5 )

        lows_array = np.zeros([1,25])
        highs_array = np.ones([1,25])
        lows_array[0] = self.SOCmin
        highs_array = highs_array*(max(self.df['Hourly_USD_per_MWh'])+1)

        highs_array[:,0] = self.SOCmax
        # Prices contains the energy values

        self.observation_space = spaces.Box(low=lows_array, high=highs_array, dtype=np.float16)

    def _next_obs(self):
        prices = self.df.Hourly_USD_per_MWh[self.step:self.step+24].to_numpy()
        done = self.step >= len(self.df)-25
        obs = torch.from_numpy(np.expand_dims(np.append([self.SOC],[prices]), 0)).float()
        # print("STEP: ", self.step, "\n", "obs: ", obs)
        return done, obs

    def eff(self):
        return self.nu

    def deg(self):
        return self.alpha

    def _take_action(self, action, ct):
        '''
        ct = current price of electricity
        action = integer between 0 and 4 inclusive

        Power is in units MW
        '''
        action_type = ACTION_LOOKUP[action]
        #if Power is negative, it's charging. If Power is positive, it's discharging
        Pow_high = min((self.SOC - self.SOCmin)*self.Eess/(self.eff()*self.T), self.Eess/2)
        Pow_low = max((self.SOC - self.SOCmax)*self.Eess/(self.eff()*self.T), -self.Eess/2)
        flag = 0
        if Pow_high < Pow_low: #if the bounds aren't possible -- which shouldnt ever come up
            Pow = 0
        else:
            if action_type == "dischargefull":
                Pow = self.Eess/2
                if not(Pow_low <= Pow <= Pow_high):
                    if Pow > Pow_high:
                        Pow = Pow_high
                        flag = 1
                    elif Pow < Pow_low:
                        Pow = Pow_low
            elif action_type == "dischargehalf":
                Pow = self.Eess/4
                if not(Pow_low <= Pow <= Pow_high):
                    if Pow > Pow_high:
                        Pow = Pow_high
                        flag = 1
                    elif Pow < Pow_low:
                        Pow = Pow_low
            elif action_type == "chargefull":
                Pow = -self.Eess/2
                if not(Pow_low <= Pow <= Pow_high):
                    if Pow > Pow_high:
                        Pow = Pow_high
                    elif Pow < Pow_low:
                        Pow = Pow_low
            elif action_type == "chargehalf":
                Pow = -self.Eess/4
                if not(Pow_low <= Pow <= Pow_high):
                    if Pow > Pow_high:
                        Pow = Pow_high
                    elif Pow < Pow_low:
                        Pow = Pow_low
        if action_type == "rest":
            SOC_dif = 1/self.Eess*self.T*self.PowStBy
            self.SOC -= SOC_dif
            Rt = 0
            self.Pow = 0
        else:
            self.SOC -= 1/self.Eess*self.T*self.eff()*Pow #charging when power is negative
            P_max = self.Eess/2
            # print(ct, Pow, self.alpha,P_max+0.0001)
            Rt = self.scaling_factor*((ct*Pow - self.deg()*abs(Pow))/P_max) + ((flag==1)* -5)
            self.profit += ct*Pow - self.deg()*abs(Pow)
            self.Pow = Pow
        self.step += 1
        return Rt

    def take_step(self, action, current_price):
        self.actions[self.step] = action
        reward = self._take_action(action, current_price)
        self.reward_total += reward
        done, observation = self._next_obs()
        return observation, reward, done

    def reset(self):
        self.SOC = self.SOCmin #a percentage of capacity
        self.actions = np.zeros(self.steps)
        self.step = 0
        self.profit = 0
        self.reward_total = 0
        self.Pow = 0

    def render(self, mode='human'):
        print("SOC:", self.SOC, "action:", self.actions[self.step-1], "profit: ", self.profit, "price", self.df.Hourly_USD_per_MWh[self.step])
        return(self.profit, self.SOCmax, self.reward_total, self.SOC, self.Pow, self.df.Hourly_USD_per_MWh[self.step])

ACTION_LOOKUP = {
    0: "dischargefull", #500 kW -- max(lowerbound, -500)
    1: "dischargehalf", #250 kW
    2: "rest", #0 kW
    3: "chargehalf", #-250kW
    4: "chargefull" #-500 kW
}


import socket as sk
import os

port = 5505 # Port 5505 for proxy server
ip = '127.0.0.1' # Localhost

# Create our proxy server socket
proxySocket = sk.socket(sk.AF_INET, sk.SOCK_STREAM)

# Reuse the port, might not work on Windows
# proxySocket.setsockopt(sk.SOL_SOCKET, sk.SO_REUSEPORT, 1)

# Bind our socket to the ip and port
proxySocket.bind((ip, port))

# Make it into listen mode with backlog queue size of 3
proxySocket.listen(1)

cache_it = True

print("Proxy server is up and running")

current_wd = os.getcwd().replace("\\", "/")

if __name__ == "__main__":
    while True:
        connection, addr = proxySocket.accept() # Block until connection is accepted
        print("Connection established")

        host = "" # Used for storing the host url that will be used for resolving the IP address

        # Receiving the request from the client
        request = connection.recv(1024).decode()
        print(request)

        # This boolean is used for to check if the request has a referer
        # which will be the host if it is found
        found_referer = False

        # First step figure out who the hell is the host
        splitted = request.split('\r\n') # split by \r\n

        for line in splitted:
            if "Referer: " in line:
                # Referer is found in the client request, geti t
                # and then break out of this for loop
                port_index = line.find(f":{port}")
                host = line[port_index + 6:]
                host = host.replace("http://", "")

                first_slash = host.find('/')

                if first_slash != -1:
                    host = host[:first_slash]

                found_referer = True # Set found_referer boolean to be true
                print(host + " is the host")
                break

        # Parse the request, taking away the first slash, and http or https
        parsed_line = request.split('\r\n')[0]
        parsed_line = parsed_line.split(' ')[1]
        parsed_line = parsed_line[1:]
        parsed_line = parsed_line.replace("https://", "")
        parsed_line = parsed_line.replace("http://", "")

        try:
            # Open the file to see if it already exists in cache
            # it will only fetch the html since that's the only thing I'm caching
            cached_file = open(f"{current_wd}/cache/{parsed_line.replace('/', '^')}.html", 'rb')
            print("Cache hit if we reached here")

            # Read the cached response
            cache_response = cached_file.read()

            # Send the response to the client
            connection.sendall(cache_response)
            print("Sent response to client and ending the server")
            connection.close()

            # I have to stop the server after it serves the cached html file
            # or else it will request other files such as favicon which will cause it to crash
            break
        except FileNotFoundError:
            # Here that means the file is not found in cache hence we
            # must retrieve it from the server
            print("File not found in cache hence retrieve from server")

            # No referer which means we have to manually find the host from the request
            if not found_referer:
                # find the first slash
                first_slash = parsed_line.find('/')
                if first_slash == -1:
                    first_slash = len(parsed_line)

                # Get us the host if there is no referer
                host = parsed_line[:first_slash]

                cache_it = True

            # Second find the resource to locate
            first_slash = parsed_line.find('/')

            # If referer is found it means the resource to locate is just parsed line
            if found_referer:
                resource_to_locate = '/' + parsed_line
            # no referer then we have to check whether it is requesting a sub directory or root directory
            elif first_slash == -1 and parsed_line == host:
                resource_to_locate = '/'
            else:
                # incldue the slash
                resource_to_locate = parsed_line[first_slash:]

            # Make the socket that connects to the web server
            proxy_server_socket = sk.socket(sk.AF_INET, sk.SOCK_STREAM)
            proxy_server_socket.settimeout(4)

            try:
                # Try the connection
                proxy_server_socket.connect((host, 80))

                header = f"GET {resource_to_locate} HTTP/1.1\r\nHost: {host}\r\n\r\n"
                print(header)

                # only store the host's html and nothing else!
                if cache_it:
                    # cache the file here, open up a new file if it doesn't exist
                    cache_file = open(f"{current_wd}/cache/{parsed_line.replace('/', '^')}.html", 'wb+')

                # Sent the GET response to the web server
                proxy_server_socket.sendall(header.encode())

                while True:
                    data = proxy_server_socket.recv(1024)
                    if cache_it:
                        cache_file.write(data)
                    # Sent data to the client
                    connection.sendall(data)
            except UnicodeDecodeError:
                print("Cannot decode some characters")
            except sk.gaierror:
                print(f"Cannot connect to host {host}")
            except sk.timeout:
                print("Timed out/Finished fetching resources")

            # Finished sending we will be closing our connections to the connection
            # to the server socket
            # as well as the cache file if we opened it
            print("Closing connection")
            if cache_it:
                cache_file.close()
                cache_it = False
            connection.close()
            proxy_server_socket.close()
        except OSError:
            print("The file name is not valid")
            connection.close()


#!/usr/bin/python3

import sys
import math
import numpy as np
from pca import pca
from gaussian import gaussian

if len(sys.argv)!=7:
  print('Usage: %s <trdata> <trlabels> <ks> <ds> <%%trper> <%%dvper>' % sys.argv[0]);
  sys.exit(1);

X= np.load(sys.argv[1])['X'];
xl=np.load(sys.argv[2])['xl'];
ks=np.fromstring(sys.argv[3],dtype=float,sep=' ');
ds=np.fromstring(sys.argv[4],dtype=int,sep=' ');
trper=int(sys.argv[5]);
dvper=int(sys.argv[6]);

N=X.shape[0];
np.random.seed(23); perm=np.random.permutation(N);
X=X[perm]; xl=xl[perm];

# Selecting a subset for train and dev sets
Ntr=round(trper/100*N);
Xtr=X[:Ntr]; xltr=xl[:Ntr];
Ndv=round(dvper/100*N);
Xdv=X[N-Ndv:]; xldv=xl[N-Ndv:];

#1. Calcular pca con xtr
[m,Mvect] = pca(Xtr);

print('Dimension\tAlpha\tError');
print('-----------\t-------\t----');

for d in ds:
  for k in ks:
    #2.1 proyectar los datos de xtr a ks dimensiones
    Xtr_p = (Xtr - m).dot(Mvect[:,1:d]);
    #2.2 proyectar los datos de xdr a ks dimensiones
    Xdv_p = (Xdv - m).dot(Mvect[:,1:d]);
    #2.3 medir error con la funcion gauss
    error = gaussian(Xtr_p, xltr, Xdv_p, xldv,k); #error con gaussian
    error = round(error,2);
    print('{}\t\t{}\t{}'.format(d,k, error));


import numpy as np
import torch
from typing import Union

EPS = 1e-8

def si_snr(target: Union[torch.tensor, np.ndarray],
           estimate: Union[torch.tensor, np.ndarray]) -> torch.tensor:
    """Calculates SI-SNR estiamte from target audio and estiamte audio. The
    audio sequene is expected to be a tensor/array of dimension more than 1.
    The last dimension is interpreted as time.

    The implementation is based on the example here:
    https://www.tutorialexample.com/wp-content/uploads/2021/12/SI-SNR-definition.png

    Parameters
    ----------
    target : Union[torch.tensor, np.ndarray]
        Target audio waveform.
    estimate : Union[torch.tensor, np.ndarray]
        Estimate audio waveform.

    Returns
    -------
    torch.tensor
        SI-SNR of each target and estimate pair.
    """
    if not torch.is_tensor(target):
        target: torch.tensor = torch.tensor(target)
    if not torch.is_tensor(estimate):
        estimate: torch.tensor = torch.tensor(estimate)

    # zero mean to ensure scale invariance
    s_target = target - torch.mean(target, dim=-1, keepdim=True)
    s_estimate = estimate - torch.mean(estimate, dim=-1, keepdim=True)

    # <s, s'> / ||s||**2 * s
    pair_wise_dot = torch.sum(s_target * s_estimate, dim=-1, keepdim=True)
    s_target_norm = torch.sum(s_target ** 2, dim=-1, keepdim=True)
    pair_wise_proj = pair_wise_dot * s_target / s_target_norm

    e_noise = s_estimate - pair_wise_proj

    pair_wise_sdr = torch.sum(pair_wise_proj ** 2,
                              dim=-1) / (torch.sum(e_noise ** 2,
                                                   dim=-1) + EPS)
    return 10 * torch.log10(pair_wise_sdr + EPS)

def sdr(estimate, target):
    # x: clean speech target
    # n: noise signal
    # y = x + n: noisy input
    # \hat{x} : estimate signal

    # x_target = <x, \hat{x}> / ||x||^2 * x
    # e_noise = <n, \hat{x}> / ||n||^2 * n
    # e_artif = \hat{x} - x_target - e_noise

    # sdr = 10 log10(||x_target||^2 / ||e_noise + e_artif||^2)
    #     = 10 log10(||x_target||^2 / ||\hat{x} - x_target||^2)
    pass


import unittest
import os
from collections import OrderedDict

from breeze import InDirectory, Breeze, NotRequirableError

from . import MockAttr

class TestMain_InDirectory(unittest.TestCase):
    def test_in_directory(self):
        curdir = os.getcwd()
        with InDirectory('/tmp'):
            self.assertEqual('/tmp', os.getcwd())
        self.assertEqual(curdir, os.getcwd())

    def test_in_directory__root(self):
        curdir = os.getcwd()
        testdir = os.path.join(curdir, 'tests')
        with InDirectory('tests', root=curdir):
            self.assertEqual(testdir, os.getcwd())
        self.assertEqual(curdir, os.getcwd())

class TestMain_Breeze(unittest.TestCase):
    def test_filelist(self):
        b = Breeze()
        b.files['foo'] = {'a': 'foo', 'b': 1}
        b.files['bar'] = {'a': 'bar', 'b': 2}
        b.files['baz'] = {'a': 'baz', 'b': 3}
        def fl(*keys):
            return [(k, b.files[k]) for k in keys]

        self.assertEqual(
            fl('foo', 'bar', 'baz'),
            list(b.filelist())
        )
        self.assertEqual(
            fl('bar', 'baz'),
            list(b.filelist(pattern='b*'))
        )
        self.assertEqual(
            fl('bar', 'baz'),
            list(b.filelist(pattern='?a?'))
        )
        self.assertEqual(
            fl('foo'),
            list(b.filelist(pattern='*o'))
        )

        self.assertEqual(
            fl('foo'),
            list(b.filelist(a__eq="foo"))
        )
        self.assertEqual(
            fl('bar', 'baz'),
            list(b.filelist(a__ne="foo"))
        )
        self.assertEqual(
            fl('bar', 'baz'),
            list(b.filelist(not__a__eq="foo"))
        )
        self.assertEqual(
            fl('foo'),
            list(b.filelist(b__lt=2))
        )
        self.assertEqual(
            fl('foo', 'bar'),
            list(b.filelist(b__lte=2))
        )
        self.assertEqual(
            fl('baz'),
            list(b.filelist(b__gt=2))
        )
        self.assertEqual(
            fl('bar', 'baz'),
            list(b.filelist(b__gte=2))
        )
        self.assertEqual(
            fl('bar', 'baz'),
            list(b.filelist(a__re="^.a.$"))
        )
        self.assertEqual(
            fl('bar', 'baz'),
            list(b.filelist(a__fn="b*"))
        )
        self.assertEqual(
            [],
            list(b.filelist(badkey__eq="foo"))
        )
        with self.assertRaises(ValueError):
            list(b.filelist(a__badop="foo"))

    def test_build_filelist(self):
        def _mock_listdir(path):
            if path == '/a':
                return [
                    'b',
                    'bar',
                    'bar.ex',
                    'bar.foo',
                    'inc.foo'
                ]
            if path == '/a/b':
                return [
                    'bar',
                    'bar.ex',
                    'bar.foo',
                    'inc.foo'
                ]

        def _mock_isdir(path):
            return path in ('/a', '/a/b')

        with MockAttr(os, listdir=_mock_listdir), MockAttr(os.path, isdir=_mock_isdir):
            b = Breeze()
            b.config = {
                'source': '/a',
                'include': ['*'],
                'exclude': ['*.ex'],
                'exclude_files': ['*.foo'],
                'include_files': ['inc.foo']
            }

            b.build_filelist()
            self.assertEqual(
                OrderedDict([
                    ('bar', {'source': 'bar', 'destination': 'bar'}),
                    ('inc.foo', {'source': 'inc.foo', 'destination': 'inc.foo'}),
                    ('b/bar', {'source': 'b/bar', 'destination': 'b/bar'}),
                    ('b/inc.foo', {'source': 'b/inc.foo', 'destination': 'b/inc.foo'}),
                ]),
                b.files
            )

    def test__plugin_require(self):
        loaded = []

        class MockRequiredPlugin(object):
            requirable = True
            run_once = False

            def __init__(self):
                loaded.append(self.__class__)

            @classmethod
            def requires(cls):
                return []

        class MockPlugin(MockRequiredPlugin):
            @classmethod
            def requires(cls):
                return [MockRequiredPlugin]

        b = Breeze()
        b._plugin_require(MockPlugin)

        self.assertEqual([MockRequiredPlugin], loaded)

    def test__plugin_require__not_requirable(self):
        loaded = []

        class MockRequiredPlugin(object):
            requirable = False
            run_once = False

            def __init__(self):
                loaded.append(self.__class__)

            @classmethod
            def requires(cls):
                return []

        class MockPlugin(MockRequiredPlugin):
            @classmethod
            def requires(cls):
                return [MockRequiredPlugin]

        b = Breeze()
        with self.assertRaises(NotRequirableError):
            b._plugin_require(MockPlugin)

        self.assertEqual([], loaded)

    def test_plugin(self):
        loaded = []

        class MockRequiredPlugin(object):
            requirable = True
            run_once = False

            def __init__(self):
                loaded.append(self.__class__)

            @classmethod
            def requires(cls):
                return []

        class MockPlugin(MockRequiredPlugin):
            @classmethod
            def requires(cls):
                return [MockRequiredPlugin]

        b = Breeze()
        res = b.plugin(MockPlugin)
        self.assertTrue(res is b)

        self.assertEqual([MockRequiredPlugin, MockPlugin], loaded)

    def test_run(self):
        loaded = []
        run = []

        class MockRequiredPlugin(object):
            requirable = True
            run_once = False

            def __init__(self):
                loaded.append(self.__class__)

            def run(self, breeze):
                run.append(self.__class__)

            @classmethod
            def requires(cls):
                return []

        class MockPlugin(MockRequiredPlugin):
            @classmethod
            def requires(cls):
                return [MockRequiredPlugin]

        b = Breeze()
        res = b.plugin(MockPlugin)
        self.assertTrue(res is b)

        b.run_plugins()
        self.assertEqual([MockRequiredPlugin, MockPlugin], loaded)
        self.assertEqual([MockRequiredPlugin, MockPlugin], run)


# Functions to facilitate demo

import pandas as pd
import numpy as np
import pickle

# Read in the pickle file of the feature space (columns names of X feature matrix)
with open('../../../data/data_subsets/X_cols.pkl', 'rb') as pickle_in:
    X_cols = pickle.load(pickle_in)

all_X_cols = X_cols

top_notes_demo = ['top_0_amalfi_lemon',  'top_0_pink_grapefruit', 'top_1_watermelon',
                  'top_1_mint', 'top_1_earl_grey_tea', 'top_1_champagne', 'top_1_creme_brulee',
                  'top_1_pepper', 'top_1_nutmeg', 'top_1_teak_wood', 'top_1_pine_needles', 'top_1_mountain_air']

# Read in the mini dataframe including top notes listed in top_notes_demo and their corresponding middle and base notes
demo_df = pd.read_csv('../../../data/data_subsets/demo/demo_df.csv')

def get_mid_and_base_notes():

    top_note_sel_top = [col for col in demo_df.columns if ('top' in col) & ('none' not in col)]
    mid_note_sel_top = [col for col in all_X_cols if ('middle' in col) & ('none' not in col)]
    base_note_sel_top = [col for col in all_X_cols if ('base' in col) & ('none' not in col)]

    return mid_note_sel_top, base_note_sel_top

def make_a_fragrance(top):

   # Grab all columns in X feature space
    all_X_cols = X_cols

    # Create a dataframe with the same features as X, set all values to zero
    notes_df = pd.DataFrame(columns = all_X_cols)
    notes_df = notes_df.append([0]).fillna(0).drop(columns = 0)

    top = top

    """Though we'd normally set a seed for reproducibility, that's not the case here because randomly selected variables are part of the fun for the demo!"""
    # np.random.seed(42)

    # Select a middle and base note randomly
    middle_random = np.random.choice(get_mid_and_base_notes()[0])
    base_random = np.random.choice(get_mid_and_base_notes()[1])

    print(f'Random middle note: {middle_random}')
    print(f'Random base note: {base_random}')

    notes_df[top] = 1
    notes_df[middle_random] = 1
    notes_df[base_random] = 1

    # print(notes_df.sum().sum())           # should be 3

    # Sanitize notes names so they're presentable
    # return middle_random[12:].replace('_', ' ').capitalize()

    top_return = f'{top}'
    mid_return = f'{middle_random}'
    base_return = f'{base_random}'
    return top_return, mid_return, base_return
    # return f'{top[0]} (top note) + {middle_random} (middle note) + {base_random} (base note)'

    # Save the synthetic dataframe as a pickle file
    with open('../../../data/data_subsets/demo/synth_df.pkl', 'wb') as pickle_out:
        pickle_out = pickle.dump(notes_df, pickle_out)

    # return notes_df

# Example
# make_a_fragrance('top_1_mountain_air')


from typing import Mapping

import sympy
import sympy.parsing.sympy_parser

class SingularityDetectionException(Exception):
    """
    Thrown in case an error occurs while detecting singularities.
    """
    pass

class SingularityDetection:
    r"""Singularity detection for generated propagator matrix.

    Some ordinary differential equations (ODEs) can be solved analytically: an expression for the solution can be readily derived by algebraic manipulation. This allows us to formulate an "exact integrator", that yields the next state of the system given the current state and the timestep Δt, to floating point (machine) precision [1]_.

    In some cases, an ODE is analytically tractable, but vulnerable to an edge case condition in the generated propagator matrices. Consider the following example: Let the system of ODEs be given by

    .. math::

       y' = A \cdot y

    Then the propagator matrix for a timestep :math:`\Delta t` is

    .. math::

       P = \exp(A \cdot \Delta t)

    which we can use to advance the system

    .. math::

       y(t + \Delta t) = P \cdot y(t)

    If :math:`A` is of the form:

    .. math::

       \begin{bmatrix}
       -a & 0  & 0\\
       1  & -a & 0\\
       0  & 1  & -b
       \end{bmatrix}

    Then the generated propagator matrix contains denominators that include the factor :math:`a - b`. When the parameters are chosen such that :math:`a = b`, a singularity (division by zero fault) occurs. However, the singularity is readily avoided if we assume that :math:`a = b` before generating the propagator, i.e. we start out with the matrix

    .. math::

       \begin{bmatrix}
       -a & 0  & 0\\
       1  & -a & 0\\
       0  & 1  & -a
       \end{bmatrix}

    The resulting propagator contains no singularities.

    This class detects the potential occurrence of such singularities (potential division by zero) in the generated propagator matrix, which occur under certain choices of parameter values. These choices are reported as "conditions" by the ``find_singularities()`` function.

    References
    ----------

    .. [1] Stefan Rotter, Markus Diesmann. Exact digital simulation of time-invariant linear systems with applications to neuronal modeling. Neurobiologie und Biophysik, Institut für Biologie III, Universität Freiburg, Freiburg, Germany Biol. Cybern. 81, 381-402 (1999)
    """

    @staticmethod
    def _is_matrix_defined_under_substitution(A: sympy.Matrix, cond: Mapping) -> bool:
        r"""
        Function to check if a matrix is defined (i.e. does not contain NaN or infinity) after we perform a given set of subsitutions.

        Parameters
        ----------
        A : sympy.Matrix
            input matrix
        cond : Mapping
            mapping from expression that is to be subsituted, to expression to put in its place
        """
        for val in sympy.flatten(A):
            for expr, subs_expr in cond.items():
                if sympy.simplify(val.subs(expr, subs_expr)) in [sympy.nan, sympy.zoo, sympy.oo]:
                    return False

        return True

    @staticmethod
    def _flatten_conditions(cond):
        r"""
        Return a list with conditions in the form of dictionaries
        """
        lst = []
        for i in range(len(cond)):
            if cond[i] not in lst:
                lst.append(cond[i])

        return lst

    @staticmethod
    def _filter_valid_conditions(cond, A: sympy.Matrix):
        filt_cond = []
        for i in range(len(cond)):  # looping over conditions
            if SingularityDetection._is_matrix_defined_under_substitution(A, cond[i]):
                filt_cond.append(cond[i])

        return filt_cond

    @staticmethod
    def _generate_singularity_conditions(A: sympy.Matrix):
        r"""
        The function solve returns a list where each element is a dictionary. And each dictionary entry (condition: expression) corresponds to a condition at which that expression goes to zero.
        If the expression is quadratic, like let's say "x**2-1" then the function 'solve() returns two dictionaries in a list. each dictionary corresponds to one solution.
        We are then collecting these lists in our own list called 'condition'.
        """
        conditions = []
        for expr in sympy.flatten(A):
            for subexpr in sympy.preorder_traversal(expr):  # traversing through the tree
                if isinstance(subexpr, sympy.Pow) and subexpr.args[1] < 0:  # find expressions of the form 1/x, which is encoded in sympy as x^-1
                    denom = subexpr.args[0]  # extracting the denominator
                    cond = sympy.solve(denom, denom.free_symbols, dict=True)  # ``cond`` here is a list of all those conditions at which the denominator goes to zero
                    if cond not in conditions:
                        conditions.extend(cond)

        return conditions

    @staticmethod
    def find_singularities(P: sympy.Matrix, A: sympy.Matrix):
        r"""Find singularities in the propagator matrix :math:`P` given the system matrix :math:`A`.

        Parameters
        ----------
        P : sympy.Matrix
            propagator matrix to check for singularities
        A : sympy.Matrix
            system matrix
        """
        try:
            conditions = SingularityDetection._generate_singularity_conditions(P)
            conditions = SingularityDetection._flatten_conditions(conditions)  # makes a list of conditions with each condition in the form of a dict
            conditions = SingularityDetection._filter_valid_conditions(conditions, A)  # filters out the invalid conditions (invalid means those for which A is not defined)
        except Exception as e:
            raise SingularityDetectionException()

        return conditions


import os
#จัดการ ไฟล์ ในภาษา Python
#อ่าน text file
#open("ชื่อไฟล์","โหมด","เข้ารหัส")   **โหมด read,write,read and write
os.chdir(r"C:\Users\AloneManZ\Desktop\Trainprogrammer\python3")
try:
    fr=open("student.txt","r",encoding="utf-8")   #encoding="utf-8" คือการเข้ารหัสให้อ่านภาษาไทยได้
    print(fr.read()) #.read(5) อ่านข้อความใน fr  พร้อมระบุตัวอักษรที่จะอ่าน
except FileNotFoundError:
    print("หาไฟล์ไม่เจอ")


import os

from pydantic import BaseSettings

class Settings(BaseSettings):
    """Provisioner settings."""

    EVENTING_HOST: str
    CREATE_EVENT_TRIGGER_ENDPOINT: str = "event-triggers"

    class Config:
        """Meta config."""

        env_file = (
            os.environ.get("MAVIS_CONFIG")  # check if the path specified.
            if os.environ.get("MAVIS_CONFIG") is not None
            else "./.env"
        )
        env_file_encoding = "utf-8"
        case_sensitive = True

provisioner_settings = Settings()  # type: ignore


"""String Compression: Implement a method to perform basic string compression
using the counts of repeated characters. For example, the string aabcccccaaa
would become a2b1c5a3. If the "compressed" string would not become smaller than
the original string, your method should return the original string. You can
assume the string has only uppercase and lowercase letters (a - z).
"""

def str_compression(word):
    word = list(word)
    start = 0
    end = 1
    count = 1

    while end < len(word):
        if word[start] == word[end]:
            count += 1
            end += 1
        else:
            # if count is only 1, add to string instead of replacing
            if count == 1:
                word[start:end] += str(count)

            else:
                word[start+1:end] = str(count)
                count = 1

            start += 2
            end = start+1

    # add rest of count
    word[start+1:end] = str(count)

    return "".join(word)

print(str_compression('aabcccccaaa')) # a2b1c5a3
print(str_compression('abccddda')) # a1b1c2d3a1
print(str_compression('abc')) # a1b1c1


import pickle
import datetime
import game
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
#
#  rate a board with scikit-learn.neural_net
#
#
class HitBoardEvaluator:
    def __init__(self, color):
        if color == game.Game.white:
            self.regressor = pickle.load(open("trained_net_white_500_runs_10_4_hidden_nodes.p", "rb"))
        else:
            self.regressor = pickle.load(open("trained_net_red_500_runs_10_4_hidden_nodes.p", "rb"))

        """
        file = open("boards_n_values_35mb.p", "rb")
        X = pickle.load(file)
        y = pickle.load(file)

        X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)

        #print(len(X), len(y), X[0], y[0])

        for i in range(len(y)):
            print(X[i])
        for i in range(len(y)):
            val = (( (int) (y[i]*100))/100 )
            print(val)

        print(len(X))
        """

        #self.regressor = MLPRegressor(solver='adam', alpha=1e-5, hidden_layer_sizes=(5, 2), random_state=1, max_iter=1000)
        #print("Training the net.")
        #self.regressor.fit(X_train, y_train)
        #print("Training finished. Score on test set:", self.regressor.score(X_test, y_test))

    def getBoardRating(self, tokens):
        return self.regressor.predict([tokens])

class WinningColorBoardEvaluator:
    def __init__(self):
        self.regressor = pickle.load(open("trained_net_305000_logistic.p", "rb"))

    def getBoardRating(self, tokens):
        return self.regressor.predict([tokens])

class OnlineBoardEvaluator:
    def __init__(self, netFilename):
        try:
            print("Trying to load neural net:", netFilename +".p")
            self.regressor = pickle.load(open(netFilename +".p", "rb"))
            print("Loading was successful.")
        except:
            print("Creating new neural net.")
            self.regressor = MLPRegressor(solver='adam', alpha=1e-5, activation="logistic", random_state=1, max_iter=1000000,)

        self.filenameBase = netFilename

        self.updates = 0
        self.saveEveryXth = 1

    def getBoardRating(self, tokens):
        return self.regressor.predict([tokens])

    def learnBatch(self, boards, whiteWins, redWins):
        X = boards
        pWhiteWins = [whiteWins[i]/(whiteWins[i] + redWins[i]) for i in range(len(X))]
        pRedWins =  [redWins[i]/(whiteWins[i] + redWins[i]) for i in range(len(X))]
        y = [pWhiteWins[i] - pRedWins[i] for i in range(len(X))]

        #X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)
        #self.regressor.fit(X_train, y_train)
        #print("net score:", self.regressor.score(X_test, y_test))

        self.regressor.partial_fit(X,y)
        self.updates +=1
        if (self.updates >= self.saveEveryXth):
            print("Saving net.")
            dateString = str(datetime.datetime.now())
            pickle.dump(self.regressor, open(self.filenameBase +"_"+ dateString +".p", "xb"))
            pickle.dump(self.regressor, open(self.filenameBase +".p", "wb"))
            self.updates = 0
            print("saving a sample batch.")
            batchFile = open("training_batch_"+ str(self.saveEveryXth) +"_"+ dateString + "_"+ str(len(boards))  +".p", "xb")
            pickle.dump(X, batchFile)
            pickle.dump(y, batchFile)
            pickle.dump(whiteWins, batchFile)
            pickle.dump(redWins, batchFile)
            batchFile.close()

            """
            fig, axes = plt.subplots(8, 8)
            # use global min / max to ensure all weights are shown on the same scale
            vmin, vmax = self.regressor.coefs_[1].min(), self.regressor.coefs_[0].max()
            for coef, ax in zip(self.regressor.coefs_[1].T, axes.ravel()):
                ax.matshow(coef.reshape(28,1), cmap=plt.cm.gray, vmin=.5 * vmin,
                        vmax=.5 * vmax)
                ax.set_xticks(())
                ax.set_yticks(())

            #plt.show()
            plt.savefig("graph_"+ dateString +".png")
            plt.close()
            """


from pywb.warcserver.inputrequest import DirectWSGIInputRequest, POSTInputRequest, MethodQueryCanonicalizer
from werkzeug.routing import Map, Rule

import webtest
from six.moves.urllib.parse import parse_qsl
from io import BytesIO
from pyamf import AMF3
from pyamf.remoting import Request, Envelope, encode

#=============================================================================
class InputReqApp(object):
    def __init__(self):
        self.url_map = Map()
        self.url_map.add(Rule('/test/<path:url>', endpoint=self.direct_input_request))
        self.url_map.add(Rule('/test-postreq', endpoint=self.post_fullrequest))

    def direct_input_request(self, environ, url=''):
        inputreq = DirectWSGIInputRequest(environ)
        return inputreq.reconstruct_request(url)

    def post_fullrequest(self, environ):
        params = dict(parse_qsl(environ.get('QUERY_STRING', '')))
        inputreq = POSTInputRequest(environ)
        return inputreq.reconstruct_request(params['url'])

    def __call__(self, environ, start_response):
        urls = self.url_map.bind_to_environ(environ)
        try:
            endpoint, args = urls.match()
        except HTTPException as e:
            return e(environ, start_response)

        result = endpoint(environ, **args)
        start_response('200 OK', [('Content-Type', 'text/plain; charset=utf-8')])
        return [result]

#=============================================================================
class TestInputReq(object):
    def setup(self):
        self.app = InputReqApp()
        self.testapp = webtest.TestApp(self.app)

    def test_get_direct(self):
        res = self.testapp.get('/test/http://example.com/', headers={'Foo': 'Bar'})
        assert res.text == '\
GET /test/http://example.com/ HTTP/1.0\r\n\
Host: example.com\r\n\
Foo: Bar\r\n\
\r\n\
'

    def test_post_direct(self):
        res = self.testapp.post('/test/http://example.com/', headers={'Foo': 'Bar'}, params='ABC')
        lines = res.text.split('\r\n')
        assert lines[0] == 'POST /test/http://example.com/ HTTP/1.0'
        assert 'Host: example.com' in lines
        assert 'Content-Length: 3' in lines
        assert 'Content-Type: application/x-www-form-urlencoded' in lines
        assert 'Foo: Bar' in lines

        assert 'ABC' in lines

    def test_post_req(self):
        postdata = '\
GET /example.html HTTP/1.0\r\n\
Foo: Bar\r\n\
\r\n\
'
        res = self.testapp.post('/test-postreq?url=http://example.com/', params=postdata)

        assert res.text == '\
GET /example.html HTTP/1.0\r\n\
Host: example.com\r\n\
Foo: Bar\r\n\
\r\n\
'

class TestPostQueryExtract(object):
    @classmethod
    def setup_class(cls):
        cls.post_data = b'foo=bar&dir=%2Fbaz'
        cls.binary_post_data = b'\x816l`L\xa04P\x0e\xe0r\x02\xb5\x89\x19\x00fP\xdb\x0e\xb0\x02,'

    def test_post_extract_1(self):
        mq = MethodQueryCanonicalizer('POST', 'application/x-www-form-urlencoded',
                                len(self.post_data), BytesIO(self.post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST&foo=bar&dir=/baz'

        assert mq.append_query('http://example.com/?123=ABC') == 'http://example.com/?123=ABC&__wb_method=POST&foo=bar&dir=/baz'

    def test_post_extract_json(self):
        post_data = b'{"a": "b", "c": {"a": 2}, "d": "e"}'
        mq = MethodQueryCanonicalizer('POST', 'application/json',
                                len(post_data), BytesIO(post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST&a=b&a.2_=2&d=e'

    def test_put_extract_method(self):
        mq = MethodQueryCanonicalizer('PUT', 'application/x-www-form-urlencoded',
                                len(self.post_data), BytesIO(self.post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=PUT&foo=bar&dir=/baz'

    def test_post_extract_non_form_data_1(self):
        mq = MethodQueryCanonicalizer('POST', 'application/octet-stream',
                                len(self.post_data), BytesIO(self.post_data))

        #base64 encoded data
        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST&__wb_post_data=Zm9vPWJhciZkaXI9JTJGYmF6'

    def test_post_extract_non_form_data_2(self):
        mq = MethodQueryCanonicalizer('POST', 'text/plain',
                                len(self.post_data), BytesIO(self.post_data))

        #base64 encoded data
        assert mq.append_query('http://example.com/pathbar?id=123') == 'http://example.com/pathbar?id=123&__wb_method=POST&__wb_post_data=Zm9vPWJhciZkaXI9JTJGYmF6'

    def test_post_extract_length_invalid_ignore(self):
        mq = MethodQueryCanonicalizer('POST', 'application/x-www-form-urlencoded',
                                0, BytesIO(self.post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST'

        mq = MethodQueryCanonicalizer('POST', 'application/x-www-form-urlencoded',
                                'abc', BytesIO(self.post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST'

    def test_post_extract_length_too_short(self):
        mq = MethodQueryCanonicalizer('POST', 'application/x-www-form-urlencoded',
                                len(self.post_data) - 4, BytesIO(self.post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST&foo=bar&dir=%2'

    def test_post_extract_length_too_long(self):
        mq = MethodQueryCanonicalizer('POST', 'application/x-www-form-urlencoded',
                                len(self.post_data) + 4, BytesIO(self.post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST&foo=bar&dir=/baz'

    def test_post_extract_malformed_form_data(self):
        mq = MethodQueryCanonicalizer('POST', 'application/x-www-form-urlencoded',
                                len(self.binary_post_data), BytesIO(self.binary_post_data))

        #base64 encoded data
        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST&__wb_post_data=gTZsYEygNFAO4HICtYkZAGZQ2w6wAiw='

    def test_post_extract_no_boundary_in_multipart_form_mimetype(self):
        mq = MethodQueryCanonicalizer('POST', 'multipart/form-data',
                                len(self.post_data), BytesIO(self.post_data))

        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=POST&__wb_post_data=Zm9vPWJhciZkaXI9JTJGYmF6'

    def test_options(self):
        mq = MethodQueryCanonicalizer('OPTIONS', '', 0, BytesIO())
        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=OPTIONS'

    def test_head(self):
        mq = MethodQueryCanonicalizer('HEAD', '', 0, BytesIO())
        assert mq.append_query('http://example.com/') == 'http://example.com/?__wb_method=HEAD'

    def test_amf_parse(self):
        mq = MethodQueryCanonicalizer('POST', 'application/x-amf', 0, BytesIO())

        req = Request(target='t', body="")
        ev_1 = Envelope(AMF3)
        ev_1['/0'] = req

        req = Request(target='t', body="alt_content")
        ev_2 = Envelope(AMF3)
        ev_2['/0'] = req

        assert mq.amf_parse(encode(ev_1).getvalue(), None) != \
               mq.amf_parse(encode(ev_2).getvalue(), None)


import numpy as np
import scipy
from scipy import signal
import matplotlib.pyplot as plt
from PIL import Image

def energy_image(image, mask, mean=None, std=None):
    """
    This function computes the energy image using the laplacian kernel.
    :param std: std width in pixels of the path
    :param mean: Mean column of the path
    :param mask: Mask with high value regions to be preserved
    :param image: input image
    :return: updated energy map
    """
    cols_idx = None
    if mean is None and std is None:
        cropped = image[:, :, 0:3]
    else:
        first_col = 0 if int(np.round(mean) - 2*np.ceil(std) - 1) < 0 else int(np.round(mean) - 2*np.ceil(std) - 1)
        last_col = image.shape[1] if int(np.round(mean) + 2*np.ceil(std) + 1) > image.shape[1] \
            else int(np.round(mean) + 2*np.ceil(std) + 1)
        cols_idx = (first_col, last_col)
        cropped = image[:, cols_idx[0]:cols_idx[1], 0:3]

    laplacian = np.array([[0, 1, 0],
                         [1, -4, 1],
                         [0, 1, 0]])
    filter = np.stack([laplacian]*3, axis=2)
    cropped = cropped.astype('float32')
    convolved = np.absolute(scipy.signal.convolve(cropped, filter, mode='same', method='auto'))
    energy_map = convolved.sum(axis=2)  # Sum channels

    out_map = image[:,:,3]
    if mean is None and std is None:
        out_map = energy_map + mask
    else: # Only add the mask in the processed region, if not the values will accumulate to be very large
        out_map[:, cols_idx[0]:cols_idx[1]] = energy_map + mask[:, cols_idx[0]:cols_idx[1]]

    return out_map

def find_row_index(image):
    """
    Get the index with the lowest row sum.
    :param image: input image
    :return: index of row
    """
    rows = np.sum(image, axis=0)
    row_index = np.argmin(rows)
    return row_index

def find_column_index(image):
    """
    Get the index with the lowest column sum.
    :param image: input image
    :return: index of column
    """
    columns = np.sum(image, axis=1)
    column_index = np.argmin(columns)
    return column_index

def cum_cost(matrix, mean=None, std=None):
    """
    Computes the cummulative sum of the energy image. If mean and std are done, the update is only done in the
    desired columns (mean - std*2 - 1, mean + std*2 + 1).
    The cummulative cost is computed over the cost matrix (we update its values iteratively).
    To speed up the computation, we substitute the areas of the cost image that are not going to be updated (based on
    the mean and std), and we substitute them by the cumulative cost image of the previous iteration.
    :param matrix: imput matrix of 6 channels + image
    :param mean: mean column
    :param std: std width of path
    :return: updated accumulated cost image
    """
    cost_matrix = matrix[:,:,0]
    cum_cost_matrix = matrix[:,:,1]

    # Get the columns that need to be updated
    cols_idx = [0, matrix.shape[1]]
    if mean is not None and std is not None:
        first_col = 0 if int(np.round(mean) - 2 * np.ceil(std) - 1) < 0 else int(np.round(mean) - 2 * np.ceil(std) - 1)
        last_col = matrix.shape[1] if int(np.round(mean) + 2 * np.ceil(std) + 1) > matrix.shape[1] \
            else int(np.round(mean) + 2 * np.ceil(std) + 1)
        cols_idx = [first_col, last_col]

    # Substitute parts of the cost_matrix that are not going to be updated by the cumulative cost image
    cost_matrix[:, :cols_idx[0]] = cum_cost_matrix[:, :cols_idx[0]]
    cost_matrix[:, cols_idx[1]:] = cum_cost_matrix[:, cols_idx[1]:]

    # Compute cumulative cost
    for i in range(1, matrix.shape[0]):
        for j in range(cols_idx[0], cols_idx[1]):
            if 0 < j < matrix.shape[1] - 1:
                cost_matrix[i][j] += np.min(cost_matrix[i - 1][j-1:j+2])
            elif j == 0:  # If we are in the leftmost column
                cost_matrix[i][j] += np.min(cost_matrix[i - 1][j:j+2])
            else:  # If we are in the rightmost column
                cost_matrix[i][j] += np.min(cost_matrix[i - 1][j-1:j+1])

    return cost_matrix

def path(matrix):
    """
    Computes the minimum cost path over the cumulative cost image.
    :param matrix: cumulative cost image.
    :return: list of path
    """
    i = matrix.shape[0] - 1
    path = []
    index = np.argmin(matrix[i])
    path.append(index)
    while i > 0:
        if index == 0:  # leftmost column
            index = index + np.argmin(matrix[i - 1][index:index+2])
            path.append(index)
            i = i - 1
        elif index == matrix.shape[1] - 1:  # rightmost column
            index = index + np.argmin(matrix[i - 1][index-1:index+1]) - 1
            path.append(index)
            i = i - 1
        else:
            index = index + np.argmin(matrix[i - 1][index-1:index+2]) - 1
            path.append(index)
            i = i - 1
    return path[::-1]

def get_seam_mask(path, image_shape):
    """
    This function creates a mask out of a seam path.
    :param path: list of column indexes for each row of the image
    :param image_shape: shape of the image used to compute the seam path
    :return: mask of the seam
    """
    path = np.array(path).astype(int)
    # Compute the mask
    seam_mask = (np.zeros(image_shape) + 1).astype(bool)
    seam_mask[np.arange(image_shape[0]), path] = False

    # Compute the expanded mask: also include pixels on the right
    seam_mask_expanded = seam_mask.copy()

    # Add 1 column to the right to account for rightmost minimum pixels
    seam_mask_expanded = np.hstack((seam_mask_expanded, (np.zeros((image_shape[0], 1)) + 1).astype(bool)))
    seam_mask_expanded[np.arange(image_shape[0]), path + 1] = False
    seam_mask_expanded = seam_mask_expanded[:,:-1]  # Remove extra column
    return seam_mask, seam_mask_expanded

def downscale_seam_image(image, seam_mask):
    """
    Creates a new image with a reduced column dimension and copies the data which is not in the seam.
    :param image: input image
    :param seam_mask: mask with the seam path
    :return: downscaled image
    """
    # Reshape the image to be a 2d array: each row is the depth vector
    res_image = image.reshape(image.shape[0] * image.shape[1], -1)
    res_mask = seam_mask.reshape(image.shape[0] * image.shape[1], -1)

    res_new_image = res_image[res_mask[:,0], :]

    # Reshape back to original size -1
    new_image = res_new_image.reshape(image.shape[0], image.shape[1]-1, image.shape[2])
    return new_image

def downscale_alg():
    """
    Downscaling the image using the seam carving method.
    """
    image = birds
    mask = birds_mask
    #mask = np.zeros((image.shape[0], image.shape[1], 1))

    cost = np.zeros((image.shape[0], image.shape[1], 1))
    ccost = np.zeros((image.shape[0], image.shape[1], 1))
    image = np.dstack((image, cost, ccost, mask))

    original_image = image.copy()

    mean = None
    std = None
    print()
    for it in range(800):  # For N iteration
        # Get some feedback
        print("\rIt: ", it, end="", flush=True)

        # Compute energy/cost
        image[:,:,3] = energy_image(image[:,:,0:4], image[:,:,5]*4, mean, std)  # Value of mask is 765

        # Compute cumulative cost
        image[:,:,4] = cum_cost(image[:,:,3:5].copy(), mean, std)

        # Get Seam:
        seam_path = path(image[:,:,4])
        seam_mask, seam_mask_expanded = get_seam_mask(seam_path, image[:,:,4].shape)

        # Compute mean and std for next iteration
        mean = np.mean(seam_path)
        std = np.std(seam_path)

        # Add Expanded Seam to mask
        image[:,:,5] += np.logical_not(seam_mask_expanded).astype(int)
        image[:,:,5] = np.where(image[:,:,5]==0, image[:,:,5], 255)

        # Show results
        if it%20 == 0:
            fig, axs = plt.subplots(2, 2)
            fig.suptitle("Image After Removing " + str(it) + " Columns")
            axs[0, 0].set_title("Cropped Image")
            axs[0, 0].imshow(image[:, :, 0:3].astype(int))
            axs[0, 1].set_title("Energy Image")
            axs[0, 1].imshow(image[:, :, 3].astype(int))
            axs[1, 0].set_title("Cummulative cost image")
            axs[1, 0].imshow(image[:, :, 4])
            axs[1, 1].set_title("Mask")
            axs[1, 1].imshow(image[:, :, 5])
            plt.savefig("birds_it" + str(it) + ".png")
            plt.close(fig)

            im = Image.fromarray(image[:, :, 0:3].astype(np.uint8))
            im.save("DownscaledImage_" + str(it) + ".png")

        # Remove seam parts
        image = downscale_seam_image(image, seam_mask)

    fig, axs = plt.subplots(2, 2)
    axs[0, 0].set_title("Original image")
    axs[0, 0].imshow(original_image[:, :, 0:3].astype(int))
    axs[0, 1].set_title("Cropped image")
    axs[0, 1].imshow(image[:, :, 0:3].astype(int))
    axs[1, 0].set_title("Original mask")
    axs[1, 0].imshow(original_image[:, :, 5])
    axs[1, 1].set_title("Cropped mask")
    axs[1, 1].imshow(image[:, :, 5])
    plt.show()
    print("\nFinished Exercise 4.4")

def expand_row(row, index):
    """
    This function expands a row. It shifts 1 pixel to the right all pixels right of the index. It fills the index pixel
    with the average of the pixels from its left and right.
    :param row: row of pixels 1D array
    :param index: index to fill and shift
    :return: shifted row
    """
    if index == row.shape[0] - 1:  # rightmost column
        average = row[index, :]  # question
    else:
        average = (row[index, :]+row[index + 1, :])/2
    row_expanded = np.zeros((row.shape[0] + 1, row.shape[1]))
    row_expanded[:index + 1, :] = row[0:index + 1, :]
    row_expanded[index + 1, :] = average
    row_expanded[index + 2:, :] = row[index + 1:, :]
    return row_expanded

def upscale_seam_image(image, path):
    """
    Upsacales the input image given the path.
    :param image: input image.
    :param path: path, defines where the image is split and filled
    :return: the upscaled image
    """
    new_image = np.zeros((image.shape[0], image.shape[1]+1, image.shape[2]))
    for i in range(image.shape[0]):
        new_image[i, :, :] = expand_row(image[i,:,:], path[i])
    return new_image

def upscale_alg():
    """
    This exercise consists in using the same method to upscale the image. We compare a nature photo (vincent on a cliff)
    and a city landscape. We appreciate how the results are better on the nature landscape. Probably due to the less
    amount of details the nature landscape has.
    """

    image = paris
    mask = np.zeros((image.shape[0], image.shape[1], 1))
    cost = np.zeros((image.shape[0], image.shape[1], 1))
    ccost = np.zeros((image.shape[0], image.shape[1], 1))
    image = np.dstack((image, cost, ccost, mask))

    mean = None
    std = None
    print()
    for it in range(501):
        print("\rIt: ", it, end="", flush=True)
        # Compute energy/cost
        image[:,:,3] = energy_image(image[:,:,0:4], image[:,:,5]*4, mean, std)

        # Compute cumulative cost
        image[:, :, 4] = cum_cost(image[:, :, 3:5].copy(), mean, std)

        # Get Seam:
        seam_path = path(image[:, :, 4])
        seam_mask, seam_mask_expanded = get_seam_mask(seam_path, image[:, :, 4].shape)

        # Compute mean and std for next iteration
        mean = np.mean(seam_path)
        std = np.std(seam_path)

        # Add Expanded Seam to mask
        image[:, :, 5] += np.logical_not(seam_mask_expanded).astype(int)
        image[:, :, 5] = np.where(image[:, :, 5] == 0, image[:, :, 5], 255)

        # Show results
        if it % 20 == 0:
            fig, axs = plt.subplots(2, 2)
            fig.suptitle("Image After Adding " + str(it) + " Columns")
            axs[0, 0].set_title("Upscaled Image")
            axs[0, 0].imshow(image[:, :, 0:3].astype(int))
            axs[0, 1].set_title("Energy Image")
            axs[0, 1].imshow(image[:, :, 3].astype(int))
            axs[1, 0].set_title("Cumulative cost image")
            axs[1, 0].imshow(image[:, :, 4])
            axs[1, 1].set_title("Mask")
            axs[1, 1].imshow(image[:, :, 5])
            plt.savefig("upscale_it" + str(it) + ".png")
            plt.close(fig)

            im = Image.fromarray(image[:, :, 0:3].astype(np.uint8))
            im.save("UpscaledImage_" + str(it) + ".png")

        # Upscale image
        image = upscale_seam_image(image, seam_path)

if __name__ == '__main__':

    # Load exercise data
    kestrel_name = 'additional-data/common-kestrel.jpg'
    birds_name = 'additional-data/kingfishers.jpg'
    mask_name = 'additional-data/kingfishers-mask.png'
    paris_name = 'additional-data/paris.jpg'

    paris = np.array(Image.open(paris_name))
    birds = np.array(Image.open(birds_name))
    birds_mask = np.array(Image.open(mask_name))[:,:,0]

    #upscale_alg()
    downscale_alg()


from GPano import *
import GPano
import csv,itertools
import pandas as pd
import multiprocessing as mp
import database_ops as db_ops

def downloadImg(lon,lat,saved_path):
    gpano = GPano.GPano()
    degrees = [90,270]
    # saved_path = "J:\Research\Trees\west_trees"
    data = gpano.getPanoJsonfrmLonat(lon, lat)
    # print(data)
    car_pano = data.get("Location")
    car_lat = car_pano.get("lat")
    car_lon = car_pano.get("lng")
    # print(car_lon)
    # angle = gpano.getDegreeOfTwoLonlat(lat,lon,float(car_lat),float(car_lon))
    angle = gpano.getDegreeOfTwoLonlat(float(car_lat), float(car_lon), lat, lon)  #  see from float(car_lat), float(car_lon) to lon/lat

    panoId = data["Location"]["panoId"]
    # ---------------------------------------------------------------------------
    projection = data.get("Projection")
    pano_yaw_deg = float(projection.get("pano_yaw_deg"))
    print('angle, pano_yaw_deg: ', angle, pano_yaw_deg)
    # degrees.append(angle)

    find_min = [abs(pano_yaw_deg + deg - angle) % 360 for deg in degrees ]
    find_min2 = []
    for f in find_min:
        if f > 180:
            find_min2.append(abs(f-360))
        else:
            find_min2.append(f)

    index = find_min2.index(min(find_min2))
    # print(data)
    yaw = degrees[index]+pano_yaw_deg
    yaw = yaw % 360
    # if yaw > 360:
    #     yaw = yaw - 360
    # if yaw < 0:
    #     yaw = yaw + 360
    # print(yaw)
    # getDegreeOfTwoLonlat
    image, jpg_name = gpano.getImagefrmAngle(float(car_lon),float(car_lat), saved_path,yaw=yaw,prefix=panoId)
    url = gpano.getGSV_url_frm_lonlat(float(car_lon),float(car_lat), heading=yaw)
    print("Google street view URL:", url)
    print("PanoID:", panoId)
    # print(image)
    # print(jpg_name)
    # ---------------------------------------------------------------------------

#Tree long lat positions as input

# downloadImg(-75.14474465,39.98868215)

def downloadImgs(lon_lat_list, saved_path):
    while len(lon_lat_list) > 0:
        try:
            lon, lat = lon_lat_list.pop(0)
            downloadImg(lon,lat, saved_path)
        except Exception as e:
            print("Error in downloadImgs():", e)
            continue

def test_downloadImgs_mp(lon_lst_csv= r"K:\OneDrive_NJIT\OneDrive - NJIT\Research\Trees\datasets\NewYorkCity\NYC_Trees20k.csv", saved_path= r"K:\Research\Trees\NewYorkCity_test\google_street_images", Process_cnt = 10):
    print("lon_lst_csv: ", lon_lst_csv)
    lon_lats = pd.read_csv(lon_lst_csv)

    mid = int(len(lon_lats)/2)

    print(len(lon_lats))
    pool = mp.Pool(processes=Process_cnt)
    lon_lats_mp = mp.Manager().list()

    for idx, lonlat in lon_lats[: ].iterrows():
        lon = lonlat['POINT_X']
        lat = lonlat['POINT_Y']
        lon_lats_mp.append((lon, lat))

    for i in range(Process_cnt):
        pool.apply_async(downloadImgs, args=(lon_lats_mp, saved_path))
    pool.close()
    pool.join()

    print("Done.")

def readCSV(n):
    with open(r"K:\OneDrive_NJIT\OneDrive - NJIT\Research\Trees\datasets\NewYorkCity\NYC_Trees20k.csv") as csv_file:
        i = 0
        # csv_reader = csv.reader(csv_file, delimiter=',')
        for row in itertools.islice(csv.DictReader(csv_file), 0,n):

            try:

                print(i, row['POINT_X'], row['POINT_Y'])
                downloadImg(row["POINT_X"],row['POINT_Y'],n)
                # each_row = frozenset(row)
                # data.append(each_row)
                i += 1
            except Exception as e:
                print("Error in downloadImg():", e)

            # for item in each_row:
            #     itemSet.add(frozenset([item]))
# readCSV(19951)

if __name__ == "__main__":
    test_downloadImgs_mp()


import pandas as pd
import numpy as np
import gc
import os
import toolbox as tl

def parse_date(date_series:pd.Series) -> pd.Series:
    date_series = date_series.astype('str')
    if len(date_series[0]) > 8:
        return pd.to_datetime(date_series, format="%Y%m%d_%H%M%S")
    return pd.to_datetime(date_series, format="%Y%m%d")

def check_date_coherence(contrat: pd.DataFrame, comp_data: pd.DataFrame, comp_col: str) -> pd.DataFrame:
    """Verifie si une date est coherente avec la date du contrat

    Args:
        contrat (pd.DataFrame): DataFrame du contrat
        comp_data (pd.DataFrame): DataFrame a comparer
        comp_col (str): Nom de la colonne

    Returns:
        pd.DataFrame: DataFrame du resultat
    """
    comp_data.rename(columns={comp_data.columns[0]: contrat.columns[0]}, inplace=True)
    merged_data = pd.merge(contrat, comp_data, on=contrat.columns[0], how="inner")

    merged_data = merged_data.loc[merged_data[comp_col].isna() == False]
    merged_data["SCON_POL_DATDEB"] = parse_date(merged_data["SCON_POL_DATDEB"])
    merged_data[comp_col] = parse_date(merged_data[comp_col])

    result = merged_data.loc[merged_data["SCON_POL_DATDEB"] > merged_data[comp_col]]
    result["Erreur"] = "La date de {} est antérieure à la date de début du contrat SCON_POL_DATDEB".format(comp_col)

    return result

def check_date_coherence_couv_coti(contrat: pd.DataFrame, couv_coti: pd.DataFrame) -> pd.DataFrame:
    result_col1 = check_date_coherence(contrat=contrat, comp_data=couv_coti, comp_col="SSCC_RGPO_DATEDEBUT")
    result_col2 = check_date_coherence(contrat=contrat, comp_data=couv_coti, comp_col="SSCC_SOR_DATEDEBUT")

    return pd.concat([result_col1, result_col2], axis=0, ignore_index=True)

def check_date_coherence_risque(contrat: pd.DataFrame, risque: pd.DataFrame) -> pd.DataFrame:
    result_col1 = check_date_coherence(contrat=contrat, comp_data=risque, comp_col="SRIS_DATE_MVT_RISQUE")
    result_col2 = check_date_coherence(contrat=contrat, comp_data=risque, comp_col="SRIS_SOR_DATEDEBUT")

    return pd.concat([result_col1, result_col2], axis=0, ignore_index=True)

if __name__ == "__main__":
    contrat_data = pd.read_csv("../tmp/input/SS05/F_SAS_CONTRAT_BM.csv", sep=";", low_memory=False)\
        .loc[:,["SCON_POL_REFECHO", "SCON_POL_DATDEB"]]
    couv_coti_data = pd.read_csv("../tmp/input/SS05/F_SAS_STRUCT_COUV_COTI.csv", sep=";", low_memory=False)\
        .loc[:,["SSCC_POL_REFECHO", "SSCC_GMA_CODE", "SSCC_TMAD_CODE", "SSCC_SOR_IDENTIFIANT", "SSCC_RGPO_DATEDEBUT", "SSCC_SOR_DATEDEBUT"]]

    gc.collect()

    print(check_date_coherence_couv_coti(contrat=contrat_data, couv_coti=couv_coti_data))

    del(couv_coti_data)

    gc.collect()

    risque_date = pd.read_csv("../tmp/input/SS05/F_SAS_RISQUE_BM.csv", sep=";", low_memory=False)\
        .loc[:, ["SRIS_POL_REFECHO", "SRIS_CLE_RGP_RISQUE", "SRIS_DATE_MVT_RISQUE", "SRIS_SOR_DATEDEBUT", "SRIS_SAR_BPP_REF_EXTERNE"]]

    print(check_date_coherence_risque(contrat=contrat_data, risque=risque_date))

    gc.collect()