import json
from flask import Flask, request
from flask_cors import CORS
from queue import Queue

from helpers.utils import utils
from helpers.db import queries
from helpers.algo import boundary
from helpers.algo import neighbours
from helpers.algo import degrees_count
from helpers.algo.new_hex_loc import*

app = Flask(__name__)
CORS(app)

def logger(val):
    print("\n{}\n".format(val))

@app.route('/get-hex-by-name', methods=['GET', 'POST'])
# @cross_origin()
def search_hex_byName():
    name = request.args['name']
    logger(name)
    if(name):
        try:
            resp = queries.get_hex_details_by_name(name)
            logger(resp)
            return resp
        except:
            return {"err": "error"}
    else:
        return {"Please enter the name correctly to get all the details"}
    return {'Network Error'}

@app.route('/get-hex-by-id', methods=['GET', 'POST'])
# @cross_origin()
def search_hex_byId():
    id = request.args['id']
    logger(id)
    if(id):
        try:
            resp = queries.get_hex_details_by_id(id)
            logger(resp)
            return resp
        except:
            logger(resp)
            return resp
    else:
        return {"Please enter the id correctly to get all the details"}
    return {"err": 'Network Error'}

@app.route('/get-all-coordinates', methods=['GET', 'POST'])
# @cross_origin()
def get_all_coords():
    try:
        coords = queries.get_all_locations()
        logger(coords)
        return {'body': coords}
    except:
        return {"err": 'Network Error'}

@app.route('/add-hex', methods=['GET', 'POST'])
# @cross_origin()
def add_hex():

    origin_hex = request.args['src']
    new_hex = request.args['new']
    boundary_of_origin_hex = request.args['loc']
    boundary_of_origin_hex = int(boundary_of_origin_hex)

    if(origin_hex and new_hex and (boundary_of_origin_hex >= 0)):
        origin_coordinates_hex = queries.get_hex_location_by_name(origin_hex)

        origin_hex_is_active_or_not = origin_coordinates_hex.get("hexagons")[0].get(
            'is_active', '')

        # checking if the src hex is_active or not
        if origin_hex_is_active_or_not == "FALSE":
            return {"err": "This origin hex is not active"}

        logger('-----here-----get_hex_location_by_name-origin---')
        logger(origin_coordinates_hex)

        origin_existing_neighbours = queries.get_hex_details_by_name(
            origin_hex).get("hexagons", "")[0].get("hex", "")

        if origin_existing_neighbours[utils.user_boundary_choice[boundary_of_origin_hex]] != 'NO':
            return {'err': 'already a hex exists at this boundary'}

        origin_id = origin_coordinates_hex.get("hexagons")[0].get(
            'location', '').get('hexagon_id', '')

        # Find location of the new hex
        # find neighbours around it , if present query their cluster table rows

        new_hex_loc = boundary.find_new_hex_loc(
            boundary_of_origin_hex, origin_hex, origin_coordinates_hex)  # New Hex location

        logger('-----here-----new-hex-loc-using-origin-loc-and-border---')
        logger(new_hex_loc)

        new_hex_neighbours = neighbours.find_new_hex_neighbours(
            new_hex_loc, boundary_of_origin_hex)                       # Neighbours around new hex

        # insertions new hex // fetch id
        logger('-----here-----inserting-new-node---')

        insert_new_hex_resp = queries.insert_new_hex(new_hex)
        new_hexagon_id = list(map(lambda data: data.get(
            'hexagon_id'),  insert_new_hex_resp))[0]

        logger(new_hexagon_id)

        # insert neighbours of new node
        logger('-----here-----inserting-new-node-neighbours---')

        new_hex_neighbours["hexagon_id"] = new_hexagon_id

        logger(new_hex_neighbours)

        column_updates = ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'updated_at']
        insert_new_hex_neighbours = queries.insert_hex_neighbours(
            {"data": new_hex_neighbours, "colm": column_updates})          # Inserting New hex Neighs. in cluster

        # insert location of new node

        insert_new_hex_loc = queries.insert_new_hex_loc(
            new_hexagon_id, new_hex_loc[0], new_hex_loc[1], new_hex_loc[2])

        # insert neighbours of origin node

        origin_req = {}
        origin_req[utils.user_boundary_choice[boundary_of_origin_hex]
                   ] = new_hexagon_id
        origin_req["hexagon_id"] = origin_id
        column_updates = [
            utils.user_boundary_choice[boundary_of_origin_hex], 'updated_at']

        logger({"data": origin_req, "colm": column_updates})

        update_origin_hex_neighbour = queries.insert_hex_neighbours(
            {"data": origin_req, "colm": column_updates})
        logger("----moving to update----")
        update_neighbours(new_hex_neighbours)

        return {"statusCode": 200, 'response': update_origin_hex_neighbour}
    else:
        return {'response': 'err'}

def update_neighbours(updating_neighbours):
    # logger(updating_neighbours)
    for border in updating_neighbours:
        if (updating_neighbours[border] != 'NO'):
            hex_id = updating_neighbours[border]
            # logger(hex_id)
            neighbour_location_obj = queries.get_hex_location_by_id(hex_id)

            neighbour_is_active = neighbour_location_obj.get(
                'hexagons', [{'location': {}}])[0].get('is_active', '')

            if neighbour_is_active == 'TRUE':

                neighbour_location_dict = neighbour_location_obj.get(
                    'hexagons', [{'location': {}}])[0].get('location', '')
                # logger(neighbour_location_dict)
                if(neighbour_location_dict):
                    loc = [
                        neighbour_location_dict['q'],
                        neighbour_location_dict['r'],
                        neighbour_location_dict['s']
                    ]
                    updated_neighbours = neighbours.find_new_hex_neighbours(
                        loc, 1)

                    logger(updated_neighbours)

                    updated_neighbours["hexagon_id"] = hex_id
                    # logger(updated_neighbours)
                    column_updates = ['n1', 'n2', 'n3',
                                      'n4', 'n5', 'n6', 'updated_at']
                    insert_updated_neighbours = queries.insert_hex_neighbours(
                        {"data": updated_neighbours, "colm": column_updates})

                    return {"body": insert_updated_neighbours}

    return {"err": "error"}

@app.route('/remove-hex', methods=['GET', 'POST'])
# @cross_origin()
def delete_hex_bfs():
    borders = ['n1', 'n2', 'n3', 'n4', 'n4', 'n5', 'n6']
    border_map = {'n1': 'n4', 'n2': 'n5', 'n3': 'n6',
                  'n4': 'n1', 'n5': 'n2', 'n6': 'n3'}

    origin_hex = request.args['src']

    if origin_hex:
        try:
            neighbours_of_origin = queries.find_neighbours_by_name(origin_hex)
        except:
            return {"err": "error"}

    # The hex is alerady deleted or doesn't exist
    if len(neighbours_of_origin) > 0:
        neighbours_of_origin = neighbours_of_origin[0]
    else:
        return {"err": "error"}

    origin_hex_id = neighbours_of_origin.get("hex", "").get("hexagon_id", "")

    degree = degrees_count.calc_degree(neighbours_of_origin)
    if degree < 2:
        delete_resp = delete_hexagon_final(
            neighbours_of_origin, origin_hex, origin_hex_id, borders, border_map)
        if delete_resp:
            return {"body": "Done!"}
        else:
            return {"err": "error while removing"}

    # starting bfs
    frontier = Queue()
    frontier.put(origin_hex_id)
    # this map for id's
    reached = set()
    reached.add(origin_hex_id)
    # this map for (id, border(n1, n2...n6)) to uniquely identify the path we are using
    # to find it
    reached_border = []

    level = 0
    count_of_origin_hits_using_diff_path = 0

    while not frontier.empty():
        level = level + 1
        current = frontier.get()
        # fetching all the neighbour id's in a level
        details_neighbour_hex = queries.get_hex_details_by_id(
            current).get("hexagons", "")

        if len(details_neighbour_hex) > 0:
            details_neighbour_hex = details_neighbour_hex[0]

        count_of_entry_to_hex = 0
        # iterating in all the neighbours of the recent id
        for border in borders:
            if details_neighbour_hex.get("hex", "").get(border, "") != "NO":
                neighbour_id = details_neighbour_hex.get(
                    "hex", "").get(border, "")

                if level == 1 and count_of_entry_to_hex == 0:
                    # reached_border.append((current_id, border))
                    reached_border.append((current, border_map[border]))
                    list(set(reached_border))
                    count_of_entry_to_hex = count_of_entry_to_hex + 1
                # already visited node also traversed through the same path
                if (neighbour_id in reached) and (neighbour_id, border) in reached_border:
                    continue

                if (level > 1):
                    if ((neighbour_id not in reached) or
                            ((neighbour_id in reached) and (neighbour_id, border) not in reached_border)):
                        # the origin hex is found but not from the same path ,
                        # from a different path
                        if(neighbour_id == origin_hex_id):
                            count_of_origin_hits_using_diff_path = count_of_origin_hits_using_diff_path + 1
                            # if there are 3 neighs , out of which 2 of them belongs to the same connected comp.
                            # and the other 1 belongs other connected comp. , we need to verify its connected or not
                            if count_of_origin_hits_using_diff_path == (degree - 1):
                                # if the hex is found update its neighs. and itself
                                delete_resp = delete_hexagon_final(
                                    neighbours_of_origin, origin_hex, origin_hex_id, borders, border_map)
                                if delete_resp:
                                    return {"body": "Done!"}
                                else:
                                    return {"err": "error while removing"}
                # mapping the new neighbour and its correspoding border
                # so that we dom't end up seeing that id from the previous path
                frontier.put(neighbour_id)
                reached.add(neighbour_id)
                logger(neighbour_id)
                logger(border)
                # reached_border.append((neighbour_id, border))
                if level > 1:
                    reached_border.append((current, border_map[border]))
                    list(set(reached_border))
    return {"err": "Not possible to remove"}

def delete_hexagon_final(neighbours_of_origin, origin_hex, origin_hex_id, borders, border_map):
    for border in borders:
        if neighbours_of_origin.get("hex", "").get(border, "") != "NO":
            neighbour_id = neighbours_of_origin.get(
                "hex", "").get(border, "")
            origin_req = {}
            origin_req["hexagon_id"] = neighbour_id
            origin_req[border_map[border]] = "NO"
            column_updates = [
                border_map[border], "updated_at"]
            insert_updated_neighbours = queries.insert_hex_neighbours(
                {"data": origin_req, "colm": column_updates})
    try:
        deletion_resp = queries.delete_hex(
            origin_hex, origin_hex_id)
        return True
    except:
        return False


from itertools import combinations

def make_combinations_set(order, menu_num):
    result = set()
    menus = sorted([ch for ch in order])
    comb_menu = combinations(menus, menu_num)
    for each_comb in comb_menu:
        result.add(''.join(each_comb))
    # print(result)
    return result

