"""
Feature 4 - Upload File for Assessment Authoring
"""

import sys
import behave
from uuid import uuid4
sys.path.append("../")
from common.models import (User)
from e2e.setup import post_method, set_cache, get_cache, delete_test_files_from_gcs
from environment import TEST_ASSESSMENT_SUBMISSION_FILE_PATH
from e2e.test_object_schemas import (TEST_USER)
from e2e.test_config import API_URL_ASSESSMENT_SERVICE
import json

API_URL = API_URL_ASSESSMENT_SERVICE

#------------------------------------------------------------------------------
# Scenario 1: LXE wants to upload a single file for assessment authoring
#------------------------------------------------------------------------------
@behave.given(
    "that valid user_id exists"
)
def step_impl_1(context):
  user_dict = {**TEST_USER}
  user_dict["email"] = f"{uuid4()}@gmail.com"
  user = User.from_dict(user_dict)
  user.user_type_ref = ""
  user.user_id = ""
  user.save()
  user.user_id = user.id
  user.update()

  context.user_id = user.user_id

  set_cache("user_id_for_file_upload", user.user_id)

@behave.when(
    "API request is sent to upload a file for assessment authoring"
)
def step_impl_2(context):
  content_file = open(TEST_ASSESSMENT_SUBMISSION_FILE_PATH,"rb")
  content_file_input_dict = {"content_file":
              ("sample_assessment_authoring.txt", content_file, "text/plain")}

  content_res = post_method(
            url=f"{API_URL_ASSESSMENT_SERVICE}/assessment-authoring/upload-sync/{context.user_id}",
            files=content_file_input_dict,
            )
  context.res_json = content_res.json()
  context.status_code = content_res.status_code

@behave.then("the API will upload file to user-id/temp folder on GCS")
def step_impl_3(context):
    assert context.status_code == 200
    assert context.res_json["success"] is True
    assert context.res_json["message"] == "Successfully uploaded file"

    expected_file_path = f"assessments/{context.user_id}"
    expected_file_path+="/temp/sample_assessment_authoring.txt"

    assert context.res_json["data"]["resource_path"] == expected_file_path

    files_to_delete = [context.res_json["data"]["resource_path"]]
    set_cache("files_to_delete", json.dumps(files_to_delete))

#------------------------------------------------------------------------------
# Scenario 2: LXE wants to reupload a file with same name for assessment authoring
#------------------------------------------------------------------------------
@behave.given(
    "that valid user_id exists and file is already uploaded"
)
def step_impl_1(context):
  context.user_id = get_cache("user_id_for_file_upload")

@behave.when(
    "API request is sent to reupload a file for assessment authoring"
)
def step_impl_2(context):
  content_file = open(TEST_ASSESSMENT_SUBMISSION_FILE_PATH,"rb")
  content_file_input_dict = {"content_file":
              ("sample_assessment_authoring.txt", content_file, "text/plain")}

  content_res = post_method(
            url=f"{API_URL_ASSESSMENT_SERVICE}/assessment-authoring/upload-sync/{context.user_id}",
            files=content_file_input_dict,
            )
  context.res_json = content_res.json()
  context.status_code = content_res.status_code

@behave.then("the API will respond with validation error for already existing file with same name")
def step_impl_3(context):
    assert context.status_code == 422
    assert context.res_json["success"] is False
    assert context.res_json["message"] == f"File with same name already exists"

    # Delete Uploaded File
    files_to_delete = json.loads(get_cache("files_to_delete"))
    delete_test_files_from_gcs(files_to_delete)

#------------------------------------------------------------------------------
# Scenario 3: LXE wants to upload a file for assessment authoring with invalid user_id
#------------------------------------------------------------------------------
@behave.given(
    "that user_id is invalid"
)
def step_impl_1(context):
  context.user_id = "invalid_user_id"

@behave.when(
    "API request is sent to upload a file for assessment authoring with invalid user_id"
)
def step_impl_2(context):
  content_file = open(TEST_ASSESSMENT_SUBMISSION_FILE_PATH,"rb")
  content_file_input_dict = {"content_file":
              ("sample_assessment_authoring_1.txt", content_file, "text/plain")}

  content_res = post_method(
            url=f"{API_URL_ASSESSMENT_SERVICE}/assessment-authoring/upload-sync/{context.user_id}",
            files=content_file_input_dict,
            )
  context.res_json = content_res.json()
  context.status_code = content_res.status_code

@behave.then("the API will respond with validation error for invalid user_id")
def step_impl_3(context):
  assert context.status_code == 404
  assert context.res_json["success"] is False
  assert context.res_json["message"] == f"User with user_id {context.user_id} not found"


import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))

ch = connection.channel()

ch.exchange_declare(exchange='direct_logs', exchange_type='direct')
result = ch.queue_declare(queue='', exclusive=True)
qname = result.method.queue

severity = 'ERROR'
ch.queue_bind(queue='', exchange='direct_logs', routing_key=severity)
print('waiting...')

def callback(ch, method, properties, body):
    with open('error_log.log', 'a') as f:
        f.write(f'str({body}) \n')
    ch.basic_ack(delivery_tag=method.delivery_tag)

ch.basic_consume(queue=qname, on_message_callback=callback)
ch.start_consuming()


import time
from rq import get_current_job
from app.app import create_app
from app.models import Task
from app.extensions import db
from flask import current_app
from cron import run
import sys
import traceback
import datetime

app = create_app()
app.app_context()

def launch_task(name, description, *args, **kwargs):
    rq_job = current_app.task_queue.enqueue('app.tasks.' + name,
                                            *args, **kwargs)
    task = Task(id=rq_job.get_id(), name=name, description=description)
    db.session.add(task)
    return task

def _set_task_progress(progress, status=None):
    job = get_current_job()
    if job:
        job.meta['progress'] = progress
        job.save_meta()
        task = Task.query.get(job.get_id())
        if status:
            task.status = status
        if progress >= 100:
            task.complete = True
            task.completed_at = db.func.current_timestamp()
        db.session.commit()

def full_sync():
    try:
        _set_task_progress(0, "job started")
        run()
    except Exception as e:
        _set_task_progress(100, f"The following error ocurred, check the logs for more information: {e}")
        traceback.format_exception(*sys.exc_info())
        raise
    _set_task_progress(100, "The sync completed successfully.")
    print('Task Completed')


#importando as bibliotecas q iremos usar
import plotly.express as px
import pandas as pd
from dash import Dash, html, dcc

#iniciando um app
app = Dash(__name__)

#criando os dados que iremos usar como teste
df = pd.DataFrame({
    "Fruit":["Apples","Oragens","Bananas","Apples","Oragens","Bananas",],
    "Amount":[4,1,2,2,4,5],
    "City":["SF","SF","SF","Montreal","Montreal","Montreal"]
})

#criando o grafico que iremos usar os dados

fig = px.bar(df,x="Fruit",y="Amount",color="City",barmode="group",text_auto=True)

#adicionando os dados no app
app.layout = html.Div(children=[
    html.H1(children="Olá Dash"),

    html.Div(children='''Dash: A web de aplicações de dados para você, fiz uma alteração'''),

    dcc.Graph(
        id="Exemplo de grafico",
        figure=fig
    )
])

#finalizando o app

if __name__ == "__main__":
    app.run(debug=True)


#! /usr/bin/env python3
#------------------------ IMPORTS --------------------------#
from __future__ import annotations
from app import *
from websocket import WebSocketConnectionClosedException
from threading import Thread
from time import sleep, time
from random import random, uniform

