from collections import namedtuple

STATEMENT_TYPE_READ_ONLY = "r"
STATEMENT_TYPE_READ_WRITE = "rw"
STATEMENT_TYPE_WRITE_ONLY = "w"
STATEMENT_TYPE_SCHEMA_WRITE = "s"

class ResultSummary(object):
    """ A summary of execution returned with a :class:`.StatementResult` object.
    """

    #: The statement that was executed to produce this result.
    statement = None

    #: Dictionary of parameters passed with the statement.
    parameters = None

    #: The type of statement (``'r'`` = read-only, ``'rw'`` = read/write).
    statement_type = None

    #: A set of statistical information held in a :class:`.Counters` instance.
    counters = None

    #: A :class:`.Plan` instance
    plan = None

    #: A :class:`.ProfiledPlan` instance
    profile = None

    #: Notifications provide extra information for a user executing a statement.
    #: They can be warnings about problematic queries or other valuable information that can be
    #: presented in a client.
    #: Unlike failures or errors, notifications do not affect the execution of a statement.
    notifications = None

    def __init__(self, statement, parameters, **metadata):
        self.statement = statement
        self.parameters = parameters
        self.statement_type = metadata.get("type")
        self.counters = SummaryCounters(metadata.get("stats", {}))
        if "plan" in metadata:
            self.plan = make_plan(metadata["plan"])
        if "profile" in metadata:
            self.profile = make_plan(metadata["profile"])
            self.plan = self.profile
        self.notifications = []
        for notification in metadata.get("notifications", []):
            position = notification.get("position")
            if position is not None:
                position = Position(position["offset"], position["line"], position["column"])
            self.notifications.append(Notification(notification["code"], notification["title"],
                                                   notification["description"], notification["severity"], position))

class SummaryCounters(object):
    """ Set of statistics from a Cypher statement execution.
    """

    #:
    nodes_created = 0

    #:
    nodes_deleted = 0

    #:
    relationships_created = 0

    #:
    relationships_deleted = 0

    #:
    properties_set = 0

    #:
    labels_added = 0

    #:
    labels_removed = 0

    #:
    indexes_added = 0

    #:
    indexes_removed = 0

    #:
    constraints_added = 0

    #:
    constraints_removed = 0

    def __init__(self, statistics):
        for key, value in dict(statistics).items():
            key = key.replace("-", "_")
            setattr(self, key, value)

    def __repr__(self):
        return repr(vars(self))

    @property
    def contains_updates(self):
        return bool(self.nodes_created or self.nodes_deleted or
                    self.relationships_created or self.relationships_deleted or
                    self.properties_set or self.labels_added or self.labels_removed or
                    self.indexes_added or self.indexes_removed or
                    self.constraints_added or self.constraints_removed)

#: A plan describes how the database will execute your statement.
#:
#: operator_type:
#:   the name of the operation performed by the plan
#: identifiers:
#:   the list of identifiers used by this plan
#: arguments:
#:   a dictionary of arguments used in the specific operation performed by the plan
#: children:
#:   a list of sub-plans
Plan = namedtuple("Plan", ("operator_type", "identifiers", "arguments", "children"))

#: A profiled plan describes how the database executed your statement.
#:
#: db_hits:
#:   the number of times this part of the plan touched the underlying data stores
#: rows:
#:   the number of records this part of the plan produced
ProfiledPlan = namedtuple("ProfiledPlan", Plan._fields + ("db_hits", "rows"))

#: Representation for notifications found when executing a statement. A
#: notification can be visualized in a client pinpointing problems or
#: other information about the statement.
#:
#: code:
#:   a notification code for the discovered issue.
#: title:
#:   a short summary of the notification
#: description:
#:   a long description of the notification
#: severity:
#:   the severity level of the notification
#: position:
#:   the position in the statement where this notification points to, if relevant.
Notification = namedtuple("Notification", ("code", "title", "description", "severity", "position"))

#: A position within a statement, consisting of offset, line and column.
#:
#: offset:
#:   the character offset referred to by this position; offset numbers start at 0
#: line:
#:   the line number referred to by the position; line numbers start at 1
#: column:
#:   the column number referred to by the position; column numbers start at 1
Position = namedtuple("Position", ("offset", "line", "column"))

def make_plan(plan_dict):
    """ Construct a Plan or ProfiledPlan from a dictionary of metadata values.

    :param plan_dict:
    :return:
    """
    operator_type = plan_dict["operatorType"]
    identifiers = plan_dict.get("identifiers", [])
    arguments = plan_dict.get("args", [])
    children = [make_plan(child) for child in plan_dict.get("children", [])]
    if "dbHits" in plan_dict or "rows" in plan_dict:
        db_hits = plan_dict.get("dbHits", 0)
        rows = plan_dict.get("rows", 0)
        return ProfiledPlan(operator_type, identifiers, arguments, children, db_hits, rows)
    else:
        return Plan(operator_type, identifiers, arguments, children)


import chevron
import pickle
from pathlib import Path
from .recipient import Recipient

from .common import print_err, parse_yaml, Config

SCHEME_ENV = 'COLORSCHEME'

class Colors:

    def __init__(self, dir):
        self.pickle_file = dir / '.current'
        self.cfg = self.__get_config(dir)
        self.schemes = self.__fetch_schemes(dir)
        self.templates = self.__fetch_templates(dir)
        self.current = self.__get_current()

    def __get_config(self, dir: Path):
        config_path = dir / 'config.yaml'
        if config_path.is_file():
            return Config(config_path)
        else:
            print_err(f'"config.yaml" not found in "{dir}"\nAborted')

    def __get_current(self):
        if self.pickle_file.is_file():
            with self.pickle_file.open("rb") as f:
                current = pickle.load(f)
        else:
            current = None

        return current

    def __fetch_schemes(self, dir: Path):
        scheme_dir = dir / 'schemes'
        if scheme_dir.is_dir():
            schemes = {}
            for child in scheme_dir.iterdir():
                items = parse_yaml(child)
                schemes[child.stem] = items

            return schemes
        else:
            print_err(f'No scheme directory found in "{dir}"')

    def __fetch_templates(self, dir):
        template_dir = dir / 'templates'
        if template_dir.is_dir():
            templates = {}
            for child in template_dir.iterdir():
                with child.open() as f:
                    templates[child.stem] = f.read()
            return templates
        else:
            print_err(f'No scheme directory found in "{dir}"')

    def get(self, name):
        if name in self.schemes:
            return self.schemes[name]
        else:
            print_err(f'Colorscheme {name} not found')

    def list(self):
        for name in self.schemes:
            if name == self.current:
                print(f'-> {name}')
            else:
                print(f'   {name}')

    def inject(self, name, verbose=False):
        completed = []
        failed = []

        if name in self.schemes:
            scheme = self.schemes[name]

            for program_name, content in self.templates.items():
                if program_name in self.cfg.PATHS:
                    recipient_path = Path(self.cfg.PATHS[program_name])
                    data = chevron.render(content, scheme)

                    r = Recipient(recipient_path, data)
                    r.write()

                    completed.append(program_name)
                else:
                    failed.append(program_name)

            if verbose:
                if len(completed) > 0:
                    print(f'Updated: {", ".join(completed)}')

                if len(failed) > 0:
                    print(f'No configuration file found: {", ".join(failed)}')
        else:
            print_err(f'Colorscheme "{name}" not found.')

        self.__save(name)

    def __save(self, name):
        if name in self.schemes:
            self.current = name
            print(f'-> {self.current}')

            with self.pickle_file.open("wb+") as f:
                pickle.dump(self.current, f)


import argparse
import math

def is_pos_num(x, try_float):
    if x is None:
        return False
    try:
        x_num = float(x) if try_float else int(x)
        return x_num >= 0
    except ValueError:
        return False