def solution(orders, course):
    answer = []

    comb_menu = set()
    for menu_num in course:
        for order in orders:
            comb_menu |= make_combinations_set(order, menu_num)
        comb_menu = sorted(list(comb_menu))
        # print(comb_menu)

        count = 0
        each_count = 0
        menus_count = []

        for each_comb in comb_menu:
            for order in orders:
                for each_menu in each_comb:
                    if each_menu not in order:
                        break
                    else:
                        each_count += 1
                if each_count == menu_num:
                    count += 1
                each_count = 0
            if count >= 2:
                menus_count.append([each_comb, count])
            count = 0

        menus_count = sorted(menus_count, key = lambda x : x[1], reverse = True)
        #print(menus_count)

        try:
            max_count = menus_count[0][1]
            for each_menu in menus_count:
                if each_menu[1] == max_count:
                    answer.append(each_menu[0])
                else:
                    break
        except:
            pass

        comb_menu = set()
    answer = sorted(answer)
    print(answer)

    return answer


#!/usr/bin/python3
""" square class """
from models.rectangle import Rectangle

class Square(Rectangle):
    """ class """

    def __init__(self, size, x=0, y=0, id=None):
        """ square construct """
        super().__init__(size, size, x, y, id)

    def __str__(self):
        """ string rep """
        return "[Square] ({:d}) {:d}/{:d} - {:d}".format(self.id,
                                                         self.x, self.y, self.size)

    @property
    def size(self):
        """ gets size """
        return self.width

    @size.setter
    def size(self, value):
        """ size setter """
        if not isinstance(value, int):
            raise TypeError("width must be an integer")
        elif value <= 0:
            raise ValueError("width must be > 0")
        else:
            self.width = value

    def to_dictionary(self):
        """ dictionary """
        squaredict = {
            'id': self.id,
            'x': self.x,
            'size': self.size,
            'y': self.y
        }
        return squaredict

    def update(self, *args, **kwargs):
        """ update """
        precheck = len(args)
        if precheck == 0:
            """ set kwargs """
            for key2, value in kwargs.items():
                if key2 == 'id':
                    self.id = value
                elif key2 == 'size':
                    self.size = value
                elif key2 == 'y':
                    self.y = value
                elif key2 == 'x':
                    self.x = value
            return
        if precheck == 1:
            self.id = args[0]
            return
        elif precheck == 2:
            self.id = args[0]
            self.size = args[1]
            return
        elif precheck == 3:
            self.id = args[0]
            self.size = args[1]
            self.x = args[2]
            return
        elif precheck == 4:
            self.id = args[0]
            self.size = args[1]
            self.x = args[2]
            self.y = args[3]
            return


class Point:
    MAX_COORD = 100
    MIN_COORD = 0

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def set_coord(self, x, y):
        if self.MIN_COORD <= x <= self.MAX_COORD and self.MIN_COORD <= y <= self.MAX_COORD:
            self.x = x
            self.y = y

    def set_min_coord(self, min):
        # создасться новая переменная в области экземпляра, атрибут класса
        # не поменяется
        self.MAX_COORD = min

    def __getattribute__(self, item):
        # Переопределение get_attr
        if item=='x':
            raise ValueError('Доступ закрыт')
        else:
            return object.__getattribute__(self,item)

pt1 = Point(12,33)
pt2 = Point(1,2)
#print(pt1.__dict__)
print(pt1.y)
print(Point.__dict__)


import datetime

from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import relationship

from app.db.base_model import Base

class ArticleModel(Base):
    __tablename__ = "articles"

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(255))
    description = Column(String(255))
    url_font = Column(String(255))
    user_id = Column(Integer, ForeignKey("users.id"))
    creator = relationship("UserModel",
                           back_populates="articles",
                           lazy="joined")

    created_at = Column(DateTime, default=datetime.datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)


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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html

import sqlite3
from datetime import datetime

db_name = 'dbmovie{0}.db'.format(str(datetime.now())[:10].replace('-', ''))

class DbmoviePipeline(object):
	def process_item(self, item, spider):
		if item:
			conn = sqlite3.connect(db_name)
			cursor = conn.cursor()
			try:
				cursor.execute(
						'CREATE TABLE IF NOT EXISTS movies(id INTEGER NOT NULL PRIMARY KEY  AUTOINCREMENT, movieName VARCHAR(50),url VARCHAR (50), directors VARCHAR(50), actors VARCHAR(200), countries VARCHAR (50), genres VARCHAR (50), languages VARCHAR (50), runtime INTEGER , udate VARCHAR (15), rate VARCHAR (5), votes INTEGER )')
				cursor.execute(
						'insert into movies(id, movieName,url, directors, actors, countries, genres, languages, runtime, udate,rate, votes) VALUES (NULL, \'{0}\',\'{1}\',\'{2}\',\'{3}\',\'{4}\',\'{5}\',\'{6}\',\'{7}\',\'{8}\',\'{9}\',\'{10}\' )'.format(
								item['movieName'], item['url'], item['directors'], item['actors'], item['countries'],
								item['genres'],
								item['languages'], item['runtime'], item['date'], item['rate'], item['votes'])
				)
			except sqlite3.Error as e:
				print(e.args[0])
				cursor.close()
				conn.close()
			else:
				conn.commit()
				cursor.close()
				conn.close()
		return item


#!/usr/bin/env python3

a, b = 65, 8921
a, b = 703, 516
a_fac, b_fac = 16807, 48271
div = 2147483647

_a, _b = a, b
matches = 0
for i in range(40000000):
    _a = (_a * a_fac) % div
    _b = (_b * b_fac) % div
    match = 1 if (_a ^ _b) & 0xffff == 0 else 0
    #print(_a, _b, match)
    matches += match
print('part1', matches)

_a, _b = a, b
matches = 0
for i in range(5000000):

    _a = (_a * a_fac) % div
    while _a % 4 != 0:
        _a = (_a * a_fac) % div

    _b = (_b * b_fac) % div
    while _b % 8 != 0:
        _b = (_b * b_fac) % div

    match = 1 if (_a ^ _b) & 0xffff == 0 else 0
    matches += match
print('part2', matches, _a, _b)


import os
import uuid
import json
import minio
import logging

class storage:
    instance = None
    client = None

    def __init__(self):
        try:
            """
            Minio does not allow another way of configuring timeout for connection.
            The rest of configuration is copied from source code of Minio.
            """
            import urllib3
            from datetime import timedelta

            timeout = timedelta(seconds=1).seconds

            mgr = urllib3.PoolManager(
                timeout=urllib3.util.Timeout(connect=timeout, read=timeout),
                maxsize=10,
                retries=urllib3.Retry(
                    total=5, backoff_factor=0.2, status_forcelist=[500, 502, 503, 504]
                )
            )
            self.client = minio.Minio(
                os.getenv("MINIO_STORAGE_CONNECTION_URL"),
                access_key=os.getenv("MINIO_STORAGE_ACCESS_KEY"),
                secret_key=os.getenv("MINIO_STORAGE_SECRET_KEY"),
                secure=False,
                http_client=mgr
            )
        except Exception as e:
            logging.info(e)
            raise e

    @staticmethod
    def unique_name(name):
        name, extension = name.split(".")
        return "{name}.{random}.{extension}".format(
            name=name, extension=extension, random=str(uuid.uuid4()).split("-")[0]
        )

    def upload(self, bucket, file, filepath):
        key_name = storage.unique_name(file)
        self.client.fput_object(bucket, key_name, filepath)
        return key_name

    def download(self, bucket, file, filepath):
        self.client.fget_object(bucket, file, filepath)

    def download_directory(self, bucket, prefix, path):
        objects = self.client.list_objects(bucket, prefix, recursive=True)
        for obj in objects:
            file_name = obj.object_name
            self.download(bucket, file_name, os.path.join(path, file_name))

    def upload_stream(self, bucket, file, bytes_data):
        key_name = storage.unique_name(file)
        self.client.put_object(
            bucket, key_name, bytes_data, bytes_data.getbuffer().nbytes
        )
        return key_name

    def download_stream(self, bucket, file):
        data = self.client.get_object(bucket, file)
        return data.read()

    @staticmethod
    def get_instance():
        if storage.instance is None:
            storage.instance = storage()
        return storage.instance


class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        seen_set = set()
        longest = 0
        start, end = 0, 0
        l = len(s)
        while start < l and end < l:
            if s[end] not in seen_set:
                seen_set.add(s[end])
                end += 1
                longest = max(longest, end - start)
            else:
                seen_set.remove(s[start])
                start += 1
        return longest


from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as pl

n = []
e = []
ep = []
with open('cohesive.txt') as file:
    next(file)
    for line in file:
        value = line.strip().split(' ')
        n.append(int(value[0]))
        e.append(float(value[1]))
        ep.append(float(value[2]))

n = [int(i) for i in n]
a = 5.256*10**-10
x = [a*i**3 for i in n]

pl.plot(n, e, '.')
pl.plot(n, ep, '.')
pl.xticks(n)
pl.xlabel('Number of Unit Cells [^(1/3)]')
pl.ylabel('Eth [eV]')
pl.grid(b=True, which='both')
pl.tight_layout()
pl.legend(['Non-periodic', 'Periodic'])
pl.show()
pl.clf()

print(x[-1])
print(e[-1])
print(ep[-1])


import sys
from pathlib import Path
sys.path.append(Path(__file__).resolve().parents[2])
# rel imports when in package
if __name__ == '__main__' and __package__ is None:
    __package__ = 'kuosc'

print(Path(__file__).resolve())
print(__package__)

# from kurosc.lib.plotformat import setup


from copy import deepcopy
import numpy as         np
from qode.fermion_field import occ_strings
from qode.fermion_field.state import state, dot, resolvent
from hamiltonian import hamiltonian, SD_excitations

# Energy calculated from Q-Chem 4.3:
# SCF energy in the final basis set = -2.8551604262
# CCSD total energy                 = -2.87178917
#
# PSI4 CISD energy                  = -2.8717891505016

occ_orbs = list(reversed([0,4]))
vrt_orbs = list(reversed([1,2,3,5,6,7]))

cisd_strings = occ_strings.CISD(occ_orbs,vrt_orbs)
num_config = len(cisd_strings)
reference = state(cisd_strings,0)
T = SD_excitations(reference, reference, cisd_strings, occ_orbs, vrt_orbs)

h_mat = np.load('data/h_mat.npy')
V_mat = np.load('data/V_mat.npy')
H = hamiltonian(h_mat, V_mat, cisd_strings, occ_orbs, vrt_orbs)

D = deepcopy(H)
Eo = dot(reference,H(reference))
D.C0 -= (Eo - 1e-10)
R = resolvent(D)

debug = True

while True:
	accumulate = state(cisd_strings)
	accumulate.increment(H(reference),-1)
	intermediate = state(cisd_strings)
	intermediate.increment(H(T(reference)))
	intermediate.increment(T(H(reference)),-1)
	#
	E = Eo + dot(reference,intermediate)
	print("E =", E)
	if debug:
		psi = T(reference)
		psi.increment(reference)
		E = dot(psi,H(psi)) / dot(psi,psi)
		print("Evar = {}  (error = {})".format(E,E+2.8717891505016))
	#
	phase = +1
	for i in range(3):
		phase *= -1
		accumulate.increment(intermediate,phase)
		if i==2:  break
		intermediate = T(intermediate)
	accumulate = R(accumulate)
	dT = SD_excitations(reference, accumulate, cisd_strings, occ_orbs, vrt_orbs)
	T.increment(dT)


