import keyboard
from time import time

from communication.bt_server import BT_Server
from communication.KEYBOARD_CONFIG import KEYBOARD_CONFIG_DICT, DEBOUNCE_INTERVAL
from communication.BT_CONFIG import BT_CONTROLLER_DICT

def graceful_exit(func):
    def wrapper(*args, **kw_args):
        try:
            return func(*args, **kw_args)
        except KeyboardInterrupt:
            self = args[0]
            self.server.clean_up()
            print("goodbye.")
            return
    return wrapper

class Controller:
    def __init__(self, debug=False):
        # how often should commands be sent
        #   NOTE: these values are in seconds, the debounce_interval should be
        #         roughly equal to RUN_TIME defined in the MotorDriver class
        self.debounce_interval = DEBOUNCE_INTERVAL
        self.last_press = 0.0

        self.debug = debug

        # keyboard_config_dict should be a dictionary with the following keys
        # this decides which keys are listened for and what messages they send
        self.right = KEYBOARD_CONFIG_DICT['RIGHT']
        self.left = KEYBOARD_CONFIG_DICT['LEFT']
        self.forward = KEYBOARD_CONFIG_DICT['FORWARD']
        self.backward = KEYBOARD_CONFIG_DICT['BACKWARD']
        self.exit = KEYBOARD_CONFIG_DICT['EXIT']

        # Run the server. It will be connected to by the leader's client
        controller_addr = BT_CONTROLLER_DICT["CONTROLLER"]["ADDR"]
        controller_port = BT_CONTROLLER_DICT["CONTROLLER"]["PORT"]
        self.server = BT_Server(controller_addr, controller_port, "CONTROLLER", debug=debug)

    @graceful_exit
    def start(self):
        while True:
            if keyboard.is_pressed(self.forward) and not self.debounce():
                if self.debug:
                    print("\nForward press detected")
                self.last_press = time()
                self.server.send('forward')
            if keyboard.is_pressed(self.right) and not self.debounce():
                if self.debug:
                    print("\nRight press detected")
                self.last_press = time()
                self.server.send('right')
            if keyboard.is_pressed(self.left) and not self.debounce():
                if self.debug:
                    print("\nLeft press detected")
                self.last_press = time()
                self.server.send('left')
            if keyboard.is_pressed(self.backward) and not self.debounce():
                if self.debug:
                    print("\nBackward press detected")
                self.last_press = time()
                self.server.send('backward')
            if keyboard.is_pressed(self.exit) and not self.debounce():
                if self.debug:
                    print("\nExit press detected")
                raise KeyboardInterrupt

    @graceful_exit
    def debounce(self):
        elapsed_time = time() - self.last_press
        if elapsed_time > self.debounce_interval:
            return False
        else:
            return True

if __name__ == '__main__':
    control = Controller(True)
    control.start()


"""Support for HomeSeer light-type devices."""
import asyncio
import logging
from typing import Any

from homeassistant.components.light import (
    ToggleEntity, LightEntity

)
from homeassistant.const import (
    CONF_NAME, STATE_ON, STATE_OFF
)
from .command import (turn_off, turn_light_up)

_LOGGER = logging.getLogger(__name__)
LIGHT_PLATFORMS = ["light"]

async def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
    """Perform the setup for Beverly water purifier."""

    light_entities = []

    light = MicoeLight(hass, config.get(CONF_NAME))
    light_entities.append(light)

    _LOGGER.warn('async_setup_platform')

    async_add_devices(light_entities)

class MicoeLight(LightEntity):
    """Representation of a HomeSeer light-type device."""

    def __init__(self, hass, name):
        self._hass = hass
        self._name = name

        self._attr_is_on = False

    @property
    def icon(self):
        return 'hass:lightbulb'

    @property
    def name(self):
        return self._name

    def turn_on(self, **kwargs: Any) -> None:
        turn_light_up('Light')
        self._attr_is_on = True

    def turn_off(self, **kwargs: Any) -> None:
        turn_off()
        self._attr_is_on = False


# -*- coding: utf-8 -*-
from PyQt4 import QtGui as qg
import PyQt4
import sys

class Example( qg.QWidget ):
    def __init__( self ):
        super(Example,self).__init__()
        PyQt4.QtCore.QTextCodec.setCodecForTr(PyQt4.QtCore.QTextCodec.codecForName('GB18030'))
        self.init()

    def init( self ):
        qg.QToolTip.setFont(qg.QFont("SansSerif",10))
        self.setToolTip(self.tr(u'show tool tip 帮助!'))
        b = qg.QPushButton(self.tr(u'帮助'),self)
        b.setToolTip(self.tr(u'button t尼玛tip'))
        b.resize(b.sizeHint())
        self.setWindowTitle('Window title')
        self.show()

def show():
    app = qg.QApplication(sys.argv)
    e = Example()

    sys.exit(app.exec_())

if __name__ == '__main__':
    show()


# word = "you "
# # first_letter = word[0]
# # end_word = word[1:-1]
# first_letter = ""
# end_word = ""
# for char in word:
#     if char == word[0:1]:
#         first_letter += char
#     elif char in word[1:-1:]:
#         end_word += char

# # print('x')
# # print(first_letter)
# # print(end_word)
# # print(word[0:1])
# # print(end_word)
# print(word[0])
# print(word[1:-1])
# print("cmcm")
# print(first_letter)
# print(end_word)

import string
line_1 = ""
line_2 = ""
line_3 = ""
line_4 = ""
line_5 = ""
line_6 = ""
line_7 = ""
print('')
title = 'Guide to Order Values '
for i in title:
    print(i+"\u0332",end='')
print('')
print('')
print('     For lowercase letters:')
print('')
for char in string.ascii_lowercase:
    if ord(char) in range(97,104):
        line_1 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(104,108):
        line_2 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(108,113):
        line_3 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(113,116):
        line_4 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(116,119):
        line_5 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(119,121):
        line_6 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(121,123):
        line_7 += char + " = " + str(ord(char)) + " "
print(line_1)
print(line_2)
print(line_3)
print(line_4)
print(line_5)
print(line_6)
print(line_7)
#...
line_1 = ""
line_2 = ""
line_3 = ""
line_4 = ""
line_5 = ""
line_6 = ""
line_7 = ""
print('')
print('     For UpperCase letters:')
print('')
for char in string.ascii_uppercase:
    if ord(char) in range(65,72):
        line_1 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(72,76):
        line_2 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(76,81):
        line_3 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(81,84):
        line_4 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(84,87):
        line_5 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(87,89):
        line_6 += char + " = " + str(ord(char)) + " "
    elif ord(char) in range(89,91):
        line_7 += char + " = " + str(ord(char)) + " "
print(line_1)
print(line_2)
print(line_3)
print(line_4)
print(line_5)
print(line_6)
print(line_7)
print('')


from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.db.models import Q
from django.urls import reverse_lazy
from django.views.generic import ListView
from applications.Producto.models import ProductoServicio
from applications.PaginaVenta.models import Suscripciones
from applications.Compra.models import Compra,Detalle
from . import functions

class CarritoListView(ListView):
    model = Detalle
    template_name = "Compra/carrito.html"
    context_object_name = 'carrito'

    def get_queryset(self):
        queryset = super(CarritoListView, self).get_queryset()
        id_compra = 'compra' in self.request.session
        if id_compra:
            queryset = Detalle.objects.get_carrito(
                self.request.session['compra']
            )
        return queryset

    def get_context_data(self, **args):
        context = super(CarritoListView, self).get_context_data(**args)
        context["suscripciones"]=Suscripciones.objects.get_suscripciones(self.request.user.id)
        return context

def validar_compra(compra,producto):
    created, total = functions.agregar_producto_a_compra(
    compra=compra,
    producto=producto,
    precio=producto.precio,
    )
    if created:
        compra.total=total
        compra.save()
        return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=producto añadirdo correctamente")
    return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=no se pudo agregar el producto, intente de nuevo")

def agregar_a_carrito(request,id1,id2):
    producto = ProductoServicio.objects.filter(
        id=id1,
        id_pagina_ventas=id2
    ).first()
    if producto:
        compra = 'compra' in request.session
        if compra:
            compra = Compra.objects.filter(id=request.session['compra']).first()
            return validar_compra(compra,producto)
        else:
            compra = Compra.objects.create(
                usuario=request.user,
                total=0,
                nombre_cliente=request.user.nombre
            )
            request.session['compra']=compra.id
            return validar_compra(compra,producto)
    return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=error al añadir producto")

def eliminar_de_carrito(request,id,idproducto):
    try:
        functions.eliminar_detalle(id,idproducto)
        return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=producto eliminado")
    except:
        return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=error al eliminar producto, intente de nuevo")

def cancelar_compra(request):
    compra = 'compra' in request.session
    if compra:
        compra = Compra.objects.filter(id=request.session['compra']).first()
        compra.estado = '2'
        details = Detalle.objects.filter(id_compra=compra.id)
        if details:
            for d in details:
                functions.eliminar_detalle(d.id, d.id_producto.id,False)
            details.delete()
            request.session['compra']=None
            compra.save()
            return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=compra cancelada")
        request.session['compra']=None
        compra.save()
        return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=no hay productos en el carrito")
    return HttpResponseRedirect(
            "http://localhost:8000/main/?mensaje=no hay un carrito de compra")


# Databricks notebook source
# MAGIC %pip install git+https://github.com/rafa-arana/fire.git

# COMMAND ----------

# MAGIC %md
# MAGIC ---
# MAGIC + STAGE 0: Setup
# MAGIC + STAGE 0 bis: File Ingestion with Autoloader
# MAGIC + STAGE 1: Data Reliable Pipelines with Live Tables and Autoloader
# MAGIC + STAGE 3: Querying the Delta Live Tables event log
# MAGIC ---

# COMMAND ----------

# MAGIC %md
# MAGIC # Load CSV files from Cloud in Streaming Mode

# COMMAND ----------

# MAGIC %md
# MAGIC
# MAGIC ## Diving into the codeðŸ‘‡

# COMMAND ----------

# MAGIC %md
# MAGIC We retrieve the name of the entity to get the FIRE data model for as well as the directory (distributed file storage) where we expect new raw files to land. These parameters are passed to the delta live table notebook via job configuration as per the screenshot above.

# COMMAND ----------

try:
  # the name of the fire entity we want to process
  fire_entity = spark.conf.get("fire_entity")
except:
  raise Exception("Please provide [fire_entity] as job configuration")

try:
  # where new data file will be received
  landing_zone = spark.conf.get("landing_zone")
except:
  raise Exception("Please provide [landing_zone] as job configuration")

try:
  # where corrupted data file will be stored
  invalid_format_path = spark.conf.get("invalid_format_path")
except:
  raise Exception("Please provide [invalid_format_path] as job configuration")

try:
  # format we ingest raw data
  file_format = spark.conf.get("file_format", "csv")
except:
  raise Exception("Please provide [file_format] as job configuration")

try:
  # format we ingest raw data
  delimiter = spark.conf.get("delimiter", "|")
except:
  raise Exception("Please provide [delimiter] as job configuration")

try:
  # number of new file to read at each iteration
  max_files = int(spark.conf.get("max_files", "1"))