def valid_args(t_, p_, n_, i_, a_):
    if (t_ != "diff" and t_ != "annuity") or not is_pos_num(i_, True):
        return False
    count = (p_ is not None) + (n_ is not None) + (a_ is not None)
    if (t_ == "diff" and a_ is not None) or count != 2:
        return False
    if p_ is not None and not is_pos_num(p_, False):
        return False
    if n_ is not None and not is_pos_num(n_, False):
        return False
    if a_ is not None and not is_pos_num(a_, False):
        return False
    return True

parser = argparse.ArgumentParser()
parser.add_argument("--type")
parser.add_argument("--principal")
parser.add_argument("--periods")
parser.add_argument("--interest")
parser.add_argument("--payment")
args = parser.parse_args()

t = args.type
p = args.principal
n = args.periods
i = args.interest
a = args.payment

if not valid_args(t, p, n, i, a):
    print("Incorrect parameters")
else:
    i = float(i) / 1200
    a = int(a) if a else None
    p = int(p) if p else None
    n = int(n) if n else None
    if t == "diff":
        total_payment = 0
        for m in range(1, n + 1):
            payment = math.ceil(p / n + i * (p - (p * (m - 1)) / n))
            total_payment += payment
            print(f"Month {m}: payment is {payment}")
        print(f"\nOverpayment = {total_payment - p}")
    else:
        if not p:
            p = math.floor(a / ((i * (1 + i) ** n) / ((1 + i) ** n - 1)))
            print(f"Your loan principal = {p}!")
        elif not a:
            a = math.ceil(p * (i * (1 + i) ** n) / ((1 + i) ** n - 1))
            print(f"Your monthly payment = {a}!")
        else:
            n = math.ceil(math.log(a / (a - i * p), 1 + i))
            years = n // 12
            months = n % 12
            time = "" if years == 0 else f"{years} years"
            if years and months:
                time += " and "
            time += f"{months} months" if months else ""
            print(f"It will take {time} to repay this loan!")
        print(f"Overpayment = {a * n - p}")


from alembic import command
from alembic.config import Config

from config import env
from model import db_conn_str

def up_migrate(version="heads"):
    alembic_cfg = Config()
    alembic_cfg.set_main_option('script_location', env.get_str("db.migrations.path"))
    alembic_cfg.set_main_option('sqlalchemy.url', db_conn_str)
    command.upgrade(alembic_cfg, version)

def down_migrate(version="0000_base_line"):
    alembic_cfg = Config()
    alembic_cfg.set_main_option('script_location', env.get_str("db.migrations.path"))
    alembic_cfg.set_main_option('sqlalchemy.url', db_conn_str)
    command.downgrade(alembic_cfg, version)


# -*- coding: utf-8 -*-
#harvest theses from Sussex U.
#FS: 2020-03-23
#FS: 2022-12-21

import sys
import os
import urllib.request, urllib.error, urllib.parse
from bs4 import BeautifulSoup
import re
import ejlmod3
import time

publisher = 'Sussex U.'
hdr = {'User-Agent' : 'Magic Browser'}

skipalreadyharvested = True
boring = ['Media and Film', 'Management', 'Media and Cultural Studies', 'Accounting and finance',
          'Accounting and Finance', 'American studies', 'Anthropology', 'Art History',
          'Biochemistry', 'Biology', 'Chemistry', 'Development Studies', 'Economics', 'Education',
          'Engineering', 'English', 'Genome stability', 'Geography', 'History',
          'Institute of Development Studies', 'International Development', 'International Relations',
          'Law', 'Life Sciences', 'Media and film', 'Music', 'Neuroscience', 'Philosophy',
          'Politics', 'Psychology', 'Science policy research unit', 'Social work', 'Social Work',
          'Sociology', '|SPRU - Science Policy Research Unit', 'SPRU - Science Policy Research Unit']
prerecs = []
jnlfilename = 'THESES-SUSSEX-%s' % (ejlmod3.stampoftoday())

if skipalreadyharvested:
    alreadyharvested = ejlmod3.getalreadyharvested(jnlfilename)

for year in [ejlmod3.year(), ejlmod3.year(backwards=1)]:
#    for (fc, dep) in [('', 'd234'), ('m', 'd235')]:
#        tocurl = 'http://sro.sussex.ac.uk/view/divisions/%s/%i.html' % (dep, year)
    tocurl = 'http://sro.sussex.ac.uk/view/type/thesis/%i.html' % (year)
    print(tocurl)
    try:
        req = urllib.request.Request(tocurl, headers=hdr)
        tocpage = BeautifulSoup(urllib.request.urlopen(req), features="lxml")
        time.sleep(2)
    except:
        continue
    for p in tocpage.find_all('p'):
        if re.search('PhD', p.text):
            for a in p.find_all('a'):
                if a.has_attr('href'):
                    rec = {'tc' : 'T', 'jnl' : 'BOOK', 'link' : a['href'], 'note' : []}
                    rec['tit'] = a.text.strip()
                    rec['doi'] = '20.2000/UCLodon/' + re.sub('\D', '', a['href'])
                    if ejlmod3.checkinterestingDOI(rec['doi']):
                        if not skipalreadyharvested or not rec['doi'] in alreadyharvested:
                            prerecs.append(rec)
    print('  %4i records so far' % (len(prerecs)))

recs = []
i = 0
for rec in prerecs:
    keepit = True
    i += 1
    ejlmod3.printprogress('-', [[i, len(prerecs)], [rec['link']], [len(recs)]])
    try:
        artpage = BeautifulSoup(urllib.request.build_opener(urllib.request.HTTPCookieProcessor).open(rec['link']), features="lxml")
        time.sleep(10)
    except:
        try:
            print('retry %s in 180 seconds' % (rec['link']))
            time.sleep(180)
            artpage = BeautifulSoup(urllib.request.build_opener(urllib.request.HTTPCookieProcessor).open(rec['link']), features="lxml")
        except:
            print('no access to %s' % (rec['link']))
            continue
    ejlmod3.metatagcheck(rec, artpage, ['eprints.creators_name', 'eprints.creators_orcid',
                                        'eprints.keywords', 'eprints.abstract',
                                        'eprints.date', 'eprints.doi', 'eprints.pages'])
    rec['autaff'][-1].append(publisher)
    for meta in artpage.head.find_all('meta'):
        if meta.has_attr('name'):
            #PDF
            if meta['name'] == 'DC.identifier':
                if re.search('pdf$', meta['content']):
                    rec['hidden'] = meta['content']
            #PDF
            elif meta['name'] == 'eprints.thesis_award':
                rec['note'].append(meta['content'])
            #department
            elif meta['name'] == 'eprints.department':
                dep = meta['content']
                if dep in boring:
                    keepit = False
                elif dep == 'Astronomy':
                    rec['fc'] = 'a'
                elif dep == 'Mathematics':
                    rec['fc'] = 'm'
                elif dep == 'Informatics':
                    rec['fc'] = 'c'
                elif not dep in ['Physics']:
                    rec['note'].append('DEP=' + dep)
    if keepit:
        ejlmod3.printrecsummary(rec)
        recs.append(rec)
    else:
        ejlmod3.adduninterestingDOI(rec['doi'])

ejlmod3.writenewXML(recs, publisher, jnlfilename)


from functools import wraps
from flask import request
from utils.function_jwt import validate_token

def verify_token_middleware(func):
    @wraps(func)
    def decorated_function(*args, **kwargs):
        token = request.headers["Authorization"].split(" ")[1]
        response = validate_token(token, output=False)

        if(response):
            return response
        return func(*args, **kwargs)
    return decorated_function


import cv2

def b_pre_processamento(img,s):
    # Transforma a imagem em tons de cinza
    imgCinza = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # Histograma da imagem
    clahe = cv2.createCLAHE(clipLimit=1.0, tileGridSize=(8,8))
    imgCinza = clahe.apply(imgCinza)

    # Suavizacao da imagem
    #imgSuav = cv2.GaussianBlur(imgCinza, (1, 1), 1)
    imgSuav = cv2.bilateralFilter(imgCinza, s[0], s[1], s[2])#Bilateral
    #imgSuav = cv2.medianBlur(imgCinza,3)
    #imgSuav = cv2.blur(imgCinza,(7,7))

    return imgSuav


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