import boto3
import json
from decimal import Decimal
from boto3.dynamodb.conditions import Key

dynamodb = boto3.resource('dynamodb')
attendance_table    = dynamodb.Table('attendance_table_user')

#queryで特定のuser_idの出社予定取ってくる
def query_attendance(id):
    result = attendance_table.query(
        KeyConditionExpression=Key('user_id').eq(id)
    )
    return result['Items']

def decimal_default_proc(obj):
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError

def lambda_handler(event, context):
    attendance = query_attendance(event['pathParameters']['user_id'])
    # print("attendanceのリスト", attendance)

    return {
        'statusCode': 200,
        'body': json.dumps(attendance, default=decimal_default_proc),
        'isBase64Encoded': False,
        'headers' : {"content-type": "application/json",
        "Access-Control-Allow-Origin": "*"}
        }


import os
from pathlib import Path
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from shutil import copyfile

config = {
    # General
    'symbol': 'spy',
    'symbol_name': 'S&P500',
    'category': {'unespecified': ['spy']},  # 'gld', 'spy','xle', 'emb','dia', 'qqq', 'ewp'
    'extension': '.csv',
    'separator': ';',
    'desired_length': 550,   # for mahab states
    'pattern': '_no_missing_data',  # besides the name, gaps have been handled (the name it's a typo)
    'cols': ['open', 'high', 'low', 'close', 'volume', 'datetime', 'gap', 'timestamp'],
    'names_per_set': {
        'dev': 'devset',
        'train': 'train',
        'mah': 'mahalanobis_state'
    },

    # ############ For sec level
    # 'years_to_explore': ['2016', '2017', '2018', '2019', '2020'],
    # 'output_path': 'C:\\Users\\suare\\data\\tmp\\spy_seeds_seconds',
    # 'name': 'spy-seconds',
    # 'lvl_str': 's',
    # 'path': 'C:\\Users\\suare\\data\\analysis\\quantquote\\',
    # 'resample': False,  # resampling done in a previous script
    # 'ms_field': 'timestamp',  # time
    # 'dt_field': 'datetime',   # date
    # 'desired_abs_mean_tresh': 0.01,
    # 'desired_abs_min_tresh': 0.00000000000001,
    # 'allowed_outliers_pct': 0.01,
    # 'pattern': 'csv',  # no pattern needed here by 05/04/2020
    # 'prefix': 'table_'
    #### get largets and get smallest applied to 1 (min and maxs)

    # ############ For minute level
    'years_to_explore': ['2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010',
                         '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020'],
    # IMP. don't do 2020 alone or period id == 1
    'output_path': 'C:\\Users\\suare\\data\\tmp\\spy_seeds_minutes',
    'name': 'spy-minutes',
    # 'lvl_str': 'm',
    # 'desired_abs_mean_tresh': 0.1,
    'lvl_str': 'm',
    'desired_abs_mean_tresh': 1,
    'path': 'C:\\Users\\suare\\data\\analysis\\quantquote\\',
    'resample': True,  # resampling done in a previous script
    'ms_field': 'timestamp',  # time
    'dt_field': 'datetime',   # date
    'desired_abs_min_tresh': 0.00000000000001,
    'allowed_outliers_pct': 0.01,
    'prefix': ''
}

def read_file(filename: str) -> pd.DataFrame:
    path = os.sep.join([config['path'], filename])
    filepath = os.sep.join([path, config['prefix'] + config['symbol'] + config['extension']])
    if os.path.isfile(filepath):
        print(f'Reading {filename}')
        df = pd.read_csv(filepath, names=config['cols'])
        # print(df.head())
        return df

def get_pretraining_states(mahabset_df: pd.DataFrame, config: dict) -> dict:
    """
    This function get the dataframes for pretraining
    :param mahabset_df:
    :param config:
    :return:
    """
    mahabset_df = remove_non_trading_hours_minimised(df=mahabset_df)  # remove non trading hours

    # Generate close price returns and moving average to select the period with a mean close to 0
    log_ret = False  # otherwise percentual
    if log_ret:
        mahabset_df['close_returns'] = np.log(mahabset_df['close'] / mahabset_df['close'].shift(1))
        # mahabset_df['close_returns'] = np.log(1 + mahabset_df['close'].pct_change())
    else:
        mahabset_df['close_returns'] = mahabset_df['close'] / mahabset_df['close'].shift(1) - 1
        # mahabset_df['close_returns'] = mahabset_df['close'].pct_change(1)  # same result
    mahabset_df.dropna(inplace=True)
    sma_col = f"SMA_{config['desired_length']}"
    mahabset_df[sma_col] = mahabset_df['close_returns'].rolling(window=config['desired_length']).mean()
    mahabset_df[sma_col+'_abs'] = mahabset_df[sma_col].abs()
    mahabset_df['roll_std'] = mahabset_df['close_returns'].rolling(window=config['desired_length']).std()
    mahabset_df['SMA_start_date'] = mahabset_df[config['dt_field']].shift(config['desired_length'])
    mahabset_df['SMA_start_ms'] = mahabset_df[config['ms_field']].shift(config['desired_length'])

    # Drop first rows as the moving average is NaN
    len_with_nans = len(mahabset_df)

    # Prepare extra cols
    # mahabset_df['datetime'] = mahabset_df.index.astype(str)   #  maybe for min level is relevant
    mahabset_df.set_index(config['dt_field'], drop=False, inplace=True)
    mahabset_df.dropna(inplace=True)
    assert (len_with_nans - len(mahabset_df)) == config['desired_length'], 'There are non expected NaNs'

    states_dict = dict()
    for i in range(1, 4):  # States 1, 2 and 3 (hardcoded by now)
        selected_df = identify_state(config, mahabset_df, sma_col, state_id=i)
        # assert len(selected_df) == 1, "The maximum value is not a unique value."
        print(len(selected_df))
        print(selected_df)

        for idx, rw in selected_df.iterrows():
            print(f"Current selection from {rw['SMA_start_date']} to {rw[config['dt_field']]} with mean {sma_col}")
            mah_state = \
                mahabset_df[(mahabset_df['SMA_start_date'].between(rw['SMA_start_date'], rw[config['dt_field']]))]

            # avoid overwriting an state with another which len is <=35 (it has to be greater because of the indicators)
            if len(mah_state) >= 35:
                states_dict[i] = mah_state
                states_dict[i].sort_index(ascending=True, inplace=True)

    assert len(states_dict) == 3, f"State missing or diff than 3 states? states ok:{states_dict.keys()}"
    return states_dict

def identify_state(config: dict, mahabset_df: pd.DataFrame, sma_col: str, state_id: int) -> pd.DataFrame:
    """
    This function identifies the last row of a mahab state depending on a logic defined manually for that state id.
    Values 35, 20 and 20 were given manually to be able to have enough records hourly for all mahab states.
        These have been left as values by default after.
    """
    if state_id == 1:  # Select one close to 0 (the closest)
        # Select one close to 0
        # (not the closest cos there are period = 0 due to lack of liquidity at certain frequencies)
        selected_df = mahabset_df[mahabset_df[sma_col + '_abs'] <= config['desired_abs_mean_tresh']]
        # selected_df = selected_df[selected_df[sma_col + '_abs'].max() == selected_df[sma_col + '_abs']]
        # Filter by desired mean fpr the lateral movement (the one with greatest STDEV)
        # selected_df = selected_df[selected_df['roll_std'].max() == selected_df['roll_std']]
        # inst.of max, t.g.m.
        selected_df = selected_df[selected_df['roll_std'].isin(list(selected_df['roll_std'].nlargest(35)))]
    elif state_id == 2:  # Select one negative (min)
        # get the min from a boundary. filter periods with 0 return at all. it may be due to lack of liquidity at s lvl
        selected_df = mahabset_df[mahabset_df[sma_col + '_abs'] >= (config['desired_abs_min_tresh'])]
        # selected_df = selected_df[selected_df[sma_col].min() == selected_df[sma_col]]
        # inst.of min, to get many
        selected_df = selected_df[selected_df[sma_col].isin(list(selected_df[sma_col].nsmallest(20)))]
    elif state_id == 3:  # Select one positive (max)
        # selected_df = mahabset_df[mahabset_df[sma_col].nlargest(3) == mahabset_df[sma_col]]
        # inst.of max, to get many
        selected_df = mahabset_df[mahabset_df[sma_col].isin(list(mahabset_df[sma_col].nlargest(20)))]
    else:
        assert False, "The trend/pattern for this state has not been specified"
    return selected_df

def remove_non_trading_hours_minimised(df) -> pd.DataFrame:
    trading_dates = pd.read_csv('trading_dates_Q11998_to_Q32021.csv')  # this list has format: dd/MM/yyyy
    # inverting date format (hardcoded)
    trading_dates = trading_dates.trading_dates.astype(str).apply(lambda x: x[6:10]+'-'+x[3:5]+'-'+x[:2])
    df.index = pd.to_datetime(df.datetime)
    df = df.between_time('09:31', '15:59')
    df = df[df.index.astype(str).str[:10].isin(trading_dates)]
    return df

def remove_non_trading_hours(df, config: dict(), level: str = None) -> pd.DataFrame:
    # Parse cols, dates and sort
    # this may be useful at minute level
    # df['date'] = pd.to_datetime(df['date'], format='%Y%m%d').dt.strftime('%Y-%m-%d')
    # df['time'] = (pd.to_datetime(df['time'].astype(str).str.strip(), format='%H%M').dt.strftime('%H:%M'))
    # df['datetime'] = df.date.astype(str) + ' ' + df.time.astype(str)
    # trading_dates = df.datetime.str[:10].unique()  # list of market days
    trading_dates = pd.read_csv('trading_dates_Q11998_to_Q32021.csv')  # this list has format: dd/MM/yyyy
    # inverting date format (hardcoded)
    trading_dates = trading_dates.trading_dates.astype(str).apply(lambda x: x[6:10]+'-'+x[3:5]+'-'+x[:2])
    df.index = pd.to_datetime(df.datetime)
    df.drop(columns=['date', 'time', 'datetime', 'splits', 'earnings', 'dividends'],
            errors='ignore', inplace=True)
    df.sort_index(inplace=True, ascending=True)

    # Resample (but not fill gaps. This should have been done already)
    print(f' - Original size: {len(df)}')
    if config['resample']:
        ohlc_dict = {'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last', 'volume': 'sum'}
        df = df.resample(level.split('-')[0]).agg(ohlc_dict)
        print(f' - Size after resampling at {level}: {len(df)}')

    # Remove non-trading hours and non-trading days
    df = df.between_time('09:31', '15:59')  # This is potentially the only important line from the function
    print(f' - Size after filtering out non-market hours: {len(df)}')
    df = df[df.index.astype(str).str[:10].isin(trading_dates)]
    # (low impact..) df = df.between_time('09:31','13:00') for half days (shortened sessions / early closing)
    print(f' - Size after filtering out non-trading days: {len(df)}')

    if config['resample']:
        # Fill gaps
        df['volume'] = df['volume'].fillna(0)
        df['close'] = df['close'].ffill()
        df['open'] = df['open'].fillna(df['close'])
        df['low'] = df['low'].fillna(df['close'])
        df['high'] = df['high'].fillna(df['close'])

    return df

