from typing import Optional

import torch
import torch.nn as nn
import torch.nn.functional as F

from rex.modules.ffn import MLP
from rex.utils.span import find_closest_span_pairs, find_closest_span_pairs_with_index

class SubjObjSpan(nn.Module):
    """
    Inputs:
        hidden: (batch_size, seq_len, hidden_size)
        one_subj_head: object golden head with one subject (batch_size, hidden_size)
        one_subj_tail: object golden tail with one subject (batch_size, hidden_size)
    """

    def __init__(self, hidden_size, num_classes, threshold: Optional[float] = 0.5):
        super().__init__()
        self.threshold = threshold
        self.subj_head_ffnn = nn.Linear(hidden_size, 1)
        self.subj_tail_ffnn = nn.Linear(hidden_size, 1)
        self.obj_head_ffnn = nn.Linear(hidden_size, num_classes)
        self.obj_tail_ffnn = nn.Linear(hidden_size, num_classes)

    def get_objs_for_specific_subj(self, subj_head_mapping, subj_tail_mapping, hidden):
        # (batch_size, 1, hidden_size)
        subj_head = torch.matmul(subj_head_mapping, hidden)
        # (batch_size, 1, hidden_size)
        subj_tail = torch.matmul(subj_tail_mapping, hidden)
        # (batch_size, 1, hidden_size)
        sub = (subj_head + subj_tail) / 2
        # (batch_size, seq_len, hidden_size)
        encoded_text = hidden + sub
        # (batch_size, seq_len, num_classes)
        pred_obj_heads = self.obj_head_ffnn(encoded_text)
        # (batch_size, seq_len, num_classes)
        pred_obj_tails = self.obj_tail_ffnn(encoded_text)
        return pred_obj_heads, pred_obj_tails

    def build_mapping(self, subj_heads, subj_tails):
        """
        Build head & tail mapping for predicted subjects,
        for each instance in a batch, for a subject in all
        the predicted subjects, return a single subject
        and its corresponding mappings.
        """
        for subj_head, subj_tail in zip(subj_heads, subj_tails):
            subjs = find_closest_span_pairs(subj_head, subj_tail)
            seq_len = subj_head.shape[0]
            for subj in subjs:
                subj_head_mapping = torch.zeros(seq_len, device=subj_head.device)
                subj_tail_mapping = torch.zeros(seq_len, device=subj_tail.device)
                subj_head_mapping[subj[0]] = 1.0
                subj_tail_mapping[subj[1]] = 1.0
                yield subj, subj_head_mapping, subj_tail_mapping

    def build_batch_mapping(self, subj_head, subj_tail):
        """
        Build head & tail mapping for predicted subjects,
        for each instance in a batch, return all the predicted
        subjects and mappings.
        """
        subjs = find_closest_span_pairs(subj_head, subj_tail)
        seq_len = subj_head.shape[0]
        if len(subjs) > 0:
            subjs_head_mapping = torch.zeros(
                len(subjs), seq_len, device=subj_head.device
            )
            subjs_tail_mapping = torch.zeros(
                len(subjs), seq_len, device=subj_tail.device
            )

            for subj_idx, subj in enumerate(subjs):
                subjs_head_mapping[subj_idx, subj[0]] = 1.0
                subjs_tail_mapping[subj_idx, subj[1]] = 1.0
            return subjs, subjs_head_mapping, subjs_tail_mapping
        else:
            return None, None, None

    def forward(self, hidden, subj_head, subj_tail):
        # subj_head_out, subj_tail_out: (batch_size, seq_len, 1)
        subj_head_out = self.subj_head_ffnn(hidden)
        subj_tail_out = self.subj_tail_ffnn(hidden)
        # subj_head, subj_tail: (batch_size, seq_len)
        # obj_head_out, obj_tail_out: (batch_size, seq_len, num_classes)
        obj_head_out, obj_tail_out = self.get_objs_for_specific_subj(
            subj_head.unsqueeze(1), subj_tail.unsqueeze(1), hidden
        )

        return (
            subj_head_out.squeeze(-1),
            subj_tail_out.squeeze(-1),
            obj_head_out,
            obj_tail_out,
        )

    def predict(self, hidden):
        # hidden: 1 x hidden_size
        if hidden.shape[0] != 1:
            raise RuntimeError(
                (
                    "eval batch size must be 1 x hidden_size, "
                    f"while hidden is {hidden.shape}"
                )
            )
        # 1, hidden_size, 1
        subj_head_out = self.subj_head_ffnn(hidden)
        # 1, hidden_size, 1
        subj_tail_out = self.subj_tail_ffnn(hidden)
        subj_head_out = torch.sigmoid(subj_head_out)
        subj_tail_out = torch.sigmoid(subj_tail_out)
        pred_subj_head = subj_head_out.ge(self.threshold).long()
        pred_subj_tail = subj_tail_out.ge(self.threshold).long()

        triples = []
        # subjs: [(1, 3), (3, 3), (17, 17)]
        # subj_head_mappings: (len(subjs), seq_len)
        subjs, subj_head_mappings, subj_tail_mappings = self.build_batch_mapping(
            pred_subj_head.squeeze(0).squeeze(-1), pred_subj_tail.squeeze(0).squeeze(-1)
        )

        if subjs:
            # obj_head_out: (len(subjs), seq_len, num_classes)
            obj_head_out, obj_tail_out = self.get_objs_for_specific_subj(
                subj_head_mappings.unsqueeze(1), subj_tail_mappings.unsqueeze(1), hidden
            )
            obj_head_out = torch.sigmoid(obj_head_out)
            obj_tail_out = torch.sigmoid(obj_tail_out)
            obj_head_out = obj_head_out.ge(self.threshold).long()
            obj_tail_out = obj_tail_out.ge(self.threshold).long()
            for subj_idx, subj in enumerate(subjs):
                objs = find_closest_span_pairs_with_index(
                    obj_head_out[subj_idx].permute(1, 0),
                    obj_tail_out[subj_idx].permute(1, 0),
                )
                for relation_idx, obj_pair_start, obj_pair_end in objs:
                    triples.append(
                        (
                            (subj[0], subj[1] + 1),
                            relation_idx,
                            (obj_pair_start, obj_pair_end + 1),
                        )
                    )
        return [triples]