from common.forms import TelefonoForm
from common.models import Telefono, ViewPort
from common.utils import direct_response, json_response
from django.forms.models import modelformset_factory
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.contrib.sites.models import Site
from django.db.models.aggregates import Min
from portal.forms import BusquedaForm, ContactoForm, ChatForm
from portal.models import Inmobiliaria, Area
from proyectos.models import Aviso, Proyecto, Desarrollado
from usuarios.forms import AreaInteresForm
from usuarios.models import AdminHelpDesk

def inicio(request):
    """
    Vista de inicio
    """
    return direct_response(request, 'portal/inicio.html',
                           {'destacados': Proyecto.get_destacados(4),
                            'form': BusquedaForm(),
                            'rango_renta': Proyecto.get_rango_precio(u"R"),
                            'rango_venta': Proyecto.get_rango_precio(u"V"),})

@csrf_exempt
def chat(request):
    """
    Chat con los administradores de servicio
    """
    if request.method == "POST":
        form_chat = ChatForm(request.POST)
        if form_chat.is_valid():

            return direct_response(request, "portal/iframes/chat.html",
                    {'form_chat': form_chat})
    else:
        form_chat = ChatForm()

    return direct_response(request, "portal/iframes/chat.html",
                           {'form_chat': form_chat})

def ayuda_en_linea(request, id_area, usuario):
    """
    Crea un canal de chat con uno de lso administradores y registra a ambos
    usuarios para comenzar el chat
    """
    area = get_object_or_404(Area, id=id_area)

    return direct_response(request, 'portal/ayuda_en_linea.html',
            {'port': 9000,
             'hostname': Site.objects.get_current().name,
             'area': area,
             'manager': AdminHelpDesk.get_area_manager(area),
             'usuario': usuario})

# TODO: Colocar las ayudas en flatpages
def ayuda(request, template):
    """
    Carga una página de ayuda
    """
    return direct_response(request, template)

def nosotros(request):
    """
    Vista informativa con datos de la inmobiliaria
    """
    return direct_response(request, 'portal/nosotros.html',
                           {'desarrollados': Desarrollado.objects.all(),
                            'inmobiliaria': Inmobiliaria.objects.latest("id")})

@csrf_exempt
def contacto(request):
    """
    Formulario de contacto
    """
    AreasFormSet = modelformset_factory(ViewPort, form=AreaInteresForm, extra=0)
    TelefonoFormSet = modelformset_factory(Telefono, form=TelefonoForm)
    if request.method == 'POST' and "contacto_submit" in request.POST:
        form = ContactoForm(request.POST)
        formset_areas = AreasFormSet(request.POST, prefix="area")
        formset_telefonos = TelefonoFormSet(request.POST, prefix="tel")
        if form.is_valid() and formset_telefonos.is_valid() and \
           formset_areas.is_valid():
            form.save(request, formset_telefonos, formset_areas)

            return direct_response(request, 'portal/contacto_exito.html')
    elif request.method == "POST" and "contacto_proyecto_id" in request.POST:
        proyecto = Proyecto.objects.get(id=request.POST["contacto_proyecto_id"])
        form = ContactoForm(initial={'proyecto': proyecto.id,
                                     "rubros_interes": [proyecto.rubro]})
    else:
        form = ContactoForm()
    formset_areas = AreasFormSet(queryset=ViewPort.objects.none(),
                                 prefix="area")
    formset_telefonos = TelefonoFormSet(queryset=Telefono.objects.none(),
        prefix="tel")

    return direct_response(request, 'portal/contacto.html',
                           {'form': form,
                            'formset_telefonos': formset_telefonos,
                            'formset_areas': formset_areas})

def json_get_aviso(request):
    """
    Devuelve un aviso según el indice enviado
    """
    if request.method == 'GET' and "index" in request.GET:
        total = Aviso.objects.all().count()
        min_id = Aviso.objects.aggregate(Min("id"))['id__min']
        if total:
            aviso = Aviso.objects.get(id=(int(request.GET['index'])%total)+min_id)
            data = {
                'url': aviso.proyecto.get_absolute_url(),
                'aviso': aviso.get_archivo_html(),
                'duracion': aviso.duracion,
                'status': True,
            }
            return json_response(data)
        else:
            return json_response({'status': False,})
    else:
        return json_response({})

def google_webmaster_verification(request):
    """
    Vista para verificar la propiedad del dominio de quimerainmobiliaria
    """
    return direct_response(request, "portal/google_verification.html")


import graphene
import pytest

from .....order import OrderStatus
from .....order.error_codes import OrderErrorCode
from ....tests.utils import get_graphql_content

def test_draft_order_delete(staff_api_client, permission_manage_orders, draft_order):
    order = draft_order
    query = """
        mutation draftDelete($id: ID!) {
            draftOrderDelete(id: $id) {
                order {
                    id
                }
            }
        }
        """
    order_id = graphene.Node.to_global_id("Order", order.id)
    variables = {"id": order_id}
    staff_api_client.post_graphql(
        query, variables, permissions=[permission_manage_orders]
    )
    with pytest.raises(order._meta.model.DoesNotExist):
        order.refresh_from_db()

def test_draft_order_delete_product(
    app_api_client, permission_manage_products, draft_order
):
    query = """
        mutation DeleteProduct($id: ID!) {
          productDelete(id: $id) {
            product {
              id
            }
          }
        }
    """
    order = draft_order
    line = order.lines.first()
    product = line.variant.product
    product_id = graphene.Node.to_global_id("Product", product.id)
    variables = {"id": product_id}
    response = app_api_client.post_graphql(
        query, variables, permissions=[permission_manage_products]
    )
    content = get_graphql_content(response)
    assert content["data"]["productDelete"]["product"]["id"] == product_id

@pytest.mark.parametrize(
    "order_status",
    [
        OrderStatus.UNFULFILLED,
        OrderStatus.UNCONFIRMED,
        OrderStatus.CANCELED,
        OrderStatus.PARTIALLY_FULFILLED,
        OrderStatus.FULFILLED,
        OrderStatus.PARTIALLY_RETURNED,
        OrderStatus.RETURNED,
    ],
)
def test_draft_order_delete_non_draft_order(
    staff_api_client, permission_manage_orders, order_with_lines, order_status
):
    order = order_with_lines
    order.status = order_status
    order.save(update_fields=["status"])
    query = """
        mutation draftDelete($id: ID!) {
            draftOrderDelete(id: $id) {
                order {
                    id
                }
                errors {
                    code
                    field
                }
            }
        }
        """
    order_id = graphene.Node.to_global_id("Order", order.id)
    variables = {"id": order_id}
    response = staff_api_client.post_graphql(
        query, variables, permissions=[permission_manage_orders]
    )
    content = get_graphql_content(response)
    account_errors = content["data"]["draftOrderDelete"]["errors"]
    assert len(account_errors) == 1
    assert account_errors[0]["field"] == "id"
    assert account_errors[0]["code"] == OrderErrorCode.INVALID.name

DRAFT_ORDER_DELETE_BY_EXTERNAL_REFERENCE = """
    mutation draftDelete($id: ID, $externalReference: String) {
        draftOrderDelete(id: $id, externalReference: $externalReference) {
            order {
                id
                externalReference
            }
            errors {
                field
                message
        }
    }
}
"""

def test_draft_order_delete_by_external_reference(
    staff_api_client, permission_manage_orders, draft_order
):
    # given
    order = draft_order
    query = DRAFT_ORDER_DELETE_BY_EXTERNAL_REFERENCE
    ext_ref = "test-ext-ref"
    order.external_reference = ext_ref
    order.save(update_fields=["external_reference"])
    variables = {"externalReference": ext_ref}

    # when
    response = staff_api_client.post_graphql(
        query, variables, permissions=[permission_manage_orders]
    )
    content = get_graphql_content(response)

    # then
    data = content["data"]["draftOrderDelete"]
    with pytest.raises(order._meta.model.DoesNotExist):
        order.refresh_from_db()
    assert graphene.Node.to_global_id("Order", order.id) == data["order"]["id"]
    assert data["order"]["externalReference"] == order.external_reference

