# -*- coding: utf-8 -*-
"""
Unit tests for the flight_log_code.py.

@author Adrian Weishaeupl (aw6g15@soton.ac.uk)
"""

import unittest
import os
import json
import sys
from autoflpy.util import flight_log_code
from datetime import datetime
from autoflpy.util import nearest_ICAO_finder
from autoflpy.util.testing.check_str_in_content import *

def notebook_sample_code(flight_data_file_path, flight_data_file_name,
                         csv_data_file_path, csv_flight_data_name):
    """Sample flight log code for testing purposes"""
    # GRAPH_DATA_IMPORT

    # Creates a base_path to the test files.
    base_path = os.path.dirname(__file__) + os.sep

    # Creates a link to where the code is stored.
    sys.path.append(base_path[:-11])

    # file_path of the flight data.
    # flight_data_file_path = base_path
    # Excel File name
    # flight_data_file_name = "test_xlsx.xlsx"
    # CSV File name
    # csv_flight_data_name = "test_csv.CSV"
    # csv Data file path
    # csv_data_file_path = base_path
    # Excel Sheets
    frame_list = flight_log_code.flight_data(flight_data_file_path,
                                             flight_data_file_name)
    # A list containing the date first and then the flight number
    date_and_flight_number = flight_log_code.date_and_flight_number(frame_list)
    # Retrieves csv flight data
    csv_flight_data_frame = \
        flight_log_code.csv_frame(csv_data_file_path,
                                  csv_flight_data_name)
    # Appends csv frame to flight data from pixhawk
    frame_list.append(csv_flight_data_frame)
    # Sorts frames by time
    sorted_frames = flight_log_code.flight_data_time_sorter(frame_list)
    # Creates a list of all the values.
    values_list = flight_log_code.flight_data_and_axis(sorted_frames)
    return (frame_list, date_and_flight_number, csv_flight_data_frame,
            sorted_frames, values_list)