def parse_and_save(file_dict: dict, level: str, period_id: int,
                   setid: str, setname: str, config: dict, all_files: list()) -> list():
    file_path = file_dict[setid]
    if setid == 'mah':
        # For the mahalanobis set, it creates a moving average of x examples over the previous period to the devset.
        states_dict = get_pretraining_states(mahabset_df=pd.read_csv(file_path, sep=config['separator']),
                                             config=config)
        for k in states_dict.keys():
            # non trading hours have been removed in get_pretraining_states
            state_filepath = \
                os.sep.join([config['output_path'], level, str(period_id), f'{config["symbol"]}_{setname}_{k}.csv'])
            states_dict[k] = \
                remove_non_trading_hours(df=states_dict[k], config=config, level=level)  # for the sake of standarisation
            assert len(states_dict[k]) >= 35, "Mahalanobis set too small (must be >40 for technical indicators)"
            states_dict[k].to_csv(state_filepath, sep=';')
            all_files.append(state_filepath)
    else:
        set_filepath = os.sep.join([config['output_path'], level, str(period_id), f'{config["symbol"]}_{setname}.csv'])
        print(file_path)
        df = remove_non_trading_hours(df=pd.read_csv(file_path, sep=config['separator']), config=config, level=level)
        assert len(df) >=35 , "Dataset set too small (must be >=35 for technical indicators)"
        df.to_csv(set_filepath, sep=';')
        all_files.append(set_filepath)
    return all_files

def compute(files: dict, periods: (), period_id: int, files_for_indicators: list, config: dict) -> (dict, list):
    """
    This function orchestrates the whole process in both levels
    """
    period, mahab_period, dev_period = periods
    files[period] = dict()

    # 1. it picks a period and changes the name.
    for level in os.listdir(config['path']):
        files[period][level] = dict()

        # Process second and minute level data. For min level, filter only files with pattern (as there are many others)
        if config['lvl_str'] in level and '.' not in level:  # and '30' in level:  # IMP!! comment last condition out
            print('=========='+level+'\n'+'==========')
            lvl_path = config['path'] + level + os.sep + config['symbol_name']
            for file in os.listdir(lvl_path):  # all of these loops are not efficient at all
                if '.csv' in file and config['pattern'] in file:
                    if mahab_period in file:
                        files[period][level]['mah'] = lvl_path + os.sep + file
                    if dev_period in file:
                        files[period][level]['dev'] = lvl_path + os.sep + file
                    if period in file:
                        files[period][level]['train'] = lvl_path + os.sep + file

            # 2. Export all sets in a folder with a period number (like a seed)
            Path(os.sep.join([config['output_path'], level, str(period_id)])).mkdir(parents=True, exist_ok=True)
            for setid, setname in config['names_per_set'].items():
                print(f'set id: {setid}')
                files_for_indicators = \
                    parse_and_save(file_dict=files[period][level],
                                   level=level, period_id=period_id, setid=setid, setname=setname,
                                   config=config, all_files=files_for_indicators)
            # Debug
            print(files[period][level]['dev'])
            print(os.sep.join([config['output_path'], level, str(period_id), f'{config["symbol"]}_devset.csv']))

    return files, files_for_indicators

##########################################################
# Specific handling for second or minute level frequencies

def compute_seconds() -> (pd.DataFrame, list):
    mahab_m = '07'
    dev_m = '10'
    first = True
    period_id = 1
    files = dict()
    files_for_indicators = list()

    for yr in config['years_to_explore']:
        # this will need to be refactored/changed (maybe to an iterator) for min level
        for q_month in ['01', '04', '07', '10']:  # just for s level
            # it picks the prior period as a devset
            if not first:
                mahab_period = dev_period
                dev_period = period
            else:
                mahab_period = f'{int(yr) - 1}-{mahab_m}'
                dev_period = f'{int(yr) - 1}-{dev_m}'
                first = False
            period = yr + '-' + q_month

            # Compute periods in order
            files, files_for_indicators = \
                compute(files=files, periods=(period, mahab_period, dev_period), period_id=period_id,
                        files_for_indicators=files_for_indicators, config=config)
            period_id = period_id + 1
    return files, files_for_indicators

def compute_minutes() -> (pd.DataFrame, list):
    files = dict()
    files_for_indicators = list()
    period_id = 1

    for yr in config['years_to_explore']:
        period = str(yr)
        dev_period = str(int(yr) - 1)
        mahab_period = str(int(yr) - 2)
        files[period] = dict()

        # if period_id == 6:
        # Compute periods in order
        files, files_for_indicators = \
            compute(files=files, periods=(period, mahab_period, dev_period), period_id=period_id,
                    files_for_indicators=files_for_indicators, config=config)

        period_id = period_id + 1
    return files, files_for_indicators

compute_func = {
    's': compute_seconds,
    'm': compute_minutes,
    'h': compute_minutes,
}

if __name__ == "__main__":
    # Difference handling periods at the second and minutes level due to data granularity and volume
    all_files_dict, file_list = compute_func[config['lvl_str']]()

    # Let's generate /txt files too in a TMP location
    pd.DataFrame({'files': file_list}).to_csv(f'tmp/files_for_indicators_lvl-{config["lvl_str"]}.csv')
    # Then trigger from here the whole convertion (technical indicators).


# считывание списка из входного потока
a = '3 Сергей', '5 Николай', '4 Елена', '7 Владимир', '5 Юлия', '4 Светлана'
lst_in = list(a)
print(lst_in)
B = [i.split() for i in lst_in]
print(B)
F = [i.split()[0] for i in lst_in]
print(F)
d = dict.fromkeys(F)
# d_key = list(d)
# for i in range(len(d)):
#     C = []
#     for j in range(len(B)):
#         if d_key[i] == B[j][0]:
#             C.append(B[j][1])
#     d[d_key[i]] = C
# for key, value in d.items():
#     print(key, ", ".join(value), sep=': ')


#!/usr/bin/env python3

import requests
import bs4

base_url = "https://quotes.toscrape.com/page/{}/"

authors = set()
quotations = []

for page_num in range(1,2):
    page = requests.get(base_url.format(page_num))
    soup = bs4.BeautifulSoup(page.text,'lxml')

    boxes = soup.select(".quote")    #selected all the quotes boxes
    for box in boxes:
        author = box.select('span')[1].select('small')[0].getText()
        quotation = box.select('span')[0].getText()

        authors.add(author)
        quotations.append(quotation)

print("Authors are: ")
print(authors)
print('\n')
print("Quotations are: ")
print(quotations)
print('\n')

top10 = soup.select(".tag-item")
for i in range(10   ):
    print(top10[i].select('a')[0].getText())


from django.conf import settings
from travels import models
from django.utils.html import escapejs

def project_settings(request):
  project_settings = models.Settings.objects.all()[0]
  return { 'project_settings' : project_settings }

def settings_variables(request):
	''' Provides base URLs for use in templates '''

	project_settings = models.Settings.objects.all()[0]

	d = {
    	'APP_NAME': escapejs(settings.APP_NAME),
    	'PROJECT_DESCRIPTION': escapejs(project_settings.project_description),
	}

	# Allows settings to define which variables
	# it wants to expose to templates
	if settings.CONTEXT_VARIABLES:
	    for var in settings.CONTEXT_VARIABLES:
	        if hasattr(settings, var):
	            d[var] = getattr(settings, var)

	return d


l = input("insert list of integers with comma")
l = l.lstrip('[').rstrip(']').split(',')
sum = 0
temp = 0
for i in range(0, len(l)):
    l[i] = int(l[i])
    sum += l[i]
    temp += l[i] ** 2

mean = sum / len(l)
var = temp / len(l) - mean ** 2
print(f"Means: {mean}")
print(f"Variance: {var}")

'''
scores = [100, 90, 80, 55, 95, 80, 65, 75, 70, 90]
sum = 0
for i in scores:
    sum = sum + i

mean = sum/len(scores)

vsum = 0
for i in scores:
    vsum = vsum + (i - mean)**2

variance = vsum / len(scores)

print("Means :", mean)
print("Variance :", variance)
'''


mhb_file = open("mhb_gesamt.txt","r",encoding="utf8")
mhb_gesamt = mhb_file.read()
mhb_file.close()
modDescrSeq = mhb_gesamt.split("Modulbezeichnung:  ")
i = 1
while i<len(modDescrSeq):
    fileName = "ModDescr_" + str(i)
    file = open(fileName + ".txt","w")
    file.write(modDescrSeq[i].strip())
    file.close()
    i += 1


import pandas as pd
import Levenshtein
import numpy as np
from anytree.search import find
from utils.category_tree import get_category_tree
from utils.io_custom import read_pickle_object
from scipy.spatial.distance import cosine
import re

def find_node(id, tree):
    return find(tree, lambda node: node.name == id)

def get_relative_depth(id, tree):
    return (find_node(id, tree).depth - find_node(872901, tree).depth)

def count_children(id, tree):
    return len(find_node(id, tree).children)

def count_descendants(id, tree):
    return len(find_node(id, tree).descendants)

def preprocessing_text(s):
    """
    Предобработка текста.

    :param s: str - входная строка.
    :return: str - обработанная строка.
    """
    return str(" ".join(re.findall("[a-zA-Zа-яА-Я0-9]+", s)).lower())

def get_levenshtein_distance_between(first_line, second_line):
    """
    Получает расстояние Левенштейна между двумя строками.

    :param first_line: str - первая строка.
    :param second_line: str - вторая строка.
    :return: int - расстояние левеншейна между этими строками.

    """
    return Levenshtein.distance(first_line, second_line)

def get_lev_dist_between_query_category(query, category):
    """
    Получает расстояние Левенштейна между двумя сериями.

    :param query: pd.Series - запрос.
    :param second_line: pd.Series - категория.
    :return: np.array, int - расстояние левеншейна между соответствующими элементами серий.
    """
    levenshtein_distances = []

    for query, category in zip(query.values, category.values):
        current_distance = get_levenshtein_distance_between(query, category)
        levenshtein_distances.append(current_distance)

    return np.array(levenshtein_distances)

def get_brands_and_products_lists(path_to_data):
    """
    Получаем и преобразовываем списки брендов и продуктов из файлов.
    """
    brands = pd.read_csv(path_to_data + "/unique_brands.csv")
    brands = [str(brand) for brand in brands.iloc[:, 0]]

    products = pd.read_csv(path_to_data + "/unique_products.csv")
    products = [str(product) for product in products.iloc[:, 0]]

    return brands, products

def create_data_with_features(path_to_data):
    """
    Загружает данные для обучения и генерирует для них.

    :param path_to_data: str - относительный путь к данным для обучения.
    :return data: pd.DataFrame - датафрейм с кучей признаков
    Оставлено для обратной совместимости с двумя блокнотами.
    """
    data = pd.read_csv(path_to_data + "/data_for_model.csv")
    return get_data_with_feature(data, path_to_data)