def test_draft_order_delete_by_both_id_and_external_reference(
    staff_api_client, permission_manage_orders
):
    # given
    query = DRAFT_ORDER_DELETE_BY_EXTERNAL_REFERENCE
    variables = {"externalReference": "whatever", "id": "whatever"}

    # when
    response = staff_api_client.post_graphql(
        query, variables, permissions=[permission_manage_orders]
    )
    content = get_graphql_content(response)

    # then
    errors = content["data"]["draftOrderDelete"]["errors"]
    assert (
        errors[0]["message"]
        == "Argument 'id' cannot be combined with 'external_reference'"
    )

def test_draft_order_delete_by_external_reference_not_existing(
    staff_api_client, permission_manage_orders
):
    # given
    query = DRAFT_ORDER_DELETE_BY_EXTERNAL_REFERENCE
    ext_ref = "non-existing-ext-ref"
    variables = {"externalReference": ext_ref}

    # when
    response = staff_api_client.post_graphql(
        query, variables, permissions=[permission_manage_orders]
    )
    content = get_graphql_content(response)

    # then
    errors = content["data"]["draftOrderDelete"]["errors"]
    assert errors[0]["message"] == f"Couldn't resolve to a node: {ext_ref}"


import sys
from typing import List

def find_increased(input: List) -> int:
    depth_increased = 0

    current_count = None
    previous_count = None

    for current_count in input:
        if previous_count and \
            current_count > previous_count:
                depth_increased += 1
        previous_count = current_count

    return depth_increased

def find_increased_sliding_window(input: List) -> int:
    depth_increased = 0
    window = []
    for count in input:
        window.append(count)
        if len(window) < 4:
            continue
        elif len(window) == 5:
            window.pop(0)

        a_sum = sum(window[:-1])  # First Window (AAA)
        b_sum = sum(window[1:])  # Second Window (BBB)

        if b_sum > a_sum:
            depth_increased += 1

    return depth_increased

if __name__ == "__main__":
    in_file = sys.argv[1]
    with open(in_file) as f:
        input = f.readlines()

    input_array = []
    for line in input:
        if line:
            entry = int(str(line.strip()))
            input_array.append(entry)

    num_increased = find_increased(input_array)
    print(num_increased)

    num_increased = find_increased_sliding_window(input_array)
    print(num_increased)


from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.database.database import global_init
from app.routers import auth, profile, project, yandex, industry, vacancy

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # WARN: development only
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(profile.router, prefix="/profile", tags=["profile"])
app.include_router(project.router, prefix="/project", tags=["project"])
app.include_router(auth.router, prefix="/auth", tags=["auth"])
app.include_router(yandex.router, prefix="/yandex", tags=["oauth", "yandex"])
app.include_router(industry.router, prefix="/industry", tags=["industry"])
app.include_router(vacancy.router, prefix="/vacancy", tags=["vacancy"])

@app.on_event("startup")
async def init_database_on_startup():
    global_init()

@app.get("/")
async def healthcheck_index():
    return {"success": True}


import random
import os
import discord
import asyncio
from discord import app_commands
from discord.ext import commands

# __file__ = 현재 이 파일의 경로
# os.path.dirname(xxx) = xxx가 속해있는 디렉토리의 경로
PATH = os.path.dirname(__file__)
# 봇
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='^', intents=intents)
with open(os.path.join(PATH, 'token.txt'), 'r') as f:
    TOKEN = f.read()
    # token.txt에 봇의 토큰을 입력해주세요.

async def main():
    dir = os.listdir('Cogs')
    for py in dir:
        if py.endswith('.py'):
            await bot.load_extension(f'Cogs.{py[:-3]}')

# guilds.txt에 서버 ID를 한 줄씩 적어주세요.
with open(os.path.join(PATH, 'guilds.txt'), 'r') as f:
    GUILDS = list(f.read().split('\n'))
GUILDS = [discord.Object(id=i) for i in GUILDS]

# 함수
def dice(min, max, num):
    if num <= 1:
        result = random.randrange(min, max + 1)
        text = f'{min}~{max} 사이의 주사위를 굴려 {result}(이)가 나왔습니다.'
    else:
        textList = [f'다음은 {min}~{max} 사이의 주사위를 {num}개 굴린 결과입니다.']
        for i in range(1, num+1):
            result = random.randrange(min, max + 1)
            textList.append(f'{i}번째 주사위: {result}')
        text = '\n'.join(textList)
    return text

@bot.event
async def on_ready():
    for guild in GUILDS:
        await bot.tree.sync(guild=guild)
    print('Logged in as')
    print(bot.user.name)
    print(bot.user.id)
    print('------')

@bot.tree.command(name='주사위', description='주사위를 굴립니다.', guilds=GUILDS)
@app_commands.describe(min='주사위의 최소치입니다.', max='주사위의 최대치입니다.', num='주사위의 개수입니다. 기본값은 1입니다.')
async def rollDice(interaction: discord.Interaction, min: int, max: int, num: int = 1):
    await interaction.response.send_message(dice(min, max, num))

@bot.command(name='주사위')
async def rollDice2(ctx, min: int, max: int, num: int = 1):
    await ctx.send(dice(min, max, num), reference=ctx.message, mention_author=False)

@commands.command(name='어')
async def howDoThis(self, ctx):
    await ctx.message.delete()
    await ctx.send('```어떻게 하시겠습니까?```')

asyncio.run(main())
bot.run(TOKEN)


import os
import io
import shutil
import time

import logging
from botocore.client import Config
from botocore.exceptions import ClientError
import boto3
import json
import datetime
from contextlib import contextmanager
from tempfile import mkdtemp

logging.getLogger('botocore').setLevel(logging.INFO)

@contextmanager
def temp_dir(*args, **kwargs):
    dir = mkdtemp(*args, **kwargs)
    try:
        yield dir
    except Exception:
        if os.path.exists(dir):
            os.rmdir(dir)
        raise

@contextmanager
def temp_file(*args, **kwargs):
    with temp_dir(*args, **kwargs) as dir:
        file = os.path.join(dir, "temp")
        try:
            yield file
        except Exception:
            if os.path.exists(file):
                os.unlink(file)
            raise

# def download(s3, object_name, file_name):
#     res = s3.get_object(Bucket=bucket, Key=object_name)
#     with open(file_name, "wb") as f:
#         f.write(res["Body"].read())
#     return bool(res)
#
#
# @contextlib.contextmanager
# def temp_download(s3, object_name):
#     with temp_file() as file_name:
#         download(s3, bucket, object_name, file_name)
#         yield file_name

# @contextlib.contextmanager
# def csv_writer(s3, object_name, public_bucket=False):
#     with temp_file() as filename:
#         with open(filename, "w") as f:
#             yield csv.writer(f)
#         write(s3, bucket, object_name, file_name=filename, public_bucket=public_bucket)

class FileBasedStorage:

    def __init__(self):
        self.base_path = '/var/datapackages/budgetkey-files/'

    def get_path(self, object_name):
        path = os.path.join(self.base_path, object_name)
        return path

    def exists(self, object_name, min_size=None):
        path = self.get_path(object_name)
        if os.path.exists(path):
            if os.path.isfile(path):
                s = os.lstat(path).st_size
                if min_size is not None:
                    return s > min_size
                else:
                    return True
        return False

    @staticmethod
    def get_read_object_data(data):
        return io.BytesIO(data)

    @staticmethod
    def get_write_object_data(data):
        if isinstance(data, str):
            data = data.encode()
        return io.BytesIO(data)

    def write(self, object_name, data=None, file_name=None):
        path = self.get_path(object_name)
        os.makedirs(os.path.dirname(path), exist_ok=True)
        if file_name is not None and data is None:
            shutil.copy(file_name, path)
        elif data is not None and file_name is None:
            with open(path, 'w') as o:
                o.write(data)
        else:
            raise AttributeError()
        return path

    def delete(self, object_name):
        if self.exists(object_name):
            self.internal_delete(object_name)

    def internal_delete(self, object_name):
        path = self.get_path(object_name)
        os.unlink(path)