class TestFlightLogCode(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        # Runs once before any tests
        # Defines the base path
        base_path = os.path.join(os.path.dirname(__file__), "test_files"
                                 ) + os.sep
        # Tidies base path
        base_path = base_path.replace(os.sep, "/")
        # Opens the input file and reads content
        with open(base_path + 'test_Input_File.json') as file:
            data = json.load(file)
        # Defines variables
        flight_data_file_path = base_path
        flight_data_file_name = "test_xlsx.xlsx"
        csv_flight_data_file_path = base_path + data[
            "flight_log_generator_input"]["csv_flight_data_file_path"]
        csv_flight_data_name = data["flight_log_generator_input"
        ]["csv_flight_data_name"]
        # Creates a global variable to be used in the testing
        global notebook_results
        # Populates the global variable
        notebook_results = \
            notebook_sample_code(flight_data_file_path,
                                 flight_data_file_name,
                                 csv_flight_data_file_path,
                                 csv_flight_data_name)

    def setUp(self):
        # Sets up all of the test variables and locations to be used
        # throughout.
        self.base_path = os.path.join(os.path.dirname(__file__),
                                      "test_files") + os.sep
        self.base_path = self.base_path.replace(os.sep, "/")
        # Imports data from template.
        with open(self.base_path + 'test_Input_File.json') as file:
            self.data = json.load(file)
        self.flight_number = self.data["log_to_xlsx_input"]["flight_number"].replace(" ", "").split(",")
        self.flight_date = self.data["log_to_xlsx_input"]["date"].replace(" ", "").split(",")
        self.template_file_path = self.base_path
        self.template_file_name = self.data["flight_log_generator_input"][
            "template_file_name"]
        self.flight_log_file_path = self.base_path + self.data[
            "flight_log_generator_input"]["flight_log_destination"]
        self.flight_data_file_path = self.base_path  # Path to xlsx file
        self.flight_data_file_name = "test_xlsx.xlsx"
        self.flight_data_file_name_list = ["test_xlsx.xlsx"]
        self.csv_flight_data_file_path = self.base_path + self.data[
            "flight_log_generator_input"]["csv_flight_data_file_path"]
        self.csv_flight_data_name = self.data["flight_log_generator_input"
        ]["csv_flight_data_name"].replace(" ", "").split(",")
        self.flight_log_file_name_header = "test_generated_flight_log"
        self.start_time_hours = self.data["flight_log_generator_input"][
            "start_time_hours"].replace(" ", "").split(",")
        self.end_time_hours = self.data["flight_log_generator_input"][
            "end_time_hours"].replace(" ", "").split(",")
        self.metar_file_path = self.base_path + self.data[
            "flight_log_generator_input"]["metar_file_path"]
        self.comp_data_file_path = self.flight_data_file_path + "test_xlsx.pkl"
        self.weather_data = flight_log_code.multi_dictionary_data_formatter(self.data["weather_data"], self.flight_date
                                                                            , "weather_data")
        self.weather_data_dict = self.data["weather_data"]
        self.runway_data = flight_log_code.multi_dictionary_data_formatter(self.data["runway_data"], self.flight_date,
                                                                           "runway_data")
        self.runway_data_dict = self.data["runway_data"]

    def tearDown(self):
        # Removes generated flight log.
        base_path = os.path.join(os.path.dirname(__file__),
                                 "test_files") + os.sep
        generated_file_names = [base_path + "test_generated_flight_logtest_xlsx.ipynb", base_path +
                               "test_generated_flight_log20190123_2.ipynb"]
        for item in range(len(generated_file_names)):
            if os.path.exists(generated_file_names[item]):
                os.remove(generated_file_names[item])

        # Removes pickled data.
        pickle_file_names = [base_path + "test_xlsx.pkl"]
        for item in range(len(pickle_file_names)):
            if os.path.exists(pickle_file_names[item]):
                os.remove(pickle_file_names[item])

    def test_flight_log_maker(self):
        self.ICAO_airfield = nearest_ICAO_finder.icao_finder(
            self.flight_data_file_path,
            self.flight_data_file_name)
        flight_log_code.flight_log_maker(self.template_file_path,
                                         self.template_file_name,
                                         self.flight_log_file_path,
                                         self.flight_data_file_path,
                                         self.flight_data_file_name_list,
                                         self.csv_flight_data_file_path,
                                         self.csv_flight_data_name,
                                         self.flight_date,
                                         self.flight_number,
                                         self.flight_log_file_name_header,
                                         self.ICAO_airfield,
                                         self.start_time_hours,
                                         self.end_time_hours,
                                         self.metar_file_path,
                                         self.weather_data,
                                         self.runway_data,
                                         True)
        # This code tests the flight_log_maker function.
        # First, check that a file has been created.
        test_flight_log_file_path = self.base_path + 'test_generated_flight_logtest_xlsx.ipynb'
        if os.path.exists(test_flight_log_file_path) is True:
            file_exists = True
        else:
            file_exists = False
        self.assertTrue(file_exists)
        # Checks that the file was recently created.
        filetime = os.stat(test_flight_log_file_path)
        # Finds the time since the file has been created.
        time_diff = datetime.now() - datetime.fromtimestamp(filetime.st_mtime)
        # Checks that the time difference is less than 1 second.
        self.assertLess(time_diff.microseconds, 1e6)
        # Check that the files weren't created in the past.
        self.assertGreaterEqual(time_diff.microseconds, 0)

    def test_flight_data(self):
        # Tests the flight data code.
        frame_list = flight_log_code.flight_data(
            self.flight_data_file_path,
            self.flight_data_file_name)
        # Checks that the expected frame dimensions are the correct size.
        frame_dimensions = [17780, 95220, 22860, 25400, 57141, 44436, 57132,
                            19044, 6, 4, 8]
        if len(frame_list) == 11:
            for frame in range(len(frame_list)):
                self.assertEqual(frame_list[frame].size,
                                 frame_dimensions[frame])
        else:
            # Raises a fault if the length of the frame_list is not as
            # expected.
            raise ValueError('Frame list length is not as expected: {0} != 11'
                             .format(len(frame_list)))

    def test_flight_log_creator(self):
        # Generates content
        content = flight_log_code.contents_opener(self.template_file_path,
                                                  self.template_file_name)
        file_name_data = str(self.flight_date[0]) + "_" + str(self.flight_number[0])
        # Runs the flight log creator code
        flight_log_code.flight_log_creator(content, self.base_path,
                                           file_name_data,
                                           self.flight_log_file_name_header)
        # Checks the file was created correctly
        file_exists = os.path.exists(self.base_path
                                     + 'test_generated_flight_log20190123'
                                       '_2.ipynb')
        self.assertTrue(file_exists)

    def test_date_and_flight_number(self):
        # Gets run in the Jupyter Notebook.
        # Extracts the desired variables from the sample notebook
        date_and_flight_number = notebook_results[1]
        # Checks that the output is as expected
        expected_date_and_flight_number = ('20190123', '2')
        self.assertEqual(expected_date_and_flight_number,
                         date_and_flight_number)

    def test_csv_frame(self):
        # Gets run in the Jupyter Notebook.
        # Runs the sample notebook code to extract teh desired variable
        csv_frame = notebook_results[2]
        try:
            # Checks if the key is correct
            csv_frame['X']
            # Failed if no error is raised
            self.assertFalse(True)
        except KeyError:
            # Passes if an error is raised
            self.assertTrue(True)
        # Loads values
        values = csv_frame['Temp0_degC_ArduinoMicro_20190123_Flight2'
        ]
        # Compares expected values with values from the data frame
        expected_values = [24.38, 24.38, 24.38, 24.44, 25.31, 26.69, 27.69,
                           28.44, 29.00, 29.38, 29.69, 30.00, 30.06, 29.69,
                           29.38, 29.06, 28.81, 28.63, 28.38, 28.25, 28.06,
                           27.88, 27.75, 27.63, 27.50, 27.38, 27.25]
        for item in range(len(expected_values)):
            self.assertEqual(expected_values[item], values[item])

    def test_flight_data_time_sorter(self):
        # Gets run in the Jupyter Notebook.
        data_frames = notebook_results[3]
        # Checks that the frames were split into the correct number of
        # subframes
        self.assertEqual(len(data_frames), 12)
        # Assigns expected titles
        data_frame_section_titles = [
            'Status_unavailable_GPS_20190123_Flight2',
            'aileron_CH1_us_RCIN_20190123_Flight2',
            'Altitude_m_BARO_20190123_Flight2',
            'Airspeed_mpers_ARSP_20190123_Flight2',
            'Desired_Roll_degrees_ATT_20190123_Flight2',
            'VibeX_mperspers_VIBE_20190123_Flight2',
            'NavRoll_unavailable_CTUN_20190123_Flight2',
            'AOA_degrees_AOA_20190123_Flight2',
            'Action_time_hh:mm_WEATHER_20190123_Flight2',
            'take_off_direction_RUNWAY_20190123_Flight2',
            'm_empty_kg_AIRCRAFT_20190123_Flight2',
            'Temp0_degC_ArduinoMicro_20190123_Flight2']
        correct_titles = 0
        # Runs through titles. Checks that each title can be called and adds 1
        # to the counter (correct_titles). If a title is not correct/cannot be
        # called, raise a failure.
        for item in range(len(data_frame_section_titles)):
            try:
                data_frames[item][data_frame_section_titles[item]]
                correct_titles += 1
            except KeyError:
                self.assertEqual(1, 2)
        # Checks that all titles are correct
        self.assertEqual(correct_titles, 12)

    def test_flight_data_and_axis(self):
        # Gets run in the Jupyter Notebook.
        # Loads the data generated previously
        flight_data_and_axis = notebook_results[4]
        # Assigns expected titles
        expected_titles = ['GPS', 'RCIN', 'BARO', 'ARSP', 'ATT', 'VIBE',
                           'CTUN', 'AOA', 'WEATHER', 'RUNWAY', 'AIRCRAFT', 'ArduinoMicro']
        # Checks that the titles are present and in the correct place
        for item in range(len(expected_titles)):
            self.assertEqual(expected_titles[item], flight_data_and_axis[1][item][0])

    def test_file_type_finder(self):
        # Detects xlsx files from the test_files folder
        detected_files = flight_log_code.file_type_finder(self.base_path, ".xlsx")
        expected_file_names = ['test_xlsx.xlsx']
        # Checks that all the expected files are present
        for file_name in expected_file_names:
            if file_name in detected_files:
                file_detected = True
            else:
                file_detected = False
            self.assertTrue(file_detected)

    def test_compile_and_compress(self):
        # Runs the compiler and compressor.
        flight_log_code.compile_and_compress(self.flight_data_file_path, [self.flight_data_file_name],
                                             self.csv_flight_data_file_path, self.csv_flight_data_name,
                                             self.comp_data_file_path)
        pickle_file_name = self.base_path + "test_xlsx.pkl"  # Defines the file name
        # Checks that the file exists
        self.assertTrue(os.path.exists(pickle_file_name))

    def test_dictionary_reader(self):
        # Returns a string of formatted weather data
        read_data = flight_log_code.dictionary_reader(self.weather_data_dict, units_present=True, flight_number="1")
        # Adds a string of formatted runway data
        read_data += flight_log_code.dictionary_reader(self.runway_data_dict, units_present=False, flight_number="2")
        expected_results = [" | Flight | Action time  (hh:mm) | Pressure  (Pa) | Temperature  (C) | Wind direction"
                            "  (degrees) | Wind speed  (mps) |",
                            " | --- | --- | --- | --- | --- | --- |",
                            "| Flight 1| 12:34 | 1234567 | -12.3 | 123 | 12.3 |",
                            " | Flight | runway surface  | surface condition  | take off direction  |",
                            " | --- | --- | --- | --- |",
                            "| Flight 2| XYZ | ZYX | 321 |"]
        # Checks that the correct data is present in the read_data string
        for string in expected_results:
            self.assertTrue(string in read_data)

    def test_multi_string_data_formatter(self):
        """A method to test the multi_string_data_formatter()"""
        # Assigns testing strings
        input1 = "Fish,Ca t,Dog,35, Mouse,   89"
        flight_names_1 = [1, 2, 3, 4, 5, 6]
        debug_name_1 = "Input 1"
        input2 = ""
        flight_names_2 = [0, 1]
        debug_name_2 = "Input 2"
        input3 = "Fail1"
        flight_names_3 = [7, 8]
        debug_name_3 = "TEST"
        # Assigns testing outputs
        expected_output1 = ["Fish", "Cat", "Dog", "35", "Mouse", "89"]
        expected_output2 = [""]
        expected_output3 = False
        # Tests that the method works as expected
        self.assertEqual(flight_log_code.multi_string_data_formatter(input1, flight_names_1, debug_name_1),
                         expected_output1)
        self.assertEqual(flight_log_code.multi_string_data_formatter(input2, flight_names_2, debug_name_2),
                         expected_output2)
        try:
            flight_log_code.multi_string_data_formatter(input3, flight_names_3, debug_name_3)
            # Should raise an index error. If not, fail the test.
            self.assertTrue(expected_output3)
        except IndexError:
            # Planned error
            self.assertTrue(True)

    def test_remove_dictionary_key(self):
        """A method to test the remove_dictionary_key()"""
        # Create variables
        dictionary1 = {"DOG": "4F", "Mouse": "Cat", "Donkey": 7, 8906: "Fish", "PiG": "Farm"}
        keys_to_remove = ["Mouse", 8906, "DOG"]
        # Remove the keys and check if they have been removed
        for key_index in range(len(keys_to_remove)):
            output = flight_log_code.remove_dictionary_key(dictionary1, keys_to_remove[key_index])
            if keys_to_remove[key_index] in output.keys():
                # Fail if the key is still present
                self.assertTrue(False)
            else:
                # Key successfully removed, pass the test
                self.assertTrue(True)

    def test_multi_dictionary_data_formatter(self):
        """A method to test the multi_dictionary_data_formatter()"""
        # Create variables
        dictionary1 = {"DOG": "4F, Squirrel", "Mouse": "Cat, 78", "Donkey": "7, 7", 8906: "Fish , Bird",
                       "PiG": "Farm, Animal"}
        debug_name1 = "dict1"
        flight_dates1 = [0, 1]
        dictionary2 = {"Face": "Nose, Ear, Mouth"}
        flight_dates2 = [2, 3]
        debug_name2 = "TEST"

        # Assigns expected outputs:
        expected_output_dict1_1 = ["4F", "Cat", "7", "Fish", "Farm"]
        expected_output_dict1_2 = ["Squirrel", "78", "7", "Bird", "Animal"]
        key = ["DOG", "Mouse", "Donkey", 8906, "PiG"]
        expected_output_dict2 = False

        # Runs the method
        output1 = flight_log_code.multi_dictionary_data_formatter(dictionary1, flight_dates1, debug_name1)

        try:
            flight_log_code.multi_dictionary_data_formatter(dictionary2, flight_dates2, debug_name2)
            # Fails if this does not raise an error
            self.assertTrue(expected_output_dict2)
        except IndexError:
            # Passes if an error is raised
            self.assertFalse(expected_output_dict2)

        for key_index in range(len(dictionary1.keys())):
            self.assertEqual(output1[0][key[key_index]], expected_output_dict1_1[key_index])
            self.assertEqual(output1[1][key[key_index]], expected_output_dict1_2[key_index])

if __name__ == '__main__':
    unittest.main()


#!/usr/bin/env python

from elasticbot.slack import SlackBot
from elasticbot.elastic import ElasticClient
from elasticbot.config import Configuration

if __name__ == "__main__":
    config = Configuration(
        token = "",
        check_interval = 2,
        elastic = "localhost:9200",
        bot_id = "U16ER7H40"
    )
    # esClient = ElasticClient()
    # esClient.search(query = "GET /api/pingAlbo 200 3ms")
    SlackBot(config).start()


import urllib.request

from bs4 import BeautifulSoup

def request_list(page):
    url = 'http://movie.naver.com/movie/bi/mi/pointWriteFormList.nhn?code=127382&type=after&isActualPointWriteExecute=false&isMileageSubscriptionAlready=false&isMileageSubscriptionReject=false&page={page}'
    url = url.format(page=page)

    res = urllib.request.urlopen(url)
    html = res.read()

    return BeautifulSoup(html, 'html.parser')

def fetch_comm_detail(soup):
    result = []

    li_tags = soup.find('div', class_='score_result').find_all('li')

    for li in li_tags:
        score_reple = li.find('div', class_='score_reple')
        content = score_reple.find('p')

        if content.span:
            content.span.extract()

        if content.span:
            content.span.extract()

        content = content.get_text(strip=True)

        dt = score_reple.find('dl').find('dt')
        em_tags = dt.find_all('em')
        name = em_tags[0].find('span').get_text(strip=True)
        date = em_tags[1].get_text(strip=True)

        result.append({
            'content' : content,
            'name' : name,
            'date' : date
            })

    return result

for i in range(1, 4):
    soup = request_list(i)
    result = fetch_comm_detail(soup)
    print(result)


import argparse
from typing import List

from dazu.components.engine import Engine
from dazu.config import DazuConfig

# noinspection PyProtectedMember
def add_subparser(
    subparsers: argparse._SubParsersAction, parents: List[argparse.ArgumentParser]
):
    train_parser = subparsers.add_parser(
        "train",
        parents=parents,
        conflict_handler="resolve",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        help="Starts train with Training Data with your configured pipeline.",
    )
    train_parser.set_defaults(func=train)

    # arguments.set_run_arguments(run_parser)

def train(config: DazuConfig, args: argparse.Namespace):
    engine = Engine(config)
    engine.train()


def merge_sort(T):
    while True:
        inversion = []
        for i in range(len(T) - 1):
            if T[i] > T[i + 1]:
                inversion.append(i)
        inversion.append(len(T) - 1)

        if len(inversion) == 1:
            return T

        p = 0
        while len(inversion) > 1:
            merge(T, p, inversion[0], inversion[1])
            p = inversion[1] + 1
            inversion = inversion[2:]

def merge(T, p, q, r):
    A = T[p:q+1]
    B = T[q + 1:r+1]
    i = p

    while len(A) != 0 and len(B) != 0:
        if A[0] >= B[0]:
            T[i] = B.pop(0)
            i += 1
        else:
            T[i] = A.pop(0)
            i += 1
    while len(A) > 0:
        T[i] = A.pop(0)
        i += 1
    while len(B) > 0:
        T[i] = B.pop(0)
        i += 1
    return T

if __name__ == '__main__':
    T = [2, 4, 6, -4, -12, 8, 10, -4]
    print(merge_sort(T))


# -*- coding: utf-8 -*-
"""
    EnhancedPythonLexer

    Sometimes a built-in lexer isn't doing what one wants.
    To enhance the built-in lexer, indicators can be used, which also automatically
    prevent clashes with the styling operations done by the built-in lexer.
    The only potential issue might be using an indicator used by npp itself.

    Usage:
        In the main function
            - define the lexer_name to be enhanced and
            - create the regex_dict with the regular expressions and
            - the associate colours

        The regex dict must be in form key_tuple:value_tuple.

        The key_tuple needs to have an unique ID followed by a colour tuple,
        like (3, (181, 188, 201)).
        In this case the same colour can be used with different regexes.

        The value_tuple should use an unicode string followed by a number
        indicating the (sub-)match,
        like (u'\\b(cls|self)\\b',0)
        which would colour the main match (the words cls and self) or like
        (u'(?:(?:def)\s\w+)\s*\((.*)\):',1)
        which would colour the first submatch, which is (.*) and in this case
        are basically the parameters of a python function.

        Run script.

        Note: could be used as an UDL alternative as well.

"""

from Npp import editor, editor1, editor2, notepad, NOTIFICATION, SCINTILLANOTIFICATION, INDICATORSTYLE

try:
    EnhancedPythonLexer().main()
except NameError:

    # ensure that only a single instance is used to prevent getting
    # multiple callbacks executed
    class SingletonEnhancedPythonLexer(type):
        _instance = None
        def __call__(cls, *args, **kwargs):
            if cls._instance is None:
                cls._instance = super(SingletonEnhancedPythonLexer, cls).__call__(*args, **kwargs)
            return cls._instance

    # main class
    class EnhancedPythonLexer(object):

        __metaclass__ = SingletonEnhancedPythonLexer

        @staticmethod
        def set_indicator_attributes(indicator_number, fore=(0,0,0)):
            editor1.indicSetFore(indicator_number, fore)
            editor1.indicSetStyle(indicator_number, INDICATORSTYLE.TEXTFORE)
            editor2.indicSetFore(indicator_number, fore)
            editor2.indicSetStyle(indicator_number, INDICATORSTYLE.TEXTFORE)
            return indicator_number

        @staticmethod
        def paint_it(indicator, pos, length):
            current_line = editor.lineFromPosition(pos)
            line_start_position = editor.positionFromLine(current_line)
            text = editor.getLine(current_line)
            found_comment_char = text.find('#')
            relative_line_position = pos-line_start_position
            if((-1 < found_comment_char < relative_line_position) or
               (text.count('"', 0, relative_line_position) % 2 == 1) or
               (text.count("'", 0, relative_line_position) % 2 == 1)):
                return
            else:
                editor.setIndicatorCurrent(indicator)
                editor.indicatorFillRange(pos,length)

        def do_regex(self, regex, indicator, start_position, end_position):
            editor.setIndicatorCurrent(indicator)
            editor.indicatorClearRange(start_position, end_position-start_position)
            editor.research(regex[0],
                            lambda m: self.paint_it(indicator, m.span(regex[1])[0], m.span(regex[1])[1] - m.span(regex[1])[0]),
                            0,
                            start_position,
                            end_position)

        def style(self):
            line_number = editor.getFirstVisibleLine()
            start_position = editor.positionFromLine(line_number)
            end_position = editor.getLineEndPosition(line_number + editor.linesOnScreen())
            for indicator, regex in self.regex_dict.items():
                self.do_regex(regex, indicator, start_position, end_position)

        def __init__(self):
            editor.callbackSync(self.on_updateui, [SCINTILLANOTIFICATION.UPDATEUI])
            notepad.callback(self.on_langchanged, [NOTIFICATION.LANGCHANGED])
            notepad.callback(self.on_bufferactivated, [NOTIFICATION.BUFFERACTIVATED])
            self.__is_lexer_doc = False
            self.get_lexer_name = lambda: notepad.getLanguageName(notepad.getLangType())

        def set_lexer_doc(self,bool_value):
            editor.setProperty(self.__class__.__name__, 1 if bool_value is True else -1)
            self.__is_lexer_doc = bool_value

        def on_bufferactivated(self,args):
            if (self.get_lexer_name() == self.lexer_name) and (editor.getPropertyInt(self.__class__.__name__, 0) != -1):
                self.__is_lexer_doc = True
            else:
                self.__is_lexer_doc = False

        def on_updateui(self,args):
            if self.__is_lexer_doc:
                self.style()

        def on_langchanged(self,args):
            self.set_lexer_doc(True if self.get_lexer_name() == self.lexer_name else False)

        # customize, if needed
        def main(self):
            # basically what is returned by notepad.getLanguageName(notepad.getLangType())
            self.lexer_name = 'Python'

            self.regex_dict = {
                                self.set_indicator_attributes(0, (224, 108, 117)) : (u'\\b(cls|self)\\b', 0), # cls and self objects
                                self.set_indicator_attributes(1, (209, 154, 102)) : (u'(?:(?:def)\s\w+)\s*\((.*)\):', 1), # function parameter
                                self.set_indicator_attributes(2, (86, 182, 194))  : (u'(\\beditor\\b|\\beditor1\\b|\\beditor2\\b|\\bnotepad\\b|\\bconsole\\b|\\b__init__\\b|\\b__call__\\b|\\b__del__\\b|\\bsuper\\b|\\bobject\\b|\\btype\\b|\\bprint\\b)', 0), # dunder functions and special keywords
                                self.set_indicator_attributes(3, (181, 188, 201)) : (u'[\(\)\[\]\{\}\=,]', 0), # delimiters - default color
                                self.set_indicator_attributes(4, (181, 188, 201)) : (u'\(\\b(bcls|self)\\b', 1), # cls and self object within function parameters - default color
                                self.set_indicator_attributes(5, (181, 188, 201)) : (u'\(\s*\K\*\*|\(\s*\K\*|,\s*\K\*\*|,\s*\K\*', 0), # args and kwargs references within function parameters - default color
                                self.set_indicator_attributes(6, (79, 175, 239))  : (u'(?(?<=def )(?:)(?=\()|(?(?<!class )\\b\w+?\\b(?=\()|(?:)))', 0), # functions and class instances but not definitions
                              }

            self.set_lexer_doc(True)
            self.style()

    EnhancedPythonLexer().main()


#!/usr/bin/python3
# 5-text_indentation.py
"""Defines a  a text with 2 new lines after each of these
   characters: ., ? and :"""

def text_indentation(text):
    """function that prints a text with 2 new lines after
    each of these characters: ., ? and :

    Args:
        text (string): A string to print and test our fucntion.
    Raises:
        TypeError: text must be a string.
    """
    if not isinstance(text, str):
        raise TypeError("text must be a string")

    result = 0
    result = len(text) - len(text.lstrip())

    while result < len(text):
        print(text[result], end="")
        if text[result] == "\n" or text[result] in ".?:":
            if text[result] in ".?:":
                print("\n")
            result += 1
            while result < len(text) and text[result] == ' ':
                result += 1
            continue
        result += 1


from collections import defaultdict
from re import findall

def get_vertical_velocity_hits(ymax, ymin):
    yspeed_steps = defaultdict(list)
    for y in range(ymin, abs(ymin) + 1):
        y_steps, cy, cvy = 0, 0, y
        while True:
            cy += cvy
            y_steps += 1
            if ymax >= cy >= ymin:
                yspeed_steps[y].append(y_steps)
            if cy < ymin:
                break
            cvy -= 1
    max_steps = max([max(i) for i in yspeed_steps.values()])
    return yspeed_steps, max_steps

def part1(target_area):
    _, _, ymin, _ = [int(x) for x in findall(r'(-?\d+)', target_area)]
    # Sum 1 to ymin
    return ymin * (ymin + 1) // 2

def part2(target_area):
    xmin, xmax, ymin, ymax = [int(x) for x in findall(r'(-?\d+)', target_area)]
    initvelocities = set([(x, y) for y in range(ymin, ymax + 1) for x in range(xmin, xmax + 1)])
    min_vx = int((2 * xmin) ** .5)
    yspeed_steps, max_steps = get_vertical_velocity_hits(ymax, ymin)

    for vx in range(min_vx - 1, xmax):
        step, x, cvx = 0, 0, vx
        while True:
            step += 1
            x += cvx
            cvx = 0 if cvx == 0 else cvx - 1
            if xmin <= x <= xmax:
                for yspeed, y_steps in yspeed_steps.items():
                    if step in y_steps:
                        initvelocities.add((vx, yspeed))
            if x > xmax or step > max_steps:
                break
    return len(initvelocities)

def run():
    target_area = open('indata/day17.txt').readline().rstrip()
    print(f'Day 17 pt1: {part1(target_area)}')
    print(f'Day 17 pt2: {part2(target_area)}')

# Day 17 pt1: 11781
# Day 17 pt2: 4531


"""
setup.py for the `ngesh` library

Requirements are listed in `requirements.txt`.
"""

# Import Python standard libraries
from setuptools import setup, find_packages
import pathlib

# The directory containing this file
LOCAL_PATH = pathlib.Path(__file__).parent

# The text of the README file
README_FILE = (LOCAL_PATH / "README.md").read_text(encoding="utf-8")

# Load requirements, so they are listed in a single place
with open("requirements.txt", encoding="utf-8") as fp:
    install_requires = [dep.strip() for dep in fp.readlines()]

# This call to setup() does all the work
setup(
    author="Tiago Tresoldi",
    author_email="tiago.tresoldi@lingfil.uu.se",
    classifiers=[
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
        "Programming Language :: Python :: 3",
        "Topic :: Software Development :: Libraries",
    ],
    description="Simulate random phylogenetic trees",
    entry_points={"console_scripts": ["ngesh=ngesh.__main__:main"]},
    extras_require={
        "gfx": ["PyQt5"],
        "dev": ["black", "flake8", "twine", "wheel"],
        "test": ["pytest"],
    },
    include_package_data=True,
    install_requires=install_requires,
    keywords=["random phylogenetic tree", "phylogenetics", "simulation"],
    license="MIT",
    long_description=README_FILE,
    long_description_content_type="text/markdown",
    name="ngesh",
    packages=find_packages(where="src"),
    package_dir={"": "src"},
    python_requires=">=3.6",
    test_suite="tests",
    tests_require=[],
    url="https://github.com/tresoldi/ngesh",
    version="1.2.1",  # remember to sync with __init__.py
    zip_safe=False,
)


from trac.core import *
from trac.web.api import IRequestFilter
from trac.config import ListOption
from trac.util.html import html
import re

try:
    set = set
except ImportError:
    from sets import Set as set

__all__ = ['NavControlModule']

class NavControlModule(Component):
    """Request filter to hide entries in navigation bars."""

    mainnav = ListOption('navcontrol', 'mainnav',
                              doc='Items to remove from the mainnav bar')

    metanav = ListOption('navcontrol', 'metanav',
                              doc='Items to remove from the metanav bar')

    main2meta = ListOption('navcontrol', 'mainnav_to_metanav',
                              doc='Items to shift from mainnav to metanav bar')

    meta2main = ListOption('navcontrol', 'metanav_to_mainnav',
                              doc='Items to shift from metanav to mainnav bar')

    labels = ListOption('navcontrol', 'labels',
                              doc='Labels to assign to navigation items. \
                                   They should be specified as navitem:label e.g \
                                   !wiki:My Wiki,!browser:Code')

    implements(IRequestFilter)

    # IRequestFilter methods
    def pre_process_request(self, req, handler):
        return handler

    def post_process_request(self, req, template, data, content_type):
        self._remove_items(req, 'mainnav')
        self._remove_items(req, 'metanav')
        self._move_items(req, 'main2meta')
        self._move_items(req, 'meta2main')
        self._relabel_items(req)
        return template, data, content_type

    # Internal methods
    def _remove_items(self, req, name):
        items = set(getattr(self, name))
        prefix_list=['-', '!']
        items |= self._get_items(req, name, prefix_list)
        for item in items:
            navitems = req.chrome['nav'][name]
            for navitem in navitems:
              if navitem['name'] == item:
                navitems.remove(navitem)

    def _move_items(self, req, name):
        items = set(getattr(self, name))
        prefix_list=['@', '^']
        if name == 'main2meta':
            nav_from = 'mainnav'
            nav_to   = 'metanav'
        else:
            nav_from = 'metanav'
            nav_to   = 'mainnav'
        items |= self._get_items(req, nav_from, prefix_list)
        nav_from_items = req.chrome['nav'][nav_from]
        nav_to_items   = req.chrome['nav'][nav_to]
        for item in items:
            for navitem in nav_from_items:
                if navitem['name'] == item:
                    nav_from_items.remove(navitem)
                    nav_to_items.append(navitem)

    def _relabel_items(self, req):
      nvp_dict = {}
      items = set(getattr(self, 'labels'))
      prefix_list=['%', '*']
      items |= self._get_items(req, 'mainnav', prefix_list) \
          |  self._get_items(req, 'metanav', prefix_list)
      if len(items) > 0:
        for nvp in items:
          try:
            index = nvp.index(':')
            nvp_dict[nvp[0:index].strip()] = nvp[index+1:].strip()
          except:
            pass
        if len(nvp_dict) > 0:
          for item in req.chrome['nav']['mainnav'] + req.chrome['nav']['metanav']:
            name = item['name']
            if nvp_dict.has_key(name):
              re_href=re.compile('<a.+?href="(.*?)"[\s.]*', re.I | re.S | re.M)
              href_val=re_href.findall(item['label'].__str__())
              if len(href_val) > 0:
                item['label'] = html.A(nvp_dict[name], href=href_val[0])

    # general helper method
    def _get_items(self, req, name, prefix_list):
      items = set()
      for item in self.config.getlist('trac', name):
        item = item.strip()
        if item[0] in prefix_list:
          items.add(item[1:])
      return items


import math
import numpy as np
import matplotlib.pyplot as plt

S = 10
A = 2
K = 1001
P = np.zeros((S*A,S)) #P of environment
for i in range(S-1):
    P[i][i+1] = 1 #e
    P[10+S-i-1][S-i-2] = 1 #w
P[9][9] = 1 #e
P[10+0][0] = 1 #w

r = np.zeros((S,A))
r[8][0] = 1
r[1][1] = 0.5
# gamma = 0.99
gamma = 0.99
mu = (0.1*np.ones((S,1)))
Q = np.zeros((S,A))
log_max_d = []
pi = np.ones((S,1)) #0 for west, 1 for east
ks = []

def main():
    records, pi = value_iteration()
    plt.xlabel('k')
    plt.ylabel('log diff')
    plt.plot(records)
    plt.show()
    print(Q)
    print(pi)

def policy_improvement(q):
    new_q = np.zeros((S, A))

    states = [s for s in range(0, S)]
    for s in range(S):
        for a in range(A):
            s_next = np.random.choice(states, p=P[s+a*S])
            new_q[s][a] = r[s][a] + gamma*np.max(q[s_next])
    # print(new_q)
    return new_q

def value_iteration():
    global Q
    records = []

    for k in range(1, K+1):
        new_q = policy_improvement(Q)
        max_diff = np.max(np.abs(new_q - Q))

        records.append([k, max_diff])
        Q = new_q

    return records, np.argmax(Q,axis=1)

if __name__ == "__main__":
    main()


"""Kernel information detection class"""

from subprocess import check_output

class Kernel:
    """Another call to `uname` to retrieve kernel release information"""
    def __init__(self):
        self.value = check_output(
            ['uname', '-r'],
            universal_newlines=True
        ).rstrip()


from bs4 import BeautifulSoup
import requests
import pandas as pd
import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from urllib.request import urlretrieve
import os

emme_url = 'https://5101137.onlineleasing.realpage.com/'

# initialize the driver and open the Chrome browser
driver = webdriver.Chrome('/Users/adouglas/Desktop/chromedriver')

# open the webpage in the current driver
driver.get(emme_url)
time.sleep(10)

WebDriverWait(driver, 60).until(EC.frame_to_be_available_and_switch_to_it(driver.find_element_by_xpath('//iframe[@id="rp-leasing-widget"]')))

# first get the floorlans
current_floorplans = os.listdir('/Users/adouglas/Google Drive/real_estate/chicago_listing_scraping/floorplans_emme')

rows = WebDriverWait(driver, 60).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'floorplan-tile')))