@dataclass(slots=True)
class Receiver:
    #Pointers
    session: DiscordWrapper
    config: ConfigManager
    menu: MainMenu

    #Objects
    captcha: Captcha = field(init=False)
    profile: Profile = field(default_factory=Profile)
    message: Message = field(default_factory=Message)
    category: MessageCategory = field(default_factory=MessageCategory)
    event: dict = None

    #Flags
    is_ready: bool = False

    def __post_init__(self) -> None:
        '''Setups captcha.'''
        self.captcha = Captcha(api_key=self.config.ocr_api_key, menu=self.menu)

    @property
    def name(self) -> str:
        '''Returns the class name in the correct format.'''
        return f'{self.__class__.__name__}'

    def check_event(self, response: dict) -> bool:
        '''Checks if event is targeted to the user (sent by the application to the selected channel),
        also defines the self.event.'''
        if not response:
            return False

        try:
            e = response['d']
            e_name = response['t']
            e_channel = e['channel_id']
            e_author = e['author']['id']
        except (KeyError, TypeError):
            return False

        if e_name in TARGET_EVENT_NAMES:
            if e_channel == self.config.channel_id:
                if e_author == APPLICATION_ID:
                    self.event = e
                    return True
        return False

    def run(self) -> None:
        '''Main loop, continuously checks for new gateway events and properly handles it.'''
        self.is_ready = True
        while True:
            try:
                response = self.session.receive_event()
            except WebSocketConnectionClosedException as e:
                debugger.log(e, f'{self.name} - run - reconnection')
                #Connection lost
                self.is_ready = False
                self.menu.notify('[!] Connection lost, attempting to reconnect...', NotificationPriority.HIGH)
                if self.session.reconnect():
                    self.is_ready = True
                    self.menu.notify('[*] Reconnection succeeded.')
                    continue
                else:
                    self.menu.kill()
                    print(f'[E] Reconnection failed. Exception: {e}')
                    break
            except Exception as e:
                debugger.log(e, f'{self.name} - run - reconnection')
                break

            if not self.check_event(response):
                #Invalid/Irrelevant gateway event
                continue

            self.message.make(self.event)

            if self.captcha.detected and not self.captcha.regenerating:
                if self.message.content == 'You may now continue.':
                    #Captcha bypassed
                    self.menu.rcv_bypasses += 1
                    self.captcha.reset()
                    self.menu.notify('[*] Captcha bypassed !')
                else:
                    if self.message.content.find('Incorrect code') > -1:
                        self.menu.notify('[*] Incorrect code.', NotificationPriority.LOW)
                        continue
                    else:
                        #Message sent by the bot while captcha is detected
                        debugger.log(self, f'{self.name} - run (Message sent by the AFB while captcha is detected)')
                        break
            elif self.captcha.regenerating:
                if self.captcha.detect(self.event):
                    self.captcha.solve()
                    continue
                else:
                    #No detection while regenerating
                    debugger.log(self, f'{self.name} - run (No detection while regenerating)')
                    exit()
            else:
                if self.captcha.detect(self.event):
                    self.menu.notify('[!] Captcha detected !', NotificationPriority.NORMAL)
                    self.captcha.solve()
                    continue
                else:
                    if self.message.title:
                        #Normal messages
                        if self.message.title == self.category.fish:
                            #Fish (/fish or button) messages
                            self.menu.items = self.message.build()
                            self.menu.rcv_streak += 1
                        elif self.message.title.find(self.category.profile) > -1:
                            #Profile (/profile) messages
                            self.profile.update(self.message.description)
                            self.menu.notify('[*] Profile updated.')
                        elif self.message.title.find(self.category.charms) > -1:
                            #Charms (/charms) messages
                            self.profile.charms.update(self.message.description)
                            self.menu.notify('[*] Charms updated.')
                        elif self.message.title.find(self.category.buffs) > -1:
                            #Buffs/multipliers (/buffs) messages
                            self.profile.buffs.update(self.message.description)
                            self.menu.notify('[*] Buffs updated.')
                        elif self.message.title.find(self.category.quests) > -1:
                            #Quest list (/quests) messages
                            self.profile.quests.update(self.message.description)
                            self.menu.notify('[*] Quests updated.')
                        elif self.message.title.find(self.category.leaderboard) > -1:
                            #Leaderboard (/pos) messages
                            self.profile.leaderboard.update(self.message.description)
                            self.menu.notify('[*] Leaderboards updated.')
                        #Todo: read '... boost ended' message and inform scheduler (?)
                        #Your fishing boost ended!
                        #Your treasure boost ended!
                        else:
                            #Unhandled titled message
                            self.menu.notify(f'{sanitize(self.message.title)}: {sanitize(self.message.description)}')
                            pass
                    else:
                        #Untitled messages
                        if self.message.content:
                            if self.message.content.find('You must wait') > -1:
                                #Intentional short cooldown
                                self.menu.notify(
                                    '[*] If automatic, this short cooldown is intentional to ensure non-bot behavior.',
                                    NotificationPriority.VERY_LOW
                                    )
                                pass
                            else:
                                #Untitled message
                                self.menu.notify(f'[*] {self.message.untitled}')
                        else:
                            #Untitled with empty content  - probably embeded only with description
                            if menu.is_alive:
                                self.menu.notify(f'[*] {self.message.untitled}')
                            else:
                                if self.message.untitled.find('You hired a worker for the next') > -1 \
                                    or self.message.untitled.find('You already have a worker working') > -1:
                                    print(f'[*] {self.message.untitled}')
                            pass

        self.is_ready = False
        exit()

@dataclass(slots=True)
class Dispatcher:
    '''Dispatcher class, responsible for making, sending commands related to
    captcha and fish commands.'''
    #Pointers
    session: DiscordWrapper
    config: ConfigManager
    menu: BaseMenu
    sch: Scheduler
    rcv: Receiver
    captcha: Captcha = field(init=False)
    message: Message = field(init=False)

    #Objects
    cooldown: CooldownManager = field(init=False)

    #Flags
    in_cooldown: bool = False
    paused: bool = False

    def __post_init__(self) -> None:
        #Setting up pointers to improve organization
        self.captcha = self.rcv.captcha
        self.message = self.rcv.message

        #Instantiate cooldown manager
        self.cooldown = CooldownManager(user_cooldown=self.config.user_cooldown)

    def make_command(self, cmd: str, name: str, value: str, type: int = 3) -> tuple:
        '''Builds a tuple containing the command (str) and the 'options' parameter (dict).'''
        parameters = {
            "type": type,
            "name": name,
            "value": value
        }
        return (cmd, parameters)

    @property
    def name(self) -> str:
        '''Returns the class name in the correct format.'''
        return f'{self.__class__.__name__}'

    @property
    def pause(self) -> None:
        '''Play/Pause switch.'''
        if self.sch.status == SchStatus.BREAK:
            self.sch.interrupt_break()
        if self.paused:
            self.paused = False
            self.menu.notify('[*] Autofishbot resumed.')
        else:
            self.paused = True
            self.menu.notify('[*] Autofishbot paused.')

    @property
    def timeout(self) -> float:
        '''Timeout cooldown for general commands (other than fish commands).'''
        return self.cooldown.custom(
            mu= uniform(3, 5),
            sigma= random()
        )

    def run(self) -> None:
        '''Main loop, send commands'''
        _delay = 0.2

        while True:
            if not self.rcv.is_ready:
                sleep(_delay)
                continue

            if self.captcha.detected and not self.captcha.regenerating:
                if self.captcha.solving or len(self.captcha.answers) > 0:
                    try:
                        answer = self.captcha.answers.pop()
                        self.menu.notify(f'[!] Attempting code: "{answer}".')
                        cmd, param = self.make_command('verify', 'answer', answer)
                        self.session.request(command=cmd, parameters=param, category=COMMAND)

                        sleep(self.timeout)
                    except IndexError:
                        continue
                else:
                    if self.captcha.regens < MAX_CAPTCHA_REGENS:
                        self.captcha.regens += 1
                        self.menu.notify(f'[!] Regenerating captcha ({self.captcha.regens + 1}/{MAX_CAPTCHA_REGENS})', NotificationPriority.HIGH)

                        #This will force a new event to be analyzed by the
                        #detect() method but also keep the captcha.regens counter
                        self.captcha.regenerating = True

                        cmd, param = self.make_command('verify', 'answer', 'regen')
                        self.session.request(command=cmd, parameters=param, category=COMMAND)

                        #This sleep timeout might be needed in case of really slow
                        #connections, it might be caused by a bad proxy or internet
                        #?Further testing needed
                        sleep(1)
                    else:
                        self.menu.notify(f'[!] MAXIMUM CAPTCHA REGENS EXCEEDED, WAITING FOR MANUAL INPUT !', NotificationPriority.VERY_HIGH)
                        #Max regens attempts exceeded, waits for manual input
                        while self.captcha.detected:
                            sleep(1)
            else:
                while  self.captcha.busy \
                    or self.captcha.regenerating \
                    or self.sch.status in [SchStatus.BUSY, SchStatus.BREAK]:
                        sleep(_delay)

                if not self.captcha.detected and not self.paused and self.menu.is_alive:
                    _start = time()

                    if self.message.id and self.message.play_id:
                        if self.session.request(message_id=self.message.id, custom_id=self.message.play_id, category=BUTTON):
                            #Successfull interaction with buttons
                            pass
                        else:
                            #Failed interaction, reset ids to trigger ussage of slash commands
                            self.message.reset_ids()
                    else:
                        self.session.request(command='fish', category=COMMAND)

                    self.in_cooldown = True
                    sleep(abs(self.cooldown.new() - (time() - _start)))
                    self.in_cooldown = False
                else:
                    sleep(_delay)