import logging

import azure.functions as func
import json
from random import randint
# from pathlib import Path

# calcola-somma function
def main(req: func.HttpRequest) -> func.HttpResponse:
        logging.info('Python HTTP trigger function processed a request.')
        users = {"1754462800": {"name": "John", "surname": "Doe", "email": "john.doe@email.com"}, "4659781230": {"name": "Mario", "surname": "Rossi", "email": "mario.rossi@email.com"}, "7845120036": {"name": "Mattia", "surname": "Di Nardo", "email": "mattia.di.nardo@email.com"}, "9956223017": {"name": "Angela", "surname": "Donadoni", "email": "angela.donadoni@email.com"}, "3328182950": {"name": "Maria", "surname": "Lorena", "email": "maria.lorena@email.com"}}

        # GET method
        if req.method == "GET":
                # read users file
                # with open(str(Path.cwd()) + "\\ServerPOST\\users.json", "r") as file:
                #         parsed = json.load(file)
                #         users = json.dumps(parsed, indent=4)

                # HTTP Response
                return func.HttpResponse(
                        f"This HTTP triggered function executed successfully.\nThe users are: {json.dumps(users, indent=4)}",
                        status_code=200
                )

        # POST method
        if req.method == "POST":
                # if there are params
                if len(req.params) >= 3:
                        # take data
                        id = randint(1000000000, 9999999999)
                        name = req.params.get("name")
                        surname = req.params.get("surname")
                        email = req.params.get("email")

                        # read users file
                        # with open(str(Path.cwd()) + "\\ServerPOST\\users.json", "r") as file:
                        #         users = json.load(file)

                        # append new user
                        # users[str(id)] = {
                        #                 "name": name,
                        #                 "surname": surname,
                        #                 "email": email
                        # }

                        user = {id: {
                                "name": name,
                                "surname": surname,
                                "email": email
                        }}

                        # insert new format file
                        # with open(str(Path.cwd()) + "\\ServerPOST\\users.json", "w") as file:
                        #         json.dump(users, file)

                        # HTTP Response
                        return func.HttpResponse(
                                f"This HTTP triggered function executed successfully.\nThe user has been added!\nDetails:{json.dumps(user, indent=4)}",
                                status_code=200
                        )
                # otherwise, check body
                else:
                        # take body
                        req_body = req.get_json()

                        # gen id
                        id = randint(1000000000, 9999999999)

                        # read file
                        # with open(str(Path.cwd()) + "\\ServerPOST\\users.json", "r") as file:
                        #         users = json.load(file)

                        # append new user
                        user = {
                                id:
                                {
                                        "name": req_body["name"],
                                        "surname": req_body["surname"],
                                        "email": req_body["email"]
                                }
                        }

                        # insert new format file
                        # with open(str(Path.cwd()) + "\\ServerPOST\\users.json", "w") as file:
                        #         json.dump(users, file)

                        # HTTP Response
                        return func.HttpResponse(
                                f"This HTTP triggered function executed successfully.\nThe user has been added!\nDetails:{json.dumps(user, indent=4)}",
                                status_code=200
                        )

        # DELETE method
        if req.method == "DELETE":
                # read users file
                # with open(str(Path.cwd()) + "\\ServerPOST\\users.json", "r") as file:
                #         users = json.load(file)

                # take id from params
                id_user = req.params.get("id")

                # deepcopy
                users_pre_delete = users.copy()

                # delete user
                users.pop(id_user)

                # insert new format file
                # with open(str(Path.cwd()) + "\\ServerPOST\\users.json", "w") as file:
                #         json.dump(users, file)

                # HTTP Response
                return func.HttpResponse(
                        f"This HTTP triggered function executed successfully.\nThe user has been deleted!\nUsers pre-delete:{json.dumps(users_pre_delete, indent=4)}\nUsers after-delete:{json.dumps(users, indent=4)}",
                        status_code=200
                )


'''
Train the highest number prediction with the rational extractor.
'''
import torch
from torch.utils.data import DataLoader
import pytorch_lightning as pl
from HighestNumber.HighestDataset import HighestDataset
from HighestNumber.reinforce_rational_extraction import ReinforceRationalExtractor, HighestNumberLSTM, ReinforceModelPL

max_epochs = 3

dataset_train = HighestDataset(n_examples=int(10e3))
dataloader_train = DataLoader(dataset_train, shuffle=True, batch_size=8)

dataset_test = HighestDataset(n_examples=int(10e2))
dataloader_test = DataLoader(dataset_test, shuffle=False, batch_size=8)

loss_module = torch.nn.CrossEntropyLoss()
model = HighestNumberLSTM()

RE = ReinforceRationalExtractor()

hparams = {
    "learning_rate": 1e-3
}

model_pl_pretrain = ReinforceModelPL(model, RE, loss_module, hparams=hparams, pretrain=True)
trainer = pl.Trainer(default_root_dir='logs',
                     checkpoint_callback=False,
                     # checkpoint_callback=ModelCheckpoint(save_weights_only=True, mode="min", monitor="val_loss"),
                     gpus=1 if torch.cuda.is_available() else 0,
                     max_epochs=5,
                     log_every_n_steps=1,
                     progress_bar_refresh_rate=1,
                     gradient_clip_val=2,
                     )
trainer.logger._default_hp_metric = None  # Optional logging argument that we don't need