class ObjectStorage(FileBasedStorage):

    def __init__(self):
        super(ObjectStorage, self).__init__()
        self.bucket_name = 'budgetkey-files'
        config = Config(signature_version=os.environ["S3_SIGNATURE_VERSION"]) if os.environ.get("S3_SIGNATURE_VERSION") else None
        self.s3 = False
        self.s3_endpoint_url = os.environ.get("S3_ENDPOINT_URL", 'https://s3.amazonaws.com')
        if os.environ.get("AWS_ACCESS_KEY_ID") and os.environ.get("AWS_SECRET_ACCESS_KEY"):
            self.s3 = boto3.client('s3',
                                   endpoint_url=self.s3_endpoint_url,
                                   aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
                                   aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
                                   config=config,
                                   region_name=os.environ.get("S3_REGION"))

    def urlfor(self, object_name):
        return os.path.join(self.s3_endpoint_url, self.bucket_name, object_name)

    def exists(self, object_name, min_size=None):
        if not self.s3:
            return super(ObjectStorage, self).exists(object_name, min_size)
        try:
            res = self.s3.head_object(Bucket=self.bucket_name, Key=object_name)
        except Exception:
            res = False
        if res and min_size:
            return res['ContentLength'] > min_size
        else:
            return bool(res)

    def write(self, object_name, data=None, file_name=None, create_bucket=True, public_bucket=False, content_type=None, attempt=0):
        addtional_attrs = {}
        if content_type is not None:
            addtional_attrs['ContentType'] = content_type
        if not self.s3:
            return super(ObjectStorage, self).write(object_name, data, file_name)
        try:
            if file_name is not None and data is None:
                self.s3.put_object(Body=open(file_name, 'rb'), Bucket=self.bucket_name, Key=object_name, ACL='public-read', **addtional_attrs)
            elif data is not None and file_name is None:
                self.s3.put_object(Body=self.get_write_object_data(data), Bucket=self.bucket_name, Key=object_name, ACL='public-read', **addtional_attrs)
            else:
                raise AttributeError()
            return self.urlfor(object_name)
        except ClientError as e:
            logging.exception('Error WRITING')
            if attempt == 0:
                logging.info('RETRYING IN A MINUTE')
                time.sleep(60)
                return self.write(
                    object_name, data=data, file_name=file_name,
                    create_bucket=create_bucket, public_bucket=public_bucket,
                    content_type=content_type, attempt=attempt+1)

            elif create_bucket:
                self.s3.create_bucket(Bucket=self.bucket_name)
                if public_bucket:
                    try:
                        self.s3.put_bucket_policy(Bucket=self.bucket_name, Policy=json.dumps({
                            "Version": str(datetime.datetime.now()).replace(" ", "-"),
                            "Statement": [{"Sid": "AddPerm", "Effect": "Allow", "Principal": "*",
                                           "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::{}/*".format(self.bucket_name)]}]}))
                    except ClientError as e2:
                        logging.exception('Failed to put bucket policy', exc_info=e2)
                        pass
                return self.write(
                    object_name, data=data, file_name=file_name,
                    create_bucket=False, public_bucket=public_bucket,
                    content_type=content_type, attempt=attempt)
            else:
                raise

    def internal_delete(self, object_name):
        self.s3.delete_object(Bucket=self.bucket_name, Key=object_name)

#
# def read(s3, bucket, object_name):
#     res = s3.get_object(Bucket=bucket, Key=object_name)
#     return res["Body"].read()
#
#
object_storage = ObjectStorage()


## U-NET# MODEL

## Imports + seed

# Common
import random
import numpy as np
import tensorflow as tf

import keras
from keras.layers import concatenate, Activation, Conv2D, Input, MaxPool2D, UpSampling2D
from keras.models import Model

seed = 2019
random.seed = seed
np.random.seed = seed
tf.seed = seed

# Image size
SIZE = 512
INPUT_SHAPE = (SIZE, SIZE, 1)

# Blocks
def conv_batchnorm_relu_block(tensor, f):

    x = Conv2D(f, (3, 3), padding='same', strides=1) (tensor)
    x = Activation('relu') (x)
    x = Conv2D(f, (3, 3), padding='same', strides=1) (x)
    x = Activation('relu') (x)

    return x

# U-Net# Model
def UNetSharp(INPUT_SHAPE = INPUT_SHAPE):

    f = [8, 16, 32, 64, 128]

    inputs = Input(INPUT_SHAPE, name = 'input')

    conv1_1 = conv_batchnorm_relu_block(inputs, f=f[0])
    pool1 = MaxPool2D((2,2), (2,2), name='maxpool1') (conv1_1)

    conv2_1 = conv_batchnorm_relu_block(pool1, f=f[1])
    pool2 = MaxPool2D((2,2), (2,2), name='maxpool2') (conv2_1)

    up1_2 = UpSampling2D((2,2), interpolation='bilinear', name='up12') (conv2_1)
    conv1_2 = concatenate([up1_2, conv1_1], name='merge12')
    conv1_2 = conv_batchnorm_relu_block(conv1_2,  f=f[0])

    conv3_1 = conv_batchnorm_relu_block(pool2, f=f[2])
    pool3 = MaxPool2D((2,2), (2,2), name='maxpool3') (conv3_1)
    conv3_1_1_3 = UpSampling2D((4,4), interpolation='bilinear') (conv3_1)

    up2_2 = UpSampling2D((2,2), interpolation='bilinear', name='up22') (conv3_1)
    conv2_2 = concatenate([up2_2, conv2_1], name='merge22')
    conv2_2 = conv_batchnorm_relu_block(conv2_2, f=f[1])

    up1_3 = UpSampling2D((2,2), interpolation='bilinear', name='up13') (conv2_2)
    conv1_3 = concatenate([up1_3, conv1_1, conv1_2, conv3_1_1_3], name='merge13')
    conv1_3 = conv_batchnorm_relu_block(conv1_3, f=f[0])

    conv4_1 = conv_batchnorm_relu_block(pool3, f=f[3])
    conv4_1_2_3 = UpSampling2D((4,4), interpolation='bilinear') (conv4_1)
    conv4_1_1_4 = UpSampling2D((8,8), interpolation='bilinear') (conv4_1)
    pool4 = MaxPool2D((2,2), (2,2), name='maxpool4') (conv4_1)

    up3_2 = UpSampling2D((2,2), interpolation='bilinear', name='up32') (conv4_1)
    conv3_2 = concatenate([up3_2, conv3_1], name='merge32')
    conv3_2 = conv_batchnorm_relu_block(conv3_2, f=f[2])
    conv3_2_1_4 = UpSampling2D((4,4), interpolation='bilinear') (conv3_2)

    up2_3 = UpSampling2D((2,2), interpolation='bilinear', name='up23') (conv3_2)
    conv2_3 = concatenate([up2_3, conv2_1, conv2_2, conv4_1_2_3], name='merge23')
    conv2_3 = conv_batchnorm_relu_block(conv2_3, f=f[1])

    up1_4 = UpSampling2D((2,2), interpolation='bilinear', name='up14') (conv2_3)
    conv1_4 = concatenate([up1_4, conv1_1, conv1_2, conv1_3, conv4_1_1_4, conv3_2_1_4], name='merge14')
    conv1_4 = conv_batchnorm_relu_block(conv1_4, f=f[0])

    conv5_1 = conv_batchnorm_relu_block(pool4, f=f[4])
    conv5_1_3_3 = UpSampling2D((4,4), interpolation='bilinear') (conv5_1)
    conv5_1_2_4 = UpSampling2D((8,8), interpolation='bilinear') (conv5_1)
    conv5_1_1_5 = UpSampling2D((16,16), interpolation='bilinear') (conv5_1)

    up4_2 = UpSampling2D((2,2), interpolation='bilinear', name='up42') (conv5_1)
    conv4_2 = concatenate([up4_2, conv4_1], name='merge42')
    conv4_2 = conv_batchnorm_relu_block(conv4_2, f=f[3])
    conv4_2_2_4 = UpSampling2D((4,4), interpolation='bilinear') (conv4_2)
    conv4_2_1_5 = UpSampling2D((8,8), interpolation='bilinear') (conv4_2)

    up3_3 = UpSampling2D((2,2), interpolation='bilinear', name='up33') (conv4_2)
    conv3_3 = concatenate([up3_3, conv3_1, conv3_2, conv5_1_3_3], name='merge33')
    conv3_3 = conv_batchnorm_relu_block(conv3_3, f=f[2])
    conv3_3_1_5 = UpSampling2D((4,4), interpolation='bilinear') (conv3_3)

    up2_4 = UpSampling2D((2,2), interpolation='bilinear', name='up24') (conv3_3)
    conv2_4 = concatenate([up2_4, conv2_1, conv2_2, conv2_3, conv4_2_2_4, conv5_1_2_4], name='merge24')
    conv2_4 = conv_batchnorm_relu_block(conv2_4, f=f[1])

    up1_5 = UpSampling2D((2,2), interpolation='bilinear', name='up15') (conv2_4)
    conv1_5 = concatenate([up1_5, conv1_1, conv1_2, conv1_3, conv1_4, conv3_3_1_5, conv4_2_1_5, conv5_1_1_5], name='merge15')
    conv1_5 = conv_batchnorm_relu_block(conv1_5, f=f[0])

    # Last convolution with sigmoid
    output = Conv2D(1, 1, activation='sigmoid', padding='same') (conv1_5)

    model = Model(inputs=inputs, outputs=output, name='UNetSharp')

    return model