#------------------------ INIT --------------------------#
if __name__ == "__main__":
    print(f'\n[*] Starting...')

    #Loads config
    config = ConfigManager()

    #Setup debugger
    debugger.setup(config.debug)

    #Instantiate menu
    if config.compact_mode:
        menu = CompactMenu()
    else:
        menu = MainMenu()

    #Instantiate session
    session = DiscordWrapper(
        config=config,
        menu=menu,
        auto_connect=True)

    #Instantiate receiver
    receiver = Receiver(
        session=session,
        config=config,
        menu=menu)

    #Instantiate Scheduler
    scheduler = Scheduler(
        session=session,
        config=config,
        menu=menu,
        captcha=receiver.captcha)

    #Instantiate dispatcher
    dispatcher = Dispatcher(
        session=session,
        config=config,
        menu=menu,
        sch=scheduler,
        rcv=receiver)

    #Async flow
    rcv_thread = Thread(target=receiver.run, daemon=True, name='Receiver')
    sch_thread = Thread(target=scheduler.run, args=(dispatcher,), daemon=True, name='Scheduler')
    dsp_thread = Thread(target=dispatcher.run, daemon=True, name='Dispatcher')

    rcv_thread.start()
    sch_thread.start()
    dsp_thread.start()

    #Start menu
    menu.run(
        config=config,
        dispatcher=dispatcher,
        profile=receiver.profile,
        scheduler=scheduler,
        threads=[rcv_thread, sch_thread, dsp_thread]
    )

    if config.fish_on_exit and menu.rcv_streak > 0:
        cmd, data = scheduler.commands.worker.data
        session.request(command=cmd, parameters=data)
        sleep(3)

    session.disconnect()
    exit(f'\n[!] User exited.')


# -*- coding: utf-8 -*-
"""
Migrate permissions
"""
import sys

from django.apps import apps
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.db.utils import IntegrityError
from django.utils.translation import gettext as _

from guardian.models import UserObjectPermissionBase

from onadata.libs.utils.model_tools import queryset_iterator

User = get_user_model()

class Command(BaseCommand):
    """Migrate permissions"""

    help = _("Migrate permissions")

    def add_arguments(self, parser):
        parser.add_argument(
            "--model",
            "-m",
            action="store_true",
            dest="app_model",
            default=False,
            help="The model the permission belong too." " (app.model format)",
        )
        parser.add_argument(
            "--perm-table",
            "-p",
            action="store_true",
            dest="perms_tbl",
            default=False,
            help="The new model permission are stored in" " (app.model format)",
        )

    def handle(self, *args, **options):
        self.stdout.write("Migrate permissions started", ending="\n")

        if len(args) < 2:
            self.stdout.write(
                "This command takes two argument -m and -p "
                "Example: "
                "-m logger.Team "
                "-p logger.TeamUserObjectPermission"
            )
            sys.exit()

        if options["app_model"]:
            app_model = args[0]
        else:
            self.stdout.write("-m , should be set as the first argument")
            sys.exit()

        if options["perms_tbl"]:
            perms_tbl = args[1]
        else:
            self.stdout.write("-p , should be set as the second argument")
            sys.exit()

        model = apps.get_model(app_model)
        perms_model = apps.get_model(perms_tbl)

        if not issubclass(perms_model, UserObjectPermissionBase):
            self.stdout.write(
                "-p , should be a model of a class that is "
                "a subclass of UserObjectPermissionBase"
            )
            sys.exit()

        content_type = ContentType.objects.get(
            model=model.__name__.lower(), app_label=model._meta.app_label
        )

        # Get all the users
        users = User.objects.exclude(
            username__iexact=settings.ANONYMOUS_DEFAULT_USERNAME
        ).order_by("username")

        for user in queryset_iterator(users):
            self.stdout.write(f"Processing: {user.pk} - {user.username}")
            for uop in (
                user.userobjectpermission_set.filter(content_type=content_type)
                .select_related("permission", "content_type")
                .prefetch_related("permission", "content_type")
            ):
                try:
                    perms_model(
                        content_object=uop.content_object,
                        user=user,
                        permission=uop.permission,
                    ).save()
                except IntegrityError:
                    continue
                except ValueError:
                    pass


import numpy as np
from catboost import CatBoostRegressor

from pyepal.pal.pal_catboost import PALCatBoost

def test_pal_catboost(binh_korn_points):
    models = [
        CatBoostRegressor(
            iterations=5000,
            learning_rate=0.05,
            loss_function="RMSEWithUncertainty",
            posterior_sampling=True,
            silent=True,
        )
        for _ in range(2)
    ]

    X_binh_korn, y_binh_korn = binh_korn_points  # pylint:disable=invalid-name

    sample_idx = np.array([0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90, 95, 99])

    pal = PALCatBoost(
        X_binh_korn, models, 2, beta_scale=1 / 15, epsilon=0.05, coef_var_threshold=100
    )

    pal.cross_val_points = 0

    pal.update_train_set(sample_idx, y_binh_korn[sample_idx])
    _ = pal.run_one_step()
    assert pal.number_discarded_points == 0
    assert pal.number_unclassified_points < 100


# MIT License
#
# Copyright (c) [2020] [Antonio Domènech L., Daniela Tarzia]
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from math import hypot
from Deteccion import *

########################################################################################################################
########################################################################################################################
##################################################### Ratio ############################################################

#La clase Ratio es para determinar los movimientos que hace la cara, los ojos y la boca.
class Ratio:

    #Crea el objeto detección
    def __init__(self):
        self.t = Deteccion()

    #Retorna el punto medio entre dos puntos
    def midpoint(self, point1, point2):
        mp = int((point1[0] + point2[0]) / 2), int((point1[1] + point2[1]) / 2)
        return(mp)

    #Retorna la distancia en valor absoluto entre dos puntos
    def distance(self, point1, point2):
        d = abs(hypot((point2[0] - point1[0]), (point2[1] - point1[1])))
        return(d)

    #Extrae puntos de interes a partir de una imagen
    def extraer_puntos(self, grayimage):
        # lista de puntos utiles
        points = [30,33,29,17,26,45,42,43,47,39,36,38,40,62,66,48,54,44,46,37,41]
        puntos = self.t.detect_landmarks(grayimage, points) #Obtenemos las coordenadas de cada punto

        #Puntos de la nariz
        self.nariz = puntos[0:2] #Punto 30
        self.nariz_inf = puntos[2:4] #Punto 33
        self.nariz_sup = puntos[4:6] #Punto 29
        self.nariz_derecha = puntos[6:8] #Punto 17
        self.nariz_izquierda = puntos[8:10] #Punto 26

        #Punto del ojo izquierdo
        self.ojo_izquierdo_izquierda = puntos[10:12] #Punto 45
        self.ojo_izquierdo_derecha = puntos[12:14] #Punto 42
        self.ojo_izquierdo_arriba1 = puntos[14:16] #Punto 43
        self.ojo_izquierdo_arriba2 = puntos[34:36] #Punto 44
        self.ojo_izquierdo_abajo1 = puntos[16:18] #Punto 47
        self.ojo_izquierdo_abajo2 = puntos[36:38] #Punto 46

        #Puntos del ojo derecho
        self.ojo_derecho_izquierda = puntos[18:20] #Punto 39
        self.ojo_derecho_derecha = puntos[20:22] #Punto 36
        self.ojo_derecho_arriba1 = puntos[22:24] #Punto 38
        self.ojo_derecho_arriba2 = puntos[38:40] #Punto 37
        self.ojo_derecho_abajo1 = puntos[24:26] #Punto 40
        self.ojo_derecho_abajo2 = puntos[40:] #Punto 41

        #Puntos de la boca
        self.labio_superior = puntos[26:28] #Punto 62
        self.labio_inferior = puntos[28:30] #Punto 66
        self.labio_derecha = puntos[30:32] #Punto 48
        self.labio_izquierda = puntos[32:34] #Punto 54

########################################################################################################################
################################################# Ratios ###############################################################
########################################################################################################################

    #Calcula un ratio que define la apertura de la boca
    def ratio_labios(self):
        # medimos la distancia entre puntos en horizontal y en vertical
        ver = Ratio.distance(self, self.labio_superior, self.labio_inferior)
        hor = Ratio.distance(self, self.labio_izquierda, self.labio_derecha)

        #Evitamos valores negativos para la distancia vertical
        if(ver < 0):
            ver = 0

        #Se dividen las distancias y obtenemos un ratio que nos indica la apertura de la boca
        ratio = (hor/ver)
        return(ratio)

    #Calcula el ratio horizontal de la cara
    def ratio_horizontal(self):
        #Medimos las distancias entre centro - derecha y centro - izquierda
        derecha = Ratio.distance(self, self.nariz, self.nariz_derecha)
        izquierda = Ratio.distance(self, self.nariz, self.nariz_izquierda)

        #Se dividen las distancias y obtenemos un ratio que nos indica el movimiento horizontal de la cara
        ratio = (derecha/izquierda)
        return(ratio)

    #Calcula el ratio vertical de la cara
    def ratio_vertical(self):
        #Medimos las distancias entre centro - arriba y centro - abajo
        arriba = Ratio.distance(self, self.nariz, self.nariz_sup)
        abajo = Ratio.distance(self, self.nariz, self.nariz_inf)

        #Se dividen las distancias y obtenemos un ratio que nos indica el movimiento vertical de la cara
        ratio = (arriba / abajo)
        return (ratio)

    #Calcula el ratio de apertura/cierre del ojo derecho
    def ratio_ojo_derecho(self):
        #Medimos la media entre los dos puntos superiores e inferiores del ojo
        centro_arriba = Ratio.midpoint(self, self.ojo_derecho_arriba1, self.ojo_derecho_arriba2)
        centro_abajo = Ratio.midpoint(self, self.ojo_derecho_abajo1, self.ojo_derecho_abajo2)

        #Medimos la distancia media superior - media inferior y derecha - izquierda
        horizontal = Ratio.distance(self, self.ojo_derecho_derecha, self.ojo_derecho_izquierda)
        vertical = Ratio.distance(self, centro_arriba, centro_abajo)

        #Se dividen las distancias y obtenemos un ratio que nos indica la apertura/cierre del ojo derecho
        ratio = (horizontal / vertical)
        return(ratio)

    #Calcula el ratio de apertura/cierre del ojo izquierdo
    def ratio_ojo_izquierdo(self):
        #Medimos la media entre los dos puntos superiores e inferiores del ojo
        centro_arriba = Ratio.midpoint(self, self.ojo_izquierdo_arriba1, self.ojo_izquierdo_arriba2)
        centro_abajo = Ratio.midpoint(self, self.ojo_izquierdo_abajo1, self.ojo_izquierdo_abajo2)

        #Medimos la distancia media superior - media inferior y derecha - izquierda
        horizontal = Ratio.distance(self, self.ojo_izquierdo_derecha, self.ojo_izquierdo_izquierda)
        vertical = Ratio.distance(self, centro_arriba, centro_abajo)

        #Se dividen las distancias y obtenemos un ratio que nos indica la apertura/cierre del ojo izquierdo
        ratio = (horizontal / vertical)
        return (ratio)