def get_cosine_dist_between_query_category(query, category, vectorizer):
    """
    Получает косинусное расстояние между двумя колонками датафрейма.

    :param query: pd.Series - запрос.
    :param second_line: pd.Series - категория.
    :param vectorizer: sklearn.feature_extraction.text.TfidfVectorizer - предобученный векторайзер на запросах и категориях из трейн выборки.
    :return: np.array, int - косинусное расстояние между соответствующими элементами серий.
    """
    query_sparse_matrix = vectorizer.transform(query.values)
    category_sparse_matrix = vectorizer.transform(category.values)

    distances = []
    for query_vec, category_vec in zip(query_sparse_matrix, category_sparse_matrix):
        current_distance = cosine(query_vec.toarray(), category_vec.toarray())
        distances.append(current_distance)

    return np.array(distances)

def get_data_with_feature(data, path_to_data):
    """
    Генерирует признаки для обучающих и валидационных данных.

    :param data: pd.DataFrame - обучающие или валидационные данные с колонками [query, category_id, category_name, is_redirect]
    :param path_to_data: str - относительный путь к данным о брендах и продуктах.
    :return data: pd.DataFrame - датафрейм с кучей признаков
    """
    brands, products = get_brands_and_products_lists(path_to_data)
    root = get_category_tree(path_to_data)

    data['query'] = data['query'].apply(preprocessing_text)
    data['category_name'] = data['category_name'].apply(preprocessing_text)

    data['len_of_query'] = data['query'].apply(lambda query: len(query))
    data['num_of_word_in_query'] = data['query'].apply(
        lambda query:
        len(query.split(' '))
    )
    data['category_name'] = data['category_name'].apply(preprocessing_text)
    data['len_of_category'] = data['category_name'].apply(
        lambda category:
        len(category)
    )
    data['num_of_word_in_category'] = data['category_name'].apply(
        lambda category:
        len(category.split(' '))
    )
    data['how_match_brands_name_in_query'] = data['query'].apply(
        lambda query:
        sum([True for brand in brands if query.find(brand) != -1])
    )
    data['how_match_products_name_in_query'] = data['query'].apply(
        lambda query:
        sum([True for product in products if query.find(product) != -1])
    )
    data['mean_word_len_in_category'] = data['category_name'].apply(
        lambda category_name:
        np.mean([len(word) for word in category_name.split(' ')])
    )
    data['mean_word_len_in_query'] = data['query'].apply(
        lambda query:
        np.mean([len(word) for word in query.split(' ')])
    )
    data['max_word_len_in_category'] = data['category_name'].apply(
        lambda category_name:
        np.max([len(word) for word in category_name.split(' ')])
    )
    data['max_word_len_in_query'] = data['query'].apply(
        lambda query:
        np.max([len(word) for word in query.split(' ')])
    )
    data['min_word_len_in_category'] = data['category_name'].apply(
        lambda category_name:
        np.min([len(word) for word in category_name.split(' ')])
    )
    data['min_word_len_in_query'] = data['query'].apply(
        lambda query:
        np.min([len(word) for word in query.split(' ')])
    )
    data['is_query_long'] = data['len_of_query'].apply(lambda l: int(l > 50))

    # TODO проверить генерацию признаков с дерева категорий (3 штуки):
    data['relative_depth'] = data['category_id'].apply(
        lambda category_id:
        get_relative_depth(category_id, root)
    )
    data['children_count'] = data['category_id'].apply(
        lambda category_id:
        count_children(category_id, root)
    )
    data['descendants_count'] = data['category_id'].apply(
        lambda category_id:
        count_descendants(category_id, root)
    )
    data['lev_dist'] = get_lev_dist_between_query_category(data['query'],
                                                           data['category_name'])

    vectorizer = read_pickle_object(path_to_data + '/vectorizer.obj')
    data['cosine_dist'] = get_cosine_dist_between_query_category(data['query'],
                                                                 data['category_name'],
                                                                 vectorizer)

    # data['number_of_children_category'] = get_relative_depth(data['category_id'])
    # data['number_of_descendants_category'] = count_descendants(data['category_id'])
    # data['category_depth'] = get_relative_depth(data['category_id'])

    data = data.drop(columns=['category_id', 'query', 'category_name'])

    return data


import sys

def change():
    change = 1000 - int(sys.stdin.readline())
    counter = [1, 5, 10, 50, 100, 500]
    cnt = 0
    counter.reverse()

    for i in counter:
        if change >= i:
            current_cnt, change = divmod(change, i)
            cnt += current_cnt

    return cnt

print(change())


"""Module with lagrangian decomposition methods."""
# Python packages

# Package modules
import logging as log
from firedecomp.AL import ARPP
from firedecomp.AL import ADPP
from firedecomp.fix_work import utils as _utils
from firedecomp.original import model as _model
from firedecomp.classes import problem as _problem

import time
import math
import gurobipy
import copy