for row in rows:
	row_soup = BeautifulSoup(row.get_attribute('innerHTML'), "html.parser")
	img_div = row_soup.find('div', class_='loaded-image')
	plan_url = img_div.attrs['style'].split('(')[1].split(')')[0].replace('"','').replace('320x320','1024x1024')
	file_name = row_soup.find('span', class_='specs').text.split('|')[0].replace(' ','_') + \
				row_soup.find('span', class_='specs').text.split('|')[1].strip().replace(' ','_') + \
				row_soup.find('span', class_='specs').text.split('|')[2].replace(' ','_') + plan_url[-4:]
	if file_name not in current_floorplans:
		urlretrieve(plan_url, '/Users/adouglas/Google Drive/real_estate/chicago_listing_scraping/floorplans_emme/' + file_name)

WebDriverWait(driver, 60).until(EC.presence_of_element_located((By.TAG_NAME, 'button')))
time.sleep(5)

rows = driver.find_elements_by_tag_name('button')

if rows[0].get_attribute('innerHTML') == 'Start':
	rows[0].click()

elem = driver.find_element_by_class_name('help-div')
elem.find_element_by_tag_name('a').click()

rows = driver.find_elements_by_tag_name('button')
row_count = len(rows)

i = 0

for i in range(row_count):
	rows = WebDriverWait(driver, 60).until(EC.presence_of_all_elements_located((By.TAG_NAME, 'button')))

	if 'Available' in rows[i].get_attribute('innerHTML'):
		rows[i].click()

		unit_data = WebDriverWait(driver, 60).until(EC.presence_of_element_located((By.CLASS_NAME, 'data-table')))
		data_soup = BeautifulSoup(unit_data.get_attribute('innerHTML'), "html.parser")
		beds  = data_soup.text.split('Bedrooms')[1].split('Bathrooms')[0]
		baths = data_soup.text.split('Bathrooms')[1].split('Square')[0]
		unit_sf = data_soup.text.split('Feet')[1].split('Occupancy')[0]

		available_rows = driver.find_elements_by_class_name('radio-option')
		for available_unit in available_rows:
			if 'aria-label' in available_unit.get_attribute('innerHTML'):
				row_soup = BeautifulSoup(available_unit.get_attribute('innerHTML'), "html.parser")
				unit_num  = row_soup.find('span', class_='unit-cell').text
				unit_rent = row_soup.find('span', class_='unit-price').text
				print(beds, baths, unit_sf, unit_num, unit_rent)

		back_button = driver.find_element_by_id('footer-back-button')
		back_button.click()
		i += 1
	else:
		i += 1