########################################################################################################################
############################################### Calibración ############################################################
########################################################################################################################

    #Calcula el valor exacto del ratio donde el ojo pasa de abierto a cerrado y viceversa
    def calibracion_ojo(self, lim_abierto, lim_cerrado):
        RatioOjo = (lim_cerrado + lim_abierto) / 2
        return(RatioOjo)

    #Calcula los valores del ratio que separan los estados de subir, bajar, o qudarse centrado
    def calibracion_cara_vertical(self, lim_up, lim_down, center):
        media_up = (lim_up + center) / 2
        media_down = (center + lim_down) / 2
        return(media_up, media_down)

    #Calcula los valores del ratio que separan los estados de derecha, izquierda o centro
    def calibracion_cara_horizontal(self, lim_right, lim_left, center):
        media_right = (center + lim_right) / 2
        media_left = (center + lim_left) / 2
        return (media_right, media_left)

##################################################### FIN ##############################################################
########################################################################################################################
########################################################################################################################

if __name__ == '__main__':
    import cv2
    from Deteccion import *
    capture = cv2.VideoCapture(0)

    _, frame = capture.read()  # obtenermos la captura
    grayimage = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # Escala de grises

    r = Ratio()
    r.extraer_puntos(grayimage)
    a = r.ratio_vertical()
    b = r.ratio_horizontal()
    c = r.ratio_ojo_derecho()
    e = r.ratio_ojo_izquierdo()

    print(a)
    print(b)
    print(c)
    print(e)


# program reads individual files created by get_data_from_bloomberg.py and aggregates them
# compiled dataframe is stored in this csv
dataframe_csv_filename ="./data/compiled_dataframe.csv"
CREATE_NEW_CSV = True
# Write here the list of files to aggregate - to work, each file must first be individually processed by get_data_from_bloomberg.py
copypaste_files_list  = [
    "./data/copypastePaloAlto.xlsx",
    "./data/copypasteDAFNA",
    "./data/copypasteBakerBros",
    # "copypasteBVF.xlsx",
    # "copypastePerceptiveNew",
    # "copypasteRA",
    # "copypasteRTW",
    # "copypasteRedmile",
    # "copypasteEcoR1",
    # "copypasteOrbimed",
    # "copypasteAvoro",
    # "copypasteCormorant",
    # "copypasteBoxer",
    #
    ]

import openpyxl as xl  # openpyxl is an excel manipulation library
import pandas as pd
import numpy as np
import utils
import pickle
import os

if CREATE_NEW_CSV:
    try:
        os.remove(dataframe_csv_filename)
    except:
        pass

try:
    df = pd.read_csv(dataframe_csv_filename) #try reading an existing csv
except:
    df = pd.DataFrame(columns = ['Fund Name', 'Name', 'Date', 'Ticker', 'Market Cap', 'Market Val Wgt', 'Market Val',
                       'Position', 'PX Close', 'PX Last', 'Prev Date', 'PX Last Prev Date', 'PX Ratio', 'Next Date',
                       'PX Last Next Date', 'PX Ratio Next']) #...if it doesn't exist, create the dataframe df

# run through various raw and pickle files one at a time
for copypaste_file in copypaste_files_list:

    print(f"Processing {copypaste_file}")
    read_from_file = "./data/"+ copypaste_file.split('.')[1].split('/')[-1] + "_raw.xlsx"
    get_ranges_from_file =  "./data/"+ copypaste_file.split('.')[1].split('/')[-1]  + "_ranges.pickle"

    ranges = pickle.load(open(get_ranges_from_file,'rb'))

    # open an existing xlsx
    wb_in = xl.load_workbook(filename = read_from_file, read_only = True)
    wb_in_data = wb_in['Data']

    for idx,r in enumerate(ranges):
        int_start = r['report_row_start']
        int_stop = r['report_row_stop']
        print('New Range')

        df1 = utils.load_workbook_range(f'A{int_start}:P{int_stop}', wb_in_data)
        df1.columns = ['Name', 'tobedeleted', 'Date', 'Ticker', 'Market Cap', 'Market Val Wgt', 'Market Val',
                       'Position', 'PX Close', 'PX Last', 'Prev Date', 'PX Last Prev Date', 'PX Ratio', 'Next Date',
                       'PX Last Next Date', 'PX Ratio Next'] #define a preliminary dataframe, using existing columns
        df1 = df1.drop(columns=['tobedeleted'])

        df_fundname = utils.load_workbook_range(f'A{int_start-1}:A{int_start-1}', wb_in_data)    #for each raw copypaste file, the fundname is (-1,-1) relative to the data
        fundname = df_fundname['A'].values[0]   #

        df1['Fund Name'] = fundname #append 'Fund Name' to the preliminary df1

        df = df.append(df1) #add this column to the processed dataframe df, that we are going to use-- this will automatically add the data to the already existing 'Fund Name' column in df

    wb_in.close()

df.to_csv(dataframe_csv_filename, index = False)


import pandas as pd
import numpy as np
# Módulo para referenciar tipagens
from typing import List, Any, Tuple
import os

if (os.system("pip install multipledispatch") == 0):
    print("------------------------------------------------")
    print("   multipledispatch instalado com sucesso!")
    print("------------------------------------------------")
else:
    print("------------------------------------------------\n")
    print("Não foi possível instalar o multipledispatch.")
    print("\n------------------------------------------------")

# Módulo externo para criar sobrecargas de funções
from multipledispatch import dispatch