###############################################################################
# CLASS LagrangianRelaxation()
###############################################################################
class AugmentedLagrangian(object):
    def __init__(
            self,
            problem_data,
            min_res_penalty=1000000,
            valid_constraints=None,
            gap=0.01,
            max_iters=100000,
            max_time=10,
            log_level="AL",
            solver_options=None,
    ):

        """Initialize the Lagrangian Relaxation object.

        Args:
            problem_data (:obj:`Problem`): problem data.
            min_res_penalty (:obj:`int`):
            gap (:obj:`float`): GAP tolerance for stop criteria.
                Defaults to 0.01.
            max_iters (:obj:`int`): maximum number of iterations. Defaults to
                10.
            max_time (:obj:`float`): maximum cpu time (in seconds). Defaults to
                3600.
            log_level (:obj:`str`): logging level. Defaults to ``'benders'``.
        """

        # PROBLEM DATA
        if problem_data.period_unit is False:
            raise ValueError("Time unit of the problem is not a period.")
        self.problem_data = problem_data
        self.solution_best = None  # index of DPP best solution
        self.solution_best_original = None
        # GLOBAL VARIABLES
        self.max_iters = max_iters
        self.max_time = max_time
        self.init_time = time.time()
        self.v = 1  # iterations
        self.NL = (1 + len(problem_data.get_names("wildfire")))  # +
        # len(problem_data.get_names("wildfire"))*len(problem_data.get_names("groups"))*2);
        # GUROBI OPTIONS
        if solver_options is None:
            solver_options = {
                'OutputFlag': 0,
                'LogToConsole': 0,
            }
        self.solver_options = solver_options

        # PARAMETERS INNER METHODS
        self.change = []
        self.beta_matrix = []
        self.lambda_matrix = []
        self.lambda_matrix_prev = []
        self.upperbound_matrix = []
        self.lobj_global = float("-inf")
        self.fobj_global = float("inf")
        self.infeas_global = float("inf")
        self.subgradient_global = []
        self.penalties_global = []
        self.index_best = -1
        self.lambda_min = 1e1
        self.lambda_max = 1e5
        self.lamdba_init = 1e3
        self.th_sol = 10

        # INITIALIZE DDecomposedPrimalProblemPP PROBLEM
        # Initialize Decomposite Primal Problem Variables
        self.problem_DPP = []
        self.N = len(self.problem_data.get_names("resources"))
        self.y_master_size = len(
            self.problem_data.get_names("wildfire") + [int(min(self.problem_data.get_names("wildfire"))) - 1])
        self.counterh_matrix = []

        self.lobj_local = []
        self.lobj_local_prev = []
        self.fobj_local = []
        self.infeas_local = []
        self.subgradient_local = []
        self.subgradient_local_prev = []
        self.penalties_local = []
        self.termination_counter = []
        self.best_list_y = []

        for i in range(0, self.y_master_size):
            self.termination_counter.append(0)
            self.lobj_local.append(float("inf"))
            self.lobj_local_prev.append(float("inf"))
            self.fobj_local.append(float("inf"))
            self.infeas_local.append(float("inf"))
            self.subgradient_local.append([])
            self.penalties_local.append([])
            self.upperbound_matrix.append(float("inf"))
        self.termination_counter[self.y_master_size - 1] = self.th_sol + 1

        # INITIALIZE LAMBDA AND BETA
        for i in range(0, self.y_master_size):
            lambda_row = []
            lambda_row_prev = []
            lambda_row_inf = []
            beta_row = []
            subgradient_prev_row = []
            for j in range(0, self.NL):
                lambda_row.append(self.lamdba_init)
                lambda_row_inf.append(float("inf"))
                beta_row.append(0.3)
                lambda_row_prev.append(self.lamdba_init)
                subgradient_prev_row.append(0)
            self.subgradient_local_prev.append(subgradient_prev_row)
            self.lambda_matrix.append(lambda_row)
            self.lambda_matrix_prev.append(lambda_row_prev)
            self.beta_matrix.append(beta_row)
            self.change.append(1.0)

        # CREATE ORIGINAL Problems list
        _utils.get_initial_sol(self.problem_data)
        dict_update = self.problem_data.get_variables_solution()
        print("UPDATE original problem")
        for i in range(0, self.y_master_size - 1):
            self.y_master = dict([(p, 1) for p in range(0, self.y_master_size)])
            for p in range(self.y_master_size - (1 + i), self.y_master_size):
                self.y_master[p] = 0
            print("Create index: " + str(i) + " y: " + str(self.y_master))
            model_DPP = ADPP.DecomposedPrimalProblem(self.problem_data,
                                                     self.lambda_matrix[i], self.beta_matrix[i],
                                                     self.y_master, self.N,
                                                     min_res_penalty=min_res_penalty,
                                                     valid_constraints=valid_constraints)
            self.problem_DPP.append(model_DPP)

    ###############################################################################
    # PUBLIC METHOD subgradient()
    ###############################################################################
    def subgradient(self, subgradient, subgradient_prev, lambda_vector, beta_vector, lambda_matrix_prev, ii):

        lambda_old = lambda_vector.copy()
        beta_old = beta_vector.copy()

        stuck = 0
        if max(subgradient_prev) < 0 and max(subgradient) > 0:
            stuck = 1

        for i in range(0, self.NL):
            LRpen = subgradient[i]
            if stuck == 1 and LRpen < 0:
                new_lambda = lambda_matrix_prev[i]
            else:
                new_lambda = (lambda_old[i] + LRpen * beta_old[i])

            lambda_vector[i] = min(max(self.lambda_min, new_lambda), self.lambda_max)
            beta_vector[i] = beta_vector[i] * 1.2
            # print(str(LRpen) + " -> lambda " + str(lambda_old[i]) + " + " + str(beta_old[i] * LRpen) + " = " + str(
            #    lambda_vector[i]) + " update " + str(beta_old[i]) + " diff " + str(
            #    abs(abs(lambda_vector[i]) - abs(lambda_old[i]))) + " beta " + str(
            #    beta_vector[i]))  # + " change_per "+str(change_per) )
        # print("")
        # print("")
        for i in range(0, self.NL):
            subgradient_prev[i] = subgradient[i]
            lambda_matrix_prev[i] = lambda_old[i]
        del lambda_old
        del beta_old

    ###############################################################################
    # PUBLIC METHOD convergence_checking()
    ###############################################################################
    def convergence_checking(self):
        stop = bool(False)
        result = 0
        optimal_solution_found = 0

        # print("TERMINATION COUNTER"+str(self.termination_counter))

        # CHECK PREVIOUS LAMBDAS CHANGES
        for i in range(0, len(self.lambda_matrix) - 1):
            # print(str(self.termination_counter[i])+"  "+str(self.infeas_local[i]))
            if self.infeas_local[i] > 0:
                self.termination_counter[i] = self.termination_counter[i] + 1

            if self.termination_counter[i] < self.th_sol and self.infeas_local[i] <= 0:
                lobj_diff = abs(
                    (abs(self.lobj_local[i]) - abs(self.lobj_local_prev[i])) / abs(self.lobj_local[i])) * 100
                #        # print(str(i) + "self.lobj_local[i] - self.lobj_local_prev[i] " + str(lobj_diff) + "% ")
                if (lobj_diff < 0.1):
                    self.termination_counter[i] = self.termination_counter[i] + 1
                else:
                    self.termination_counter[i] = 0
                    self.lobj_local_prev[i] = self.lobj_local[i]

        # CHECK TERMINATION COUNTER MATRIX
        counter = 0
        all_termination_counter_finished = 0
        for i in range(0, self.y_master_size):
            if self.termination_counter[i] >= (self.th_sol):
                counter = counter + 1
        if counter == self.y_master_size:
            all_termination_counter_finished = 1
        # print("counter" + str(counter) + " termination_counter" + str(self.y_master_size))

        # STOPPING CRITERIA CASES
        current_time = time.time() - self.init_time
        # check convergence
        if (self.v >= self.max_iters):
            print("[STOP] Max iters achieved!")
            stop = bool(True)
        if (current_time >= self.max_time):
            print("[STOP] Max execution time achieved!")
            stop = bool(True)
        elif (all_termination_counter_finished == 1):
            print("[STOP] Convergence achieved, optimal local point searched!")
            stop = bool(True)
        elif (optimal_solution_found == 1):
            print("[STOP] Convergence achieved, optimal solution found!")
            stop = bool(True)

        return stop

    ###############################################################################
    # PUBLIC METHOD solve()
    ###############################################################################
    def solve(self):
        print("SOLVE ALGORITHM")
        termination_criteria = bool(False)

        while termination_criteria == False:
            # (1) Solve DPP problems
            for i in range(0, self.y_master_size - 1):
                # Show iteration results
                if i == 0:
                    log.info("Iteration # mi lambda f(x) L(x,mi,lambda) penL")
                    print("\n\nIter: " + str(self.v) + " " +
                          "LR(x): " + str(self.lobj_global) + " " +
                          "f(x):" + str(self.fobj_global) + " " +
                          "penL:" + str(self.infeas_global) + " time:" +
                          str(time.time() - self.init_time) + "\n")
                if self.termination_counter[i] < self.th_sol:
                    # print("### Y -> " + str(self.problem_DPP[i].list_y))
                    DPP_sol_row = []
                    DPP_sol_unfeasible = False
                    total_obj_function = []
                    total_unfeasibility = []
                    total_subgradient = []
                    total_obj_function_pen = []
                    total_problem = []
                    self.lobj_local[i] = 0
                    self.fobj_local[i] = 0
                    self.subgradient_local[i] = []
                    for z in range(0, self.NL):
                        self.subgradient_local[i].append(float("-inf"))
                    self.penalties_local[i] = []
                    self.infeas_local[i] = 0
                    for j in range(0, self.N):
                        try:
                            self.problem_DPP[i].change_resource(j, self.lambda_matrix[i], self.beta_matrix[i], self.v)
                            DPP_sol_row.append(self.problem_DPP[i].solve(self.solver_options))

                            if (DPP_sol_row[j].model.Status == 3) or (DPP_sol_row[j].model.Status == 4):
                                DPP_sol_unfeasible = True
                                break
                        except:
                            print("Error Solver: Lambda/beta error")
                            DPP_sol_unfeasible = True
                            break
                        total_problem.append(self.problem_DPP[i].problem_data.copy_problem())
                        subgradient = self.problem_DPP[i].return_LR_obj2()
                        total_obj_function_pen.append(self.problem_DPP[i].return_function_obj_total_pen())
                        total_obj_function.append(self.problem_DPP[i].return_function_obj_total())
                        total_unfeasibility.append(max(subgradient))
                        total_subgradient.append(subgradient)
                        # print(str(j) + " fobj " + str(self.problem_DPP[i].return_function_obj()) + " total " +
                        #      str(self.problem_DPP[i].return_function_obj_total()) + "unfeas " + str(max(subgradient)))

                    if DPP_sol_unfeasible:
                        self.termination_counter[i] = self.th_sol + 1
                    else:
                        bestid = self.problem_DPP[i].return_best_candidate(total_obj_function, total_unfeasibility)
                        self.lobj_local[i] = total_obj_function_pen[bestid]
                        self.fobj_local[i] = total_obj_function[bestid]
                        self.infeas_local[i] = total_unfeasibility[bestid]
                        self.subgradient_local[i] = total_subgradient[bestid]
                        #print("TOTAL" + str(i) +
                        #      " LR " + str(self.lobj_local[i]) +
                        #      " fobj " + str(self.fobj_local[i]) +
                        #      " Infeas " + str(self.infeas_local[i]))

                        self.subgradient(self.subgradient_local[i], self.subgradient_local_prev[i],
                                         self.lambda_matrix[i], self.beta_matrix[i],
                                         self.lambda_matrix_prev[i], i)
                        self.change[i] = 0
                        if self.fobj_global > self.fobj_local[i] and (self.infeas_local[i] <= 0):
                            self.problem_DPP[i].problem_data = total_problem[bestid]
                            self.lobj_global = self.lobj_local[i]
                            self.fobj_global = self.fobj_local[i]
                            self.subgradient_global = self.subgradient_local[i]
                            self.infeas_global = self.infeas_local[i]

                            self.solution_best_original = total_problem[
                                bestid].copy_problem()  # self.update_problem_data_sol(self.problem_DPP[i])
                            self.solution_best_original.constrvio = self.infeas_global
                            self.solution_best_original.solve_status = 2
                            # print("New Solution:")
                            # print(self.solution_best_original.get_solution_info())
                            self.change[i] = 1
                        self.problem_DPP[i].update_original_values(DPP_sol_row[bestid], self.change[i])

                    DPP_sol_row.clear()
            # (3) Check termination criteria
            termination_criteria = self.convergence_checking()
            self.v = self.v + 1

        # DESTROY DPP
        # print(self.solution_best_original.get_solution_info())
        if self.solution_best_original is None:
            self.problem_DPP[0].change_resource(0, self.lambda_matrix[i], self.beta_matrix[i], self.v)
            self.problem_DPP[0].solve(self.solver_options)
            min_fobj = self.problem_DPP[0].return_function_obj_total()
            min_feasibility = max(self.problem_DPP[0].return_LR_obj2())
            best_index = 0
            for i in range(1, self.N):
                self.problem_DPP[i].change_resource(0, self.lambda_matrix[i], self.beta_matrix[i], self.v)
                self.problem_DPP[i].solve(self.solver_options)
                fobj = self.problem_DPP[i].return_function_obj_total()
                feas = max(self.problem_DPP[i].return_LR_obj2())
                if min_feasibility >= feas:
                    if min_feasibility == feas:
                        if min_fobj > fobj:
                            best_index = i
                    else:
                        best_index = i
            self.solution_best_original = self.problem_DPP[best_index].problem_data.copy_problem()
            self.solution_best_original.constrvio = max(self.problem_DPP[i].return_LR_obj2())
            self.solution_best_original.solve_status = 2

        self.problem_data = self.solution_best_original
        return self.solution_best_original

    ###############################################################################
    # PRIVATE extract_infeasibility()
    ###############################################################################
    def extract_infeasibility(self, subgradient):
        infeas = 0
        for i in range(0, len(subgradient)):
            if (subgradient[i] > 0):
                infeas = infeas + subgradient[i]
        return infeas

    ###############################################################################
    # PRIVATE destroy_DPP_set()
    ###############################################################################
    def destroy_DPP_set(self):
        for i in range(0, len(self.problem_DPP)):
            len_p = len(self.problem_DPP[i])
            if (len_p > 0):
                for j in range(0, len_p):
                    del self.problem_DPP[i][0]
                self.problem_DPP[i] = []
        self.problem_DPP = []
        # print("DESTROY")

    ###############################################################################
    # PRIVATE METHOD __log__()
    ###############################################################################
    #    def __log__(self, level="AL"):
    #        log.addLevelName(80, "AL")
    #        log.Logger.LR = logging.LR

    #        if level != 'AL':
    #            log_level = getattr(log, level)
    #            logger = log.getLogger('AL_logging')
    #            logger.setLevel(log_level)
    #            logger.addFilter(logging.LRFilter())
    #            if len(logger.handlers) == 0:
    #                ch = log.StreamHandler()
    #                ch.setLevel(log_level)
    #                # create formatter and add it to the handlers
    #                formatter = log.Formatter("%(levelname)8s: %(message)s")
    #                ch.setFormatter(formatter)
    #                logger.addHandler(ch)
    #        else:
    #            log_level = 80
    #            logger = log.getLogger('AL')
    #            logger.setLevel(log_level)
    #            if len(logger.handlers) == 0:
    #                ch = log.StreamHandler()
    #                ch.setLevel(log_level)
    #                # create formatter and add it to the handlers
    #                formatter = log.Formatter("%(message)s")
    #                ch.setFormatter(formatter)
    #                logger.addHandler(ch)
    #
    #        self.log = logger
    #        return 1

    def update_problem_data_sol(self, solution):

        problem = self.problem_data.copy_problem()
        problem = self.solution_to_problem(problem, solution)

        return problem

    def solution_to_problem(self, problem, solution):
        problem.mipgap = None
        problem.mipgapabs = None
        problem.constrvio = self.infeas_global
        problem.solve_status = 2

        variables = solution
        data = problem.data

        problem.resources.update(
            {i: {'select': round(variables.z[i].getValue()) == 1}
             for i in data.I})

        s = {(i, t): round(variables.s[i, t].x) == 1
             for i in data.I for t in data.T}
        u = {(i, t): round(variables.u[i, t].getValue()) == 1
             for i in data.I for t in data.T}
        e = {(i, t): round(variables.e[i, t].x) == 1
             for i in data.I for t in data.T}
        w = {(i, t): round(variables.w[i, t].getValue()) == 1
             for i in data.I for t in data.T}
        r = {(i, t): round(variables.r[i, t].x) == 1
             for i in data.I for t in data.T}
        er = {(i, t): round(variables.er[i, t].x) == 1
              for i in data.I for t in data.T}
        tr = {(i, t): round(variables.tr[i, t].x) == 1
              for i in data.I for t in data.T}

        problem.resources_wildfire.update(
            {(i, t): {
                'start': s[i, t],
                'use': u[i, t],
                'end': e[i, t],
                'work': w[i, t],
                'travel': tr[i, t],
                'rest': r[i, t],
                'end_rest': er[i, t]
            }
                for i in data.I for t in data.T})

        problem.groups_wildfire.update(
            {(g, t): {'num_left_resources': variables.mu[g, t].x}
             for g in data.G for t in data.T})

        contained = {t: variables.y[t].x == 0
                     for t in data.T}
        contained_period = [t for t, v in contained.items()
                            if v is True]

        if len(contained_period) > 0:
            first_contained = min(contained_period) + 1
        else:
            first_contained = data.max_t + 1

        problem.wildfire.update(
            {t: {'contained': False if t < first_contained else True}
             for t in data.T})

        return problem

    def create_init_solution(self, problem_data):

        T = problem_data.get_names("wildfire")

        min_t = int(min(T))
        list_y = dict([(p, 1) for p in range(0, len(T + [min_t - 1]))])
        list_y[len(list_y) - 1] = 0
        print(list_y)

        problem_data_copy = problem_data.copy_problem()
        init_problem = _model.InputModel(problem_data_copy)
        solver_options = {
            'OutputFlag': 1,
            'LogToConsole': 1,
            'TimeLimit': 10,
        }
        for i in range(0, len(list_y)):
            init_problem.y[i].UB = list_y[i]
            init_problem.y[i].LB = list_y[i]
        init_problem.m.update()
        print("COMPUTE INIT SOLUTION")
        init_problem.solve(solver_options)
        print("END COMPUTE INIT SOLUTION")

        return init_problem