except:
  raise Exception("Please provide [max_files] as job configuration")

# COMMAND ----------

# DLT import
import dlt
from pyspark.sql.functions import *

# Pyspark functions
from pyspark.sql.types import StringType, StructField, StructType, IntegerType, DateType, TimestampType, DecimalType, LongType

from fire.spark import FireModel

# COMMAND ----------

ingestionDate = current_date()
ingestionTime = current_timestamp()

# COMMAND ----------

schemas_dir = "/dbfs/Users/rafael.arana@databricks.com/DLT/dlt_san/entities/"
fire_model = FireModel(schemas_dir).load(fire_entity)
fire_schema = fire_model.schema
fire_constraints = fire_model.constraints

# COMMAND ----------

# DBTITLE 1,Ingest files with Autoloader into Bronze layer
@dlt.table(
  name=fire_entity+"_bronze",
  comment="This is an incremental streaming source from autoloader csv files on ADLS",
  table_properties={
                    "delta.autoOptimize.optimizeWrite" : "true",
                    "quality" : "bronze"
  })
def get_cloudfiles():
  return (
    spark.readStream
      .format("cloudFiles")
      .option("cloudFiles.format",file_format)
      .option("badRecordsPath", invalid_format_path)
      .option("rescuedDataColumn", "_rescue")
      .option("cloudFiles.maxFilesPerTrigger", max_files)
      .option("header", "true")
      .option("delimiter", delimiter)
      .schema(fire_schema)
      .load(landing_zone)
      .withColumn("InputFileName",input_file_name())
      .withColumn("IngestionDate",ingestionDate)
      .withColumn("IngestionTime",ingestionTime)
    )

# COMMAND ----------

# DBTITLE 1,Silver table with clean and validated data
@dlt.table(
    name=fire_entity+"_silver",
    comment="This is an incremental streaming source from Auto loader csv files on ADLS",
    table_properties={
                    "delta.autoOptimize.optimizeWrite" : "true",
                    "quality" : "silver"
  })
@dlt.expect_all_or_drop(dict(zip(fire_constraints, fire_constraints)))
def silver():
  return dlt.read_stream(fire_entity+"_bronze")

# COMMAND ----------

@udf("array<string>")
def failed_expectations(expectations):
  # retrieve the name of each failed expectation Iâ€™m
  return [name for name, success in zip(fire_constraints, expectations) if not success]

# COMMAND ----------

# DBTITLE 1,Quarantine table with invalid data
@dlt.table(
    name=fire_entity+"_quarantine",
    comment="This is an incremental streaming source from Auto loader csv files on ADLS"
)
def quarantine():
  return (
      dlt
        .read_stream(fire_entity+"_bronze")
        .withColumn("_fire", array([expr(value) for value in fire_constraints]))
        .withColumn("_fire", failed_expectations("_fire"))
        .filter(size("_fire") > 0)
  )

# COMMAND ----------

# MAGIC %md
# MAGIC ---
# MAGIC + STAGE 0: Setup
# MAGIC + STAGE 0 bis: File Ingestion with Autoloader
# MAGIC + STAGE 1: Data Reliable Pipelines with Live Tables and Autoloader
# MAGIC + STAGE 3: Querying the Delta Live Tables event log
# MAGIC ---

# COMMAND ----------

# MAGIC %md
# MAGIC
# MAGIC © 2021 Databricks, Inc. All rights reserved. The source in this notebook is provided subject to the Databricks License [https://databricks.com/db-license-source].  All included or referenced third party libraries are subject to the licenses set forth below.


from multiprocessing import Process, Value, RLock
import time

start = time.time()

numa = Value('i', 0)
numb = Value('i', 0)

rlock = RLock()

def do_sth():
    """ """
    """
    rlock.acquire()
    try:
        adda()
        addb()
    finally:
        rlock.release()
    """
    with rlock:
        for i in range(1000000):
            numa.value += 1
        adda()
        addb()

def adda():
    global numa
    """
    rlock.acquire()
    try:
        numa.value += 1
    finally:
        rlock.release()
    """
    with rlock:
        for i in range(1000000):
            numa.value += 1

def addb():
    global numb
    """
    rlock.acquire()
    try:
        numb.value += 1
    finally:
        rlock.release()
    """
    with rlock:
        for i in range(1000000):
            numb.value += 1

plist = []

for i in range(10):
    p = Process(target=do_sth)
    plist.append(p)
    p.start()

for item in plist:
    item.join()

print(numa.value)
print(numb.value)
stop = time.time()
print(stop - start)


import functools
import io
import json
import logging
import mimetypes
import os.path
import re
import shutil
import urllib.parse
from typing import Dict, Type, TextIO

import yaml
from swagger_ui_bundle import swagger_ui_3_path  # type: ignore[import]
from werkzeug import Response
from werkzeug.exceptions import HTTPException

from werkzeug.routing import Map, Submount, Rule

from cmk.gui import config
from cmk.gui.exceptions import MKUserError, MKAuthException
from cmk.gui.openapi import ENDPOINT_REGISTRY
from cmk.gui.plugins.openapi.utils import problem, ProblemException
from cmk.gui.wsgi.auth import verify_user, bearer_auth
from cmk.gui.wsgi.middleware import with_context_middleware, OverrideRequestMethod
from cmk.gui.wsgi.wrappers import ParameterDict
from cmk.utils import paths, crash_reporting
from cmk.utils.exceptions import MKException

ARGS_KEY = 'CHECK_MK_REST_API_ARGS'

logger = logging.getLogger('cmk.gui.wsgi.rest_api')

EXCEPTION_STATUS: Dict[Type[Exception], int] = {
    MKUserError: 400,
    MKAuthException: 401,
}

def spec_file() -> TextIO:
    spec_buffer = io.StringIO()
    with open(openapi_spec_dir() + "/checkmk.yaml", "r") as yaml_file:
        shutil.copyfileobj(yaml_file, spec_buffer)
    spec_buffer.seek(0)
    return spec_buffer

def openapi_spec_dir():
    return paths.web_dir + "/htdocs/openapi"

def serve_content(file_handle: TextIO, content_type):
    file_handle.seek(0)
    content = file_handle.read()

    resp = Response()
    resp.content_type = content_type
    resp.status_code = 200
    resp.data = content
    resp.freeze()

    return resp

def json_file(file_handle: TextIO) -> TextIO:
    """

    >>> yf = io.StringIO("data:\\n  foo:\\n  - bar\\n")
    >>> json_file(yf).read()
    '{"data": {"foo": ["bar"]}}'

    Args:
        file_handle:

    Returns:

    """
    file_handle.seek(0)
    data = yaml.safe_load(file_handle)
    buffer = io.StringIO()
    json.dump(data, buffer)
    buffer.seek(0)
    return buffer

class Authenticate:
    """Wrap an Endpoint so it will be authenticated

    This is not very memory efficient as it wraps every individual endpoint in its own
    authenticator, even though this does not need to be. This has to be done this way right now,
    because we have multiple endpoints without authentication in this app. A refactoring to lower
    the memory foot-print of this is feasible and should be done if a good way has been found.
    """
    def __init__(self, func):
        self.func = func

    def __call__(self, environ, start_response):
        path_args = environ[ARGS_KEY]
        auth_header = environ.get('HTTP_AUTHORIZATION', '')
        try:
            rfc7662 = bearer_auth(auth_header)
        except MKException as exc:
            return problem(
                status=401,
                title=str(exc),
                ext={'auth_header': auth_header},
            )(environ, start_response)

        with verify_user(rfc7662['sub'], rfc7662):
            wsgi_app = self.func(ParameterDict(path_args))
            return wsgi_app(environ, start_response)

@functools.lru_cache
def serve_file(file_path):
    with open(file_path, "r") as fh:
        file_size = os.path.getsize(file_path)
        return serve_file_handle(fh, file_path, file_size)

def serve_file_handle(fh, file_path, file_size=None):
    resp = Response(fh)
    resp.direct_passthrough = True
    if file_size is not None:
        resp.headers['Content-Length'] = file_size
    content_type, _ = mimetypes.guess_type(file_path)
    if content_type is not None:
        resp.headers['Content-Type'] = content_type
    resp.freeze()
    return resp

class ServeSwaggerUI:
    def __init__(self, prefix=''):
        self.prefix = prefix

    def __call__(self, environ, start_response):
        path_info = environ['PATH_INFO']
        path = re.sub(self.prefix, '', path_info)
        prefix = path_info[:-len(path)]
        if prefix.endswith("/ui"):
            prefix = prefix[:-3]

        if path == "/":
            path = "/index.html"

        if path == "/index.html":
            with open(swagger_ui_3_path + path) as fh:
                content = fh.read()
            content = content.replace("https://petstore.swagger.io/v2/swagger.json",
                                      prefix + "/openapi.yaml")
            resp = Response()
            resp.content_type = 'text/html'
            resp.status_code = 200
            resp.data = content
            resp.freeze()
            return resp(environ, start_response)

        return serve_file(swagger_ui_3_path + path)(environ, start_response)

class CheckmkRESTAPI:
    def __init__(self, debug: bool = False):
        self.debug = debug
        # TODO: Add resources for swagger-ui and json/yaml endpoints.
        # TODO: Add redoc.js endpoint.
        rules = []
        for endpoint in ENDPOINT_REGISTRY:
            if self.debug:
                # This helps us to make sure we can always generate a valid OpenAPI yaml file.
                _ = endpoint.to_operation_dict()

            rules.append(
                Rule(endpoint.default_path,
                     methods=[endpoint.method],
                     endpoint=Authenticate(endpoint.wrapped)))

        spec_file_buffer = spec_file()
        swagger_ui = ServeSwaggerUI(prefix="^/[^/]+/check_mk/api/[^/]+/ui")

        self.url_map = Map([
            Submount(
                "/<path:_path>",
                [
                    Rule("/ui/", endpoint=swagger_ui),
                    Rule("/ui/<path:path>", endpoint=swagger_ui),
                    # Rule("/doc/<path:file>", endpoint=serve_content()),
                    Rule(
                        "/openapi.yaml",
                        endpoint=serve_content(
                            file_handle=spec_file_buffer,
                            content_type='application/x-yaml; charset=utf-8',
                        ),
                    ),
                    Rule(
                        "/openapi.json",
                        endpoint=serve_content(
                            file_handle=json_file(spec_file_buffer),
                            content_type='application/json',
                        ),
                    ),
                    *rules,
                ],
            ),
        ])
        self.wsgi_app = with_context_middleware(OverrideRequestMethod(self._wsgi_app))

    def __call__(self, environ, start_response):
        return self.wsgi_app(environ, start_response)

    def _wsgi_app(self, environ, start_response):
        urls = self.url_map.bind_to_environ(environ)
        try:
            wsgi_app, path_args = urls.match()

            # Remove this again (see Submount above), so the validators don't go crazy.
            del path_args['_path']

            # This is an implicit dependency, as we only know the args at runtime, but the
            # function at setup-time.
            environ[ARGS_KEY] = path_args
            return wsgi_app(environ, start_response)
        except ProblemException as exc:
            # ProblemException is derived from HTTPException, so we have to catch it first.
            return exc.to_problem()(environ, start_response)
        except HTTPException as e:
            # We don't want to log explicit HTTPExceptions as these are intentional.
            # HTTPExceptions are WSGI apps
            return e(environ, start_response)
        except MKException as exc:
            if self.debug:
                raise

            return problem(
                status=EXCEPTION_STATUS.get(type(exc), 500),
                title=str(exc),
                detail="An exception occurred.",
            )(environ, start_response)
        except Exception as exc:
            crash = APICrashReport.from_exception()
            crash_reporting.CrashReportStore().save(crash)
            logger.exception("Unhandled exception (Crash-ID: %s)", crash.ident_to_text())
            if self.debug:
                raise

            crash_url = f"/{config.omd_site()}/check_mk/crash.py?" + urllib.parse.urlencode([
                ("crash_id", crash.ident_to_text()),
                ("site", config.omd_site()),
            ],)

            return problem(status=EXCEPTION_STATUS.get(type(exc), 500),
                           title=str(exc),
                           detail="An internal error occured while processing your request.",
                           ext={
                               'crash_report': {
                                   'href': crash_url,
                                   'method': 'get',
                                   'rel': 'cmk/crash-report',
                                   'type': 'text/html',
                               },
                               'crash_id': crash.ident_to_text(),
                           })(environ, start_response)