import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from proto_mdd.utils import euclidean_metric

class ScaledDotProductAttention(nn.Module):
    ''' Scaled Dot-Product Attention '''

    def __init__(self, temperature, attn_dropout=0.1):
        super().__init__()
        self.temperature = temperature
        self.dropout = nn.Dropout(attn_dropout)
        self.softmax = nn.Softmax(dim=2)

    def forward(self, q, k, v):

        attn = torch.bmm(q, k.transpose(1, 2))
        attn = attn / self.temperature
        log_attn = F.log_softmax(attn, 2)
        attn = self.softmax(attn)
        attn = self.dropout(attn)
        output = torch.bmm(attn, v)
        return output, attn, log_attn

class MultiHeadAttention(nn.Module):
    ''' Multi-Head Attention module '''

    def __init__(self, args, n_head, d_model, d_k, d_v, dropout=0.1):
        super().__init__()
        self.n_head = n_head
        self.d_k = d_k
        self.d_v = d_v

        self.w_qs = nn.Linear(d_model, n_head * d_k)
        self.w_ks = nn.Linear(d_model, n_head * d_k)
        self.w_vs = nn.Linear(d_model, n_head * d_v)
        nn.init.normal_(self.w_qs.weight, mean=0, std=np.sqrt(2.0 / (d_model + d_k)))
        nn.init.normal_(self.w_ks.weight, mean=0, std=np.sqrt(2.0 / (d_model + d_k)))
        nn.init.normal_(self.w_vs.weight, mean=0, std=np.sqrt(2.0 / (d_model + d_v)))

        self.attention = ScaledDotProductAttention(temperature=np.power(d_k, 0.5))
        self.layer_norm = nn.LayerNorm(d_model)

        self.fc = nn.Linear(n_head * d_v, d_model)
        nn.init.xavier_normal_(self.fc.weight)
        self.dropout = nn.Dropout(dropout)

    def forward(self, q, k, v):
        d_k, d_v, n_head = self.d_k, self.d_v, self.n_head
        sz_b, len_q, _ = q.size()
        sz_b, len_k, _ = k.size()
        sz_b, len_v, _ = v.size()

        residual = q
        q = self.w_qs(q).view(sz_b, len_q, n_head, d_k)
        k = self.w_ks(k).view(sz_b, len_k, n_head, d_k)
        v = self.w_vs(v).view(sz_b, len_v, n_head, d_v)

        q = q.permute(2, 0, 1, 3).contiguous().view(-1, len_q, d_k) # (n*b) x lq x dk
        k = k.permute(2, 0, 1, 3).contiguous().view(-1, len_k, d_k) # (n*b) x lk x dk
        v = v.permute(2, 0, 1, 3).contiguous().view(-1, len_v, d_v) # (n*b) x lv x dv

        output, attn, log_attn = self.attention(q, k, v)

        output = output.view(n_head, sz_b, len_q, d_v)
        output = output.permute(1, 2, 0, 3).contiguous().view(sz_b, len_q, -1) # b x lq x (n*dv)

        output = self.dropout(self.fc(output))
        output = self.layer_norm(output + residual)

        return output

class proto_attention_net(nn.Module):

    def __init__(self, args, dropout=0.2):
        super().__init__()
        if args.model_type == 'ConvNet':
            from proto_mdd.networks.convnet import ConvNet
            self.encoder = ConvNet()
            z_dim = 64
        elif args.model_type == 'ResNet':
            from proto_mdd.networks.resnet import ResNet
            self.encoder = ResNet()
            z_dim = 640
        elif args.model_type == 'ResNet18':
            hdim = 512
            z_dim = 512
            from proto_mdd.networks.resnet_pytorch import resnet18
            self.encoder = resnet18(pretrained = False)
        else:
            raise ValueError('')

        self.slf_attn = MultiHeadAttention(args, args.head, z_dim, z_dim, z_dim, dropout=dropout)
        self.z_dim = z_dim
        self.args = args

    def forward(self, support, query, input_type = "data"):

        if input_type == "data":
            # feature extraction
            support = self.encoder(support)
            query = self.encoder(query)
            proto = support.reshape(self.args.shot, -1, support.shape[-1]).mean(dim=0) # N x d

            # refine by attention machenism
            proto = proto.unsqueeze(0)  # 1 x N x d
            proto = self.slf_attn(proto, proto, proto)
            proto = proto.squeeze(0)

            # compute distance for all batches
            logitis = euclidean_metric(query, proto) / self.args.temperature

            return support, query, logitis

        elif input_type == "feature":
            # get mean of the support
            proto = support.reshape(self.args.shot, -1, support.shape[-1]).mean(dim=0) # N x d
            # refine by attention machenism
            proto = proto.unsqueeze(0)  # 1 x N x d
            proto = self.slf_attn(proto, proto, proto)
            proto = proto.squeeze(0)

            # compute distance for all batches
            logitis = euclidean_metric(query, proto) / self.args.temperature

            return logitis


import os
import unittest

from checkov.terraform.module_loading.loaders.local_path_loader import loader

class TestLocalPathLoader(unittest.TestCase):
    def test_child_dir(self):
        current_dir = os.path.dirname(os.path.realpath(__file__))
        with loader.load(current_dir, "./resources", None, '') as content:
            assert content.loaded()
            assert content.path() == os.path.join(current_dir, "resources")

    def test_unhandled_source(self):
        with loader.load("current_dir", "hashicorp/consul/aws", None, '') as content:
            assert not content.loaded()

    def test_bad_source(self):
        current_dir = os.path.dirname(os.path.realpath(__file__))
        with self.assertRaises(FileNotFoundError):
            loader.load(current_dir, "./path_that_doesnt_exist", None, '')


import numpy as np
import pandas as pd
from tqdm import tqdm
from collections import Counter