class detail:
    def __init__(self) -> None:
        self.__name="harry"

a=detail()
# print(a.__name) #cannot access directly
# print(a._detail__name) #can be accessed indirectly #NAME MANGLING
print(a.__dir__()) #from this we see all the available methods on a


# Задача-2:
# Даны два произвольные списка.
# Удалите из первого списка элементы, присутствующие во втором списке.

lst_1 = [1, 3, 5, 7, 9]
lst_2 = [3, 8, 6, 5]
new = []
for i in lst_1:
    if i not in lst_2:
        new.append(i)
lst_1 = new
print(lst_1, lst_2)


from flask import Flask,render_template,request,jsonify
import utils

app = Flask(__name__)

@app.route('/')  #Base API
def home():
    print('Testing Home API')
    return render_template('home.html')

@app.route('/predict', methods = ['POST'])
def prediction():
    print('Testing prediction API')
    data = request.form
    if request.method == 'POST':
        print('Input data is :',data)
        x1 = float(data['SepalLengthCm'])
        x2 = float(data['SepalWidthCm'])
        x3 = float(data['PetalLengthCm'])
        x4 = float(data['PetalWidthCm'])

        prediction = utils.predict_class(x1,x2,x3,x4)

        return render_template('after.html', data=prediction)

    else:
        return jsonify({'Message':'Unsuccessful'})

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5000, debug=False)


from tkinter import *
import os
import platform

### FUNCTION TO KILL
def stopProg(e):
	root.destroy()

### FUCNTION THAT DOES CALCULATIONS FOR CENTER OF SCREEN
### AND THEN CENTERS THE WINDOW
def center(window,w,h):
	ws = window.winfo_screenwidth()
	hs = window.winfo_screenheight()
	x = (ws/2) - (w/2)
	y = (hs/2) - (h/2)
	window.geometry('%dx%d+%d+%d' % (w, h, x, y))

### FUNCTION THAT ACTIVATES IF TIMESHEET ALREADY EXISTS
def ts_exists(timesheet):

	### FUNCTION TO KILL POPUP WINDOW
	def destroy_ts_exists(e):
		win.destroy()

	### FUNCTION THAT STARTS Edit.py WITH RIGHT ARGUMENTS
	### KILLS Main.py
	def edit(event, ts):
		win.destroy()
		root.destroy()
		op_s = platform.system()
		print(op_s)
		if op_s == "Windows":
			os.system("python Edit.py "+'"'+ts+'"')
		elif op_s == "Linux":
			os.system("python3.4 Edit.py "+'"'+ts+'"')
	### CREATE AND CENTER POPUP WINDOW
	win = Toplevel()
	win.title("Timesheet Found")
	center(win, 250, 125)

	### THERE'S THIS LINE AGAIN, PRETTY SURE IT'S OKAY NOW
	win.wm_attributes('-topmost', 1)

	### LABELS
	Label(win, text = "Timesheet Found", background = "green").pack()
	Label(win, text = timesheet).pack()
	Label(win, text = "Edit This Timesheet?").pack()

	### BUTTONS AND BINDINGS
	n = Button(win, text = "No")
	n.pack()
	n.bind('<Button-1>', destroy_ts_exists)
	y = Button(win, text = "Yes")
	y.pack()
	y.bind('<Button-1>',
		lambda event, ts=timesheet: edit(event, ts))

### FUNCTION THAT ACTIVATES IF TIMESHEET DOES NOT EXIST
def ts_no_exist(timesheet, case):
	### FUNCTION TO KILL POPUP WINDOW
	def destroy_ts_no_exist(e):
		pop.destroy()

	### FUNCTION THAT STARTS Create.py WITH THE APPROPRIATE ARGUMENTS
	def edit(event, ts):
		pop.destroy()
		root.destroy()

		op_s = platform.system()
		print(op_s)
		if op_s == "Windows":
			os.system("python Edit.py "+'"'+ts+'"')
		elif op_s == "Linux":
			os.system("python3.4 Edit.py "+'"'+ts+'"')

	### CREATE AND CENTER POPUP WINDOW
	pop = Toplevel()
	pop.title("Timesheet Doesn't Exist")
	center(pop, 250, 125)

	## THIS LINE IS A TOTAL NO-GO ---- ???? KEEPS ON TOP?? ...wtf
	pop.wm_attributes('-topmost', 1)

	### LABELS
	Label(pop, text = "Timesheet does not exist.", background = "red").pack()
	Label(pop, text = "Create Time sheet?").pack()

	### BUTTONS AND BINDINGS
	n = Button(pop, text = "No")
	n.pack()
	n.bind('<Button-1>', destroy_ts_no_exist)
	y = Button(pop, text = "Yes")
	y.pack()
	y.bind('<Button-1>',
		lambda event, ts=timesheet: edit(event, ts))

### SUBMIT FUNCTION
### USES FIRST AND LAST NAME TO FORMAT A FILENAME
### CHECKS IF IT EXISTS, AND ACTIAVTES THE APPROPRIATE FUNCTION
def submit(e):
	first = f_name.get()
	last = l_name.get()
	case = case_no.get()
	#format a file name from user input
	full_fn = last.upper()+", "+first.upper()+" "+case.upper()+".txt"
	if os.path.isfile(full_fn) == False:
		ts_no_exist(full_fn, case)
	elif os.path.isfile(full_fn):
		ts_exists(full_fn)

###################
### DRAWING GUI ###
###################

### CREATE MAIN WINDOW
root = Tk()
root.title("Select Timesheet")

### CENTER WINDOW
center(root, 252, 125)

### CREATING AND PLACING LABELS
Label(root,text = "First Name").grid(row = 0)
Label(root, text = "Last Name").grid(row = 1)
Label(root, text = "Case #").grid(row = 2)

### CREATING AND PLACING ENTRY BOXES
f_name = Entry(root)
f_name.grid(row = 0, column = 1)
l_name = Entry(root)
l_name.grid(row = 1, column = 1)
case_no= Entry(root)
case_no.grid(row = 2, column = 1)

### CREATING, PLACING AND BINDING BUTTONS
submit_but = Button(root, text = "Submit")
submit_but.grid(row = 3)
submit_but.bind('<Button-1>', submit)

### START MAINLOOP
root.mainloop()


#! /usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import unicode_literals
import logging
import unittest

from tutorons.regex.extract import ApacheConfigRegexExtractor, JavascriptRegexExtractor,\
    GrepRegexExtractor, SedRegexExtractor
from tutorons.common.htmltools import HtmlDocument

logging.basicConfig(level=logging.INFO, format="%(message)s")

'''
TODO consider implementing regular expression checking for these languages:
1. tcl shell
2. Python regular expression methods
3. Java methods
'''