class APICrashReport(crash_reporting.ABCCrashReport):
    """API specific crash reporting class.
    """
    @classmethod
    def type(cls):
        return "rest_api"


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options

import time
import os
import shutil

# Setup of chrome preferences (download directory) -------
chromeOptions = webdriver.ChromeOptions()
prefs = {"download.default_directory" : "C:\journals\BJUI\Landing"}
chromeOptions.add_experimental_option("prefs",prefs)

driver = webdriver.Chrome(ChromeDriverManager().install(), options=chromeOptions)

volume_issue = []

def years(start_year,end_year):
    while start_year <= end_year:
        driver.get("https://bjui-journals.onlinelibrary.wiley.com/loi/1464410x/year/"+str(start_year))
        driver.implicitly_wait(40)
        _issues(start_year)
        start_year += 1

def _issues(start_year):
    global volume_issue

    WebDriverWait(driver, 10).until(EC.presence_of_element_located
                                    ((By.CLASS_NAME, "visitable")))
    issue_list = driver.find_elements_by_class_name('visitable')
    issue_link = driver.current_url

    issue_num = 0
    while issue_num <= len(issue_list):
        issue_list = driver.find_elements_by_class_name('visitable')
        issue_list[issue_num].click()
        time.sleep(3)
        volume_issue = driver.find_element_by_class_name('cover-image__parent-item').text
        volume_issue = volume_issue.replace('Volume ','V')
        volume_issue = volume_issue.replace('Issue ','I')
        volume_issue = volume_issue.split(", ")
        WebDriverWait(driver, 10).until(EC.presence_of_element_located
                                        ((By.CLASS_NAME, "issue-item__title")))
        article_list = driver.find_elements_by_class_name('issue-item__title')
        article_link = driver.current_url
        issue_num += 1

        article_num = 0
        while article_num <= len(article_list):
            article_list = driver.find_elements_by_class_name('issue-item__title')
            article_list[article_num].click()
            time.sleep(3)
            _infoGrabber(start_year)
            driver.get(article_link)
            WebDriverWait(driver, 10).until(EC.presence_of_element_located
                                        ((By.CLASS_NAME, "issue-item__title")))
            article_num += 1
        driver.get(issue_link)

def _infoGrabber(start_year):
    title = driver.find_element_by_class_name('citation__title').text
    page = driver.find_element_by_class_name('page-range').text
    doi = driver.find_element_by_class_name('epub-doi').text
    doi = doi.replace('https://doi.org/','')
    doi = doi.replace('.','_')
    doi = doi.replace('/','_')
    pdflink = driver.find_element_by_class_name('coolBar__ctrl.pdf-download').get_attribute('href')
    driver.get(pdflink)
    time.sleep(3)
    rename = f"{volume_issue[0]}"f"_{volume_issue[1]}"f"_{doi}" f"_{title}.pdf"
    if len(rename) >= 255:
        rename = rename[0:255]
    if not driver.find_elements_by_id('app-navbar'):
        print('Article not available for download: 'f"{rename}")
        return
    driver.find_element_by_tag_name('body').send_keys('g')
    time.sleep(2)
    # shortcut for opening a download popup in the BJUI journal viewer
    filename = _fileName(10)
    source = "c:\\BJUI\\landing" f"\\{filename}"

    destination =  "c:\\BJUI" f"\\{start_year}"
    path = os.path.join(destination)
    if not os.path.exists(path):
        os.makedirs(path)
    # looks for existing file path, creates if absent
    shutil.move(source,destination)
    try:
        os.rename(f"{destination}"f"\\{filename}",f"{destination}"f"\\{rename}")
    except FileExistsError:
        os.remove(f"{destination}"f"\\{filename}")

def _fileName(waitTime):
    # driver.execute_script("window.open()")
    # WebDriverWait(driver,10).until(EC.new_window_is_opened)
    # driver.switch_to.window(driver.window_handles[-1])
    driver.get("chrome://downloads/")
    endTime = time.time()+waitTime
    while True:
        try:
            # https://stackoverflow.com/questions/34548041/selenium-give-file-name-when-downloading
            # downloadPercentage = driver.execute_script(
            #     "return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value")
            # check if downloadPercentage is 100 (otherwise the script will keep waiting)
            time.sleep(10)
            # if downloadPercentage == 100:
                # return the file name once the download is completed
            return driver.execute_script("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content  #file-link').text")
        except:
            pass
        time.sleep(1)
        if time.time() > endTime:
            break
            # this goes into downloads and finds the name of the most recently downloaded file

years(1996, 1997)


import json

import torch
import yaml
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
from tqdm import tqdm

from src.data.tooth_dataset import ToothDataset
from src.model.vgg.vgg import Vgg
from src.utils.transforms import SquarePad

if __name__ == "__main__":
    with open("./src/model/unet/scripts/config.yml", "r") as f:
        config = yaml.safe_load(f)

    # Find out whether gpu is available
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # Load model
    model = Vgg.load_from_checkpoint(
        f"checkpoints/vgg/version_29/checkpoints/epoch=epoch=14-val_loss=val_f1=0.72.ckpt",
        map_location=device
    )
    model.eval()

    # Load data
    with open("data/final/train_quadrant_enumeration_disease_healthy_unpacked_test.json") as f:
        X = json.load(f)

    if model.hparams.config["n_classes"] > 1:
        # Remove healthy samples
        X = list(filter(lambda x: int(x["annotation"]["category_id_3"]) != 4, X))
    else:
        X = list(filter(lambda x: "score" not in x["annotation"] or x["annotation"]["score"] >= .9, X))
        for x in X:
            if x["annotation"]["category_id_3"] == 4:
                x["annotation"]["category_id_3"] = 0
            else:
                x["annotation"]["category_id_3"] = 1

    transform = transforms.Compose([
        SquarePad(),
        transforms.Resize(224, interpolation=transforms.InterpolationMode.BILINEAR)
    ])
    to_pil = transforms.ToPILImage()

    # Define dataset
    dataset_args = dict(image_dir=f"data/raw/training_data/quadrant_enumeration_disease/xrays",
                        n_classes=model.hparams.config["n_classes"])
    dataset = ToothDataset(X, transform=transform, **dataset_args)

    # Define loaders
    loader_args = dict(batch_size=config["batch_size"], num_workers=0, pin_memory=True)
    loader_train = DataLoader(dataset, **loader_args)

    # Predict for each sample
    prediction_list = []
    for sample in tqdm(dataset, total=len(dataset)):
        input = sample["image"]
        file_name = sample["file_name"]
        label = sample["label"]

        with torch.no_grad():
            prediction = model(input.unsqueeze(0).to(device))[0]
        prediction_list.append(dict(
            file_name=file_name,
            label=label.cpu().tolist(),
            prediction=prediction.detach().cpu().tolist()))

    with open(f"output/vgg_binary_predict.json", "w") as f:
        json.dump(prediction_list, f)


import logging
import csv
import re

from . import Indicator
from ..interfaces import CountryPolyInterface

class WebsiteIndicator(Indicator):
    """
    Indicator which detects the TLD of the website in the users profile and maps it to an area.
    Note: domains such as .com, .net and .org are ignored, and only country domains are detected.
    """

    tld_regex = r"[^\s\/](?:\.([a-z]{2,3}))?(?:\s|\/|$)"

    def __init__(self, config):
        super().__init__()
        csv_loc = config.get("multiindicator", "tld_csv")
        polydb_url = config.get("multiindicator", "gadm_polydb_path")

        self.weight = config.getfloat("mi_weights", "WS_1")

        self.cpi = CountryPolyInterface(polydb_url)

        # load the tlds from the csv, and get and store the polygons
        self.codes = {}
        with open(csv_loc, newline='') as csvfile:
            tldreader = csv.reader(csvfile, delimiter=',', quotechar='|')
            for row in tldreader:
                countries = self.cpi.get_polys(row[1], self.get_weight(1))
                self.codes[row[0]] = (row[1], countries)

        self.tldre = re.compile(self.tld_regex)

    def get_loc(self, website):
        if website is None:
            return []

        # search the field for all websites
        tlds = self.tldre.findall(website)
        polys = []
        for t in tlds:
            # find the polys from the prebuilt dictionary
            td = t.strip()
            logging.debug("TLD found: %s exists = %s" % (td, (td in self.codes)))
            if td in self.codes:
                polys += self.codes[td][1]

        return polys


import pprint
import re  # noqa: F401

import six

from asposeslidescloud.models.math_element import MathElement