class ExtratorDeProbabilidades:
    # Letra a
    def __init__(self, path: str) -> None:
        # Seta o path como um atributo da classe; não será usado1

        self.path = path
        try:
            # Cria o dataframe a partir do path passado
            self.df = pd.read_csv(path, sep=',', encoding="iso-8859-1")

        except:
            self.df = pd.DataFrame({})
            print("------------------------------------------------")
            print("    Ocorreu um erro ao carregar o arquivo.")
            print("------------------------------------------------")
            os.system("pause")
            os.system("cls")

    # Letra b
    def carregar_colunas(self, lista_colunas: List[str], quantidade: int) -> pd.DataFrame:
        try:
            # Tenta carregar as colunas baseado no limite que o usuário desejar;
            return self.df[lista_colunas][:quantidade]
        except:
            print("------------------------------------------------")
            print("    Ocoreu um erro ao carregar as colunas")
            print("------------------------------------------------")
            os.system("pause")
            os.system("cls")
    # Letra c
    def descarregar_colunas(self) -> None:
        self.df = pd.DataFrame({})

    # Letra d
    def probabilidade_apriori(self, caracteristica: str, valor: Any) -> float or None:
        try:
            # Filtra o dataframe pela coluna desejada da tabela e calcula o tamanho
            num_espec = len(self.df[self.df[caracteristica] == valor])
            # Retorna o tamanho do tabela filtrada dividido pela tabela total
            return num_espec/len(self.df)
        except:
            print("------------------------------------------------")
            print("  Ocorreu um erro ao calcular a porcentagem.")
            print("------------------------------------------------")
            os.system("cls")

    # Letra e
    @dispatch(str, tuple) # Decorator usado para utilizar a sobrecarga; como definido na questão, a função deve possuir mesmo nome
    def probabilidade_apriori_intervalo(self, caracteristica: str, intervalo: Tuple[int, int]) -> float or None:
        try:

            inicio, fim = intervalo
            num_espec = len(self.df[caracteristica][inicio:fim])
            return num_espec / len(self.df[caracteristica])

        except:
            print("------------------------------------------------")
            print("  Ocorreu um erro ao calcular a porcentagem.")
            print("------------------------------------------------")
            os.system("pause")
            os.system("cls")

    # Letra f
    def probabilidade_condicional(self, cond_a: Tuple[str, str], cond_b: Tuple[str, str]) -> float or None:
        try:
            # Recebe duas colunas e valores a serem filtrados
            carac_a, val_a = cond_a
            carac_b, val_b = cond_b
            # Cria duas condições que serão utilizadas para gerar o filtro no dataframe
            filter_a = self.df[carac_a] == val_a
            filter_b = self.df[carac_b] == val_b
            # Retorna o tamanho das duas condições a e b aplicadas no dataframe dividido pelo tamanho do dataframe aplicado à condição b
            return len(self.df[filter_a & filter_b])/len(self.df[filter_b])
        except:
            print("------------------------------------------------")
            print("  Ocorreu um erro ao calcular a porcentagem.")
            print("------------------------------------------------")
            os.system("pause")
            os.system("cls")

    # Letra g
    @dispatch(tuple, tuple)
    def probabilidade_apriori_intervalo(self, a: Tuple[str, str], b: Tuple[str, Tuple[int, int]]):
        try:
            carac, valor = a
            _, (inicio, fim) = b

            try:
                qtd_filtro = (self.df[carac][inicio:fim] == valor).value_counts()[True]
            except KeyError:
                qtd_filtro = 0

            qtd_total = len(self.df[carac] == valor)
            return qtd_filtro/qtd_total

        except ZeroDivisionError:
            return 0

    # Desafios
    def desafio_a(self, a: Tuple[str, str], b: Tuple[str, str], column=str, percentage: float = 0.9):
        try:
            carac_a, valor_a = a
            carac_b, valor_b = b
            modelos = self.df[(self.df[carac_a] == valor_a) & (self.df[carac_b] < valor_b)][column].value_counts(normalize=True) > percentage
            # Cria um conjunto que irá guardar o valor dos carros
            carros = set()
            # Itera sobre os valores verdade da tabela criada pelo filtro, junto aos índices, que nesse caso
            for modelo, valor in zip(modelos.index, modelos):
                # Caso o valor seja true, adiciona o modelo do carro no conjunto
                if valor == True: carros.add(modelo)
            # Retorna o conjunto de carros caso exista pelo menos um, caso contrário retorna "{}"
            return carros if carros else "{}"
        except:
            print("Ocorreu um erro ao resolver o desafio.")

    def desafio_b(self, a: Tuple[str, str], b: Tuple[str, str], pct: float):
        try:
            # Gera um dataframe com os filtros passados
            carac_a, valor_a = a
            carac_b, valor_b = b
            valores = self.df[(self.df[carac_a] == valor_a) & (self.df[carac_b] == valor_b)]
            # Caso o índice seja maior que 2, iremos receber o primeiro e último índice
            if len(valores.index) >= 2:
                # Retorna o primeiro e o último índice, representando os limites
                val = len(valores.index)
                for i in range(val):
                    if (i/val) > pct: break
                return (valores.index[0], valores.index[i])
            # Caso haja apenas um valor, não faz sentido querer enviar um range, pois qualquer range contendo o valor
            # satisfaz a condição; nesse caso enviamos apenas o índice do valor que satisfaz a condição
            elif len(valores.index) == 1:
                return {valores.index[0]}
            else:
                # Caso não exista, retorna None
                return None
        except:
            print("Ocorreu um erro ao resolver o desafio.")

    def menu(self):
        print(" __________________________________________________")
        print("|1 - Carregar Arquivo                              |")
        print("|2 - Mostrar DataFrame                             |")
        print("|3 - Carregar Colunas                              |")
        print("|4 - Probabilidade à Priori                        |")
        print("|5 - Probabilidade à Priori - Intervalo            |")
        print("|6 - Probabilidade Condicional                     |")
        print("|7 - Probabilidade à Priori - Intervalo (Tipo 2)   |")
        print("|8 - Desafio                                       |")
        print("|9 - Descarregar Arquivo                           |")
        print("|10- Créditos                                      |")
        print("|0 - Sair                                          |")
        print("|__________________________________________________|")
        print()

        opt = int(input("Insira o número relativo à operação desejada: "))
        if (opt == 1):

            filename = input("\nInsira o filename: ")
            self.__init__(filename)
            print("<<<------------------------------------------>>>")
            print("     BASE DE DADOS CARREGADA COM SUCESSO!")
            print("<<<------------------------------------------>>>")
            os.system("pause")
            os.system("cls")
            return True

        elif (opt == 2):
            os.system("cls")
            print(self.df)
            os.system("pause")
            os.system("cls")
            return True

        elif (opt == 3):
            print("------------------------------------------------")
            colunas = input("Insira o nome das colunas que deseja verificar, separadas por espaço: ").split()
            lim = int(input("Insira a quantidade de elementos desejada: "))
            print(self.carregar_colunas(colunas, lim))
            os.system("pause")
            os.system("cls")
            return True

        elif (opt == 4):
            print("------------------------------------------------")
            carac = input("Insira a coluna: ")
            val = input("Insira o valor")
            print(self.probabilidade_apriori(carac, val))
            os.system("pause")
            os.system("cls")
            return True

        elif (opt == 5):
            print("------------------------------------------------")
            carac = input("Insira a coluna desejada: ")
            inf = input("Insira o limite inferior: ")
            sup = input("Insira o limite superior: ")
            print(self.probabilidade_apriori_intervalo(carac, (inf, sup)))
            os.system("pause")
            os.system("cls")
            return True

        elif (opt == 6):
            print("------------------------------------------------")
            cond_a, valor_a = input("Insira a coluna e o valor seguidos por espaço: ").split()
            cond_b, valor_b = input("Insira a segunda coluna e o valor seguidos por espaço: ").split()
            print(self.probabilidade_condicional((cond_a, valor_a), (cond_b, valor_b)))
            os.system("pause")
            os.system("cls")
            return True

        elif (opt == 7):
            print("------------------------------------------------")
            os.system("cls")
            cond, valor = input("Insira a coluna e o valor seguidos por espaço: ").split()
            inf = input("Insira o limite inferior: ")
            sup = input("Insira o limite superior: ")
            print(self.probabilidade_apriori_intervalo((cond, valor), (cond, (inf, sup))))
            os.system("pause")
            os.system("cls")
            return True

            print(self.desafio_a((cond_a, valor_a), (cond_b, valor_b), col, pct))

        elif (opt == 8):
            print("------------------------------------------------")
            cond_a, valor_a = input("Insira a coluna e o valor seguidos por espaço: ").split()
            cond_b, valor_b = input("Insira a segunda coluna e o valor seguidos por espaço: ").split()
            pct = float(input("Insira a porcentagem entre 0 e 1: "))
            print(self.desafio_b((cond_a, valor_a), (cond_b, valor_b), pct))
            os.system("pause")
            os.system("cls")

        elif (opt == 9):
            os.system("cls")
            self.descarregar_colunas()
            print("------------------------------------------------")
            print("     Dataframe limpo com sucesso!")
            print("------------------------------------------------")
            os.system("pause")
            os.system("cls")
            return True

        elif (opt == 10):
            os.system("cls")
            print("  ______________________________________________ ")
            print(" |                                              |")
            print(" |     2º Projeto de IP - PYTHON                |")
            print(" | Prof. Dr. Luis Filipe Alves Pereira          |")
            print(" |----------------------------------------------|")
            print(" |                                              |")
            print(" |  Aluno1: Claudierio Baltazar Barra Nova      |")
            print(" |  Aluno2: Filipe Alencar Andrade Amorim Gomes |")
            print(" |______________________________________________|\n")
            os.system("pause")
            os.system("cls")

        elif (opt == 0):
            print("\n------------------------------------------------")
            print("     O programa foi encerrado com sucesso.")
            print("------------------------------------------------\n")
            os.system("pause")
            os.system("cls")
            return

"""### Testes com o csv vehicles-light"""

t = ExtratorDeProbabilidades('vehicles-light.csv')
t.probabilidade_apriori(caracteristica='region', valor='birmingham')

t.probabilidade_apriori_intervalo('region', (1, 10))

t.probabilidade_condicional(cond_a=('region', 'birmingham'), cond_b=('transmission', 'other'))

t.probabilidade_apriori_intervalo(("transmission", "manual"), ("transmission", (29, 150)))

"""### Main Loop"""

while t.menu() != None:
    continue


import argparse
import math

def output_periods(periods):
    start = 'It will take'
    joiner = 'and'
    end = 'to repay this loan!'

    years = periods // 12
    months = periods % 12

    years_str = str(f'{years} {"year" if years == 1 else "years"}')
    months_str = str(f'{months} {"month" if months == 1 else "months"}')

    if years > 0 and months > 0:
        return str(f'{start} {years_str} {joiner} {months_str} {end}')
    elif years == 0:
        return str(f'{start} {months_str} {end}')
    elif months == 0:
        return str(f'{start} {years_str} {end}')

def count_empty_args(arguments):
    count = 0
    for field in vars(arguments):
        if field is None:
            count += 1

    return count