class AutoDatatyper(object):
    def __init__(self, vector_dim=300, num_rows=1000):
        self.vector_dim = vector_dim
        self.num_rows = num_rows
        self.decode_dict = {0: 'numeric', 1: 'character', 2: 'time', 3: 'complex'}

    def create_dataset_from_data_column(self, iterable, label):
        iterable_str = self.__remove_na_and_stringify_iterable(iterable)
        choice_range = len(iterable_str)

        vector_list = []
        for i in tqdm(list(range(self.num_rows))):
            try:
                vec = self.__get_sample_from_column_data(iterable_str, choice_range)
            except ValueError:
                raise ValueError('All data are NaNs.')
            vector_list.append(vec)

        return np.array(vector_list), np.array([label] * self.num_rows).reshape(-1, 1)

    def __remove_na_and_stringify_iterable(self, iterable):
        # Convert iterable to Series
        if not isinstance(iterable, pd.Series):
            iterable = pd.Series(iterable)

        # Drop NAs
        iterable.dropna(inplace=True)
        iterable = iterable.values
        iterable_str = iterable.astype(str)

        return iterable_str

    def __get_data_column_type(self, iterable, estimator, robustness):
        iterable_str = self.__remove_na_and_stringify_iterable(iterable)
        choice_range = len(iterable_str)

        vector_list = []

        for i in (range(int(100 * robustness))):
            try:
                vec = self.__get_sample_from_column_data(iterable_str, choice_range)
            except ValueError:
                return 'NaN', 1.0
            vector_list.append(vec)

        prediction = estimator.predict(np.array(vector_list))
        prediction_count = Counter(np.vectorize(lambda x: round(x, 1))(prediction))
        confidence = prediction_count.most_common(1)[0][1] / len(prediction)

        return self.decode_dict[round(prediction.mean())], confidence

    def get_data_column_type_df(self, data, estimator, robustness=0.1):
        result_dict = {}

        if isinstance(data, pd.DataFrame):
            column_names = data.columns.values

            for i, colname in tqdm(list(enumerate(column_names))):
                datatype, confidence = self.__get_data_column_type(data[colname], estimator, robustness=robustness)
                result_dict[colname] = datatype, confidence
        else:
            column_names = list(range(data.shape[1]))

            for i, colname in tqdm(list(enumerate(column_names))):
                datatype, confidence = self.__get_data_column_type(data[colname], estimator, robustness=robustness)
                result_dict[colname] = datatype, confidence

        return result_dict

    def __get_sample_from_column_data(self, iterable_str, choice_range):
        indices = np.random.choice(choice_range, self.vector_dim)
        stringified_data = iterable_str[indices]

        raw_feature_names = ['length', 'max', 'min', 'range', 'sum', 'avg', 'std', 'float', 'time', \
                             'nan', 'json1', 'json2', 'json3', 'array1', 'array2', 'array3', 'array4', \
                            'tag1', 'tag2', 'tag3', 'tag4', 'url']

        raw_feature_dict = {
            'length': np.vectorize(len)(stringified_data),
            'max': np.vectorize(lambda x: max([ord(char) for char in x]))(stringified_data),
            'min': np.vectorize(lambda x: min([ord(char) for char in x]))(stringified_data),
            'range': np.vectorize(lambda x: max([ord(char) for char in x]) - min([ord(char) for char in x]))(stringified_data),
            'sum': np.vectorize(lambda x: sum([ord(char) for char in x]))(stringified_data),
            'avg': np.vectorize(lambda x: sum([ord(char) for char in x]))(stringified_data) / np.vectorize(len)(stringified_data),
            'std': np.vectorize(lambda x: np.array([ord(char) for char in x]).std())(stringified_data),
            'float': np.vectorize(lambda x: x.count('.'))(stringified_data),
            'time': np.vectorize(self.__contains_time_characters)(stringified_data),
            'nan': np.vectorize(self.__is_nan)(stringified_data),
            'json1': np.vectorize(lambda x: x.count('{'))(stringified_data),
            'json2': np.vectorize(lambda x: x.count('}'))(stringified_data),
            'json3': np.vectorize(lambda x: x.count(':'))(stringified_data),
            'array1': np.vectorize(lambda x: x.count('['))(stringified_data),
            'array2': np.vectorize(lambda x: x.count(']'))(stringified_data),
            'array3': np.vectorize(lambda x: x.count(','))(stringified_data),
            'array4': np.vectorize(lambda x: x.count(';'))(stringified_data),
            'tag1': np.vectorize(lambda x: x.count('\\'))(stringified_data),
            'tag2': np.vectorize(lambda x: x.count('/'))(stringified_data),
            'tag3': np.vectorize(lambda x: x.count('|'))(stringified_data),
            'tag4': np.vectorize(lambda x: x.count('-'))(stringified_data),
            'url': np.vectorize(self.__contains_url_characters)(stringified_data)
        }

        range_feature_dict = {feature_name + '_range':
           np.array([raw_feature_dict[feature_name].max() - raw_feature_dict[feature_name].min()]) for feature_name in raw_feature_names
        }

        sum_feature_dict = {feature_name + '_sum':
           np.array([raw_feature_dict[feature_name].sum()]) for feature_name in raw_feature_names
        }

        avg_feature_dict = {feature_name + '_avg':
           np.array([raw_feature_dict[feature_name].mean()]) for feature_name in raw_feature_names
        }

        std_feature_dict = {feature_name + '_std':
           np.array([raw_feature_dict[feature_name].std()]) for feature_name in raw_feature_names
        }

        count_distinct_feature_dict = {feature_name + '_distinct':
           np.array([len(Counter(raw_feature_dict[feature_name]))]) for feature_name in raw_feature_names
        }

        concat_list = [value for key, value in raw_feature_dict.items()] \
        + [value for key, value in sum_feature_dict.items()] \
        + [value for key, value in avg_feature_dict.items()] \
        + [value for key, value in std_feature_dict.items()] \
        + [value for key, value in count_distinct_feature_dict.items()]

        vec = np.concatenate(concat_list)

        return vec

    def __contains_time_characters(self, string):
            time_chars = {':', '/', '-', '\\', '.', '+',
                         'hr', 'hour', 'min', 'minute', 'sec', 'second',
                         'day', 'week', 'year',
                         '年', '月', '日', '时', '分', '秒',
                         '年', '月', '日', '時', '分', '秒'}

            count = 0
            for char in time_chars:
                if char in string:
                    count += 1
            return count

    def __is_nan(self, string):
        return 1 if string.lower() == 'nan' else 0

    def __contains_url_characters(self, string):
            url_chars = {'http', '//', 'www', 'com', 'cn', '_'}

            count = 0
            for char in url_chars:
                if char in string:
                    count += 1
            return count

    def reduce_data_dict_to_ndarray(self, data_dict):
        return np.concatenate([value[0] for key, value in data_dict.items()], axis=0), np.concatenate([value[1] for key, value in data_dict.items()])

    def consolidate_data(self, foundation_features, new_features, foundation_label, new_label):
        return np.concatenate((foundation_features, new_features), axis=0), np.concatenate((foundation_label, new_label), axis=0)


# -*- coding: utf-8 -*-
#IT's assumed that starting variable is the first typed
import sys
# import helper
import re
import itertools

left, right = 0, 1

K, V, Productions = [],[],[]
variablesJar = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "W", "X", "Y", "Z"]

def isUnitary(rule, variables):
	if rule[left] in variables and rule[right][0] in variables and len(rule[right]) == 1:
		return True
	return False

def isSimple(rule):
	if rule[left] in V and rule[right][0] in K and len(rule[right]) == 1:
		return True
	return False

for nonTerminal in V:
	if nonTerminal in variablesJar:
		variablesJar.remove(nonTerminal)

#Add S0->S rule––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––START
def START(productions, variables):
	variables.append('S0')
	return [('S0', [variables[0]])] + productions