class BorderBoxElement(MathElement):

    """
    Attributes:
      swagger_types (dict): The key is attribute name
                            and the value is attribute type.
      attribute_map (dict): The key is attribute name
                            and the value is json key in definition.
    """
    swagger_types = {
        'type': 'str',
        'base': 'MathElement',
        'hide_top': 'bool',
        'hide_bottom': 'bool',
        'hide_left': 'bool',
        'hide_right': 'bool',
        'strikethrough_horizontal': 'bool',
        'strikethrough_vertical': 'bool',
        'strikethrough_bottom_left_to_top_right': 'bool',
        'strikethrough_top_left_to_bottom_right': 'bool'
    }

    attribute_map = {
        'type': 'type',
        'base': 'base',
        'hide_top': 'hideTop',
        'hide_bottom': 'hideBottom',
        'hide_left': 'hideLeft',
        'hide_right': 'hideRight',
        'strikethrough_horizontal': 'strikethroughHorizontal',
        'strikethrough_vertical': 'strikethroughVertical',
        'strikethrough_bottom_left_to_top_right': 'strikethroughBottomLeftToTopRight',
        'strikethrough_top_left_to_bottom_right': 'strikethroughTopLeftToBottomRight'
    }

    type_determiners = {
        'type': 'BorderBox',
    }

    def __init__(self, type='BorderBox', base=None, hide_top=None, hide_bottom=None, hide_left=None, hide_right=None, strikethrough_horizontal=None, strikethrough_vertical=None, strikethrough_bottom_left_to_top_right=None, strikethrough_top_left_to_bottom_right=None):  # noqa: E501
        """BorderBoxElement - a model defined in Swagger"""  # noqa: E501
        super(BorderBoxElement, self).__init__(type)

        self._base = None
        self._hide_top = None
        self._hide_bottom = None
        self._hide_left = None
        self._hide_right = None
        self._strikethrough_horizontal = None
        self._strikethrough_vertical = None
        self._strikethrough_bottom_left_to_top_right = None
        self._strikethrough_top_left_to_bottom_right = None
        self.type = 'BorderBox'

        if base is not None:
            self.base = base
        if hide_top is not None:
            self.hide_top = hide_top
        if hide_bottom is not None:
            self.hide_bottom = hide_bottom
        if hide_left is not None:
            self.hide_left = hide_left
        if hide_right is not None:
            self.hide_right = hide_right
        if strikethrough_horizontal is not None:
            self.strikethrough_horizontal = strikethrough_horizontal
        if strikethrough_vertical is not None:
            self.strikethrough_vertical = strikethrough_vertical
        if strikethrough_bottom_left_to_top_right is not None:
            self.strikethrough_bottom_left_to_top_right = strikethrough_bottom_left_to_top_right
        if strikethrough_top_left_to_bottom_right is not None:
            self.strikethrough_top_left_to_bottom_right = strikethrough_top_left_to_bottom_right

    @property
    def base(self):
        """Gets the base of this BorderBoxElement.  # noqa: E501

        Base  # noqa: E501

        :return: The base of this BorderBoxElement.  # noqa: E501
        :rtype: MathElement
        """
        return self._base

    @base.setter
    def base(self, base):
        """Sets the base of this BorderBoxElement.

        Base  # noqa: E501

        :param base: The base of this BorderBoxElement.  # noqa: E501
        :type: MathElement
        """
        self._base = base

    @property
    def hide_top(self):
        """Gets the hide_top of this BorderBoxElement.  # noqa: E501

        Hide Top Edge  # noqa: E501

        :return: The hide_top of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._hide_top

    @hide_top.setter
    def hide_top(self, hide_top):
        """Sets the hide_top of this BorderBoxElement.

        Hide Top Edge  # noqa: E501

        :param hide_top: The hide_top of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._hide_top = hide_top

    @property
    def hide_bottom(self):
        """Gets the hide_bottom of this BorderBoxElement.  # noqa: E501

        Hide Bottom Edge  # noqa: E501

        :return: The hide_bottom of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._hide_bottom

    @hide_bottom.setter
    def hide_bottom(self, hide_bottom):
        """Sets the hide_bottom of this BorderBoxElement.

        Hide Bottom Edge  # noqa: E501

        :param hide_bottom: The hide_bottom of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._hide_bottom = hide_bottom

    @property
    def hide_left(self):
        """Gets the hide_left of this BorderBoxElement.  # noqa: E501

        Hide Left Edge  # noqa: E501

        :return: The hide_left of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._hide_left

    @hide_left.setter
    def hide_left(self, hide_left):
        """Sets the hide_left of this BorderBoxElement.

        Hide Left Edge  # noqa: E501

        :param hide_left: The hide_left of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._hide_left = hide_left

    @property
    def hide_right(self):
        """Gets the hide_right of this BorderBoxElement.  # noqa: E501

        Hide Right Edge  # noqa: E501

        :return: The hide_right of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._hide_right

    @hide_right.setter
    def hide_right(self, hide_right):
        """Sets the hide_right of this BorderBoxElement.

        Hide Right Edge  # noqa: E501

        :param hide_right: The hide_right of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._hide_right = hide_right

    @property
    def strikethrough_horizontal(self):
        """Gets the strikethrough_horizontal of this BorderBoxElement.  # noqa: E501

        Strikethrough Horizontal  # noqa: E501

        :return: The strikethrough_horizontal of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._strikethrough_horizontal

    @strikethrough_horizontal.setter
    def strikethrough_horizontal(self, strikethrough_horizontal):
        """Sets the strikethrough_horizontal of this BorderBoxElement.

        Strikethrough Horizontal  # noqa: E501

        :param strikethrough_horizontal: The strikethrough_horizontal of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._strikethrough_horizontal = strikethrough_horizontal

    @property
    def strikethrough_vertical(self):
        """Gets the strikethrough_vertical of this BorderBoxElement.  # noqa: E501

        Strikethrough Vertical  # noqa: E501

        :return: The strikethrough_vertical of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._strikethrough_vertical

    @strikethrough_vertical.setter
    def strikethrough_vertical(self, strikethrough_vertical):
        """Sets the strikethrough_vertical of this BorderBoxElement.

        Strikethrough Vertical  # noqa: E501

        :param strikethrough_vertical: The strikethrough_vertical of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._strikethrough_vertical = strikethrough_vertical

    @property
    def strikethrough_bottom_left_to_top_right(self):
        """Gets the strikethrough_bottom_left_to_top_right of this BorderBoxElement.  # noqa: E501

        Strikethrough Bottom-Left to Top-Right  # noqa: E501

        :return: The strikethrough_bottom_left_to_top_right of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._strikethrough_bottom_left_to_top_right

    @strikethrough_bottom_left_to_top_right.setter
    def strikethrough_bottom_left_to_top_right(self, strikethrough_bottom_left_to_top_right):
        """Sets the strikethrough_bottom_left_to_top_right of this BorderBoxElement.

        Strikethrough Bottom-Left to Top-Right  # noqa: E501

        :param strikethrough_bottom_left_to_top_right: The strikethrough_bottom_left_to_top_right of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._strikethrough_bottom_left_to_top_right = strikethrough_bottom_left_to_top_right

    @property
    def strikethrough_top_left_to_bottom_right(self):
        """Gets the strikethrough_top_left_to_bottom_right of this BorderBoxElement.  # noqa: E501

        Strikethrough Top-Left to Bottom-Right.  # noqa: E501

        :return: The strikethrough_top_left_to_bottom_right of this BorderBoxElement.  # noqa: E501
        :rtype: bool
        """
        return self._strikethrough_top_left_to_bottom_right

    @strikethrough_top_left_to_bottom_right.setter
    def strikethrough_top_left_to_bottom_right(self, strikethrough_top_left_to_bottom_right):
        """Sets the strikethrough_top_left_to_bottom_right of this BorderBoxElement.

        Strikethrough Top-Left to Bottom-Right.  # noqa: E501

        :param strikethrough_top_left_to_bottom_right: The strikethrough_top_left_to_bottom_right of this BorderBoxElement.  # noqa: E501
        :type: bool
        """
        self._strikethrough_top_left_to_bottom_right = strikethrough_top_left_to_bottom_right

    def to_dict(self):
        """Returns the model properties as a dict"""
        result = {}

        for attr, _ in six.iteritems(self.swagger_types):
            value = getattr(self, attr)
            if isinstance(value, list):
                result[attr] = list(map(
                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
                    value
                ))
            elif hasattr(value, "to_dict"):
                result[attr] = value.to_dict()
            elif isinstance(value, dict):
                result[attr] = dict(map(
                    lambda item: (item[0], item[1].to_dict())
                    if hasattr(item[1], "to_dict") else item,
                    value.items()
                ))
            else:
                result[attr] = value

        return result

    def to_str(self):
        """Returns the string representation of the model"""
        return pprint.pformat(self.to_dict())

    def __repr__(self):
        """For `print` and `pprint`"""
        return self.to_str()

    def __eq__(self, other):
        """Returns true if both objects are equal"""
        if not isinstance(other, BorderBoxElement):
            return False

        return self.__dict__ == other.__dict__

    def __ne__(self, other):
        """Returns true if both objects are not equal"""
        return not self == other


from apmiiib.abstract.geom.Point import Point
from apmiiib.abstract.represent.microbot.AbstractMicrobotLineup import AbstractMicrobotLineup
from apmiiib.abstract.represent.microbot.MicrobotSpikeParametrics import MicrobotSpikeParametrics

from math import pi, floor, pow

pi2 = pi*2