driver.close()


import shutil
import tempfile
import unittest

from trac import __version__ as trac_version
from trac.core import Component, implements
from trac.db import Table, Column, Index
from trac.db.api import DatabaseManager
from trac.test import EnvironmentStub

from announcer import db_default
from announcer.api import AnnouncementSystem, AnnouncementEvent
from announcer.api import IAnnouncementSubscriptionFilter
from announcer.api import SubscriptionResolver

class AnnouncementEventTestCase(unittest.TestCase):
    def setUp(self):
        self.event = AnnouncementEvent('realm', 'category', 'target')

    # Tests

    def test_init(self):
        # Examine properties of the initialized objekt.
        event = self.event
        event_props = [event.realm, event.category, event.target, event.author]
        self.assertEquals(event_props, ['realm', 'category', 'target', ''])

    def test_get_basic_terms(self):
        # Method doesn't accept any argument.
        self.assertRaises(TypeError, self.event.get_basic_terms, None)
        self.assertEquals(self.event.get_basic_terms(), ('realm', 'category'))

    def test_get_session_terms(self):
        # While having mandatory argument, return value is a constant.
        self.assertRaises(TypeError, self.event.get_session_terms)
        self.assertEquals(self.event.get_session_terms(None), tuple())
        self.assertEquals(self.event.get_session_terms('anonymous'), tuple())

class AnnouncementSystemSetupTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*'])
        self.env.path = tempfile.mkdtemp()
        self.db_mgr = DatabaseManager(self.env)
        self.db = self.env.get_db_cnx()
        self.an_sys = AnnouncementSystem(self.env)

    def tearDown(self):
        self.db.close()
        # Really close db connections.
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    # Helpers

    def _get_cursor_description(self, cursor):
        # Cursors don't look the same across Trac versions
        if trac_version < '0.12':
            return cursor.description
        else:
            return cursor.cursor.description

    def _schema_init(self, schema=None):
        # Current announcer schema is setup with enabled component anyway.
        #   Revert these changes for clean install testing.
        cursor = self.db.cursor()
        cursor.execute("DROP TABLE IF EXISTS subscriptions")
        cursor.execute("DROP TABLE IF EXISTS subscription")
        cursor.execute("DROP TABLE IF EXISTS subscription_attribute")
        cursor.execute("DELETE FROM system WHERE name='announcer_version'")

        if schema:
            connector = self.db_mgr._get_connector()[0]
            for table in schema:
                for stmt in connector.to_sql(table):
                    cursor.execute(stmt)

    def _verify_curr_schema(self):
        self.assertFalse(self.an_sys.environment_needs_upgrade(self.db))
        cursor = self.db.cursor()
        cursor.execute("SELECT * FROM subscription_attribute")
        columns = [col[0] for col in self._get_cursor_description(cursor)]
        self.assertTrue('name' not in columns)
        self.assertTrue('value' not in columns)
        self.assertEquals(
            ['id', 'sid', 'authenticated', 'class', 'realm', 'target'],
            columns
        )
        cursor.execute("""
            SELECT value
              FROM system
             WHERE name='announcer_version'
        """)
        version = int(cursor.fetchone()[0])
        self.assertEquals(db_default.schema_version, version)

    def _verify_version_unregistered(self):
        cursor = self.db.cursor()
        cursor.execute("""
            SELECT value
              FROM system
             WHERE name='announcer_version'
        """)
        self.assertFalse(cursor.fetchone())

    # Tests

    def test_new_install(self):
        # Just do db table clean-up.
        self._schema_init()

        self.assertEquals(0, self.an_sys.get_schema_version(self.db))
        self.assertTrue(self.an_sys.environment_needs_upgrade(self.db))

        self.an_sys.upgrade_environment(self.db)
        self._verify_curr_schema()

    def test_upgrade_v1_to_current(self):
        # The initial db schema from r3015 - 10-Jan-2008 by Stephen Hansen.
        schema = [
            Table('subscriptions', key='id')[
                Column('id', auto_increment=True),
                Column('sid'),
                Column('enabled', type='int'),
                Column('managed', type='int'),
                Column('realm'),
                Column('category'),
                Column('rule'),
                Column('destination'),
                Column('format'),
                Index(['id']),
                Index(['realm', 'category', 'enabled']),
            ]
        ]
        self._schema_init(schema)

        # Populate tables with test data.
        cursor = self.db.cursor()
        cursor.executemany("""
            INSERT INTO session
                   (sid,authenticated,last_visit)
            VALUES (%s,%s,%s)
        """, (('somebody','0','0'), ('user','1','0')))
        cursor.executemany("""
            INSERT INTO session_attribute
                   (sid,authenticated,name,value)
            VALUES (%s,1,%s,%s)
        """, (('user','announcer_email_format_ticket','text/html'),
              ('user','announcer_specified_email','')))
        cursor.executemany("""
            INSERT INTO subscriptions
                   (sid,enabled,managed,
                    realm,category,rule,destination,format)
            VALUES (%s,%s,0,%s,%s,%s,%s,%s)
        """, (('somebody',1,'ticket','changed','1','1','email'),
              ('user',1,'ticket','attachment added','1','1','email')))

        self.assertEquals(1, self.an_sys.get_schema_version(self.db))
        target = 6
        db_default.schema_version = target
        self.assertTrue(self.an_sys.environment_needs_upgrade(self.db))

        self.an_sys.upgrade_environment(self.db)
        self._verify_curr_schema()

    def test_upgrade_to_schema_v2(self):
        # The initial db schema from r3015 - 10-Jan-2008 by Stephen Hansen.
        schema = [
            Table('subscriptions', key='id')[
                Column('id', auto_increment=True),
                Column('sid'),
                Column('enabled', type='int'),
                Column('managed', type='int'),
                Column('realm'),
                Column('category'),
                Column('rule'),
                Column('destination'),
                Column('format'),
                Index(['id']),
                Index(['realm', 'category', 'enabled']),
            ]
        ]
        self._schema_init(schema)

        # Populate tables with test data.
        cursor = self.db.cursor()
        cursor.executemany("""
            INSERT INTO session
                   (sid,authenticated,last_visit)
            VALUES (%s,%s,%s)
        """, (('somebody','0','0'), ('user','1','0')))
        cursor.executemany("""
            INSERT INTO session_attribute
                   (sid,authenticated,name,value)
            VALUES (%s,1,%s,%s)
        """, (('user','announcer_email_format_ticket','text/html'),
              ('user','announcer_specified_email','')))
        cursor.executemany("""
            INSERT INTO subscriptions
                   (sid,enabled,managed,
                    realm,category,rule,destination,format)
            VALUES (%s,%s,0,%s,%s,%s,%s,%s)
        """, (('somebody',1,'ticket','changed','1','1','email'),
              ('user',1,'ticket','attachment added','1','1','email')))

        self.assertEquals(1, self.an_sys.get_schema_version(self.db))
        target = 2
        db_default.schema_version = target
        self.assertTrue(self.an_sys.environment_needs_upgrade(self.db))

        # Change from r3047 - 13-Jan-2008 for announcer-0.2 by Stephen Hansen.
        # - 'subscriptions.destination', 'subscriptions.format'
        # + 'subscriptions.authenticated', 'subscriptions.transport'
        # 'subscriptions.managed' type='int' --> (default == char)
        self.an_sys.upgrade_environment(self.db)

        self.assertEquals(target, self.an_sys.get_schema_version(self.db))
        self._verify_version_unregistered()
        cursor = self.db.cursor()
        cursor.execute("SELECT * FROM subscriptions")
        columns = [col[0] for col in self._get_cursor_description(cursor)]
        self.assertEquals(['id', 'sid', 'authenticated', 'enabled', 'managed',
                           'realm', 'category', 'rule', 'transport'],
                          columns
        )

    def test_upgrade_to_schema_v3(self):
        # Schema from r3047 - 13-Jan-2008 for announcer-0.2 by Stephen Hansen.
        schema = [
            Table('subscriptions', key='id')[
                Column('id', auto_increment=True),
                Column('sid'),
                Column('authenticated', type='int'),
                Column('enabled', type='int'),
                Column('managed'),
                Column('realm'),
                Column('category'),
                Column('rule'),
                Column('transport'),
                Index(['id']),
                Index(['realm', 'category', 'enabled']),
            ]
        ]
        self._schema_init(schema)

        # Populate tables with test data.
        cursor = self.db.cursor()
        cursor.executemany("""
            INSERT INTO session_attribute
                   (sid,authenticated,name,value)
            VALUES (%s,1,%s,%s)
        """, (('user','announcer_email_format_ticket','text/html'),
              ('user','announcer_email_format_wiki','text/plain'),
              ('user','announcer_specified_email','')))
        cursor.executemany("""
            INSERT INTO subscriptions
                   (sid,authenticated,enabled,managed,
                    realm,category,rule,transport)
            VALUES (%s,%s,1,%s,%s,%s,%s,%s)
        """, (('user',1,'watcher','ticket','changed','1','email'),
              ('user',1,'watcher','wiki','*','WikiStart','email')))

        self.assertEquals(2, self.an_sys.get_schema_version(self.db))
        target = 3
        db_default.schema_version = target
        self.assertTrue(self.an_sys.environment_needs_upgrade(self.db))

        # From r9116 - 25-Sep-2010 for announcer-0.12.1 by Robert Corsaro.
        # + table 'subscription', 'subscription_attribute'
        self.an_sys.upgrade_environment(self.db)

        self.assertEquals(target, self.an_sys.get_schema_version(self.db))

    def test_upgrade_to_schema_v4(self):
        # Schema from r9116 - 25-Sep-2010 for announcer-0.12.1 by R. Corsaro.
        schema = [
            Table('subscriptions', key='id')[
                Column('id', auto_increment=True),
                Column('sid'),
                Column('authenticated', type='int'),
                Column('enabled', type='int'),
                Column('managed'),
                Column('realm'),
                Column('category'),
                Column('rule'),
                Column('transport'),
                Index(['id']),
                Index(['realm', 'category', 'enabled']),
            ],
            Table('subscription', key='id')[
                Column('id', auto_increment=True),
                Column('time', type='int64'),
                Column('changetime', type='int64'),
                Column('class'),
                Column('sid'),
                Column('authenticated', type='int'),
                Column('distributor'),
                Column('format'),
                Column('priority'),
                Column('adverb')
            ],
            Table('subscription_attribute', key='id')[
                Column('id', auto_increment=True),
                Column('sid'),
                Column('class'),
                Column('name'),
                Column('value')
            ]
        ]
        self._schema_init(schema)

        # Populate tables with test data.
        cursor = self.db.cursor()
        cursor.execute("""
            INSERT INTO subscription
                   (time,changetime,class,sid,authenticated,
                    distributor,format,priority,adverb)
            VALUES ('0','0','GeneralWikiSubscriber','user','1',
                    'email','text/plain','1','always')
        """)
        cursor.executemany("""
            INSERT INTO subscription_attribute
                   (sid,class,name,value)
            VALUES (%s,%s,%s,%s)
        """, (('somebody','GeneralWikiSubscriber','wiki', '*'),
              ('somebody','UserChangeSubscriber','wiki','created'),
              ('user','GeneralWikiSubscriber','wiki', 'TracWiki')))

        self.assertEquals(3, self.an_sys.get_schema_version(self.db))
        target = 4
        db_default.schema_version = target
        self.assertTrue(self.an_sys.environment_needs_upgrade(self.db))

        # From r9210 - 29-Sep-2010 for announcer-0.12.1 by Robert Corsaro.
        # - table 'subscriptions'
        # 'subscription.priority' type=(default == char) --> 'int'
        # 'subscription_attribute.name --> 'subscription_attribute.realm'
        # 'subscription_attribute.value --> 'subscription_attribute.target'
        self.an_sys.upgrade_environment(self.db)

        self.assertEquals(target, self.an_sys.get_schema_version(self.db))
        # Check type of priority value.
        cursor = self.db.cursor()
        cursor.execute("SELECT priority FROM subscription")
        for priority in cursor:
            # Shouldn't raise an TypeError with appropriate column type.
            result = priority[0] + 0

    def test_upgrade_to_schema_v5(self):
        # Schema from r9210 - 29-Sep-2010 for announcer-0.12.1 by R. Corsaro.
        schema = [
            Table('subscription', key='id')[
                Column('id', auto_increment=True),
                Column('time', type='int64'),
                Column('changetime', type='int64'),
                Column('class'),
                Column('sid'),
                Column('authenticated', type='int'),
                Column('distributor'),
                Column('format'),
                Column('priority', type='int'),
                Column('adverb')
            ],
            Table('subscription_attribute', key='id')[
                Column('id', auto_increment=True),
                Column('sid'),
                Column('class'),
                Column('realm'),
                Column('target')
            ]
        ]
        self._schema_init(schema)

        # Populate tables with test data.
        cursor = self.db.cursor()
        cursor.executemany("""
            INSERT INTO session
                   (sid,authenticated,last_visit)
            VALUES (%s,%s,%s)
        """, (('somebody','0','0'), ('user','1','0')))
        cursor.executemany("""
            INSERT INTO subscription_attribute
                   (sid,class,realm,target)
            VALUES (%s,%s,%s,%s)
        """, (('somebody','GeneralWikiSubscriber','wiki', '*'),
              ('somebody','UserChangeSubscriber','wiki','created'),
              ('user','GeneralWikiSubscriber','wiki', 'TracWiki')))

        self.assertEquals(4, self.an_sys.get_schema_version(self.db))
        target = 5
        db_default.schema_version = target
        self.assertTrue(self.an_sys.environment_needs_upgrade(self.db))

        # From r9235 - 01-Oct-2010 for announcer-0.12.1 by Robert Corsaro.
        # + 'subscription_attribute.authenticated'
        self.an_sys.upgrade_environment(self.db)

        self.assertEquals(target, self.an_sys.get_schema_version(self.db))
        self._verify_version_unregistered()
        cursor = self.db.cursor()
        cursor.execute("SELECT * FROM subscription_attribute")
        columns = [col[0] for col in self._get_cursor_description(cursor)]
        self.assertTrue('name' not in columns)
        self.assertTrue('value' not in columns)
        self.assertEquals(
            ['id', 'sid', 'authenticated', 'class', 'realm', 'target'],
            columns
        )
        # Check authenticated attribute for session IDs.
        subscriptions = [(row[1],(row[2])) for row in cursor]
        for sub in subscriptions:
            self.assertTrue((sub[0] == 'user' and sub[1] == 1) or sub[1] == 0)

    def test_upgrade_to_schema_v6(self):
        # Check data migration and registration of unversioned schema.

        # Table definitions are identical to current schema here, see
        # schema from r9235 - 01-Oct-2010 for announcer-0.12.1 by R. Corsaro.
        self._schema_init(db_default.schema)

        # Populate table with test data.
        cursor = self.db.cursor()
        if self.env.config.get('trac', 'database').startswith('sqlite'):
            # Add dataset with CURRENT_TIMESTAMP strings.
            cursor.execute("""
                INSERT INTO subscription
                       (time,changetime,
                        class,sid,authenticated,
                        distributor,format,priority,adverb)
                VALUES ('1970-01-01 00:00:00','2012-10-31 23:59:59',
                        'GeneralWikiSubscriber','user','1',
                        'email','text/plain','1','always')
            """)
        else:
            cursor.execute("""
                INSERT INTO subscription
                       (time,changetime,
                        class,sid,authenticated,
                        distributor,format,priority,adverb)
                VALUES ('0','1351724399',
                        'GeneralWikiSubscriber','user','1',
                        'email','text/plain','1','always')
            """)
        cursor.execute("""
            INSERT INTO subscription_attribute
                   (sid,authenticated,class,realm,target)
            VALUES ('user','1','GeneralWikiSubscriber','wiki', 'TracWiki')
        """)
        self.assertEquals(5, self.an_sys.get_schema_version(self.db))
        target = 6
        db_default.schema_version = target
        self.assertTrue(self.an_sys.environment_needs_upgrade(self.db))

        # Data migration and registration of unversioned schema.
        self.an_sys.upgrade_environment(self.db)

        self._verify_curr_schema()
        cursor.execute("SELECT time,changetime FROM subscription")
        for time in cursor:
            # Shouldn't raise an TypeError with proper int/long values.
            check = time[1] - time[0]

class SubscriptionResolverTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*'])
        self.env.path = tempfile.mkdtemp()
        self.db_mgr = DatabaseManager(self.env)
        self.db = self.env.get_db_cnx()

    def tearDown(self):
        self.db.close()
        # Really close db connections.
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    # Tests

    def test_init(self):
        # Test just to confirm that SubscriptionResolver initializes cleanly
        #   and that setUp and tearDown both work.
        SubscriptionResolver(self.env)
        pass

class AnnouncementSystemSendTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'announcer.*'])
        self.env.path = tempfile.mkdtemp()
        self.db_mgr = DatabaseManager(self.env)
        self.db = self.env.get_db_cnx()
        self.an_sys = AnnouncementSystem(self.env)

    def tearDown(self):
        self.db.close()
        # Really close db connections.
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    # Tests

    def test_filter_added(self):
        class DummySubscriptionFilter(Component):
            """Test implementation for checking the filter ExtensionPoint."""
            implements(IAnnouncementSubscriptionFilter)

            def filter_subscriptions(self, event, subscriptions):
                """Just a pass-through."""
                return subscriptions

        dummy = DummySubscriptionFilter(self.env)
        self.assertTrue(dummy in self.an_sys.subscription_filters)

def suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(AnnouncementEventTestCase, 'test'))
    suite.addTest(unittest.makeSuite(AnnouncementSystemSetupTestCase, 'test'))
    suite.addTest(unittest.makeSuite(AnnouncementSystemSendTestCase, 'test'))
    suite.addTest(unittest.makeSuite(SubscriptionResolverTestCase, 'test'))
    return suite

if __name__ == '__main__':
    unittest.main(defaultTest='suite')


# check_eigvectors.py

import numpy as np
from math import pi
import matplotlib.pyplot as plt
from create_hamiltonian import HamiltonianTilt

if __name__ == "__main__":

    case = "check eigvecs"

    if case == "check eigvecs":

        N = 1
        M = 3
        t = 1
        a = 1
        b = 4 * pi / 3 / a
        delta_nnn = np.zeros((N, M, 2, 3))

        t_bar = 0
        t_amp = 0.1
        p = 1
        try:
            t_freq = 2 * pi * p / a / (M - 1)
        except:
            t_freq = 1
        delta_nn = HamiltonianTilt.generate_nn_vary_ttilda(N, M, t_bar, t_amp, t_freq, a)

        ham = HamiltonianTilt(N, M, t, delta_nn, delta_nnn, a)

        k1 = ham.k1
        k2 = np.array([-np.sqrt(3) / 2 * b, -b / 2])

        k_shift = 2 / 6 * (k1 + k2)

        k_max = 2/20
        k_num = 2000
        k_list = [k_shift + k_max * (i-k_num/2) / k_num * (k1 + k2) for i in range(k_num)]
        spectrum = []

        for i in range(k_num):
            ham.construct_ham_inK(k_list[i])
            ev = np.linalg.eigvals(ham.H)
            ev = np.sort(ev)
            spectrum.append(ev)

        spectrum = np.array(spectrum)

        fig, ax = plt.subplots()
        ax.plot(spectrum)

        plt.show()


class Solution:
    def addStrings(self, num1, num2):
        """
        :type num1: str
        :type num2: str
        :rtype: str
        """
        # int carry=0,i=num1.size()-1,j=num2.size()-1;
        # char ch1,ch2;
        # string answer;
        # while(i>-1||j>-1)
        # {   ch1=i>-1?num1[i--]:'0';
        #     ch2=j>-1?num2[j--]:'0';
        #     answer+=to_string((carry+ch1+ch2-96)%10);
        #     carry=(carry+ch1+ch2-96)/10;   }
        # if(carry) answer+="1";
        # reverse(answer.begin(),answer.end());
        # return answer;
        t1, t2 = 0, 0
        for i in num1:
            t1 *= 10
            t1 += ord(i) - 48

        for i in num2:
            t2 *= 10
            t2 += ord(i) - 48

        return str(t1 + t2)


"""
Item 20:  Prefer Raising Exceptions to Returning None
(EF, p. 80)

Division function that checks for division by zero and has type annotations.
"""

def careful_divide(a: float, b: float) -> float:
	"""Divides a by b.

	Raises:
		ValueError:  When the inputs cannot be divided.
	"""
	try:
		return a / b
	except ZeroDivisionError as e:
		raise ValueError('Invalid inputs')

print('careful_divide documentation provided by doc string')
print(careful_divide.__doc__)
print(f'1.0 / 3.0 = {careful_divide(1.0, 3.0)}')
print(f'1.0 / 3 = {careful_divide(1.0, 3)}')
careful_divide(1.0, 0.0)


import torch

MAX_FLOW = 400

def sequence_loss(flow_preds, flow_gt, valid, cfg):
    """ Loss function defined over sequence of flow predictions """

    gamma = cfg.gamma
    max_flow = cfg.max_flow
    n_predictions = len(flow_preds)
    flow_loss = 0.0
    flow_gt_thresholds = [5, 10, 20]

    # exlude invalid pixels and extremely large diplacements
    mag = torch.sum(flow_gt**2, dim=1).sqrt()
    valid = (valid >= 0.5) & (mag < max_flow)

    for i in range(n_predictions):
        i_weight = gamma**(n_predictions - i - 1)
        i_loss = (flow_preds[i] - flow_gt).abs()
        flow_loss += i_weight * (valid[:, None] * i_loss).mean()

    epe = torch.sum((flow_preds[-1] - flow_gt)**2, dim=1).sqrt()
    epe = epe.view(-1)[valid.view(-1)]

    metrics = {
        'epe': epe.mean().item(),
        '1px': (epe < 1).float().mean().item(),
        '3px': (epe < 3).float().mean().item(),
        '5px': (epe < 5).float().mean().item(),
    }

    flow_gt_length = torch.sum(flow_gt**2, dim=1).sqrt()
    flow_gt_length = flow_gt_length.view(-1)[valid.view(-1)]
    for t in flow_gt_thresholds:
        e = epe[flow_gt_length < t]
        metrics.update({
                f"{t}-th-5px": (e < 5).float().mean().item()
        })

    return flow_loss, metrics


"""--- Day 2: I Was Told There Would Be No Math ---"""

paper = ribbon = 0

with open("input/02.txt") as f:
  for line in f:
    dimensions = list(map(int, line.split("x"))) # "8x5x3" -> [ 8, 5, 3]
    dimensions.sort()                            # [ 8, 5, 3 ] -> [ 3, 5, 8 ]
    l, w, h = dimensions                         # l = 3, w = 5, h = 8
    paper += (2*l*w + 2*w*h + 2*h*l) + l*w       # (surface) + slack
    ribbon += (2*l+2*w) + l*w*h                  # (wrap) + bow

print(paper)
print(ribbon)


from flask import Flask, render_template, request, jsonify, redirect
from database import signup_to_db, login_from_db, mobile_bill_db, elec_bill_db, gas_bill_db,broadband_bill_db, dth_bill_db, update_elec_last_bill_date, update_mobile_last_bill_date, update_gas_last_bill_date, update_broadband_last_bill_date, update_dth_last_bill_date
import random
from datetime import date, datetime

app= Flask(__name__)

@app.route("/")
def home():
  return render_template('home.html')

@app.route("/signup")
def signup():
  return render_template('signup.html')

@app.route("/signup/apply", methods=['post'])
def signup_done():
  data= request.form
  # return jsonify(data)
  signup_to_db(data)
  return render_template('signup_success.html')

@app.route("/login")
def login():
  return render_template('login.html')

@app.route("/login/success", methods=['post'])
def login_success():
  data= request.form
  is_user=login_from_db(data)

  if not is_user:
    return render_template('login_fail.html')

  return render_template('login_success.html')
  # return jsonify(data)

@app.route("/login/dashboard")
def dashboard():
  return render_template('dashboard.html')

@app.route("/login/elec")
def elec():
  return render_template('elec.html')

@app.route("/login/gas")
def gas():
  return render_template('gas.html')

@app.route("/login/broadband")
def broadband():
  return render_template('broadband.html')

@app.route("/login/dth")
def dth():
  return render_template('dth.html')

# @app.route("/login/mobile")
# def mobile():
#   return render_template('mobile.html')

@app.route("/login/mobile")
def water():
  return render_template('mobile.html')

@app.route("/elec/first_time")
def elec_first_time():
  today=date.today()
  id=random.randrange(2000000,3000000)
  return render_template('elec_first_time.html',today=today,id=id)

@app.route("/gas/first_time")
def gas_first_time():
  today=date.today()
  id=random.randrange(3000000,4000000)
  return render_template('gas_first_time.html',today=today,id=id)

@app.route("/mobile/first_time")
def mobile_first_time():
  today=date.today()
  id=random.randrange(1000000,2000000)
  return render_template('mobile_first_time.html',today=today,id=id)

@app.route("/broadband/first_time")
def broadband_first_time():
  today=date.today()
  id=random.randrange(4000000,5000000)
  return render_template('broadband_first_time.html',today=today,id=id)

@app.route("/dth/first_time")
def dth_first_time():
  today=date.today()
  id=random.randrange(5000000,6000000)
  return render_template('dth_first_time.html',today=today,id=id)

@app.route("/elec/re")
def elec_re():
  today=date.today()
  return render_template("elec_re.html", today=today)

@app.route("/gas/re")
def gas_re():
  today=date.today()
  return render_template("gas_re.html", today=today)

@app.route("/mobile/re")
def mobile_re():
  today=date.today()
  return render_template("mobile_re.html", today=today)

@app.route("/broadband/re")
def broadband_re():
  today=date.today()
  return render_template("broadband_re.html", today=today)