class ExtractRegexFromModRewriteTest(unittest.TestCase):

    def setUp(self):
        self.extractor = ApacheConfigRegexExtractor()

    def test_extract_regex_for_rewrite_rule(self):
        node = HtmlDocument('\n'.join([
            "",
            "RewriteRule ^.*$ index.php",
            "",
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 1)
        r = regions[0]
        self.assertEqual(r.node, node)
        self.assertEqual(r.start_offset, 13)
        self.assertEqual(r.end_offset, 16)

    def test_extract_regex_for_rewrite_condition(self):
        node = HtmlDocument('\n'.join([
            "",
            "RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla",
            "",
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 1)
        r = regions[0]
        self.assertEqual(r.start_offset, 34)
        self.assertEqual(r.end_offset, 41)

    def test_allow_whitespace_before_directive(self):
        node = HtmlDocument('\n'.join([
            "",
            "    RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla",
            "",
        ]))
        regions = self.extractor.extract(node)
        r = regions[0]
        self.assertEqual(r.start_offset, 38)
        self.assertEqual(r.end_offset, 45)

    def test_case_insensitive_directive_detected(self):
        node = HtmlDocument('\n'.join([
            "",
            "REWRITEcOnD  %{HTTP_USER_AGENT}  ^Mozilla",
            "",
        ]))
        regions = self.extractor.extract(node)
        r = regions[0]
        self.assertEqual(r.start_offset, 34)
        self.assertEqual(r.end_offset, 41)

class ExtractRegexFromJavascriptTest(unittest.TestCase):

    def setUp(self):
        self.extractor = JavascriptRegexExtractor()

    def test_extract_regex_from_variable_declaration(self):
        node = HtmlDocument('\n'.join([
            '',
            "var pattern = /regular-expression/g;",
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 1)
        r = regions[0]
        self.assertEqual(r.node, node)
        self.assertEqual(r.start_offset, 16)
        self.assertEqual(r.end_offset, 33)

    def test_skip_code_that_doesnt_pass_javascript_parser(self):
        node = HtmlDocument('\n'.join([
            '',
            "<>/regex/;",
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 0)

    def test_skip_regex_with_repeated_flags(self):
        node = HtmlDocument('\n'.join([
            '',
            "var pattern = /regular-expression/gg;",
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 0)

    def test_skip_regex_with_invalid_flags(self):
        node = HtmlDocument('\n'.join([
            '',
            "var pattern = /regular-expression/x;",
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 0)

class ExtractRegexFromGrepTest(unittest.TestCase):

    def setUp(self):
        self.extractor = GrepRegexExtractor()

    def test_extract_regex_from_variable_declaration(self):
        node = HtmlDocument('\n'.join([
            '',
            "grep pattern *",
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 1)
        r = regions[0]
        self.assertEqual(r.node, node)
        self.assertEqual(r.start_offset, 6)
        self.assertEqual(r.end_offset, 12)

    def test_extract_same_pattern_from_multiple_greps_in_one_element(self):
        node = HtmlDocument('\n'.join([
            '',
            "grep pattern *",
            "grep pattern *",
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 2)
        r1 = regions[0]
        self.assertEqual(r1.start_offset, 6)
        self.assertEqual(r1.end_offset, 12)
        r2 = regions[1]
        self.assertEqual(r2.start_offset, 21)
        self.assertEqual(r2.end_offset, 27)

    def test_extract_pattern_containing_spaces(self):
        node = HtmlDocument('\n'.join([
            '',
            "grep 'Pattern with spaces' *",
            '',
        ]))
        regions = self.extractor.extract(node)
        r = regions[0]
        self.assertEqual(r.start_offset, 7)
        self.assertEqual(r.end_offset, 25)

    def test_extract_pattern_from_option(self):
        node = HtmlDocument('\n'.join([
            '',
            "grep -e pattern *",
            '',
        ]))
        regions = self.extractor.extract(node)
        r = regions[0]
        self.assertEqual(r.start_offset, 9)
        self.assertEqual(r.end_offset, 15)

    def test_extract_patterns_from_multiple_options(self):
        node = HtmlDocument('\n'.join([
            '',
            "grep -e pattern1 -e pattern2 *",
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 2)
        self.assertTrue(any([r.start_offset == 9 and r.end_offset == 16 for r in regions]))
        self.assertTrue(any([r.start_offset == 21 and r.end_offset == 28 for r in regions]))

class ExtractRegexFromSedTest(unittest.TestCase):

    def setUp(self):
        self.extractor = SedRegexExtractor()

    def test_extract_regexes_from_address_range(self):
        node = HtmlDocument('\n'.join([
            '',
            'sed "/addr1/,/addr2/p" file',
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 2)
        r1 = regions[0]
        self.assertEqual(r1.node, node)
        self.assertEqual(r1.start_offset, 7)
        self.assertEqual(r1.end_offset, 11)
        r2 = regions[1]
        self.assertEqual(r2.start_offset, 15)
        self.assertEqual(r2.end_offset, 19)

    def test_ignore_addresses_that_arent_regex(self):
        node = HtmlDocument('\n'.join([
            '',
            'sed "0,1p" file',
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 0)

    def test_extract_regex_from_substitute_pattern(self):
        node = HtmlDocument('\n'.join([
            '',
            'sed "s/patt/replace/" file',
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 1)
        r = regions[0]
        self.assertEqual(r.start_offset, 8)
        self.assertEqual(r.end_offset, 11)

    def test_extract_regex_from_multiple_substitute_patterns(self):
        node = HtmlDocument('\n'.join([
            '',
            'sed -e "s/patt1/replace/" -e "s/patt2/replace/" file',
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 2)
        self.assertTrue(any([r.start_offset == 11 and r.end_offset == 15 for r in regions]))
        self.assertTrue(any([r.start_offset == 33 and r.end_offset == 37 for r in regions]))

    def test_handle_escaped_characters(self):
        node = HtmlDocument('\n'.join([
            '',
            'sed \'s/pa\/tt/replace/\' file',
            '',
        ]))
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 1)
        r = regions[0]
        self.assertEqual(r.start_offset, 8)
        self.assertEqual(r.end_offset, 13)
        self.assertEqual(r.pattern, r'pa/tt')

    def test_handle_find_pattern_with_character_class(self):
        '''
        This test case failed earlier as we performed a regex search with the pattern found
        against the original command, and it was being interpreted as a regex, and not a raw string.
        '''
        node = HtmlDocument('sed "s/[A-Z]bc//g" file.txt')
        regions = self.extractor.extract(node)
        self.assertEqual(len(regions), 1)

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


from rest_framework.parsers import JSONParser
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.decorators import api_view
import io
from rest_framework import status
from todos.models import Task
from .serializers import TaskSerializer

@api_view(['GET'])
def get_task_list(request):
    tasks = Task.objects.all()
    # print('>>> tasks : ',tasks)
    serializer = TaskSerializer(tasks, many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(['GET'])
def get_task_detail(request, pk):
    task = Task.objects.get(pk=pk)
    serializer = TaskSerializer(task)
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(['POST'])
def create_task(request):
    serializer = TaskSerializer(data=request.data, context={'request':request})
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['DELETE'])
def delete_task(request, pk):
    task = Task.objects.get(pk=pk)
    task.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

@api_view(['PUT', 'PATCH'])
def update_task(request, pk):
    task = Task.objects.get(pk=pk)
    if request.method == 'PUT':
        serializer = TaskSerializer(task, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'PATCH':
        serializer = TaskSerializer(task, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['POST'])
def completed(request,pk):
        task = Task.objects.get(pk=pk)
        serializer = TaskSerializer(task, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# from microbit import *
# from mpu9250 import MPU9250
# from mpu9250 import MPU9250
# imu = MPU9250('X')

# while True:

#     print(imu.accel.xyz)
#     print(imu.gyro.xyz)
#     print(imu.mag.xyz)
#     print(imu.temperature)
#     print(imu.accel.z)

#     sleep(1000)
from PiicoDev_Unified import sleep_ms
from PiicoDev_MPU6050 import PiicoDev_MPU6050

# Example code for Motion Sensor MPU6050
# Cross-platform compatible sleep function

motion = PiicoDev_MPU6050()

while True:

    # Accelerometer data
    accel = motion.read_accel_data()  # read the accelerometer [ms^-2]
    aX = accel["x"]
    aY = accel["y"]
    aZ = accel["z"]
    print("x:" + str(aX) + " y:" + str(aY) + " z:" + str(aZ))

    # Gyroscope Data
#     gyro = motion.read_gyro_data()   # read the gyro [deg/s]
#     gX = gyro["x"]
#     gY = gyro["y"]
#     gZ = gyro["z"]
#     print("x:" + str(gX) + " y:" + str(gY) + " z:" + str(gZ))

    # Rough temperature
#     temp = motion.read_temperature()   # read the device temperature [degC]
#     print("Temperature: " + str(temp) + "°C")

    # G-Force
#     gforce = motion.read_accel_abs(g=True) # read the absolute acceleration magnitude
#     print("G-Force: " + str(gforce))

    sleep_ms(100)

# from microbit import *

# sleep(1000)

# print("Hello Terminal!")


from json import loads
from logging_tools import Logger
from population import create_sample
from requests import get
from requests import post
from requests.auth import HTTPBasicAuth
from string import Template
from time import sleep
from uuid import uuid1

""" Template for the whisk rest api. """
whisk_rest_api = Template(
    '$APIHOST/api/v1/namespaces/$NAMESPACE/$ENDPOINT/$VALUE'
)

def evolution_parameters(function=3, instance=1, dim=3, population_size=20):
    """ Returns the evolution parameters. """

    return {
        'id': str(uuid1()),
        'problem': {
            'name': 'BBOB',
            'function': function,
            'instance': instance,
            'search_space': [-5, 5],
            'dim': dim,
            'error': 1e-8
        },
        'population': [],
        'population_size': population_size,
        'experiment': {
            'experiment_id': 'dc74efeb-9d64-11e7-a2bd-54e43af0c111',
            'owner': 'mariosky',
            'type': 'benchmark'
        },
        'algorithm': {
            'name': 'GA',
            'iterations': 5,
            'selection': {
                'type': 'tools.selTournament',
                'tournsize': 12
            },
            'crossover': {
                'type': 'cxTwoPoint',
                'CXPB': [0, 0.2]
            },
            'mutation': {
                'type': 'mutGaussian',
                'mu': 0,
                'sigma': 0.5,
                'indpb' : 0.05,
                'MUTPB':0.5
            }
        }
    }

def create_parameters(settings, population=None):
    """ Creates the evolution parameters with a population. """

    parameters = evolution_parameters(
        settings.function,
        settings.instance,
        settings.dim,
        settings.population_size
    )
    parameters['population'] = population or create_sample(parameters)
    return parameters

def get_request_data(settings, endpoint, value, json={}):
    """ Gets the request data. """

    auth = settings.auth.split(':')
    return {
        'url': whisk_rest_api.safe_substitute(
            APIHOST=settings.apihost,
            NAMESPACE=settings.namespace,
            ENDPOINT=endpoint,
            VALUE=value,
        ),
        'json': json,
        'params': {
            'blocking': str(settings.blocking),
            'result': 'True'
        },
        'auth': HTTPBasicAuth(auth[0], auth[1]),
        'verify': not settings.insecure
    }

def crossover_migration(pop1, pop2, key = lambda p: p['fitness']['score']):
    """ Does the crossover migration. """

    pop1.sort(key=key)
    pop2.sort(key=key)
    size = min(len(pop1), len(pop2))

    cxpoint = int(size / 2)

    pop1[cxpoint:] = pop2[:cxpoint + size % 2]

    return pop1

def request_evolution(settings, population):
    """ Gets the population using blocking. """

    data = get_request_data(settings, 'actions', 'gaService', population)

    logger = Logger(settings.verbose)
    logger.log('POST request to ' + data['url'])

    response = post(**data).json()
    logger.log('POST complete!')
    return response

def request_evolution_id(settings, population):
    """ Evolves a population and returns it's OpenWhisk activationid. """

    response = request_evolution(settings, population)
    return response['activationId']

def request_evolved(settings, id):
    """ Gets the population data with it's OpenWhisk activation id. """

    data = get_request_data(settings, 'activations', id)

    logger = Logger(settings.verbose)
    logger.log('Polling activationId ' + str(id))

    for _ in range(0, settings.timeout):
        logger.log('GET request to ' + data['url'])

        response = get(**data).json()
        logger.log('GET complete!')

        if 'error' not in response:
            return loads(response['response']['result']['value'])

        sleep(1)

    raise ValueError('Timeout exception.')

def evolve(settings, population):
    """ Evolves the population with the given settings. """

    response = request_evolution(settings, population)
    print(response)
    if 'activationId' in response:
        return request_evolved(settings, response['activationId'])
    else:
        return loads(response['value'])


from __future__ import annotations

import falcon

from app.models import Rating
from app.schemas.ratings import rating_item_schema

class RateResource:
    deserializers = {"post": rating_item_schema}

    def on_post(self, req: falcon.Request, resp: falcon.Response, id: int):
        """
        ---
        summary: Add rating for movie as logged in user
        tags:
            - Rating
        parameters:
            - in: body
              schema: RatingSchema
        consumes:
            - application/json
        produces:
            - application/json
        responses:
            201:
                description: Vote successful
            401:
                description: Unauthorized
            422:
                description: Input body formatting issue
        """
        db = req.context["db"]
        user = req.context["user"]
        rating = req._deserialized["rating"]

        user_rating = Rating(rating=rating, user=user, movie_id=id)
        db.session.add(user_rating)
        db.session.commit()

        resp.status = falcon.HTTP_CREATED
        resp.media = {"message": "rating saved"}


# Дан список чисел. Если среди них есть ноль - вывести yes, иначе no.

my_list = [1, 2, 100, 0, 3]

# а можно было запросить у пользователя ввести числа через пробел
# my_list = [int(i) for i in input().split()]

has_zero = False
for i in my_list:
    if i == 0:
        has_zero = True
        break

if has_zero:
    print('yes')
else:
    print('no')