class AbstractMicrobotBasicSpike:
	"""This class builds a construct of Microbots that form a spike.
	This uses a technique normally used for A* search in determining the order
		of Microbots that would be set in place.
	"""

	def defaultSpikeShape(self, r, t, z):
		""" Takes a polar-coordinate and height value and returns its weight.
		The Microbot placement algorithm prioritizes points with smaller weights first.
		"""

		return r*self.radiusHeightRatio+z

	def defaultFc(self, o):
		return floor(pi2*o)

	def defaultFr(self, o, c):
		return o

	def defaultFt(self, o, c):
		return pi2*c/floor(pi2*o)

	def __init__(self, radiusHeightRatio, microbotSpan, microbotBreadth, basePoint=Point.ZERO, spikeDirection=Point.Z, spikeShape=None):
		self.basePoint = basePoint
		self.spikeDirection = spikeDirection.getDirection()
		self.radiusHeightRatio = radiusHeightRatio
		self.rHR = self.radiusHeightRatio
		self.microbotSpan = microbotSpan
		self.microbotBreadth = microbotBreadth
		self.spikeShape = spikeShape
		if (spikeShape == None):
			self.spikeShape = AbstractMicrobotBasicSpike.defaultSpikeShape
		self.abstractionsUsed = None

		self.fc = AbstractMicrobotBasicSpike.defaultFc
		self.fr = AbstractMicrobotBasicSpike.defaultFr
		self.ft = AbstractMicrobotBasicSpike.defaultFt

	def heuristic(self, freeNodePoint, angle):
		""" Computes the value of a freeNodePoint: a point in space that might be taken up by a Microbot.

		Lower values are prioritized. """

		# get the distance from the basePoint along the spikeDirection.

		## To compute easily, subtract by basePointPoint. This makes basePoint 0,0,0.
		freeNodePoint_basePoint = freeNodePoint.subtract(self.basePoint)

		## Now, dot them to get the first value.
		distAlongSpikeDirection = freeNodePoint_basePoint.getDot(self.spikeDirection)

		# get the distance from the freeNodePoint to the line formed through basePoint pointing to spikeDirection
		a_p = freeNodePoint.subtract(self.basePoint)
		a_pdn = a_p.getDot(self.spikeDirection)
		a_pdnxn = self.spikeDirection.multiply(a_pdn)
		a_p_a_pdnxn = a_p.subtract(a_pdnxn)
		distToLineThroughBasePoint = a_p_a_pdnxn.getMagnitude()

		# We can compute our heuristic value now.
		# If the value is lower, it means this point will be prioritized when setting a Microbot.

		return self.spikeShape(self, distToLineThroughBasePoint, angle, distAlongSpikeDirection)

	class BotThread:
		def __init__(self, spike, firstPoint, angle):
			self.bots = []
			self.spike = spike
			self.nextPoint = firstPoint
			self.angle = angle

		def heuristic(self):
			return self.spike.heuristic(self.nextPoint, self.angle)

		def append(self, microbot):
			""" When appending, the Microbot is posed. """

			self.bots.append(microbot)

			tailPoint = self.nextPoint.add(self.spike.spikeDirection.multiply(self.spike.microbotSpan))

			microbot.setPose(
				self.nextPoint,
				self.nextPoint.add(self.spike.spikeDirection.multiply(self.spike.microbotSpan/2)),
				tailPoint)

			self.nextPoint = tailPoint

	class BotPlacementLinkedList:
		class BotPlacementElement:
			def __init__(self, point, value=float("inf")):
				self.prev = None
				self.next = None
				self.point = point
				self.value = value

		def __init__(self):
			self.head = AbstractMicrobotBasicSpike.BotPlacementLinkedList.BotPlacementElement(None)
			self.tail = self.head

		def shift(self):
			if (self.head == self.tail):
				return None
			output = self.head.next
			self.head.next = output.next
			if (output == self.tail):
				self.tail = self.head
			else:
				self.head.next.prev = self.head
			return output

		def add(self, point, value=float("inf")):
			n = AbstractMicrobotBasicSpike.BotPlacementLinkedList.BotPlacementElement(point, value)

			rover = self.head.next
			while (rover != None and rover.value<=value):
				rover = rover.next
			if (rover == None):
				self.tail.next = n
				n.prev = self.tail
				self.tail = n
			else:
				n.next = rover
				n.prev = rover.prev
				rover.prev.next = n
				rover.prev = n
			return n

	def calculate(self, microbotLineup, microbotCount, microbotThreadCount):
		""" Takes a Microbot from a lineup, up to the number of Microbots specified.
		This builds the spike, made of up to a number of microbot threads.

		Returns a list of AbstractMicrobotOriginArmTip that was used by this method.
		"""

		self.spikeDirection.normalize()

		# Process:
		## Imagine a disk whose normal vector is the spikeDirection.
		## Fill this disk with circles through which a microbotThread will go through.
		## From a point in the center of each of these circles, imagine a line with spikeDirection.
		## Through that line, find the point where it intersects with the ground (or wherever the thread will begin forming.)

		# Part 1.1: Make the disk.

		## Produce a vector perpendicular to the spikeDirection.
		diskSweepVector = self.spikeDirection.getCross(Point.Z)
		if (diskSweepVector.isZero()):
			diskSweepVector = Point.X
		diskSweepVector.normalize()

		# Part 1.2: Fill this disk with circles.
		microbotThreads = [AbstractMicrobotBasicSpike.BotThread(self, self.basePoint, 0)]

		microbotThreadOrbit = 0
		microbotThreadCapacity = 0
		microbotThreadCapacityMax = 0
		microbotBreadth = self.microbotBreadth
		microbotThreadRadians = 0
		while (len(microbotThreads)<microbotThreadCount):
			if (microbotThreadCapacity == 0):
				microbotThreadOrbit += 1

				# Compute the largest number of circles that can fit at that point.
				# Get the circumference at that orbit, then divide by the diamter of a microbot.
				# microbotThreadRadians = 2*pi*microbotThreadOrbit #*microbotBreadth/microbotBreadth
				microbotThreadCapacityMax = self.fc(self, microbotThreadOrbit)
				microbotThreadCapacity = microbotThreadCapacityMax

			microbotThreadCapacity -= 1

			# rotate the diskSweepVector
			microbotThreadOrbitAngle = diskSweepVector.rotate(self.spikeDirection, self.ft(self, microbotThreadOrbit, microbotThreadCapacity))

			# get the point at this angle.
			threadPoint = self.basePoint.add(microbotThreadOrbitAngle.multiply(microbotBreadth*self.fr(self, microbotThreadOrbit, microbotThreadCapacity)))
			microbotThreads.append(AbstractMicrobotBasicSpike.BotThread(self, threadPoint, microbotThreadOrbitAngle))

		## Part 1.3: Find the point where a line through each circle's center and normal intersects with the ground.

		for i in microbotThreads:
			i.nextPoint = i.nextPoint.getPointIntersectionByLineToPlane(self.spikeDirection, Point.ZERO, Point.Z)

		# Part 2: Prepare to begin.

		## Part 2.1: Set up a priority lane.
		microbotPriority = AbstractMicrobotBasicSpike.BotPlacementLinkedList()
		for i in microbotThreads:
			microbotPriority.add(i, i.heuristic())

		## Part 2.2: Initialize the microbots usage.
		microbotCounter = 0
		microbotAccounting = []

		## Part 3: begin.
		while (microbotCounter<microbotCount):
			# Get the next microbot we can use.
			nextMicrobot = microbotLineup.getOneOriginArmTip()
			if (nextMicrobot == None):
				break

			# Get the next point we can use.
			nextThread = microbotPriority.shift().point

			# Add this microbot to that thread. It will be posed as it is added.
			nextThread.append(nextMicrobot)

			# Put this back in the priority. The append operation earlier has updated its value.
			microbotPriority.add(nextThread, nextThread.heuristic())

			# Increment things.
			microbotAccounting.append(nextMicrobot)
			microbotCounter += 1

		# By this point, all the Microbots used have been posed.
		# Return a list of those Microbots.

		self.abstractionsUsed = AbstractMicrobotLineup(microbotAccounting)
		self.microbotThreadCount = microbotThreadCount

		return microbotAccounting

	def setThreadParametrics(self, fc=None, fr=None, ft=None):
		""" Accepts functions that determine how the threads will be set up.

		fc - accepts an orbit index, returns the number of threads that can fit that orbit. (a circle is floor(pi*2*x), a square is 4+4*x)
		fr - accepts a thread count and orbit index, returns distance from center. one unit is one Microbot diameter.
		ft - accepts a thread count and orbit index, returns angle of rotation.

		"""

		if (isinstance(fc, MicrobotSpikeParametrics)):
			ft = fc.ft
			fr = fc.fr
			fc = fc.fc

		if (fc != None):
			self.fc = fc

		if (fr != None):
			self.fr = fr

		if (ft != None):
			self.ft = ft

		return self

	def reshape(self, shape=None, position=None, direction=None, threads=None, lineup=None, limit=None):
		if (shape != None):
			self.spikeShape = shape

		if (direction != None):
			self.spikeDirection = direction

		if (threads == None):
			threads = self.microbotThreadCount

		if (lineup == None):
			lineup = self.abstractionsUsed;

		if (limit == None):
			limit = len(lineup)

		if (position != None):
			self.basePoint = position

		abstractions = self.calculate(lineup, limit, threads)
		for i in abstractions:
			if (i.being != None):
				i.being.update()

		return abstractions


from typing import List

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals.sort()
        res = 0
        prevEnd = intervals[0][1]
        for start, end in intervals[1:]:
            if start >= prevEnd:
                prevEnd = end
            else:
                res += 1
                prevEnd = min(end, prevEnd) # delete the interval that has the bigger end value

        return res


import random

RandomNumber = random.randint(1,30)
print(RandomNumber)

print('Wylosowałem liczbę z zakresu 1-30. Odganij ją\n')

while 1:
    Guess = int(input())
    if Guess == RandomNumber:
        break
print('Brawo wygrałeś!')


import cv2
import numpy as np
import os
import svgwrite

# load image, change color spaces, and smoothing
img = cv2.imread(os.path.dirname(os.path.abspath(__file__))+"/INIAD_logo.png")
im=cv2.resize(img,(10000,10000))