@app.route("/dth/re")
def dth_re():
  today=date.today()
  return render_template("dth_re.html", today=today)

@app.route("/elec/bill", methods=['post'])
def elec_bill():
  data= request.form
  # return jsonify(data)
  db_data=elec_bill_db(data)

  units=random.randrange(90,170)
  price_per_unit=10.73
  bill=units * price_per_unit

  curr_date = db_data['curr_date'].strftime('%Y-%m-%d')
  last_bill_date = db_data['last_bill_date'].strftime('%Y-%m-%d')

  if (datetime.strptime(curr_date, "%Y-%m-%d")-datetime.strptime(last_bill_date, "%Y-%m-%d")).days >30:
    update_elec_last_bill_date(data)
    return render_template('pay_elec_bill.html',db_data=db_data,units=units, price_per_unit=price_per_unit , bill=bill)

  else:
    return render_template("no_bill.html")

@app.route("/gas/bill", methods=['post'])
def gas_bill():
  data= request.form
  # return jsonify(data)
  db_data=gas_bill_db(data)

  units=random.randrange(20,37)
  price_per_unit=25
  bill=units * price_per_unit

  curr_date = db_data['curr_date'].strftime('%Y-%m-%d')
  last_bill_date = db_data['last_bill_date'].strftime('%Y-%m-%d')

  if (datetime.strptime(curr_date, "%Y-%m-%d")-datetime.strptime(last_bill_date, "%Y-%m-%d")).days >30:
    update_gas_last_bill_date(data)
    return render_template('pay_gas_bill.html',db_data=db_data,units=units, price_per_unit=price_per_unit , bill=bill)

  else:
    return render_template("no_bill.html")

@app.route("/mobile/bill", methods=['post'])
def mobile_bill():
  data= request.form
  # return jsonify(data)
  db_data=mobile_bill_db(data)

  curr_date = db_data['curr_date'].strftime('%Y-%m-%d')
  last_bill_date = db_data['last_bill_date'].strftime('%Y-%m-%d')

  if (datetime.strptime(curr_date, "%Y-%m-%d")-datetime.strptime(last_bill_date, "%Y-%m-%d")).days >30:
    update_mobile_last_bill_date(data)
    return render_template('pay_mobile_bill.html',db_data=db_data)

  else:
    return render_template("no_bill.html")

@app.route("/broadband/bill", methods=['post'])
def broadband_bill():
  data= request.form
  # return jsonify(data)
  db_data=broadband_bill_db(data)

  curr_date = db_data['curr_date'].strftime('%Y-%m-%d')
  last_bill_date = db_data['last_bill_date'].strftime('%Y-%m-%d')

  if (datetime.strptime(curr_date, "%Y-%m-%d")-datetime.strptime(last_bill_date, "%Y-%m-%d")).days >30:
    update_broadband_last_bill_date(data)
    return render_template('pay_broadband_bill.html',db_data=db_data)

  else:
    return render_template("no_bill.html")

@app.route("/dth/bill", methods=['post'])
def dth_bill():
  data= request.form
  # return jsonify(data)
  db_data=dth_bill_db(data)

  curr_date = db_data['curr_date'].strftime('%Y-%m-%d')
  last_bill_date = db_data['last_bill_date'].strftime('%Y-%m-%d')

  if (datetime.strptime(curr_date, "%Y-%m-%d")-datetime.strptime(last_bill_date, "%Y-%m-%d")).days >30:
    update_dth_last_bill_date(data)
    return render_template('pay_dth_bill.html',db_data=db_data)

  else:
    return render_template("no_bill.html")

@app.route("/login/bill_paid")
def bill_paid():
  return render_template('bill_paid.html')

@app.route("/contact")
def contact():
  return render_template('contact.html')

if __name__ =='__main__':
  app.run(host='0.0.0.0', debug=True)


from typing import List, Optional, Tuple, Union

import jax
import jax.numpy as jnp
import pywt
from jax.config import config
from functools import partial

from .conv_fwt import _get_filter_arrays
from .utils import Wavelet

config.update("jax_enable_x64", False)

@partial(jax.jit, static_argnames=['level'])
def wavedec2(
    data: jnp.ndarray,
    wavelet: jnp.ndarray,
    level: Optional[int] = None
) -> List[Union[jnp.ndarray, Tuple[jnp.ndarray, jnp.ndarray, jnp.ndarray]]]:
    """Compute the two dimensional wavelet analysis transform on the last two dimensions of the input data array.

    Args:
        data (jnp.array): Jax array containing the data to be transformed. Assumed shape:
                         [batch size, hight, width].
        wavelet (Wavelet): A namedtouple containing the filters for the transformation.
        level (int): The max level to be used, if not set as many levels as possible
                               will be used. Defaults to None.
        mode (str): The desired padding mode. Choose reflect, symmetric or zero.
            Defaults to reflect.

    Returns:
        list: The wavelet coefficients in a nested list.
            The coefficients are in pywt order. That is:
            [cAn, (cHn, cVn, cDn), … (cH1, cV1, cD1)].
            A denotes approximation, H horizontal, V vertical
            and D diagonal coefficients.

    Examples:
        >>> import pywt, scipy.misc
        >>> import jaxwt as jwt
        >>> import jax.numpy as jnp
        >>> face = jnp.transpose(scipy.misc.face(), [2, 0, 1]).astype(jnp.float64)
        >>> jwt.wavedec2(face, pywt.Wavelet("haar"), level=2, mode="reflect")
    """
    data = jnp.expand_dims(data, 1)
    mode = "reflect"

    if level is None:
        level = pywt.dwtn_max_level(
            [data.shape[-1], data.shape[-2]], pywt.Wavelet("MyWavelet", wavelet)
        )

    wavelen = wavelet.shape[-1]
    dec_lo, dec_hi, _, _ = _get_custom_filter_arrays(wavelet)
    dec_filt = construct_2d_filt(lo=dec_lo, hi=dec_hi)

    result_lst: List[
        Union[jnp.ndarray, Tuple[jnp.ndarray, jnp.ndarray, jnp.ndarray]]
    ] = []
    res_ll = data
    for _ in range(level):
        res_ll = _fwt_pad2d(res_ll, wavelen, mode=mode)

        ## FFT Routine
        res_ll = jnp.squeeze(_fwt_pad2d(res_ll, len(wavelet), mode=mode))
        dec_filt = jnp.squeeze(dec_filt)

        fft_shape = (res_ll.shape[1], res_ll.shape[2])

        a = jnp.fft.rfftn(res_ll, s=fft_shape, axes=[1,2])
        b = jnp.fft.rfftn(dec_filt, s=fft_shape, axes=[1,2])

        a = jnp.expand_dims(a, axis=1)
        ret = jnp.fft.irfftn(a * b, fft_shape)

        # Strides
        res = ret[:,:,::2,::2]

        res_ll, res_lh, res_hl, res_hh = jnp.split(res, 4, 1)
        result_lst.append([res_lh.squeeze(1), res_hl.squeeze(1), res_hh.squeeze(1)])
    result_lst.append(res_ll.squeeze(1))
    result_lst.reverse()
    return result_lst

@jax.jit
def waverec2(
    coeffs: List[Union[jnp.ndarray, Tuple[jnp.ndarray, jnp.ndarray, jnp.ndarray]]],
    wavelet: jnp.ndarray,
) -> jnp.ndarray:
    """Compute a two dimensional synthesis wavelet transfrom.

       Use it to reconstruct the original input image from the wavelet coefficients.

    Args:
        coeffs (list): The input coefficients, typically the output of wavedec2.
        wavelet (Wavelet): The named tuple contining the filters used to compute the analysis transform.

    Returns:
        jnp.array: Reconstruction of the original input data array of shape [batch, height, width].

    Raises:
        ValueError: If `coeffs` is not in the shape as it is returned from `wavedec2`.

    Example:
        >>> import pywt, scipy.misc
        >>> import jaxwt as jwt
        >>> import jax.numpy as jnp
        >>> face = jnp.transpose(scipy.misc.face(), [2, 0, 1]).astype(jnp.float64)
        >>> transformed = jwt.wavedec2(face, pywt.Wavelet("haar"), level=2, mode="reflect")
        >>> jwt.waverec2(transformed, pywt.Wavelet("haar"))

    """
    if not isinstance(coeffs[0], jnp.ndarray):
        raise ValueError(
            "First element of coeffs must be the approximation coefficient tensor."
        )

    _, _, rec_lo, rec_hi = _get_custom_filter_arrays(wavelet)
    filt_len = rec_lo.shape[-1]
    rec_filt = construct_2d_filt(lo=rec_lo, hi=rec_hi)
    rec_filt = jnp.transpose(rec_filt, [1, 0, 2, 3])
    res_ll = jnp.expand_dims(coeffs[0], 1)
    for c_pos, res_lh_hl_hh in enumerate(coeffs[1:]):

        res_ll = jnp.concatenate(
            [
                res_ll,
                jnp.expand_dims(res_lh_hl_hh[0], 1),
                jnp.expand_dims(res_lh_hl_hh[1], 1),
                jnp.expand_dims(res_lh_hl_hh[2], 1),
            ],
            1,
        )

        ## FFT ROUTINE
        res_ll = jnp.squeeze(res_ll)
        rec_filt = jnp.squeeze(rec_filt)

        res_ll_dialated = jnp.zeros((res_ll.shape[0], res_ll.shape[1], res_ll.shape[2]*2, res_ll.shape[3]*2))
        res_ll = res_ll_dialated.at[:,:,::2,::2].set(res_ll)

        fft_shape = (res_ll.shape[-2], res_ll.shape[-1])
        a = jnp.fft.rfftn(res_ll, axes=[-2,-1])
        b = jnp.fft.rfftn(rec_filt, s=fft_shape, axes=[-2,-1])

        ret = jnp.fft.irfftn(a * b, s=fft_shape, axes=[-2,-1])
        res_ll = jnp.sum(ret, axis=1)

        # remove the padding
        padl = (2 * filt_len - 3) // 2
        padr = (2 * filt_len - 3) // 2
        padt = (2 * filt_len - 3) // 2
        padb = (2 * filt_len - 3) // 2
        if c_pos < len(coeffs) - 2:
            pred_len = res_ll.shape[-1] - (padl + padr)
            next_len = coeffs[c_pos + 2][0].shape[-1]
            pred_len2 = res_ll.shape[-2] - (padt + padb)
            next_len2 = coeffs[c_pos + 2][0].shape[-2]
            if next_len != pred_len:
                padr += 1
                pred_len = res_ll.shape[-1] - (padl + padr)
                assert (
                    next_len == pred_len
                ), "padding error, please open an issue on github "
            if next_len2 != pred_len2:
                padb += 1
                pred_len2 = res_ll.shape[-2] - (padt + padb)
                assert (
                    next_len2 == pred_len2
                ), "padding error, please open an issue on github "
        # print('padding', padt, padb, padl, padr)
        if padt > 0:
            res_ll = res_ll[..., padt:, :]
        if padb > 0:
            res_ll = res_ll[..., :-padb, :]
        if padl > 0:
            res_ll = res_ll[..., padl:]
        if padr > 0:
            res_ll = res_ll[..., :-padr]
    return res_ll