def has_negative_args(arguments):
    is_negative = False
    args_array = [arguments.payment, arguments.periods, arguments.interest, arguments.principal]
    for arg in args_array:
        if arg is not None and float(arg) < 0:
            is_negative = True

    return is_negative

def check_input(arguments):
    count = count_empty_args(arguments)
    if count > 1 \
            or arguments.type is None \
            or arguments.type == 'diff' and arguments.payment \
            or arguments.interest is None \
            or has_negative_args(arguments):
        print('Incorrect parameters')
        return False
    return True

def calc_principal(periods, payment, interest_rate):
    principal = payment / ((interest_rate * math.pow(1 + interest_rate, periods)) / (math.pow(1 + interest_rate, periods) - 1))
    print(f'Your loan principal = {math.floor(principal)}!')
    calc_overpayment(periods * payment, math.floor(principal))

def calc_payment(periods, principal, interest_rate):
    payment = principal * interest_rate * math.pow(1 + interest_rate, periods) / (math.pow(1 + interest_rate, periods) - 1)
    print(f'Your annuity payment = {math.ceil(payment)}!')
    calc_overpayment(periods * math.ceil(payment), principal)

def calc_periods(principal, payment, interest_rate):
    periods = math.ceil(math.log(payment / (payment - interest_rate * principal), 1 + interest_rate))
    print(output_periods(periods))
    calc_overpayment(periods * payment, principal)

def calc_overpayment(result_payment, principal):
    print(f'Overpayment = {(result_payment - principal)}')

def calc_diff_payment(periods, principal, interest_rate, month):
    payment = math.ceil(principal / periods + interest_rate * (principal - principal * (month - 1) / periods))
    print(f'Month {month}: payment is {payment}')
    return payment

parser = argparse.ArgumentParser()
parser.add_argument('--type')
parser.add_argument('--payment')
parser.add_argument('--principal')
parser.add_argument('--periods')
parser.add_argument('--interest')

args = parser.parse_args()

if check_input(args):
    interest = float(args.interest) / 1200
    if args.type == 'annuity':
        if args.principal is None:
            calc_principal(int(args.periods), int(args.payment), interest)
        elif args.payment is None:
            calc_payment(int(args.periods), int(args.principal), interest)
        elif args.periods is None:
            calc_periods(int(args.principal), int(args.payment), interest)
    else:
        acc = 0
        for period in range(int(args.periods)):
            acc += calc_diff_payment(int(args.periods), int(args.principal), interest, period + 1)
        calc_overpayment(acc, int(args.principal))


from numpy import *
import matplotlib.pyplot as plt

data_infile = "train.csv"
test_infile = "test.csv"

IteraterTime = 490 #867
DIVIDE = (0.75, 0.25) #训练集和验证集的比例，四舍五入用round，返回浮点数

def Read_data(infile, Col, is_test = False) : # 读入数据集路径，列数，是否为测试集
    data = loadtxt(infile, dtype = float, usecols = range(Col) , delimiter=',')
    row = len(data)
    add = ones(row)
    if not is_test :
        label = data[:,-1]
        data = c_[add, data[:,:-1]]
        return data, label
    else :
        data = c_[add, data]
        return data

def sigmoid(v) : #logistics函数
    return 1.0 / (1.0 + exp(-v))

def pidDynamic(w, err, lastError, accumulateError) :
    errorDifferential = (err - lastError) / 0.0001
    lastError = err
    accumulateError = accumulateError + err
    kp = 0.5
    ki = 3
    kd = 0.012
    return w - (kp * err + ki * accumulateError + kd * errorDifferential), lastError, accumulateError

def LR(eta, trainDataSet, trainLabelSet, IteraterTime) :
    w = zeros(trainDataSet.shape[1])              #这里列数为维度数，行数为样本数
    wt = dot(trainDataSet, w)
    lastError = dot((sigmoid(wt) - trainLabelSet), trainDataSet)
    accumulateError = zeros(trainDataSet.shape[1])
    for i in range(IteraterTime) :
        wt = dot(trainDataSet,w)
        err = dot((sigmoid(wt) - trainLabelSet), trainDataSet)
        if sqrt(dot(err,err)) < 0.00001 :
            break
        else :
            w, lastError, accumulateError = pidDynamic(w, err, lastError, accumulateError)
            # w = w - eta * err
    return w

def regularLR(eta, trainDataSet, trainLabelSet, IteraterTime, Lambda) :
    w = ones(trainDataSet.shape[1])              #这里列数为维度数，行数为样本数
    for i in range(IteraterTime) :
        wt = dot(trainDataSet,w)
        err = dot((sigmoid(wt) - trainLabelSet), trainDataSet)
        err = err + Lambda * sum(w)
        err /= trainDataSet.shape[0]
        # if sqrt(dot(err,err)) < 0.00001 :
        #     break
        # else :
        w = w - eta * err
    return w

def LRSingle(eta, trainDataSet, trainLabelSet, IteraterTime) :
    w = ones(trainDataSet.shape[1])              #这里列数为维度数，行数为样本数
    for i in range(IteraterTime) :
        for j in range(trainDataSet.shape[0]) :
            wt = trainDataSet[j] * w
            err = (sigmoid(wt) - trainLabelSet[j]) * trainDataSet[j]
            if len(err.nonzero()) == 0 :
                break
            else :
                w = w - eta * err
    return w

def Classify(w, DataSet):
    valProbability = sigmoid(dot(DataSet, w))
    predictLabel = valProbability > 0.5
    return predictLabel

def Validation(w, valDataSet, valLabelSet) :
    result = Classify(w, valDataSet)
    TP = FP = TN = FN = 0
    for i in range(len(result)) :
        if result[i] == valLabelSet[i] and valLabelSet[i] == 1:
            TP = TP + 1
        elif result[i] != valLabelSet[i] and valLabelSet[i] == 0 :
            FP = FP + 1
        elif result[i] == valLabelSet[i] and valLabelSet[i] == 0 :
            TN = TN + 1
        else :
            FN = FN + 1
    # print(TP, FP, TN, FN)
    accuracy = (TP + TN) / (TP + FP + TN + FN)
    if TP == FP == 0 :
        recall = 0
    else:
        recall = 1.0 * TP / (TP + FN)
    if TP == FP == 0:
        precision = 0
    else:
        precision = 1.0 * TP / (TP + FP)
    if TP != 0 :
        f1 = 2.0 * precision * recall / (precision + recall)
    else:
        f1 = 0
    return accuracy, recall, precision, f1

if __name__ == '__main__' :
    data, label = Read_data(data_infile, 8)
    # test_data = Read_data(test_infile,40, True)
    #
    # ys_data, ys_label = Read_data(yanshou_tr, 7)
    # ys_te_data = Read_data(yanshou_te, 6, True)
    # ys_w = LR(1, ys_data,ys_label,1)
    # ys_pre_label = Classify(ys_w, ys_te_data)
    # print (ys_pre_label)

    # eta = [i for i in range(100,1000)]
    eta = [392]
    numberOfLine = int(round(DIVIDE[0] * data.shape[0])) #data.shape返回一个元组，值分别为行数和列数
    # re_w = regularLR(0.013, data[:numberOfLine], label[:numberOfLine], 200, 575)
    # predictLabel = Classify(re_w, test_data)
    # f = open("testResult.txt", 'w')
    # for i in predictLabel:
    #     if i :
    #         f.write(str(1))
    #     else:
    #         f.write(str(0))
    #     f.write('\n')
    best_w = []
    best_f1 = 0
    Result = [[],[],[],[]]
    for i in eta : #575 0.7855
        re_w = LR(0.013,data[:numberOfLine], label[:numberOfLine], i)
        accuracy, recall, precision, f1 = Validation(re_w, data[numberOfLine:data.shape[0]], label[numberOfLine:label.shape[0]])
        if f1 > best_f1:
            best_w = re_w
        Result[0].append(accuracy)
        Result[1].append(recall)
        Result[2].append(precision)
        Result[3].append(f1)
    # w = LR(eta, data[:numberOfLine], label[:numberOfLine], IteraterTime)#Batch Gradient
    # Validation(w, data[numberOfLine:data.shape[0]], label[numberOfLine:label.shape[0]])

    # for i in eta :
    #     w_single = LR(0, data[:numberOfLine], label[:numberOfLine], i)#Single Gradient
    #     accuracy, recall, precision, f1 = Validation(w_single, data[numberOfLine:data.shape[0]], label[numberOfLine:label.shape[0]])
    #     Result[0].append(accuracy)
    #     # Result[1].append(recall)
    #     # Result[2].append(precision)
    #     # Result[3].append(f1)

    print(re_w)
    print(eta[Result[0].index(max(Result[0]))])
    print("F1",max(Result[3]))
    print(Result)
    plt.plot(eta, Result[0], label="Accuracy",lw=1)
    plt.plot(eta, Result[1], label="Recall")
    plt.plot(eta, Result[2], label="Precision")
    plt.plot(eta, Result[3], label="F1")
    # plt.plot(eta, singleResult, label = "Single Gradient")
    plt.grid()
    plt.xlabel('Lambda')
    plt.ylabel('Accuracy')
    plt.legend()
    plt.show()

    test_data = Read_data(test_infile, 7, True)
    predictLabel = Classify(best_w, test_data)
    f = open("Result.csv", 'w')
    for i in predictLabel:
        if i :
            f.write(str(1))
        else:
            f.write(str(0))
        f.write('\n')