im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
retval, im_bw = cv2.threshold(im_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 輪郭の検出
contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 全ての輪郭を書き込んで出力
#im_con = im.copy()
#cv2.drawContours(im_con, contours, -1, (0,255,0), 2)

# 輪郭直線近似
approx = []
for i in range(len(contours)):
    cnt = contours[i]
    epsilon = 0.0001*cv2.arcLength(cnt,True)
    a = len(cv2.approxPolyDP(cnt,epsilon,True))
    for j in range(a):
        x = cv2.approxPolyDP(cnt,epsilon,True)[j][0][0]*0.01
        y = cv2.approxPolyDP(cnt,epsilon,True)[j][0][1]*0.01
        #print(x)
        approx.append([x, y])
    #print(cv2.approxPolyDP(cnt,epsilon,True))
    #approx.append(cv2.approxPolyDP(cnt,epsilon,True))

#print(approx)

img = cv2.imread(os.path.dirname(os.path.abspath(__file__))+"/INIAD_logo.png")
img_HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
img_HSV = cv2.GaussianBlur(img_HSV, (9, 9), 3)

# detect
img_H, img_S, img_V = cv2.split(img_HSV)

ret,img_1 = cv2.threshold(img_H, 50, 255, cv2.THRESH_BINARY)
cv2.imwrite(os.path.dirname(os.path.abspath(__file__))+"/iniad1.bmp", img_1)

# load image, change color spaces, and smoothing
img1 = cv2.imread(os.path.dirname(os.path.abspath(__file__))+"/iniad1.bmp")
im=cv2.resize(img1,(10000,10000))
im1 = cv2.bitwise_not(im)
im_gray1 = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
retval, im_bw = cv2.threshold(im_gray1, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 輪郭の検出
contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 輪郭直線近似
approx1 = []
for i in range(len(contours)):
    cnt = contours[i]
    epsilon = 0.0001*cv2.arcLength(cnt,True)
    a = len(cv2.approxPolyDP(cnt,epsilon,True))
    for j in range(a):
        x = cv2.approxPolyDP(cnt,epsilon,True)[j][0][0]*0.01
        y = cv2.approxPolyDP(cnt,epsilon,True)[j][0][1]*0.01
        approx1.append([x, y])

color = "blue"
dwg = svgwrite.Drawing(os.path.dirname(os.path.abspath(__file__))+"/INIAD_logo.svg")
dwg.add( dwg.polygon( points=approx ) )
dwg.add( dwg.polygon( points=approx1, fill=color ) )
dwg.save()


from django.shortcuts import render, HttpResponse, redirect
from django.db.models import Max, Min, Count

from attendance.models import extemployeeatt, holiday, classlist, classes, classsolt, timesolt, checkinout
from hr.models import employee

from . import msslqdb

import datetime
import time
import threading
from xml.etree.ElementTree import parse

# Create your views here.
def index(request):
    return redirect('/att/attendance/')

def attendance(request):
    context = {}
    context['title'] = '签到'

    if request.method == "GET":
        # print('get')
        if 'datecheck' in request.GET:
            datecheck = request.GET['datecheck']
            daytoday = datetime.datetime.strptime(datecheck, '%Y-%m-%d')
        else:
            daytoday = datetime.datetime.today()

        if "namecheck" in request.GET:
            employeename = request.GET['namecheck']
            if employeename == '':
                pass

        if 'departmentcheck' in request.GET:
            department = request.GET['departmentcheck']
            if department == '':
                pass

    context['daytoday'] = daytoday

    d = []
    pindicts= {}
    # 查找PIN
    # emppins = employee.objects.all() \
    emppins = employee.objects.exclude(extemployeeatt__pin=None) \
        .order_by('employee_department__departmentid__name', 'name')\
        .values('name', 'extemployeeatt__pin', 'employee_department__departmentid__name')
    print(len(emppins))
    for emppin in emppins:
        pindicts[emppin['extemployeeatt__pin']] = emppin
        print(emppin)

    # # 查找班次
    # ks = classlist.objects.all() \
    #     .values('id',
    #             'employeeid',
    #             'classid__name',
    #             'employeeid__extemployeeatt__pin',
    #             'datestart',
    #             'dateend') \
    #     .order_by('datestart')
    # print(ks)

    # 填写一览
    ps = checkinout.objects.filter(checktime__year=daytoday.year,
                                   checktime__month=daytoday.month,
                                   checktime__day=daytoday.day) \
        .values('pin') \
        .annotate(last=Max('checktime'), fast=Min('checktime'), count=Count('userid'))

    for p in ps:
        i = {}
        if p['pin'] in pindicts:
            i.update(pindicts[p['pin']])
        i.update(p)
        i['long'] = i['last'] - i['fast']
        d.append(i)
        # print(i)
    context['context2'] = d

    # ps = checkinout.objects.filter(checktime__year=daytoday.year,
    #                                checktime__month=daytoday.month,
    #                                checktime__day=daytoday.day,
    #                                pin=32).values().order_by('-checktime')
    # emppins = employee.objects.exclude(extemployeeatt__pin=None)\
    #     .order_by('employee_department__departmentid__name', 'name')\
    #     .values('name', 'extemployeeatt__pin', 'employee_department__departmentid__name')
    # pinsdict = {}
    # for i in emppins:
    #     pinsdict[i['extemployeeatt__pin']] = i
    #     del pinsdict[i['extemployeeatt__pin']]['extemployeeatt__pin']
    # p = []
    # for k in ps:
    #     if k['pin']:
    #         if k['pin'] in pinsdict:
    #             k.update(pinsdict[k['pin']])
    #     p.append(k)
    # context['context'] = p

    return render(request, 'att_attendance_list.html', context)

def summary(request):
    context={}
    context['title'] = '出勤'
    return render(request, 'att_summary_list.html', context)

def att_collect_detail(request):
    context={}
    context['title'] = '明细'
    return render(request, 'att_collect_detailed.html', context)

def attclass(request):
    context={}
    context['title'] = '班次'

    ps = classlist.objects.all()\
        .values('employeeid_id',
                 'employeeid__name',
                 'employeeid__employee_department__departmentid__name',
                 'employeeid__extemployeeatt__pin',
                 'classid__name',
                 'datestart',
                 'dateend',
                 'active').order_by('employeeid_id', 'employeeid__employee_department__departmentid__name', 'datestart')
    context['context'] = ps

    return render(request, 'att_class_board.html', context)

def attholiday(request):
    context={}
    context['title'] = '假期'
    return render(request, 'att_holiday_board.html', context)

def configatt(request):
    context={}
    context['title'] = '设置'
    return render(request, 'attendance_conf.html', context)

def institem(items=None):
    for userid, checktime, checktype, verifycode, sensorid, memoinfo, workcode, sn, userextfmt, logid, id in items:
        nitem = checkinout.objects.get_or_create(userid=userid,
                                                 checktime=checktime,
                                                 checktype=checktype,
                                                 verifycode=verifycode,
                                                 sensorid=sensorid,
                                                 memoinfo=memoinfo,
                                                 workcode=workcode,
                                                 sn=sn,
                                                 userextfmt=userextfmt)

def inputxml(request):
    with open('CHECKINOUT.XML', 'r', encoding="UTF-8") as f:
        et = parse(f)
    root = et.getroot()
    checkinouts = []
    for childone in root:
        item = []
        for childtwo in childone:
            item.append(childtwo.text)
            # print(childtwo.tag, ":", childtwo.text)
        checkinouts.append(item)
        # print(item)

    i = 0
    threads = []
    itemgroup = []
    for item in checkinouts:
        item.append(i)
        itemgroup.append(item)
        if (i % 2000) == 0:
            thread = threading.Thread(target=institem, args=(tuple(itemgroup),))
            threads.append(thread)
            itemgroup = []
        i += 1
    if itemgroup:
        thread = threading.Thread(target=institem, args=(tuple(itemgroup),))
        threads.append(thread)

    for threadrun in threads:
        threadrun.start()
    while True:
        if len(threading.enumerate()) <= 3:
            print('='*24)
            break
        time.sleep(5)
        print(len(threading.enumerate()))
    print('all done')

    with open('USERINFO.xml', 'r', encoding="UTF-8") as f:
        et = parse(f)
    root = et.getroot()
    checkinouts = []
    for childone in root:
        item = []
        for childtwo in childone:
            item.append(childtwo.text)
        checkinouts.append(item)
    for useritem in checkinouts:
        checkinouts = checkinout.objects.filter(userid=useritem[0])
        if checkinouts:
            checkinouts.update(pin=useritem[1])
        print(useritem[0], useritem[1], useritem[3], len(checkinouts))
        k = employee.objects.filter(name=useritem[3]).last()
        if k:
            l = extemployeeatt.objects.get_or_create(employeeid=k,
                                                     pin=useritem[1])
            print(l)
    return HttpResponse(len(checkinouts))

def checkeveryday(request):
    context = []
    body = 400
    daystart = datetime.datetime.strptime('2015-12-1', '%Y-%m-%d')
    dayend = datetime.datetime.strptime('2015-12-31', '%Y-%m-%d')

    eitems = checkinout.objects.filter(checktime__range=(daystart, dayend), userid=body).order_by('userid', 'checktime')
    context = eitems.values_list()
    # for i in eitems.values_list():
    #     print(i)
    lenday = dayend - daystart
    daytag = daystart
    while True:
        if daytag > dayend:
            break
        print(daytag)
        daytag += datetime.timedelta(days=1)

    print(lenday.days)
    print(daystart.year)
    print(daystart.month)
    print(daystart.day)
    print(len(eitems))

    # 方式
        #不打 为1
        #打   为1
        #和   为1
    # 设计班次
    # 天排班、周期
    # 人员周期内的排班表

    # 人员表
    # 计算得出每天状况
    # 产生全表
    # 汇总统计
    return HttpResponse(context)

def getmssql(request):
    import pymssql

    if request.method == "POST":
        if "days" in request.POST:
            # days = request.POST.get('days', '1')
            days = request.POST['days']

            days = int(days)
            dayfrom = datetime.datetime.today() - datetime.timedelta(days=days)

    dbsql = msslqdb.getmssqldb()
    conn = pymssql.connect(dbsql['server'], dbsql['user'], dbsql['password'], database=dbsql['database'])

    cursor = conn.cursor()
    strsql = "select * from CHECKINOUT where CHECKTIME >='" + dayfrom.strftime("%Y-%m-%d") + "'"
    cursor.execute(strsql)
    row = cursor.fetchone()
    crows = []
    while row:
        crows.append(row)
        row = cursor.fetchone()

    cursor = conn.cursor()
    cursor.execute('select * from userinfo')
    row = cursor.fetchone()
    prows = []
    while row:
        prows.append(row)
        row = cursor.fetchone()
    conn.close()

    uidpin = {}
    for prow in prows:
        uidpin[prow[0]] = prow[1]

    r = 0
    for userid, checktime, checktype, verifycode, sensorid, memoinfo, workcode, sn, userextfmt in crows:
        nitem = checkinout.objects.get_or_create(userid=userid,
                                                 checktime=checktime,
                                                 checktype=checktype,
                                                 verifycode=verifycode,
                                                 sensorid=sensorid,
                                                 memoinfo=memoinfo,
                                                 workcode=workcode,
                                                 sn=sn,
                                                 userextfmt=userextfmt,
                                                 pin=uidpin[userid])
        m, n = nitem
        if n:
            r += 1
    return HttpResponse(" 更新记录:" + str(r))

def getmssqlpin(request):
    import pymssql

    dbsql = msslqdb.getmssqldb()
    conn = pymssql.connect(dbsql['server'], dbsql['user'], dbsql['password'], database=dbsql['database'])

    cursor = conn.cursor()
    cursor.execute('select * from userinfo')
    row = cursor.fetchone()
    prows = []
    while row:
        prows.append(row)
        row = cursor.fetchone()
    conn.close()

    for prow in prows:
        k = employee.objects.filter(name=prow[3])
        if k:
            l = extemployeeatt.objects.filter(employeeid=k.first())
            if l:
                # 更新
                l.update(pin=prow[1])
            else:
                # 新记录
                ttt = extemployeeatt.objects.get_or_create(employeeid=k.first(), pin=prow[1])
        else:
            print("+"*3, prow[3])
    r = u = 0

    return HttpResponse("已有记录: " + str(u) +" 更新记录:" + str(r))

def cmpcheck(request):
    employeeid = 17
    checkday = datetime.datetime.strptime('2019-4-1', '%Y-%m-%d')

    datestart = datetime.datetime.strptime('2019-4-1', '%Y-%m-%d')
    dateend = datetime.datetime.strptime('2019-4-30', '%Y-%m-%d')

    # 计算工作日 ==========================
    holidays = holiday.objects.filter(starttime__range=[datestart, dateend]).values().order_by('starttime')

    thisdate = datestart
    ppds=[]
    while thisdate <= dateend:
        ee = {}
        ee['employeeid'] = employeeid
        ee['daycheck'] = thisdate
        ee['weekday'] = thisdate.weekday()
        ee['autopb'] = True

        # 周末计算
        if (ee['weekday'] == 5) or (ee['weekday'] == 6):
            ee['workday'] = False
            ee['quot'] = 1
        else:
            ee['workday'] = True
            ee['quot'] = 0
        thisdate += datetime.timedelta(days=1)
        ppds.append(ee)

    #  节假日更新
    for hday in holidays:
        firsday = datetime.datetime.strptime(str(hday['starttime']), '%Y-%m-%d')
        adddays = hday['duration']
        quotient = hday['quotient']
        endday = firsday + datetime.timedelta(days=(adddays-1))
        for pb in ppds:
            if (pb['daycheck'] >= firsday) and (pb['daycheck'] <= endday):
                if quotient == 0:
                    pb['workday'] = True
                else:
                    pb['workday'] = False
                pb['quot'] = quotient

    # =======================
    # 填写班次
    chcemployee = employee.objects.get(pk=employeeid)
    ks = classlist.objects.filter(employeeid=chcemployee) \
        .values('id',
                'classid',
                'classid__name',
                'employeeid__name',
                'employeeid__extemployeeatt__pin',
                'datestart',
                'dateend')\
        .order_by('employeeid', 'datestart')
    print(ks)

    for pb in ppds:
        thisdate = pb['daycheck']
        if pb['workday'] and ks:
            for k in ks:
                # pb['pin'] = k['employeeid__extemployeeatt__pin']
                sr = datetime.datetime.strptime(str(k['datestart']), "%Y-%m-%d")
                sp = datetime.datetime.strptime(str(k['dateend']), "%Y-%m-%d")
                if (thisdate >= sr) and (thisdate <= sp):
                    pb['classes'] = k['classid']
                    pb['classname'] = k['classid__name']
        else:
            pb['classes'] = 0
            pb['classname'] = None
        print(pb)

    # =======================

    # 计算步骤
    # 计算排班
    chcemployee = employee.objects.get(pk=employeeid)
    # k = classlist.objects.filter(employeeid=chcemployee)\
    k = classlist.objects.all() \
        .values('id',
                'employeeid',
                'employeeid__name',
                'employeeid__extemployeeatt__pin',
                'datestart',
                'dateend',
                'classid__classsolt__timesoltid_id',
                'classid__classsolt__timesoltid_id__name',
                'classid__classsolt__timesoltid_id__intime')\
        .order_by('employeeid', 'datestart')

    timequery = timesolt.objects.all().values()
    timedicts = {}
    for i in timequery:
        timedicts[i['id']] = i

    # 根据排班规则自动排班
    emppbs = []
    for i in k:
        # print(i)
        e = i['datestart'].strftime("%Y-%m-%d")
        sr = datetime.datetime.strptime(e, "%Y-%m-%d")

        e = i['dateend'].strftime("%Y-%m-%d")
        sp = datetime.datetime.strptime(e, "%Y-%m-%d")

        thisdate = datestart
        while thisdate <= dateend:
            pb = {}
            pb['employeeid'] = i['employeeid']
            pb['daycheck'] = thisdate
            pb['pin'] = i['employeeid__extemployeeatt__pin']
            pb['weekday'] = thisdate.weekday()
            pb['autopb'] = True
            if (thisdate >= sr)and(thisdate <= sp):
                pb['timesoltid'] = i['classid__classsolt__timesoltid_id']
            else:
                pb['timesoltid'] = 0
            emppbs.append(pb)
            thisdate += datetime.timedelta(days=1)

    # 根据周末数据，校正周末排班
    # 工作日为0，公休日1，节假日2
    for pb in emppbs:
        if (pb['weekday'] == 5) or (pb['weekday'] == 6):
            pb['timesoltid'] = 0
            pb['quot'] = 1
        else:
            # pb.update(timedicts[i['classid__classsolt__timesoltid_id']])
            pb['quot'] = 0
        # print(pb)

    #  根据节假日数据，校正节假日排班
    holidays = holiday.objects.filter(starttime__range=[datestart, dateend]).values().order_by('starttime')
    # print(len(holidays))
    for hday in holidays:
        firsday = datetime.datetime.strptime(str(hday['starttime']), '%Y-%m-%d')
        adddays = hday['duration']
        quotient = hday['quotient']
        endday = firsday + datetime.timedelta(days=(adddays-1))

        for pb in emppbs:
            if (pb['daycheck'] >= firsday) and (pb['daycheck'] <= endday):
                pb['timesoltid'] = 0
                pb['quot'] = quotient

    # print(len(emppbs))

    # 根据单据校正打卡规则及时段时间
    pass

    # 根据排班表提取当时数据
    ps = checkinout.objects.filter(checktime__range=[datestart, dateend]) \
        .values_list('id', 'pin', 'checktime')\
        .order_by('checktime')
    # print(len(ps))

    for pb in emppbs:
        if pb['timesoltid'] != 0:
            pb['ckecktimes'] = []
            for checkt in ps.filter(checktime__year=pb['daycheck'].year, checktime__month=pb['daycheck'].month, checktime__day=pb['daycheck'].day, pin=pb['pin']):
                pb['ckecktimes'].append(checkt[2])
        # print(pb)

    # 找到对应数据，计算规所需的对应源数据
    # 使用源数据，核对规则
    # 计算出结果并保存进表格
    # kkk=llll
    return HttpResponse("ok")


from typing import Any, Dict

from django.contrib.auth.mixins import PermissionRequiredMixin

from .exceptions import UnfoldException

class UnfoldModelAdminViewMixin(PermissionRequiredMixin):
    """
    Prepares views to be displayed in admin
    """

    def get_context_data(self, **kwargs) -> Dict[str, Any]:
        if "model_admin" not in self.kwargs:
            raise UnfoldException(
                "UnfoldModelAdminViewMixin was not provided with 'model_admin' argument"
            )
        model_admin = self.kwargs["model_admin"]
        context_data = super().get_context_data(
            **kwargs, **model_admin.admin_site.each_context(self.request)
        )
        return context_data


#!/usr/bin/env python3

import time

rot = []
for i in (1,-1):
    for j in (1,-1):
        for k in (1,-1):
            rot.append((i,j,k))
shuffle = [[0,1,2], [0,2,1], [1,0,2], [1,2,0], [2,0,1], [2,1,0]]

flag = False

class Scanner:
    def __init__(self, measures):
        self.data = measures
        self.num_data = list(map(pToNum, measures))

    def has12Common(self, scannerb):
        for i in range(len(self.data)):
            for r in rot:
                for s in shuffle:
                    start_time = time.time()
                    man_data = self.center(r,s)
                    man_data_num = list(map(pToNum, man_data))
                    for j in range(len(scannerb.data)):
                        # print("1:--- %s seconds ---" % (time.time() - start_time))
                        shift = (
                            scannerb.data[j][0] - man_data[i][0],
                            scannerb.data[j][1] - man_data[i][1],
                            scannerb.data[j][2] - man_data[i][2]
                        )
                        # print("2:--- %s seconds ---" % (time.time() - start_time))
                        adjusted = []
                        for d in scannerb.num_data:
                            adjusted.append(d-pToNum(shift))
                        # scannerb.adjust(shift[0],shift[1],shift[2])
                        # print("3:--- %s seconds ---" % (time.time() - start_time))
                        common = intersectionLen(man_data_num,adjusted)
                        # print("4:--- %s seconds ---" % (time.time() - start_time))
                        if common >= 12:
                            self.data = man_data
                            self.data = self.adjust(-shift[0],-shift[1],-shift[2])
                            self.num_data = list(map(pToNum, self.data))
                            return (shift,r,s)
                        # quit()

    def adjust(self, x, y, z):
        changed_data = []
        for d in self.data:
            changed_data.append((
                d[0] - x,
                d[1] - y,
                d[2] - z
            ))
        return changed_data

    def center(self,r,s):
        changed_data = []
        for d in self.data:
            changed_data.append((
                d[s[0]] * r[0],
                d[s[1]] * r[1],
                d[s[2]] * r[2]
            ))
        return changed_data

# f = open("puzzle_test.txt","r")
f = open("puzzle.txt","r")
lines = f.readlines()

def pToNum(p):
    return p[0] * 200001 * 200001 + p[1] * 200001 + p[2]

def intersectionLen(listA, listB):
    return len(set(listA) & set(listB))
    # inside = {}
    # for a in listA:
    #     inside[pToNum(a)] = True

    # ans = 0
    # for b in listB:
    #     if pToNum(b) in inside:
    #         ans += 1

    # return ans

def union(listA, listB):
    # print(sorted(listA, key=pToNum))
    # print(sorted(listB, key=pToNum))
    inside = {}
    for a in listA:
        inside[pToNum(a)] = True

    for b in listB:
        if pToNum(b) in inside:
            continue
        listA.append(b)

    return listA

scanners = []
scanner_data = []
for line in lines:
    if line[0] == '-' and line[1] == '-':
        scanner_data = []
        continue
    if line[0] == '\n':
        scanners.append(Scanner(scanner_data))
        continue
    scanner_data.append(tuple(map(int, line[:-1].split(','))))
scanners.append(Scanner(scanner_data))

# for i in range(len(scanners)):
    # for j in range(len(scanners)):
        # print(i,j,scanners[j].has12Common(scanners[i]))

matched = {0}
def match(scanId):
    for u in range(len(scanners)):
        if u in matched:
            continue
        start_time = time.time()
        val = scanners[u].has12Common(scanners[0])
        # print("1:--- %s seconds ---" % (time.time() - start_time))
        if val is not None:
            print(u," shares common with",scanId,val)
            matched.add(u)
            match(u)
            # scanners[0].data = union(scanners[0].data, scanners[u].data)
            # scanners[0].num_data = list(map(pToNum, scanners[0].data))
            continue

ans = []
for i in range(len(scanners)):
    ans = union(ans,scanners[i].data)
print(len(ans))


from menu import resources, MENU

order = input("What would you like? (espresso/latte/cappuccino):")

def calculate_amount():
    t_quarter = float(input("how many quarters?:"))
    t_dime = float(input("how many dimes?:"))
    t_nickel = float(input("how many nickels?:"))
    t_penny = float(input("how many pennies?:"))
    total_amount = (t_quarter * 0.25) + (t_dime * 0.10) + (t_nickel * 0.05) + (t_penny * 0.01)
    refund = total_amount - float(MENU[order]["cost"])
    return refund

do_prepare = True

while do_prepare:
    print("please enter your coins")
    total = calculate_amount()

    if total > 0:
        print(f"enjoy your {order}, and here is your exchange ${total}")
    if total < 0:
        print("not sufficient amount !!")
    for item in resources:
        resources[item] -= MENU[order]["ingredients"][item]
    order = input("What would you like? (espresso/latte/cappuccino):")
    for item2 in resources:
        if resources[item2] < MENU[order]["ingredients"][item2]:
            print("insufficient resources!")
            do_prepare = False


from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    # polls的首页
    path('', views.IndexView.as_view(), name='index'),
    # 显示第三个问题的内容，例如: /polls/2/
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    # 显示第三个问题的内容回答，例如:: /polls/2/results/
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    # 显示第三个问题的打分，例如:: /polls/2/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]


"""
Binary Search Trees (BST) - tree structure that follow the search property, ie, for every node, all the nodes in the left subtree are smaller than the current node and all the nodes in the right subtree are larger than the current node.
rank(n) => the rank of a node in a tree is the sum of the number of nodes that its subtrees have, including itself.

		   2 (rank-4)
		  / \
(rank-1) 1   5 (rank-2)
			/
		   3 (rank-1)

Rank will be used in calculating the number of values in the tree that are smaller than or equal to a particular value.
For example-
To find number of nodes smaller than 4
- traverse tree to find where 4 would be inserted
- at every step, if you go right, add the rank of left sub tree (before actually going right)
- at every such step, add 1 to the total, for the current node.
- if you go left, don't add anything

# NOTE: In-order traversal of a BST will give us the sorted list of elements.
Main two important things about BSTs - search and rotation (for balancing the tree).
"""

class TreeNode:
	def __init__(self, val):
		self.val = val
		self.left = None
		self.right = None
		self.rank = 1

	def add_item(self, root, val):
		current_node = root
		while current_node:
			current_node.rank += 1 # for rank calculation
			if val < current_node.val:
				if current_node.left:
					current_node = current_node.left
				else:
					current_node.left = TreeNode(val)
					break
			else:
				if current_node.right:
					current_node = current_node.right
				else:
					current_node.right = TreeNode(val)
					break
		return root

	def get_nodes_smaller(self, root, val, res=None):
		if res == None:
			res = 0
		if root:
			if val > root.val: # if going to the left
				if root.left: # if the left of root exists
					res += root.left.rank # add the rank of the left subtree, since all the nodes on that left side will be smaller than val
				res += 1 # add 1 for current node
				return self.get_nodes_smaller(root.right, val, res)
			elif val < root.val: # if going to the left, cannot add anything, as we haven't encountered a node smaller than val yet
				return self.get_nodes_smaller(root.left, val, res)
			else:
				if root.left: # if the current node matches value, add the rank of left subtree, as all nodes on left will be smaller
					res += root.left.rank
				return res + 1 # add one for current node, as we check for less than equal to
		return res

	def get_min(self, root):
		if root:
			if root.left:
				return self.get_min(root.left)
			return root.val

	def get_max(self, root):
		if root:
			if root.right:
				return self.get_min(root.right)
			return root.val

a = TreeNode(49)
a.add_item(a, 46)
a.add_item(a, 43)
a.add_item(a, 79)
a.add_item(a, 64)
a.add_item(a, 83)

print(a.get_max(a))
print(a.get_nodes_smaller(a, 79))


from typing import List
from scripts.faceswaplab_ui.faceswaplab_inpainting_ui import face_inpainting_ui
from scripts.faceswaplab_swapping.face_checkpoints import get_face_checkpoints
import gradio as gr
from modules import shared
from scripts.faceswaplab_utils.sd_utils import get_sd_option

def faceswap_unit_advanced_options(
    is_img2img: bool, unit_num: int = 1, id_prefix: str = "faceswaplab_"
) -> List[gr.components.Component]:
    with gr.Accordion(f"Post-Processing & Advanced Mask Options", open=False):
        gr.Markdown(
            """Post-processing and mask settings for unit faces. Best result : checks all, use LDSR, use Codeformer"""
        )
        with gr.Row():
            face_restorer_name = gr.Radio(
                label="Restore Face",
                choices=["None"] + [x.name() for x in shared.face_restorers],
                value=get_sd_option(
                    "faceswaplab_default_upscaled_swapper_face_restorer",
                    "None",
                ),
                type="value",
                elem_id=f"{id_prefix}_face{unit_num}_face_restorer",
            )
            with gr.Column():
                face_restorer_visibility = gr.Slider(
                    0,
                    1,
                    value=get_sd_option(
                        "faceswaplab_default_upscaled_swapper_face_restorer_visibility",
                        1.0,
                    ),
                    step=0.001,
                    label="Restore visibility",
                    elem_id=f"{id_prefix}_face{unit_num}_face_restorer_visibility",
                )
                codeformer_weight = gr.Slider(
                    0,
                    1,
                    value=get_sd_option(
                        "faceswaplab_default_upscaled_swapper_face_restorer_weight", 1.0
                    ),
                    step=0.001,
                    label="codeformer weight",
                    elem_id=f"{id_prefix}_face{unit_num}_face_restorer_weight",
                )
        upscaler_name = gr.Dropdown(
            choices=[upscaler.name for upscaler in shared.sd_upscalers],
            value=get_sd_option("faceswaplab_default_upscaled_swapper_upscaler", ""),
            label="Upscaler",
            elem_id=f"{id_prefix}_face{unit_num}_upscaler",
        )

        improved_mask = gr.Checkbox(
            get_sd_option("faceswaplab_default_upscaled_swapper_improved_mask", False),
            interactive=True,
            label="Use improved segmented mask (use pastenet to mask only the face)",
            elem_id=f"{id_prefix}_face{unit_num}_improved_mask",
        )
        color_corrections = gr.Checkbox(
            get_sd_option("faceswaplab_default_upscaled_swapper_fixcolor", False),
            interactive=True,
            label="Use color corrections",
            elem_id=f"{id_prefix}_face{unit_num}_color_corrections",
        )
        sharpen_face = gr.Checkbox(
            get_sd_option("faceswaplab_default_upscaled_swapper_sharpen", False),
            interactive=True,
            label="sharpen face",
            elem_id=f"{id_prefix}_face{unit_num}_sharpen_face",
        )
        erosion_factor = gr.Slider(
            0.0,
            10.0,
            get_sd_option("faceswaplab_default_upscaled_swapper_erosion", 1.0),
            step=0.01,
            label="Upscaled swapper mask erosion factor, 1 = default behaviour.",
            elem_id=f"{id_prefix}_face{unit_num}_erosion_factor",
        )

    components = [
        face_restorer_name,
        face_restorer_visibility,
        codeformer_weight,
        upscaler_name,
        improved_mask,
        color_corrections,
        sharpen_face,
        erosion_factor,
    ]

    for component in components:
        setattr(component, "do_not_save_to_config", True)

    return components

def faceswap_unit_ui(
    is_img2img: bool, unit_num: int = 1, id_prefix: str = "faceswaplab"
) -> List[gr.components.Component]:
    with gr.Tab(f"Face {unit_num}"):
        with gr.Column():
            gr.Markdown(
                """Reference is an image. First face will be extracted.
            First face of batches sources will be extracted and used as input (or blended if blend is activated)."""
            )
            with gr.Row():
                img = gr.components.Image(
                    type="pil",
                    label="Reference",
                    elem_id=f"{id_prefix}_face{unit_num}_reference_image",
                )
                batch_files = gr.components.File(
                    type="file",
                    file_count="multiple",
                    label="Batch Sources Images",
                    optional=True,
                    elem_id=f"{id_prefix}_face{unit_num}_batch_source_face_files",
                )
            gr.Markdown(
                """Face checkpoint built with the checkpoint builder in tools. Will overwrite reference image."""
            )
            with gr.Row():
                face = gr.Dropdown(
                    choices=get_face_checkpoints(),
                    label="Face Checkpoint (precedence over reference face)",
                    elem_id=f"{id_prefix}_face{unit_num}_face_checkpoint",
                )
                refresh = gr.Button(
                    value="↻",
                    variant="tool",
                    elem_id=f"{id_prefix}_face{unit_num}_refresh_checkpoints",
                )

                def refresh_fn(selected: str):
                    return gr.Dropdown.update(
                        value=selected, choices=get_face_checkpoints()
                    )

                refresh.click(fn=refresh_fn, inputs=face, outputs=face)

            with gr.Row():
                enable = gr.Checkbox(
                    False,
                    placeholder="enable",
                    label="Enable",
                    elem_id=f"{id_prefix}_face{unit_num}_enable",
                )
                blend_faces = gr.Checkbox(
                    True,
                    placeholder="Blend Faces",
                    label="Blend Faces ((Source|Checkpoint)+References = 1)",
                    elem_id=f"{id_prefix}_face{unit_num}_blend_faces",
                    interactive=True,
                )

            gr.Markdown(
                """Select the face to be swapped, you can sort by size or use the same gender as the desired face:"""
            )
            with gr.Row():
                same_gender = gr.Checkbox(
                    False,
                    placeholder="Same Gender",
                    label="Same Gender",
                    elem_id=f"{id_prefix}_face{unit_num}_same_gender",
                )
                sort_by_size = gr.Checkbox(
                    False,
                    placeholder="Sort by size",
                    label="Sort by size (larger>smaller)",
                    elem_id=f"{id_prefix}_face{unit_num}_sort_by_size",
                )
            target_faces_index = gr.Textbox(
                value=f"{unit_num-1}",
                placeholder="Which face to swap (comma separated), start from 0 (by gender if same_gender is enabled)",
                label="Target face : Comma separated face number(s)",
                elem_id=f"{id_prefix}_face{unit_num}_target_faces_index",
            )
            gr.Markdown(
                """The following will only affect reference face image (and is not affected by sort by size) :"""
            )
            reference_faces_index = gr.Number(
                value=0,
                precision=0,
                minimum=0,
                placeholder="Which face to get from reference image start from 0",
                label="Reference source face : start from 0",
                elem_id=f"{id_prefix}_face{unit_num}_reference_face_index",
            )
            gr.Markdown(
                """Configure swapping. Swapping can occure before img2img, after or both :""",
                visible=is_img2img,
            )
            swap_in_source = gr.Checkbox(
                False,
                placeholder="Swap face in source image",
                label="Swap in source image (blended face)",
                visible=is_img2img,
                elem_id=f"{id_prefix}_face{unit_num}_swap_in_source",
            )
            swap_in_generated = gr.Checkbox(
                True,
                placeholder="Swap face in generated image",
                label="Swap in generated image",
                visible=is_img2img,
                elem_id=f"{id_prefix}_face{unit_num}_swap_in_generated",
            )

        gr.Markdown(
            """
## Advanced Options

**Simple :** If you have bad results and don't want to fine-tune here, just enable Codeformer in "Global Post-Processing".
Otherwise, read the [doc](https://glucauze.github.io/sd-webui-faceswaplab/doc/) to understand following options.

"""
        )

        with gr.Accordion("Similarity", open=False):
            gr.Markdown("""Discard images with low similarity or no faces :""")
            with gr.Row():
                check_similarity = gr.Checkbox(
                    False,
                    placeholder="discard",
                    label="Check similarity",
                    elem_id=f"{id_prefix}_face{unit_num}_check_similarity",
                )
                compute_similarity = gr.Checkbox(
                    False,
                    label="Compute similarity",
                    elem_id=f"{id_prefix}_face{unit_num}_compute_similarity",
                )
            min_sim = gr.Slider(
                0,
                1,
                0,
                step=0.01,
                label="Min similarity",
                elem_id=f"{id_prefix}_face{unit_num}_min_similarity",
            )
            min_ref_sim = gr.Slider(
                0,
                1,
                0,
                step=0.01,
                label="Min reference similarity",
                elem_id=f"{id_prefix}_face{unit_num}_min_ref_similarity",
            )

        with gr.Accordion(label="Pre-Inpainting (before swapping)", open=False):
            gr.Markdown("Pre-inpainting sends face to inpainting before swapping")
            pre_inpainting = face_inpainting_ui(
                id_prefix=f"{id_prefix}_face{unit_num}_preinpainting",
            )

        options = faceswap_unit_advanced_options(is_img2img, unit_num, id_prefix)

        with gr.Accordion(label="Post-Inpainting (After swapping)", open=False):
            gr.Markdown("Pre-inpainting sends face to inpainting before swapping")
            post_inpainting = face_inpainting_ui(
                id_prefix=f"{id_prefix}_face{unit_num}_postinpainting",
            )

    gradio_components: List[gr.components.Component] = (
        [
            img,
            face,
            batch_files,
            blend_faces,
            enable,
            same_gender,
            sort_by_size,
            check_similarity,
            compute_similarity,
            min_sim,
            min_ref_sim,
            target_faces_index,
            reference_faces_index,
            swap_in_source,
            swap_in_generated,
        ]
        + pre_inpainting
        + options
        + post_inpainting
    )

    # If changed, you need to change FaceSwapUnitSettings accordingly
    # ORDER of parameters is IMPORTANT. It should match the result of FaceSwapUnitSettings
    return gradio_components


# factorial 알고리즘 (2가지 방법)
# (1) 1~n까지 연속한 정수의 곱을 구하기

def facto(n):
  s = 1
  for i in range(1, n+1):
    s = i * s
  return s

print(facto(10))

# (2) 재귀호출을 통한 구현

def facto2(n):
  if n <= 1:
    return 1
  return n * facto2(n-1)

print(facto2(10))

# 활용1. 1~n까지 연속된 숫자 합을 재귀 함수로 구하기

# firtst trial
def sum_num(n):
  if n<= 1:
    return 1
  return n + sum_num(n-1)

print(sum_num(100))
# n=0 일 경우, return 1 ? 해당 조건일 경우 바로 종료 ?

# 활용2. 숫자 n개 중에서 재귀 함수를 이용해 최댓값 찾기

# for 문을 이용했을 때

def find_max(a):
  s = a[0]
  n = len(a)
  for i in range(0, n-1):
    for j in range(i+1, n):
      if a[i] < a[j]:
        s = a[j]
  return s

v = [13, 66, 83, 92, 100]
print(find_max(v))

# 재귀 함수를 이용했을 때