@jax.jit
def CQF_expansion(dec_lo: jnp.ndarray) -> Tuple[jnp.ndarray, jnp.ndarray, jnp.ndarray, jnp.ndarray]:
    N = dec_lo.shape[0]
    a = jnp.empty((N,),int)
    a = a.at[::2].set(1)
    a = a.at[1::2].set(-1)

    #a[::2] = 1
    #a[1::2] = -1

    dec_hi = -1 * a * jnp.flip(dec_lo)
    rec_lo = jnp.flip(dec_lo)
    rec_hi = a * dec_lo
    return dec_lo, dec_hi, rec_lo, rec_hi

@jax.jit
def _get_custom_filter_arrays(
    wavelet: jnp.ndarray, dtype: jnp.dtype = jnp.float32  # type: ignore
) -> Tuple[jnp.ndarray, jnp.ndarray, jnp.ndarray, jnp.ndarray]:
    """Extract the filter coefficients from an input wavelet object.

    Args:
        wavelet (Wavelet): input wavelet dec_lo parameters
        flip (bool): If true flip the input coefficients.
        dtype: The desired precision. Defaults to jnp.float64 .

    Returns:
        tuple: The dec_lo, dec_hi, rec_lo and rec_hi
            filter coefficients as jax arrays.
    """

    def create_array(filter: Union[List[float], jnp.ndarray]) -> jnp.ndarray:

        return jnp.expand_dims(filter, 0)

    dec_lo, dec_hi, rec_lo, rec_hi = CQF_expansion(wavelet)
    return dec_lo, dec_hi, rec_lo, rec_hi

@jax.jit
def construct_2d_filt(lo: jnp.ndarray, hi: jnp.ndarray) -> jnp.ndarray:
    """Construct 2d filters from 1d inputs using outer products.

    Args:
        lo (jnp.array): 1d lowpass input filter of size [1, length].
        hi (jnp.array): 1d highpass input filter of size [1, length].

    Returns
        jnp.array: 2d filter arrays of shape [4, 1, length, length].
    """
    ll = jnp.outer(lo, lo)
    lh = jnp.outer(hi, lo)
    hl = jnp.outer(lo, hi)
    hh = jnp.outer(hi, hi)
    filt = jnp.stack([ll, lh, hl, hh], 0)
    filt = jnp.expand_dims(filt, 1)
    return filt

def _fwt_pad2d(data: jnp.ndarray, filt_len: int, mode: str = "reflect") -> jnp.ndarray:
    padr = 0
    padl = 0
    padt = 0
    padb = 0
    if filt_len > 2:
        # we pad half of the total requried padding on each side.
        padr += (2 * filt_len - 3) // 2
        padl += (2 * filt_len - 3) // 2
        padt += (2 * filt_len - 3) // 2
        padb += (2 * filt_len - 3) // 2

    # pad to even singal length.
    if data.shape[-1] % 2 != 0:
        padr += 1
    if data.shape[-2] % 2 != 0:
        padb += 1

    data = jnp.pad(data, ((0, 0), (0, 0), (padt, padb), (padl, padr)), mode)
    return data


from Utils.Singleton import Singleton
from configparser import ConfigParser
from os.path import exists
from Utils.Exceptions import GeneralException, ErrorCodes

class Environment(metaclass=Singleton):
    def __init__(self):
        self.__hash = {"version": "0.0.1"}
        self.__config_parser = ConfigParser()

    def read(self):
        path = self["configuration_file"]
        if exists(path):
            self.__config_parser.read(path)
        else:
            raise GeneralException(ErrorCodes.CONFIG_FILE_DOESNT_EXIST,
                                   "Configuration file doesn't exist.")
        if "General" not in self.__config_parser:
            raise GeneralException(ErrorCodes.CONFIG_FILE_INCORRECT_STRUCTURE,
                                   "Missing 'General' Section.")
        if "Communication" not in self.__config_parser:
            raise GeneralException(ErrorCodes.CONFIG_FILE_INCORRECT_STRUCTURE,
                                   "Missing 'General' Section.")
        for key in self.__config_parser["General"]:
            self.__hash[key] = self.__config_parser["General"][key]
        for key in self.__config_parser["Communication"]:
            self.__hash[key] = self.__config_parser["Communication"][key]

    def __getitem__(self, key):
        return self.__hash[key] if key in self.__hash else None

    def __setitem__(self, key, value):
        self.__hash[key] = value


import numpy as np
import matplotlib.pyplot as plot
import matplotlib.patches as patches
import data
from sklearn.decomposition import PCA
import pandas as pd

def add_rects(ax):
    rect1 = patches.Rectangle((420, 320),
                              60,
                              30,
                              linewidth=1,
                              edgecolor='r',
                              facecolor='none',
                              label='C')
    ax.add_patch(rect1)

    rect2 = patches.Rectangle((380, 250),
                              100,
                              10,
                              linewidth=1,
                              edgecolor='g',
                              facecolor='none',
                              label='A')
    ax.add_patch(rect2)

    rect3 = patches.Rectangle((380, 310),
                              40,
                              10,
                              linewidth=1,
                              edgecolor='b',
                              facecolor='none',
                              label='M')
    ax.add_patch(rect3)

    rect4 = patches.Rectangle((300, 270),
                              20,
                              10,
                              linewidth=1,
                              edgecolor='y',
                              facecolor='none',
                              label='B')
    ax.add_patch(rect4)

    rect5 = patches.Rectangle((320, 270),
                              30,
                              10,
                              linewidth=1,
                              edgecolor='w',
                              facecolor='none',
                              label='T')
    ax.add_patch(rect5)

def get_local_max(data, koeff, X, Y):
    local_max = []
    x, y = data.shape
    rad = 10

    for i in range(x):
        for j in range(y):
            l = i - rad if i - rad > 0 else 0
            r = i + rad if i + rad < x else x
            u = j - rad if j - rad > 0 else 0
            d = j + rad if j + rad < y else y
            slice = data[l:r, u:d]

            if data[i][j] == np.max(slice) and data[i][j] > koeff:
                local_max.append([X[j], Y[i], data[i][j]])

    return np.array(local_max).T

def parse_line(line):
    line = line.replace('\n', '').split('\t')
    data = []
    for number in line:
        if number == '':
            data.append(0)
        elif not number.isdigit() and not "," in number:
            continue
        else:
            data.append(float(number.replace(',', '.')))

    return data

def del_ryley(Z, X, Y):
    for i in range(len(Y)):
        for j in range (len(X)):
            if X[j] <= 1.026 * Y[i]:
                Z[i][j] = -0.001

        continue
    return Z

def del_roman(Z, X, Y):
    for i in range(len(Y)):
        for j in range(len(X)):
            if 1.9 * Y[i] <= X[j]:
                Z[i][j] = -0.001
        continue
    return Z

# reading sample out of the file
def read_data(filename, line=None):
    with open(filename) as file:
        lines = file.readlines()
        y = parse_line(lines[3])
        x = []
        # making matrix for the input data
        matrix = []
        for i in range(4, len(lines)):
            numbers = parse_line(lines[i])
            x.append(numbers[0])
            if len(numbers) < 52:
                numbers.extend([0 for _ in range(77 - len(numbers))])
            zs = [numbers[j] for j in range(1, len(numbers))]
            matrix.append(zs)
        z = np.array(matrix).T
        return x, y, z

# getting samples out of files list
def get_data(files_list, dir):
    z_samples = []
    for filename in files_list:
        X, Y, z_matrix = read_data(dir + filename + data.file_type)
        # smoothing the input samples and making common samples list
        z_samples.append(np.ravel(del_roman(del_ryley(z_matrix, X, Y), X, Y)))
        # for getting raw samples
        #z_samples.append(np.ravel(z_matrix))
    return X, Y, z_samples

# PCA decomposition of the samples represented with res_shape shape
def get_pca_res(samples, res_shape, region):
    pca = PCA()
    # making long list of the input data
    pca_data = pca.fit_transform(np.array(samples).T.tolist())
    # drawing histogram
    per_var = np.round(pca.explained_variance_ratio_ * 100, decimals=1)
    labels = ['pc_' + str(x) for x in range(1, len(per_var) + 1)]
    # plot.bar(x=range(1, 11), height=per_var[0:10], tick_label=labels[0:10])
    plot.bar(labels, per_var)
    plot.title(region)
    # getting principal components
    pca_df = pd.DataFrame(pca_data, columns=labels)
    # xy_grids = np.meshgrid(x, y)
    comp1_grid = np.reshape(pca_df.pc_1.to_numpy(), res_shape)
    comp2_grid = np.reshape(pca_df.pc_2.to_numpy(), res_shape)
    return comp1_grid, comp2_grid

# use to draw 3 dimensional graph
def draw_3d_plot(x_mesh, y_mesh, z_mesh, name):
    fig = plot.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.plot_surface(x_mesh, y_mesh, z_mesh, cmap='inferno')
    ax.set_xlabel('Emission, nm.')
    ax.set_ylabel('Excitation, nm.')
    ax.set_zlabel('Intencity')
    ax.set_xlabel(name)

# use to draw contour graph
def draw_contour(x_mesh, y_mesh, z_mesh, name):
    fig = plot.figure()
    ax = fig.add_subplot()
    cs = ax.contourf(x_mesh, y_mesh, z_mesh, cmap='inferno', levels=60)
    add_rects(ax)
    ax.set_xlabel('Emission, nm.')
    ax.set_ylabel('Excitation, nm.')
    ax.set_xlabel(name)
    plot.colorbar(cs)

if __name__ == '__main__':
    path = data.path_Kivu
    files = data.files_Kivu

    # listing all .txt files in the directory
    files_list = []
    for elem in files:
        files_list.append(elem)
    # files_list = filter(lambda str: str.endswith('.txt'), os.listdir('Permafrost'))
    # getting data from them
    x, y, z_samples = get_data(files_list, path)
    # getting x and y grids for graphics
    xy_grids = np.meshgrid(x, y)
    # getting 1'st and 2'nd principal components
    comp1_grid, comp2_grid = get_pca_res(z_samples, xy_grids[0].shape, path)
    # making graphs
    print(get_local_max(comp1_grid, 200, x, y))
    draw_3d_plot(xy_grids[0], xy_grids[1], comp1_grid, "1 comp")
    draw_contour(xy_grids[0], xy_grids[1], comp1_grid, "1 comp")
    print('get_local_max(comp2_grid)')
    print(get_local_max(comp2_grid, 50, x, y))
    draw_3d_plot(xy_grids[0], xy_grids[1], comp2_grid, "2 comp")
    draw_contour(xy_grids[0], xy_grids[1], comp2_grid, "2 comp")
    plot.show()