import uno
import unohelper

from com.sun.star.awt.FontWeight import BOLD

from com.sun.star.ucb.ConnectionMode import OFFLINE

from com.sun.star.logging.LogLevel import ALL

from com.sun.star.mail.MailServiceType import IMAP
from com.sun.star.mail.MailServiceType import SMTP

from com.sun.star.rest.HTTPStatusCode import NOT_FOUND
from com.sun.star.rest import HTTPException
from com.sun.star.rest import RequestException

from com.sun.star.uno import Exception as UnoException

from ..transferable import Transferable

from ..unotool import createService
from ..unotool import getConfiguration
from ..unotool import getConnectionMode
from ..unotool import getResourceLocation
from ..unotool import getStringResource
from ..unotool import getUrl
from ..unotool import hasInterface

from ..mailertool import getMailService
from ..mailertool import getMailMessage
from ..mailertool import getMessageImage

from ..logger import LogController
from ..logger import RollerHandler

from ..oauth2 import g_service

from ..configuration import g_identifier
from ..configuration import g_extension
from ..configuration import g_mailservicelog
from ..configuration import g_logo
from ..configuration import g_logourl
from ..configuration import g_chunk

from ..user import User

from .ispdbserver import IspdbServer

from email.utils import parseaddr
import xml.etree.ElementTree as ET
from time import sleep
from threading import Thread
import validators
import traceback

class IspdbModel(unohelper.Base):
    def __init__(self, ctx, sender, readonly):
        self._ctx = ctx
        self._sender = sender
        self._readonly = readonly
        self._servers = None
        self._services = [SMTP.value, IMAP.value]
        self._offline = 0
        self._diposed = False
        self._version = 0
        self._listener = None
        secure = {0: 3, 1: 4, 2: 5}
        unsecure = {0: 0, 1: 1, 2: 2}
        self._levels = {0: unsecure, 1: secure, 2: secure}
        self._connections = {0: 'Insecure', 1: 'SSL', 2: 'TLS'}
        self._authentications = {0: 'None', 1: 'Login', 2: 'OAuth2'}
        configuration = getConfiguration(ctx, g_identifier)
        self._url = configuration.getByName('IspDBUrl')
        self._timeout = configuration.getByName('ConnectTimeout')
        self._logger = LogController(ctx, g_mailservicelog)
        self._resolver = getStringResource(ctx, g_identifier, g_extension)
        self._resources = {'Step': 'IspdbPage%s.Step',
                           'Title': 'IspdbPage%s.Title.%s',
                           'PageLabel': 'IspdbPage%s.Label1.Label',
                           'PagesLabel': 'IspdbPages.Label1.Label',
                           'Progress': 'IspdbPage2.Label2.Label.%s',
                           'Security': 'IspdbPages.Label10.Label.%s',
                           'SendTitle': 'SendDialog.Title',
                           'SendSubject': 'SendDialog.TextField2.Text',
                           'SendMessage': 'SendDialog.TextField3.Text',
                           'ThreadTitle': 'SendThread.Title'}

    @property
    def Email(self):
        name, address = parseaddr(self._sender)
        return address

    @property
    def Sender(self):
        return self._sender
    @Sender.setter
    def Sender(self, sender):
        self._sender = sender

    @property
    def Offline(self):
        return self._offline
    @Offline.setter
    def Offline(self, offline):
        self._offline = offline

    def resolveString(self, resource):
        return self._stringResource.resolveString(resource)

# IspdbModel getter methods called by IspdbWizard
    def dispose(self):
        self._diposed = True
        if self._listener is not None:
            self._logger.removeModifyListener(self._listener)
            self._listener = None

# IspdbModel getter methods called by WizardPages 1
    def getSender(self):
        return self._sender, not self._readonly

# IspdbModel getter methods called by WizardPages 2 and 4
    def isDisposed(self):
        return self._diposed

# IspdbModel getter methods called by WizardPage1
    def isEmailValid(self, sender):
        name, address = parseaddr(sender)
        if validators.email(address):
            return True
        return False

# IspdbModel getter methods called by WizardPage2
    def getServerConfig(self, *args):
        self._version += 1
        Thread(target=self._getServerConfig, args=args).start()

    def _getServerConfig(self, progress, update):
        # FIXME: Because we call this thread in the WizardPage.activatePage(),
        # FIXME: if we want to be able to navigate through the Wizard roadmap
        # FIXME: without GUI refreshing problem then we need to pause this thread.
        sleep(0.2)
        auto = False
        config = None
        progress(10)
        url = getUrl(self._ctx, self._url)
        progress(20)
        mode = getConnectionMode(self._ctx, url.Server)
        progress(30)
        user = User(self._ctx, self.Sender)
        progress(40)
        request = createService(self._ctx, g_service)
        progress(50)
        if request is None:
            offset = 1 if user.isNew() else 2
            status = (100, offset, BOLD)
        elif mode == OFFLINE:
            offset = 3 if user.isNew() else 4
            status = (100, offset, BOLD)
        else:
            progress(60)
            try:
                config = self._getIspdbConfig(user, request, url.Complete)
            except RequestException as e:
                offset = 5 if user.isNew() else 6
                status = (100, offset, BOLD)
            else:
                progress(80)
                if not user.isNew():
                    status = (100, 7)
                elif config is None:
                    status = (100, 8)
                else:
                    auto = True
                    status = (100, 9)
        self._servers = IspdbServer(user, config)
        self._offline = mode
        progress(*status)
        update(self.getPageTitle(2), auto, user.getReplyToState(), user.ReplyToAddress, user.getImapState(), mode)

    def _getIspdbConfig(self, user, request, url):
        config = None
        parameter = request.getRequestParameter('getIspdbConfig')
        parameter.Url = '%s%s' % (url, user.getUserDomain())
        parameter.NoAuth = True
        response = request.execute(parameter)
        if response.Ok:
            config = self._parseIspdbConfig(user, response)
        elif response.StatusCode != NOT_FOUND:
            response.raiseForStatus()
        response.close()
        return config

    def _parseIspdbConfig(self, user, response):
        smtps = []
        imaps = []
        config = {}
        map1 = {'plain': 0, 'SSL': 1, 'STARTTLS': 2}
        map2 = {'none': 0, 'password-cleartext': 1, 'plain': 1,
                'password-encrypted': 1, 'secure': 1, 'OAuth2': 2}
        map3 = {'%EMAILLOCALPART%': 0, '%EMAILADDRESS%': 1, '%EMAILDOMAIN%': 2}
        parser = ET.XMLPullParser(('end', ))
        iterator = response.iterContent(g_chunk, False)
        while iterator.hasMoreElements():
            # FIXME: As Decode is False we obtain a sequence of bytes
            parser.feed(iterator.nextElement().value)
            for event, element in parser.read_events():
                if element.tag != 'emailProvider':
                    continue
                for child in element.findall('outgoingServer'):
                    if child.get('type') == 'smtp':
                        smtps.append(self._parseServer(child, map1, map2, map3))
                for child in element.findall('incomingServer'):
                    if child.get('type') == 'imap':
                        imaps.append(self._parseServer(child, map1, map2, map3))
        config[SMTP.value] = tuple(smtps)
        config[IMAP.value] = tuple(imaps)
        if user.isNew():
            user.enableImap(len(imaps) > 0)
        return config

    def _parseServer(self, element, map1, map2, map3):
        server = {}
        server['ServerName'] = element.find('hostname').text
        server['Port'] = int(element.find('port').text)
        server['ConnectionType'] = map1.get(element.find('socketType').text, 1)
        server['AuthenticationType'] = map2.get(element.find('authentication').text, 1)
        server['LoginMode'] = map3.get(element.find('username').text, 1)
        return server

# IspdbModel setter methods called by WizardPage2
    def enableReplyTo(self, enabled):
        self._servers.User.enableReplyTo(enabled)
        return self._servers.User.ReplyToAddress

    def setReplyToAddress(self, replyto):
        self._servers.User.setReplyToAddress(replyto)

    def enableIMAP(self, imap):
        self._servers.User.enableImap(bool(imap))
        return self._offline