trainer.fit(model_pl_pretrain, dataloader_train, dataloader_test)
loss_module = torch.nn.CrossEntropyLoss(reduce=False)
model_pl = ReinforceModelPL(model, RE, loss_module, hparams=hparams, pretrain=False)
trainer = pl.Trainer(default_root_dir='logs',
                     checkpoint_callback=False,
                     # checkpoint_callback=ModelCheckpoint(save_weights_only=True, mode="min", monitor="val_loss"),
                     gpus=1 if torch.cuda.is_available() else 0,
                     max_epochs=40,
                     log_every_n_steps=1,
                     progress_bar_refresh_rate=1,
                     gradient_clip_val=2,
                     )
trainer.logger._default_hp_metric = None  # Optional logging argument that we don't need

trainer.fit(model_pl, dataloader_train, dataloader_test)


import cv2 as cv
import numpy as np

video=cv.VideoCapture(0)
windowClose = np.ones((5, 5), np.uint8)
windowOpen = np.ones((2, 2), np.uint8)
windowErode = np.ones((2, 2), np.uint8)
face_cascade = cv.CascadeClassifier('D:/opencvextracted/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
eye_cascade = cv.CascadeClassifier('D:/opencvextracted/opencv/sources/data/haarcascades/haarcascade_eye.xml')

while(True):
    _,frame=video.read()
    gray=cv.cvtColor(frame,cv.COLOR_BGR2GRAY)
    faces=face_cascade.detectMultiScale(gray,1.3,5)
    for (x,y,w,h) in faces:
        roiForEyes = gray[y:y+h,x:x+w]
        cv.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
        eyes=eye_cascade.detectMultiScale(roiForEyes)

        for (ex,ey,ew,eh) in eyes:

            mainEyeRegion=gray[eyes[0][1]+y:eyes[0][1]+h+eyes[0][3],eyes[0][0]+x:eyes[0][0]+w+eyes[0][2]]
            # if len(eyes)>0:
            #  cv.imshow('gg',mainEyeRegion)
            ret,eyeFrame=cv.threshold(mainEyeRegion,55,255,cv.THRESH_BINARY)
            if eyeFrame is not None:
             eyeFrame = cv.morphologyEx(eyeFrame, cv.MORPH_CLOSE, windowClose)
             eyeFrame = cv.morphologyEx(eyeFrame, cv.MORPH_ERODE, windowErode)
             eyeFrame = cv.morphologyEx(eyeFrame, cv.MORPH_OPEN, windowOpen)

             im2, contours, hierarchy = cv.findContours(eyeFrame, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

             if len(contours) >= 2:
                 # find biggest blob
                 maxArea = 0
                 MAindex = 0  # to get the unwanted frame
                 distanceX = []  # delete the left most (for right eye)
                 currentIndex = 0
                 for cnt in contours:
                     area = cv.contourArea(cnt)
                     center = cv.moments(cnt)
                     cx, cy = int(center['m10'] ), int(center['m01'] )
                     distanceX.append(cx)
                     if area > maxArea:
                         maxArea = area
                         MAindex = currentIndex
                     currentIndex = currentIndex + 1

                 del contours[MAindex]  # remove the picture frame contour
                 del distanceX[MAindex]

             eye = 'right'

             if len(contours) >= 2:  # delete the left most blob for right eye
                 if eye == 'right':
                     edgeOfEye = distanceX.index(min(distanceX))
                 else:
                     edgeOfEye = distanceX.index(max(distanceX))
                 del contours[edgeOfEye]
                 del distanceX[edgeOfEye]

             if len(contours) >= 1:  # get largest blob
                 maxArea = 0
                 for cnt in contours:
                     area = cv.contourArea(cnt)
                     if area > maxArea:
                         maxArea = area
                         largeBlob = cnt

             if len(largeBlob) > 0:
                 center = cv.moments(largeBlob)
                 cx, cy = int(center['m10'] / center['m00']), int(center['m01'] / center['m00'])
                 cv.circle(eyeFrame, (cx, cy), 5, 255, -1)

             if contours is not None:

              print('circles',len(contours))
              cv.drawContours(frame,contours,-1,(0,0,255),3)
              cv.resizeWindow('eyecontours',400,400)
              cv.imshow('eyecontours',eyeFrame)
             cv.rectangle(frame[y:y+h,x:x+w],(ex,ey),(ex+ew,ey+eh),(255,0,0),2)

    cv.imshow('final',frame)
    cv.waitKey(1)


import datetime
import uuid

from py4web import request, URL
from pydal.validators import *
from .my_validators import IS_ISO_DATETIME, IS_REAL_LIST_OF_EMAILS, IS_DOMAIN

from .components.vueform import VueForm

from .constants import *
from .common import db, session, auth, Field
from .util import random_id
from .common import url_signer
from .models import get_assignment_teachers, set_assignment_teachers, get_user_email
from .util import normalize_email_list
from .settings import MAX_GRADES_24H

FIELDS = [
    Field('name', length=STRING_FIELD_LENGTH, required=True,
          requires=[IS_NOT_EMPTY(), IS_LENGTH(STRING_FIELD_LENGTH)],
          help="Name of the assignment."),  # Assignment name.
    Field('domain_restriction', length=STRING_FIELD_LENGTH,
          requires=IS_DOMAIN(),
          help="If specified, students must use Google accounts from the domain.  For instance, if you specify ucsc.edu as domain restrictions, students must use accounts of the form name@ucsc.edu to participate in the assignment."),
    Field('instructors', length=STRING_FIELD_LENGTH,
          requires=IS_REAL_LIST_OF_EMAILS(),
          help="List of email addresses of additional instructors.  These instructors will be able to view student submissions, but they will not be able to edit the assignment."),
    Field('available_from', 'datetime', required=True, requires=[IS_ISO_DATETIME(), IS_NOT_EMPTY()],
          help="Date from which students can access the assignment."),
    Field('submission_deadline', 'datetime', required=True, requires=[IS_ISO_DATETIME(), IS_NOT_EMPTY()],
          label="Due Date",
          help="Date when students need to submit the assignment for it to be considered submitted on time."),
    Field('available_until', 'datetime', required=True, requires=[IS_ISO_DATETIME(), IS_NOT_EMPTY()],
          help="Date until when student can access the assignment and submit a solution, even if late."),
    Field('max_submissions_in_24h_period', 'integer', default=3, requires=[IS_INT_IN_RANGE(1, MAX_GRADES_24H), IS_NOT_EMPTY()], label="Maximum number of submissions in a 24h period", help="Students will be able to only submit this many solutions in any 24h period."),
]

class AssignmentForm(VueForm):

    def __init__(self, fields, path, **kwargs):
        super().__init__(fields, session, path, auth=auth, db=db, signer=url_signer, **kwargs)

    def read_values(self, record_id):
        values = {}
        assert record_id is not None
        row = self.db.assignment[record_id]
        if row is not None:
            for f_name, f in self.fields.items():
                values[f_name] = f.formatter(row.get(f_name))
            # Reads the additional instructors.
            values['instructors'] = ", ".join(get_assignment_teachers(record_id))
        return values

class AssignmentFormView(AssignmentForm):

    def __init__(self, path, **kwargs):
        super().__init__(FIELDS, path, use_id=True, readonly=True, **kwargs)

class AssignmentFormEdit(AssignmentForm):
    """This class must also enforce the ordering relations between dates."""

    def __init__(self, path, use_id=True, redirect_url=None, readonly=False,
                 validate=None, **kwargs):
        super().__init__(FIELDS, path, use_id=use_id, readonly=readonly,
                         validate=validate or self.validate_dates, **kwargs)
        self.redirect_url = redirect_url

    def validate_dates(self, fields, validated_values):
        d1 = validated_values['available_from']
        d2 = validated_values['submission_deadline']
        d3 = validated_values['available_until']
        errors = {}
        if d2 < d1:
            errors['submission_deadline'] = "The submission deadline should come after the assignment is available"
        if d3 < d2:
            errors['available_until'] = "An assignment should be available at least until its deadline"
        user = get_user_email()
        if user not in validated_values['instructors']:
            validated_values['instructors'].append(user)
        validated_values['instructors'] = normalize_email_list(validated_values['instructors'])
        return errors

    def process_post(self, record_id, validated_values):
        new_instructors = validated_values['instructors']
        user = get_user_email()
        if user not in new_instructors:
            new_instructors.append(user)
        set_assignment_teachers(record_id, new_instructors)
        del validated_values['instructors']
        self.db(self.db.assignment.id == record_id).update(**validated_values)
        return dict(redirect_url=URL(self.redirect_url, record_id))

class AssignmentFormCreate(AssignmentFormEdit):

    def __init__(self, path, redirect_url=None, **kwargs):
        super().__init__(path, use_id=False, readonly=False,
                         validate=self.validate_dates, **kwargs)
        self.redirect_url = redirect_url

    def validate_dates(self, fields, validated_values):
        d1 = validated_values['available_from']
        d2 = validated_values['submission_deadline']
        d3 = validated_values['available_until']
        errors = {}
        if d2 < datetime.datetime.utcnow():
            errors['submission_deadline'] = "The submission deadline should be in the future"
        if d2 < d1:
            errors['submission_deadline'] = "The submission deadline should come after the assignment is available"
        if d3 < d2:
            errors['available_until'] = "An assignment should be available at least until its deadline"
        return errors

    def read_values(self, record_id):
        values = {}
        for f_name, f in self.fields.items():
            values[f_name] = f.formatter(None)
        return values

    def process_post(self, null_record_id, validated_values):
        new_instructors = validated_values['instructors']
        del validated_values['instructors']
        new_id = self.db.assignment.insert(**validated_values)
        user = get_user_email()
        if user not in new_instructors:
            new_instructors.append(user)
        set_assignment_teachers(new_id, new_instructors)
        return dict(redirect_url=URL(self.redirect_url, new_id))


import re
import csv
import requests
from bs4 import BeautifulSoup
from random import choice

COUNTER = 0

def get_proxy():
    html = requests.get('https://free-proxy-list.net/').text
    soup = BeautifulSoup(html, 'lxml')
    trs = soup.find('table', id='proxylisttable').find_all('tr')[50:100]
    proxies = []
    for tr in trs:
        tds = tr.find_all('td')
        ip = tds[0].text.strip()
        port = tds[1].text.strip()
        schema = 'https' if 'yes' in tds[6].text.strip() else 'http'
        proxy = {'schema': schema, 'address': ip + ':' + port}
        proxies.append(proxy)
    return choice(proxies)

def get_html(url):
    p = get_proxy()
    proxy = { p['schema']: p['address']  }
    r = requests.get(url)#, proxies=proxy)
    return r.text if r.ok else print(r.status_code)

def get_categories(url):
  soup = BeautifulSoup(get_html(url), 'lxml')

  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  categories = soup.find('ul', id='menu-list').find_all('a')
  for category in categories[:-1]:
    cat_name = category.text
    cat_link = category.get('href') + '?limit=10000'
    get_products(cat_link)
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

def get_products(url, *args, **kwargs):
  soup = BeautifulSoup(get_html(url), 'lxml')

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  products = soup.find_all('div' ,class_="product-layout")
  for i in products:
    product_link = i.find('div', class_="product-name-modules").a.get('href')
    get_product(product_link)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

def get_product(url, *args, **kwargs):
  soup = BeautifulSoup(get_html(url), 'lxml')

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  panel = soup.find('div', class_='panel panel-default panel-body')
  divs = panel.find_all('div')
  quicks = {}
  for div in divs:
    if div.get('class') and div.get('class')[0].split('-')[0] == 'quick':
      text = div.text.split(':')
      quicks.update({text[0].strip():text[1].strip()})
  articule = quicks.get('Артикул', '')
  name = panel.h1.text
  price_raw = panel.find('ul', class_='list-unstyled')
  try: price_new = price_raw.find('span', class_="price-new").text
  except: price_new = ''
  try: price_old = price_raw.find('span', class_="price-old").text
  except: price_old = ''
  try: action = price_raw.find('span', class_='you-save').text.split(' ')[-1].strip('()')
  except: action = ''
  try: price = price_raw.find('span', class_='price').text
  except: price = ''
  price = price_new or price
  img = []
  main_img = soup.find('a', class_='thumbnail img-responsive card-product').img.get('src')
  img.append(main_img)
  additional_imgs = soup.find_all('a', class_='img-thumbnail thumbnail')
  for i in additional_imgs:
    img.append(i.get('href'))
  manufacturer = quicks.get('Производитель', '')
  country = quicks.get('Страна', '')
  avaliable = quicks.get('Наличие', '')
  category = soup.find('ul', class_='breadcrumb').find_all('li')[1].a.text
  desc = soup.find('div', id='tab-description').text.strip()
  sizes_name = 'Размеры'
  sizes_measurment = 'см'
  sizes = []
  for radio in soup.find_all('div', class_='radio'):
    sizes.append(''.join(radio.text.replace(' ', '').split()))
  # sizes = set(sizes)
  # print(sizes)
  if sizes == []:
    sizes = quicks.get('Размеры', '')
  print(sizes)
  weight = quicks.get('Вес', '')
  extends = quicks.get('Расширение', '')
  material = quicks.get('Материал', '')
  table = soup.find('table', class_='table table-bordered')
  gender = ''
  colour = ''
  wheels = ''
  beauty = 'Нет'
  hand = 'Нет'
  try:
    text = table.text.split()
    if text.index('Кол-во'):
      wheels = text[text.index('Кол-во')+2]
    if text.index('Цвет'):
      colour = text[text.index('Цвет')+1]
      print(colour)
    beauty = 'Да' if 'Бьюти-кейс' in table.text else 'Нет'
    hand = 'Да' if 'Ручная кладь' in table.text else 'Нет'
    gender = ''
  except: pass
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

  data = {
    # основные поля
    'articule':articule,
    'name':name,
    'searches':'',
    'desc':desc,
    'type':'r',
    'price':price.replace('р.',''),
    'price_from':'',
    'currency': 'RUB',
    'measurment_unit':"шт",
    'minimum':'', 'wholesale':'', 'minimums_wholesale':'', 'amount':'',
    'img':[i for i in img],
    'avaliable':'+',#avaliable,
    'action':action, 'action_from':'', 'action_to':'', 'label':'',
    'manufacturer':manufacturer,
    'country':country,
    'HTML_header':'', 'HTML_description':'', 'HTML_keywords':'',
    'gifts':'', 'group_number':'', 'group_name':'', 'subsection_address':'',
    'delivery_possibility':'', 'delivery_terms':'', 'packing':'', 'personal_notes':'',
    'product_link':url,
    'GTIN':'', 'MPN':'',
    'product_id':articule,
    'product_unique_id':'', 'subsection_id':'',
    'group_id':category,
    'species_group_id':'',

    'sizes_name': sizes_name,           # Название_Характеристики
    "sizes_measurment":sizes_measurment,# Измерение_Характеристики
    'sizes':sizes,                      # Значение_Характеристики

    'weight_name': 'Вес',
    "weight_measurment":'кг',
    'weight':weight,

    'extends_name': "Расширение",
    "extends_measurment":"",
    'extends':extends,

    'material_name': "Материал",
    "material_measurment":"",
    'material':material,

    # 'gender_name':'Пол',
    # 'gender_measurment':'',
    # 'gender':gender,

    'wheels_name':"Кол-во колес",
    'wheels_measurment':'',
    'wheels':wheels,

    'colour_name':'Цвет',
    'colour_measurment':'',
    'colour':colour,

    'beauty_name': 'Бьюти-кейс',
    'beauty_measurment': '',
    'beauty': beauty,

    'hand_name': 'Ручная кладь',
    'hand_measurment': '',
    'hand': hand,

  }
  global COUNTER; COUNTER += 1; print(COUNTER);
  print(name)
  print(url)
  write_csv(data)

def write_csv(data):
  with open('raw_blezer.csv', 'a') as f:
      # order = [
      #   'name', 'price', 'desc',
      #   'cat', 'subcat', 'link',
      #   'img_name', 'img_link'
      # ]
      order = list(data.keys())
      writer = csv.DictWriter(f, fieldnames=order)
      writer.writerow(data)

def edit_fields():
  raw_2 = open('raw_blezer2.csv', 'r')
  edited_raw_2 = open('edited_raw_blezer.csv', 'w')
  # for line in f:
  #   print(line)
  c = raw_2.read()
  c = c.replace("['","'")
  c = c.replace("']","'")
  c = c.replace('Чемоданы на колесиках', "9980")
  c = c.replace('Пластиковые чемоданы', "9981")
  c = c.replace('Дорожные саквояжи', "9982")
  c = c.replace('Детские чемоданы', "9983")
  c = c.replace('Детские игрушки', "9984")
  c = c.replace('Сумки на колесиках', "9985")
  c = c.replace('Чемоданы кейс-пилот', "9986")
  c = c.replace('Хозяйственные сумки тележки', "9987")
  c = c.replace('Рюкзаки', "9988")
  c = c.replace('Чехлы для чемоданов', "9989")
  c = c.replace('Детское постельное белье', "9990")
  c = c.replace('Постельное белье', "9991")
  c = c.replace('Сумки для ноутбука', "9992")
  c = c.replace('Комплекты чемоданов', "9993")
  c = c.replace('Мешки для обуви', "9994")
  c = c.replace('Рюкзаки школьные', "9995")
  c = c.replace('Уцененный товар', "9996")
  edited_raw_2.write(c)
  edited_raw_2.close()
  raw_2.close()

def cats():
  url2 = 'https://www.blezer.ru/chemodany_na_kolesikax/'+ '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/plastikovii_chemodan/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/index.php?route=product/category&path=79' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/detskie_chemodani/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/detskie_igrushki/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/symki_na_kolesikah/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/index.php?route=product/category&path=162' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/hozyaistvenie_symki/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/portfel/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/chekhly-dlya-chemodanov/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/detskoe-postelnoe-belie/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/postelnoe-belio/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/index.php?route=product/category&path=157' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/index.php?route=product/category&path=159' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/meshki_dlya_obuvi/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/shkolnye_ryukzaki/' + '?limit=10000'
  get_products(url2)
  url2 = 'https://www.blezer.ru/discounted/' + '?limit=10000'
  get_products(url2)

def solo():
  # url3 = 'https://www.blezer.ru/index.php?route=product/product&path=162&product_id=3351'
  # url3 = 'https://www.blezer.ru/index.php?route=product/product&path=67&product_id=1749'
  # url3 = 'https://www.blezer.ru/plastikovii_chemodan/1203.html'
  # url3 = 'https://www.blezer.ru/index.php?route=product/product&path=79&product_id=673'
  # url3 = 'https://www.blezer.ru/index.php?route=product/product&path=79&product_id=678'
  url3 = 'https://www.blezer.ru/index.php?route=product/product&path=63&product_id=2949'
  get_product(url3)

def main():
  get_categories('https://www.blezer.ru/')

if __name__ == '__main__':
  # main()
  # cats()
  # solo()
  edit_fields()


import json
from database import ForumDB
import requests

TOKEN = "5466989984:AAHIwjOaHUMHPkMNlGqRtta_T8oWx9L_1bg"
URL = "https://api.telegram.org/bot{}/".format(TOKEN)

DB = ForumDB()
last_msg = 'none'

def send_msg(msg):
    url = URL + 'sendMessage?chat_id=224133650&text={}'.format(msg) + '&parse_mode=HTML&reply_markup='
    requests.post(url)

def send_photo(msg):
    try:
        url = URL + 'sendPhoto'
        requests.post(url, {'chat_id': '224133650', }, files = {'photo' : open('static/images/' + msg,"rb")})
    except:
        url = URL + 'sendPhoto'
        requests.post(url, {'chat_id': '224133650', }, files = {'photo' : open('default.png',"rb")})

# check for mistakes if ok add category
def add_category(msg):
    if msg.strip() == '' or len(msg) < 2 or len(msg) > 20 or msg.isalpha() != True:
        send_msg('This name is not valid!')
    else:
        result = DB.add_category(msg.lower())
        send_msg(result)

# check for mistakes if ok edit category
def edit_category(msg):
    try:
        msg = msg.split(',')
        msg[1] = msg[1].lower().strip()
    except:
        send_msg('Invalid input, Please check!')
        return 1

    if msg[0].isdigit() != True or msg[1].isalpha() != True or len(msg[1]) < 2 or len(msg[1]) > 20:
        print(msg[0].isdigit())
        print(msg[1].isalpha())
        print(len(msg[1]) < 2)
        print(len(msg[1]) > 20)
        send_msg('Invalid input, Please check!')
    else:
        result = DB.edit_categ(msg)
        send_msg(result)

# information about user
def user_info(msg):
    result = DB.info_user(msg)
    send_msg(result)
    send_photo(msg + '.png')

def get_updates(offset=None):
    url = URL + "getUpdates?timeout=100"
    if offset:
        url += "&offset={}".format(offset)

    response = requests.get(url)
    content = response.content.decode("utf8")
    return content

def parsing(updates):
    updates = json.loads(updates)
    global last_msg

    if 'entities' in updates['result'][-1]['message']:
        last_msg = updates['result'][-1]['message']['text']

        if updates['result'][-1]['message']['text'] == '/list':
            # selecting the list of all users
            users = DB.select_all_users()
            send_msg(users)

        elif updates['result'][-1]['message']['text'] == '/add':
            send_msg('Enter category name')

        elif updates['result'][-1]['message']['text'] == '/edit':
            category = DB.select_category()
            send_msg(category)
            send_msg('Send № and new name of category \nEx:  1, nature')

        elif updates['result'][-1]['message']['text'] == '/info':
            send_msg("Enter username of person")

    else:
        if last_msg == '/add':
            last_msg = updates['result'][-1]['message']['text']
            # check for mistakes if ok add category
            add_category(last_msg)

        elif last_msg == '/edit':
            last_msg = updates['result'][-1]['message']['text']
            # check for mistakes if ok edit category
            edit_category(last_msg)

        elif last_msg == '/info':
            last_msg = updates['result'][-1]['message']['text']
            # check for mistakes if ok edit category
            user_info(last_msg)

        else:
            last_msg = updates['result'][-1]['message']['text']
            send_msg('Choose command, Bro')

def main():
    last_update_id = None

    while True:
        updates = get_updates(last_update_id)
        if len(json.loads(updates)['result']) > 0:
           last_update_id = json.loads(updates)['result'][-1]['update_id'] + 1
           parsing(updates)

if __name__ == '__main__':
    main()


import datetime

current_Date_Time = datetime.datetime.now()
date = current_Date_Time.date()
year = date.strftime("%Y")
print(f"Current Year -> {year}")
year = int(year)

username = input("What is your username? ")
print(f"Wow that is a nice name {username}")

user_age = input("What is your age? ")
print(f"Dear {username} , {user_age} is the best age?")

user_age = int(user_age)
years_to_100 = 100 - user_age
year_when_100 = year + years_to_100
print(f" after {years_to_100} you be 100 year old in {year_when_100}")
print(sep="\n")

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

room_width = input("please input Room width ")
print(f"Room width is {room_width}")
room_length = input("please input Room length ")
print(f"Room length is{room_length}")
room_height = input("please input Room height ")
print(f"Room height is{room_height}")
room_width = float(room_width)
room_length = float(room_length)
room_height = float(room_height)

room_square_meters = room_width * room_length
room_volume = room_width * room_length * room_height

print(f"room square meters {room_square_meters} and room volume is {room_volume}")

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

user_temperature_C = float(input("What is your temperature in Celsius? "))
user_temperature_F = round((32+user_temperature_C*(9/5)), 2)
print(f"{user_temperature_C} in Celsius is  {user_temperature_F} in Farenheit")


"""empty message

Revision ID: 34a42af4014a
Revises:
Create Date: 2023-09-06 17:37:29.581281

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = '34a42af4014a'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('user', schema=None) as batch_op:
        batch_op.drop_index('email')

    op.drop_table('user')
    op.drop_table('roles_users')
    with op.batch_alter_table('role', schema=None) as batch_op:
        batch_op.drop_index('name')

    op.drop_table('role')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('role',
    sa.Column('id', mysql.INTEGER(), autoincrement=True, nullable=False),
    sa.Column('name', mysql.VARCHAR(length=80), nullable=True),
    sa.Column('description', mysql.VARCHAR(length=255), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    mysql_collate='utf8mb4_0900_ai_ci',
    mysql_default_charset='utf8mb4',
    mysql_engine='InnoDB'
    )
    with op.batch_alter_table('role', schema=None) as batch_op:
        batch_op.create_index('name', ['name'], unique=False)

    op.create_table('roles_users',
    sa.Column('user_id', mysql.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('role_id', mysql.INTEGER(), autoincrement=False, nullable=True),
    sa.ForeignKeyConstraint(['role_id'], ['role.id'], name='roles_users_ibfk_2'),
    sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='roles_users_ibfk_1'),
    mysql_collate='utf8mb4_0900_ai_ci',
    mysql_default_charset='utf8mb4',
    mysql_engine='InnoDB'
    )
    op.create_table('user',
    sa.Column('id', mysql.INTEGER(), autoincrement=True, nullable=False),
    sa.Column('email', mysql.VARCHAR(length=40), nullable=True),
    sa.Column('password', mysql.VARCHAR(length=200), nullable=True),
    sa.Column('name', mysql.VARCHAR(length=30), nullable=True),
    sa.Column('surname', mysql.VARCHAR(length=50), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    mysql_collate='utf8mb4_0900_ai_ci',
    mysql_default_charset='utf8mb4',
    mysql_engine='InnoDB'
    )
    with op.batch_alter_table('user', schema=None) as batch_op:
        batch_op.create_index('email', ['email'], unique=False)

    # ### end Alembic commands ###


"""
ASGI config for optima project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
"""

import os
import dotenv
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from app.middlewares import QueryAuthMiddleware

import app.routing

dotenv.load_dotenv(
    os.path.join(os.path.dirname(os.path.dirname(__file__)), '.env')
)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'optima.settings')

if os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = os.getenv('DJANGO_SETTINGS_MODULE')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    'websocket': QueryAuthMiddleware(
        URLRouter(
            app.routing.ws_urlpatterns
        )
    )
})


import sys
from functools import partial
from defect.circuit import load_circuit
from defect import analysis
import defect.filetypes.internal as fileio
import networkx as nx

EATTR_CHANGE = 'delta'     # float - change in current
EATTR_SOURCE = 'src'       # node - positive-sign source for EATTR_CHANGE
EATTRS = [EATTR_CHANGE, EATTR_SOURCE]
VATTR_POS    = 'pos'       # (x,y) - position (for display)
VATTR_DEFECT = 'newdefect' # bool - was defect introduced between steps?
VATTRS = [VATTR_POS, VATTR_DEFECT]

def main():
	import argparse
	parser = argparse.ArgumentParser()
	add_modes(parser)
	args = parser.parse_args()

	if hasattr(args, 'func'): # workaround for Python 3.3+: http://bugs.python.org/issue16308
		args.func(args)
	else:
		parser.print_usage(file=sys.stderr)
		print('Error: No mode specified', file=sys.stderr)
		sys.exit(1)

def add_modes(parser):
	subparsers = parser.add_subparsers()
	add_generate_mode(subparsers, 'create')
	add_plot_mode(subparsers, 'plot')

def add_generate_mode(subparsers, cmd):
	sub = subparsers.add_parser(cmd, description='generate plot data')
	sub.add_argument('circuit', type=str, help='path to initial circuit')
	sub.add_argument('cyclebasis', type=str, help='path to initial cycles')
	sub.add_argument('gpos', type=str, help='path to gpos file')
	sub.add_argument('results', type=str, help='path to results.json from trial')
	sub.add_argument('trialid', type=int, help='trial index in results.json')
	sub.add_argument('step', type=int, help='trial step for which to compute currents')
	def callback(args):
		data = Data.from_trial_data(
			circuit = load_circuit(args.circuit),
			cycles = fileio.cycles.read_cycles(args.cyclebasis, repeatfirst=True),
			pos = fileio.gpos.read_gpos(args.gpos),
			resultinfo = analysis.read_info(args.results),
			trialid = args.trialid,
			step = args.step,
		)
		# FIXME -- TERRIBLE HACK for obvious reasons
		outpath = args.results[:-len('.results.json')]
		outpath += '-{}-{}-currents.dat'.format(args.trialid, args.step)

		print("Writing to '{}'...".format(outpath))
		data.save(outpath)

	sub.set_defaults(func = callback)

def add_plot_mode(subparsers, cmd):
	sub = subparsers.add_parser(cmd, description='display plot data')
	sub.add_argument('data', type=str, help='path to -currents.dat')
	sub.add_argument('--output', '-o', type=str, default='out.pdf', help='path to plot')
	sub.add_argument('--noshow', dest='show', action='store_false', help='no preview')
	def callback(args):
		data = Data.load(args.data)
		plot_data(data, args.output, args.show)

	sub.set_defaults(func = callback)

class Data:
	def __init__(self, g):
		self.g = g

	@classmethod
	def from_trial_data(cls, circuit, cycles, pos, resultinfo, trialid, step):
		# several parts of this script would require reconsideration to support trials
		# where the vertices weren't actually deleted
		if resultinfo['defect_mode']['mode'] != 'direct removal':
			raise RuntimeError('This script was only written with "remove" mode in mind')

		# Find change in currents
		before = analysis.trial_edge_currents_at_step(circuit, cycles, resultinfo, trialid, step)
		after  = analysis.trial_edge_currents_at_step(circuit, cycles, resultinfo, trialid, step+1)

		before = edict_remove_redundant_entries(before)
		delta  = {e: after.get(e, 0.0) - before[e] for e in before}

		# NOTE: this reconstruction will lack some isolated vertices
		defects = set(get_added_defects(resultinfo, trialid, step))
		defect_dict = {v:False for v in edict_vertices(delta)}
		defect_dict.update({v:True for v in defects})

		sources = {(s,t):s for (s,t) in delta}

		g = nx.Graph()
		g.add_edges_from(delta)
		g.add_nodes_from(defects) # in case any of the defects are isolated vertices

		# ``pos`` contains all vertices from the graph's initial state.  Limit it to those currently
		#  in the modified graph (because set_node_attributes crashes on nodes that don't exist)
		pos = {k:v for k,v in pos.items() if k in g}

		nx.set_edge_attributes(g, EATTR_CHANGE, delta)
		nx.set_edge_attributes(g, EATTR_SOURCE, sources)
		nx.set_node_attributes(g, VATTR_POS, pos)
		nx.set_node_attributes(g, VATTR_DEFECT, defect_dict)
		return cls(g)

	def save(self, path):
		fileio.graph.write_networkx(self.g, path)

	@classmethod
	def load(cls, path):
		g = fileio.graph.read_networkx(path)
		for attr in EATTRS:
			if len(nx.get_edge_attributes(g, attr)) == 0:
				raise RuntimeError('Graph is missing edge attribute {}.'.format(repr(attr)))
		for attr in VATTRS:
			if len(nx.get_node_attributes(g, attr)) == 0:
				raise RuntimeError('Graph is missing node attribute {}.'.format(repr(attr)))
		return cls(g)

# for a dict assigning attributes to an undirected graph, ensure each edge only appears once
def edict_remove_redundant_entries(d):
	d = dict(d)
	for (s,t) in list(d):
		if (s,t) in d and (t,s) in d:
			del d[(t,s)]
	return d

# flatten iterable
def flat(it):
	for x in it: yield from x

# get all vertices that appear in an edge dict
def edict_vertices(d):
	return set(flat(d))

# vertices deleted between step and step+1
def get_added_defects(resultinfo, trialid, step):
	trials = resultinfo['trials']
	trial = trials[trialid]
	arr = analysis.trial_array(trial)
	return arr['deleted'][step+1]

def remove_nodes(it, removed):
	return set(it) - set(removed)

def remove_edges(it, removed):
	it = set(it)
	for s,t in removed:
		it.discard((s,t))
		it.discard((t,s))
	return it

def plot_data(data, path, show):
	import matplotlib.pyplot as plt

	# position attributes
	g = data.g
	pos = nx.get_node_attributes(g, VATTR_POS)
	delta = nx.get_edge_attributes(g, EATTR_CHANGE)

	deleted_dict = nx.get_node_attributes(g, VATTR_DEFECT)

	# things to be used as nodelists and edgelists in draw_networkx
	# (use these when defining e.g. edge_color to ensure order is consistent)
	deleted_nodes = [v for v in g if deleted_dict[v]]
	deleted_edges = [e for e in delta if any(v in deleted_nodes for v in e)] # edges attached to deleted nodes
	remaining_nodes = list(remove_nodes(g, deleted_nodes))
	remaining_edges = list(remove_edges(delta, deleted_edges))

	draw_g = partial(nx.draw_networkx, g, pos=pos, with_labels=False)
	draw_remaining_nodes = partial(draw_g, edgelist=[], nodelist=remaining_nodes)
	draw_deleted_nodes   = partial(draw_g, edgelist=[], nodelist=deleted_nodes)
	draw_remaining_edges = partial(draw_g, nodelist=[], edgelist=remaining_edges)
	draw_deleted_edges   = partial(draw_g, nodelist=[], edgelist=deleted_edges)

	def edge_intensities(es):
		deltas = list(map(delta.__getitem__, es))
		deltas = list(map(abs, deltas))
		delta_max = max(deltas)
		return [max(x / delta_max * 5., 0.25) for x in deltas]

	fig, ax = plt.subplots()
	ax.set_xticks([])
	ax.set_yticks([])
	draw_remaining_edges(ax=ax,
#		edge_color = [abs(ecurrents[0][e] - ecurrents[1][e]) for e in remaining_edges],
#		edge_cmap = mpl.cm.get_cmap('gist_heat_r'),
		width=edge_intensities(remaining_edges),
	)
	draw_deleted_nodes(ax=ax, node_color='g', node_size=40)
	draw_deleted_edges(ax=ax, edge_color='r', width=5.)
#	draw_deleted_edges(ax=ax, edge_color='r', width=list(range(len(deleted_edges))))
	fig.savefig(path)
	if show:
		plt.show()

if __name__ == '__main__':
	main()