#Remove rules containing both terms and variables, like A->Bc, replacing by A->BZ and Z->c–––––––––––TERM
def TERM(productions, variables):
	newProductions = []
	#create a dictionari for all base production, like A->a, in the form dic['a'] = 'A'
	dictionary = setupDict(productions, variables, terms=K)
	for production in productions:
		#check if the production is simple
		if isSimple(production):
			#in that case there is nothing to change
			newProductions.append(production)
		else:
			for term in K:
				for index, value in enumerate(production[right]):
					if term == value and not term in dictionary:
						#it's created a new production vaiable->term and added to it
						dictionary[term] = variablesJar.pop()
						#Variables set it's updated adding new variable
						V.append(dictionary[term])
						newProductions.append( (dictionary[term], [term]) )

						production[right][index] = dictionary[term]
					elif term == value:
						production[right][index] = dictionary[term]
			newProductions.append( (production[left], production[right]) )

	#merge created set and the introduced rules
	return newProductions

#Eliminate non unitry rules––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––BIN
def BIN(productions, variables):
	result = []
	for production in productions:
		k = len(production[right])
		#newVar = production[left]
		if k <= 2:
			result.append( production )
		else:
			newVar = variablesJar.pop(0)
			variables.append(newVar+'1')
			result.append( (production[left], [production[right][0]]+[newVar+'1']) )
			i = 1
#TODO
			for i in range(1, k-2 ):
				var, var2 = newVar+str(i), newVar+str(i+1)
				variables.append(var2)
				result.append( (var, [production[right][i], var2]) )
			result.append( (newVar+str(k-2), production[right][k-2:k]) )
	return result

#Delete non terminal rules–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––DEL
def DEL(productions):
	newSet = []
	#seekAndDestroy throw back in:
	#        – outlaws all left side of productions such that right side is equal to the outlaw
	#        – productions the productions without outlaws
	outlaws, productions = seekAndDestroy(target='%', productions=productions)
	#add new reformulation of old rules
	for outlaw in outlaws:
		#consider every production: old + new resulting important when more than one outlaws are in the same prod.
		for production in productions + [e for e in newSet if e not in productions]:
			#if outlaw is present in the right side of a rule
			if outlaw in production[right]:
				#the rule is rewrited in all combination of it, rewriting "e" rather than outlaw
				#this cycle prevent to insert duplicate rules
				newSet = newSet + [e for e in  rewrite(outlaw, production) if e not in newSet]

	#add unchanged rules and return
	return newSet + ([productions[i] for i in range(len(productions))
							if productions[i] not in newSet])

def unit_routine(rules, variables):
	unitaries, result = [], []
	#controllo se una regola è unaria
	for aRule in rules:
		if isUnitary(aRule, variables):
			unitaries.append( (aRule[left], aRule[right][0]) )
		else:
			result.append(aRule)
	#altrimenti controllo se posso sostituirla in tutte le altre
	for uni in unitaries:
		for rule in rules:
			if uni[right]==rule[left] and uni[left]!=rule[left]:
				result.append( (uni[left],rule[right]) )

	return result

def UNIT(productions, variables):
	i = 0
	result = unit_routine(productions, variables)
	tmp = unit_routine(result, variables)
	while result != tmp and i < 1000:
		result = unit_routine(tmp, variables)
		tmp = unit_routine(result, variables)
		i+=1
	return result

def union(lst1, lst2):
    final_list = list(set().union(lst1, lst2))
    return final_list

def loadModel(file):
	# file = open(modelPath).read()
	K = (file.split("Variables:\n")[0].replace("Terminales:\n","").replace("\n",""))
	V = (file.split("Variables:\n")[1].split("Producciones:\n")[0].replace("Variables:\n","").replace("\n",""))
	P = (file.split("Producciones:\n")[1])

	return cleanAlphabet(K), cleanAlphabet(V), cleanProduction(P)

#Make production easy to work with
def cleanProduction(expression):
	result = []
	#remove spaces and explode on ";"
	rawRulse = expression.replace('\n','').split(';')

	for rule in rawRulse:
		#Explode evry rule on "->" and make a couple
		leftSide = rule.split(' -> ')[0].replace(' ','')
		rightTerms = rule.split(' -> ')[1].split(' | ')
		for term in rightTerms:
			result.append( (leftSide, term.split(' ')) )
	return result

def cleanAlphabet(expression):
	return expression.replace('  ',' ').split(' ')

def seekAndDestroy(target, productions):
	trash, ereased = [],[]
	for production in productions:
		if target in production[right] and len(production[right]) == 1:
			trash.append(production[left])
		else:
			ereased.append(production)

	return trash, ereased

def setupDict(productions, variables, terms):
	result = {}
	for production in productions:
		#
		if production[left] in variables and production[right][0] in terms and len(production[right]) == 1:
			result[production[right][0]] = production[left]
	return result

def rewrite(target, production):
	result = []
	#get positions corresponding to the occurrences of target in production right side
	#positions = [m.start() for m in re.finditer(target, production[right])]
	positions = [i for i,x in enumerate(production[right]) if x == target]
	#for all found targets in production
	for i in range(len(positions)+1):
 		#for all combinations of all possible lenght phrases of targets
 		for element in list(itertools.combinations(positions, i)):
 			#Example: if positions is [1 4 6]
 			#now i've got: [] [1] [4] [6] [1 4] [1 6] [4 6] [1 4 6]
 			#erease position corresponding to the target in production right side
 			tadan = [production[right][i] for i in range(len(production[right])) if i not in element]
 			if tadan != []:
 				result.append((production[left], tadan))
	return result

def dict2Set(dictionary):
	result = []
	for key in dictionary:
		result.append( (dictionary[key], key) )
	return result

def pprintRules(rules):
	for rule in rules:
		tot = ""
		for term in rule[right]:
			tot = tot +" "+ term
		print(rule[left]+" -> "+tot)

def prettyForm(rules):
	dictionary = {}
	for rule in rules:
		if rule[left] in dictionary:
			dictionary[rule[left]] += ' | '+' '.join(rule[right])
		else:
			dictionary[rule[left]] = ' '.join(rule[right])
	result = ""
	for key in dictionary:
		result += key+" -> "+dictionary[key]+"\n"
	return result

if __name__ == '__main__':
	if len(sys.argv) > 1:
		modelPath = str(sys.argv[1])
	else:
		modelPath = 'model.txt'

	file = open(modelPath).read()
	K, V, Productions = loadModel( file )

	# Productions = START(Productions, variables=V) #S0 -> s
	Productions = TERM(Productions, variables=V)
	Productions = BIN(Productions, variables=V)
	Productions = DEL(Productions) # simbolo de anulables %
	Productions = UNIT(Productions, variables=V)

	rst = prettyForm(Productions)
	# print(rst)
	# print( len(Productions) )
	open('out.txt', 'w').write(	prettyForm(Productions) )


from utils.auth import login
from utils.problem import ProblemSystem
import json

record_filepath = 'data/record.json'
record = json.load(open(record_filepath))

min_value = min(record.values())

for cls in record:
    cookies = login("crack" + cls, "1358282318")

    if record[cls] >= min_value + 5:
        continue

    cur = 0
    while cur < 5:
        try:
            ps = ProblemSystem(record[cls])
            ps.ac(cookies)
            if ps.score > 10:
                cur += 1
            print("{} [{}] {}".format(cls, ps.title, ps.score))
        except:
            pass
        finally:
            record[cls] += 1
    json.dump(record, open(record_filepath, 'w'), indent=4)


import numpy
import pandas
import pykalman

def modified_Kalman_filter(data_table: pandas.DataFrame, column: str, mode: str = 'smooth'):
    original_array = data_table[column].values.astype(numpy.single)
    masked_array = numpy.ma.masked_invalid(original_array)

    # Initialize the Kalman filter with the trivial transition and observation matrices.
    f = pykalman.KalmanFilter(transition_matrices=[[1]], observation_matrices=[[1]])
    # Find the best other parameters based on the data (e.g. Q)
    f = f.em(masked_array, n_iter=5)

    # And apply the filter.
    if mode == 'filter':
        (new_data, filtered_state_covariances) = f.filter(masked_array)
    elif mode == 'smooth':
        (new_data, filtered_state_covariances) = f.smooth(masked_array)
    # modify the column in-place
    for i in range(0, len(data_table.index)):
        if numpy.isnan(original_array[i]):
            data_table.loc[data_table.index[i], column] = new_data[i]