# IspdbModel getter methods called by WizardPage3 / WizardPage4
    def refreshView(self, version):
        return version < self._version

    def getVersion(self):
        return self._version

    def getConfig(self, service):
        config = {}
        config['First'] = self._servers.isFirst(service)
        config['Last'] = self._servers.isLast(service)
        config['Page'] = self._servers.getServerPage(service)
        config['Default'] = self._servers.isDefaultPage(service)
        config.update(self._servers.getCurrentServer(service))
        config['UserName'] = self._getUserName(service)
        config['Password'] = self._getPassword(service)
        return config

    def isConnectionValid(self, host, port):
        return self._isHostValid(host) and self._isPortValid(port)

    def isStringValid(self, value):
        if validators.length(value, min=1):
            return True
        return False

    def previousServerPage(self, service, server):
        self._servers.updateCurrentServer(service, server)
        self._servers.decrementIndex(service)

    def nextServerPage(self, service, server):
        self._servers.updateCurrentServer(service, server)
        self._servers.incrementIndex(service)

    def updateConfiguration(self, service, server, user):
        self._servers.updateCurrentServer(service, server)
        self._servers.User.updateConfig(service, user)

    def saveConfiguration(self):
        self._servers.User.saveConfig()

    def getSecurity(self, i, j):
        level = self._levels.get(i).get(j)
        message = self.getSecurityMessage(level)
        return message, level

# IspdbModel getter methods called by WizardPage5
    def addLogListener(self, listener):
        self._logger.addModifyListener(listener)
        self._listener = listener

    def getLogContent(self):
        return self._logger.getLogContent(True)

    def connectServers(self, *args):
        Thread(target=self._connectServers, args=args).start()

    def _connectServers(self, reset, progress, setlabel, setstep):
        handler = RollerHandler(self._ctx, self._logger.Name)
        level = self._getLogLevel(handler)
        i = 0
        connect = True
        range = 100
        count = 2 if self._servers.User.useIMAP() else 1
        reset(count * range)
        for service in self._services:
            if service == SMTP.value or self._servers.User.useIMAP():
                setlabel(service, self._getHost(service), self._getPort(service))
                context = self._servers.User.getConnectionContext(service)
                authenticator = self._servers.User.getAuthenticator(service)
                if not self._connectServer(context, authenticator, service, i * range, progress):
                    connect = False
                    break
                i += 1
        self._setLogLevel(handler, level)
        setstep(4 if connect else 2)

    def _connectServer(self, context, authenticator, service, i, progress):
        connect = False
        progress(i + 25)
        server = getMailService(self._ctx, service)
        progress(i + 50)
        try:
            server.connect(context, authenticator)
        except UnoException as e:
            progress(i + 100)
        else:
            progress(i + 75)
            if server.isConnected():
                server.disconnect()
                connect = True
                progress(i + 100)
            else:
                progress(i + 100)
        return connect

    def _getHost(self, service):
        return self._servers.getServerHost(service)

    def _getPort(self, service):
        return self._servers.getServerPort(service)

    def sendMessage(self, *args):
        Thread(target=self._sendMessage, args=args).start()

    def _sendMessage(self, recipient, subject, message, reset, progress, setstep):
        handler = RollerHandler(self._ctx, self._logger.Name)
        level = self._getLogLevel(handler)
        transferable = Transferable(self._ctx, self._logger)
        if self._servers.User.useIMAP():
            i = 100
            reset(200)
            threadid = self._uploadMessage(transferable, subject, progress)
        else:
            i = 0
            reset(100)
            threadid = None
        progress(i + 5)
        smtp = SMTP.value
        context = self._servers.User.getConnectionContext(smtp)
        authenticator = self._servers.User.getAuthenticator(smtp)
        step = 3
        progress(i + 25)
        server = getMailService(self._ctx, smtp)
        progress(i + 50)
        try:
            server.connect(context, authenticator)
        except UnoException as e:
            print("IspdbModel._sendMessage() 1 Error: %s" % e.Message)
        else:
            progress(i + 75)
            if server.isConnected():
                #body = MailTransferable(self._ctx, message, False)
                body = transferable.getByString(message)
                mail = getMailMessage(self._ctx, self.Sender, recipient, subject, body)
                interface = 'com.sun.star.mail.XMailMessage2'
                if hasInterface(mail, interface) and threadid is not None:
                    mail.ThreadId = threadid
                    print("IspdbModel._sendMessage() 2 ******************")
                print("IspdbModel._sendMessage() 3: %s - %s" % (type(mail), mail))
                try:
                    server.sendMailMessage(mail)
                    print("IspdbModel._sendMessage() 4: %s" % mail.MessageId)
                except UnoException as e:
                    print("IspdbModel._sendMessage() 5 Error: %s - %s" % (e.Message, traceback.format_exc()))
                else:
                    step = 5
                server.disconnect()
        progress(i + 100)
        self._setLogLevel(handler, level)
        setstep(step)

    def _uploadMessage(self, transferable, subject, progress):
        mail = msgid = None
        imap = IMAP.value
        context = self._servers.User.getConnectionContext(imap)
        authenticator = self._servers.User.getAuthenticator(imap)
        progress(10)
        server = getMailService(self._ctx, imap)
        progress(20)
        try:
            server.connect(context, authenticator)
        except UnoException as e:
            print("IspdbModel._uploadMessage() 1 Error: %s" % e.Message)
        else:
            progress(40)
            if server.isConnected():
                try:
                    folder = server.getSentFolder()
                    if server.hasFolder(folder):
                        message = self._getThreadMessage()
                        #body = MailTransferable(self._ctx, message, True)
                        body = transferable.getByString(message)
                        mail = getMailMessage(self._ctx, self.Sender, self.Email, subject, body)
                        progress(60)
                        server.uploadMessage(folder, mail)
                except UnoException as e:
                    print("IspdbModel._uploadMessage() 2 Error: %s - %s" % (e.Message, traceback.format_exc()))
                else:
                    interface = 'com.sun.star.mail.XMailMessage2'
                    if mail is not None and hasInterface(mail, interface):
                        msgid = mail.MessageId
                        print("IspdbModel._uploadMessage() 3 *****************")
                progress(80)
                server.disconnect()
        progress(100)
        print("IspdbModel._uploadMessage() 4 MessageId: %s" % msgid)
        return msgid

    def _getLogLevel(self, handler):
        self._logger.addRollerHandler(handler)
        level = self._logger.Level
        self._logger.Level = ALL
        return level

    def _setLogLevel(self, handler, level):
        self._logger.removeRollerHandler(handler)
        self._logger.Level = level

# IspdbModel getter methods called by SendDialog
    def validSend(self, recipient, subject, message):
        enabled = all((self.isEmailValid(recipient),
                       self.isStringValid(subject),
                       self.isStringValid(message)))
        return enabled

# IspdbModel private getter methods called by WizardPage3 / WizardPage4
    def _getUserName(self, service):
        if self._servers.User.isNew():
            username = self._getUserNameFromEmail(service)
        else:
            username = self._servers.User.getUserName(service)
        return username

    def _getUserNameFromEmail(self, service):
        mode = self._servers.getLoginMode(service)
        return self.Email.partition('@')[mode] if mode != 1 else self.Email

    def _getPassword(self, service):
        return self._servers.User.getPassword(service)

    def _isHostValid(self, host):
        if validators.domain(host):
            return True
        return False

    def _isPortValid(self, port):
        if validators.between(port, min=1, max=1023):
            return True
        return False

# IspdbModel private getter methods called by WizardPage5
    def _getThreadMessage(self):
        title = self._getThreadTitle()
        path = '%s/%s' % (g_extension, g_logo)
        url = getResourceLocation(self._ctx, g_identifier, path)
        logo = getMessageImage(self._ctx, url)
        return '''\
<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

 %s

''' % (g_extension, logo, g_logourl, title)

# IspdbModel private shared methods
    def _getServicesCount(self):
        return len(self._services)

# IspdbModel StringResource methods
    def getPageStep(self, pageid):
        resource = self._resources.get('Step') % pageid
        return self._resolver.resolveString(resource)

    def getPageTitle(self, pageid):
        resource = self._resources.get('Title') % (pageid, self._offline)
        return self._resolver.resolveString(resource)

    def getPageLabel(self, pageid, *format):
        resource = self._resources.get('PageLabel') % pageid
        return self._resolver.resolveString(resource) % format

    def getPagesLabel(self, service):
        resource = self._resources.get('PagesLabel')
        label = self._resolver.resolveString(resource)
        return label % (service, self.Email)

    def getProgressMessage(self, value):
        resource = self._resources.get('Progress') % value
        return self._resolver.resolveString(resource)

    def getSecurityMessage(self, level):
        resource = self._resources.get('Security') % level
        return self._resolver.resolveString(resource)

    def getSendTitle(self):
        resource = self._resources.get('SendTitle')
        title = self._resolver.resolveString(resource)
        return title % self.Email

    def getSendSubject(self):
        resource = self._resources.get('SendSubject')
        return self._resolver.resolveString(resource)

    def getSendMessage(self):
        resource = self._resources.get('SendMessage')
        return self._resolver.resolveString(resource)

    def _getThreadTitle(self):
        resource = self._resources.get('ThreadTitle')
        return self._resolver.resolveString(resource) % g_extension


import cv2

# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture(0)

while True:
    # Capture frame by frame
    ret, frame = cap.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame.
    cv2.imshow('Its front view', gray)

    # Press Q to exit.
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release
# the video capture object
cap.release()
cv2.destroyAllWindows()