import logging

from flask import Flask, render_template, request
from google.cloud import datastore
import jsonlines, json
import pandas as pd

app = Flask(__name__)

def getSupplierContracts(ABN):
    client = datastore.Client()
    collection = 'supplier_contracts'
    query = client.query(kind=collection)
    query.add_filter('ABN', '=', ABN)
    query.order = ['-Value']

    results = list(query.fetch())
    contracts = []
    for r in results:
        s = datastore.Entity(r)
        contract = {}
        contract['ContractID'] = s.key.key.name
        contract['Title'] = s.key.get('Title')
        contract['Agency'] = s.key.get('Agency')
        contract['Category'] = s.key.get('Category')
        contract['Value'] = s.key.get('Value')
        contracts.append(contract)
    return contracts

@app.route('/')
def hello():
    """Return a friendly HTTP greeting."""
    return 'Hello World!'

@app.errorhandler(500)
def server_error(e):
    logging.exception('An error occurred during a request.')
    return """
    An internal error occurred: <pre>{}</pre>
    See logs for full stacktrace.
    """.format(e), 500

@app.route("/data/supplier/<ABN>/contracts_by_category")
def supplier_contracts_by_category(ABN):
    contracts = getSupplierContracts(ABN)

    df = pd.DataFrame(contracts)
    sorted_df = df[['Category', 'Value']].groupby('Category').sum().sort_values('Value', ascending=True)
    #sorted_df.reset_index().to_dict('records')
    #t = {'name': 'IT Services', 'value': 6644},{'name': 'Project Management', 'value': 9998}
    return json.dumps(sorted_df.reset_index().to_dict('records'))

@app.route("/data/supplier/<ABN>/contracts_by_agency")
def supplier_contracts_by_agency(ABN):
    contracts = getSupplierContracts(ABN)

    df = pd.DataFrame(contracts)
    sorted_df = df[['Agency', 'Value']].groupby('Agency').sum().sort_values('Value', ascending=True)
    #sorted_df.reset_index().to_dict('records')
    #t = {'name': 'IT Services', 'value': 6644},{'name': 'Project Management', 'value': 9998}
    return json.dumps(sorted_df.reset_index().to_dict('records'))

@app.route("/contracts/supplier/<ABN>")
def supplier_contracts(ABN):

    client = datastore.Client()
    collection = 'supplier_contracts'
    query = client.query(kind=collection)
    query.add_filter('ABN', '=', ABN)
    query.order = ['Title']

    results = list(query.fetch())
    contract_count = len(results)

    contracts = []
    for r in results:
        s = datastore.Entity(r)
        contract = {}
        contract['ContractID'] = s.key.key.name
        contract['Title'] = s.key.get('Title')
        contract['Agency'] = s.key.get('Agency')
        contract['Category'] = s.key.get('Category')
        contract['Value'] = s.key.get('Value')
        contracts.append(contract)

    query_suppliername = client.query(kind='suppliers')
    query_suppliername.add_filter('ABN', '=', ABN)
    results_suppliername = list(query_suppliername.fetch(limit=1))
    supplier_name = datastore.Entity(results_suppliername[0]).key.get('Name')

    return render_template('contracts.html',
        contracts=contracts,
        ABN=ABN,
        supplier_name=supplier_name,
        contract_count=contract_count)

@app.route("/all_suppliers")
def suppliers():

    client = datastore.Client()
    collection = 'suppliers'

    query = client.query(kind=collection)
    query.order = ['Name']

    results = list(query.fetch())
    supplier_count = len(results)

    suppliers = []
    for r in results:
        s = datastore.Entity(r)
        supplier = {}
        supplier['ABN'] = s.key.key.name
        supplier['Name'] = s.key.get('Name')
        supplier['State'] = s.key.get('State')
        supplier['Postcode'] = s.key.get('Postcode')
        suppliers.append(supplier)

    return render_template('suppliers.html', suppliers=suppliers, supplier_count=supplier_count)

if __name__ == '__main__':
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine. See entrypoint in app.yaml.
    app.run(host='127.0.0.1', port=8080, debug=True)


#!/usr/bin/env python

import os
import logging
from dataclasses import dataclass

from tqdm import tqdm

from detectron2.data import DatasetCatalog

logger = logging.getLogger(__name__)

LABELS = (
    'aeroplane',
    'bicycle',
    'bird',
    'boat',
    'bottle',
    'bus',
    'car',
    'cat',
    'chair',
    'cow',
    'diningtable',
    'dog',
    'horse',
    'motorbike',
    'person',
    'pottedplant',
    'sheep',
    'sofa',
    'train',
    'tvmonitor',
)

@dataclass
class CocoDataset(object):

    coco_names: str
    name: str = 'coco_2017_train'
    class_label = None

    def __post_init__(self):
        assert os.path.isfile(self.coco_names)

        with open(self.coco_names, 'r') as f:
            lines = f.read().split('\n')

        self.class_label = {}
        self.match_index = {}
        for i, line in enumerate(lines, 1):
            if line not in LABELS:
                continue
            self.class_label[line] = i
            self.match_index[i] = [len(self.match_index) + 1, line]

    def filter(self):
        logger.warning(f'Reading Catalog for {self.name}')
        coco_data = DatasetCatalog.get(self.name)

        self.dataset = []
        for data in tqdm(coco_data):
            annotations = []
            for anno in data['annotations']:
                category_id = anno['category_id']
                if category_id in self.class_label.values():
                    anno['category_id'] = self.match_index[category_id][0]
                    annotations.append(anno)
            if len(annotations) > 0:
                data['annotations'] = annotations
                self.dataset.append(data)

        logger.warning(f'New dataset size {len(self.dataset)}')
        assert len(self.dataset) > 0

    def __call__(self):
        self.filter()
        return self.dataset

if __name__ == '__main__':

    import sys

    c = CocoDataset(coco_names=sys.argv[1])

    import IPython

    IPython.embed()


import jax
import haiku as hk
import numpy as np
import jax.numpy as jnp

from model.prior import Prior

class Embedding(hk.Module):
    """
    Embeds tokens and positions into an array of shape [n_batch, n_seq, n_hidden].
    Choose between learnable and VI embeddings.
    """
    def __init__(self, config, vocab_size, hidden_size, name):
        """
        Build Embedding from configuration.
        :params config: configuration dictionary.
        """
        super().__init__(name=name)
        self.config = config
        self.vocab_size = vocab_size
        self.hidden_size = hidden_size
        if self.config["bayesian_emb"]:
            self.embedding = BayesianEmbedding(config, vocab_size=vocab_size, hidden_size=hidden_size)
        else:
            self.embedding = LearnableEmbedding(config, vocab_size=vocab_size, hidden_size=hidden_size)

    def __call__(self, ids, key, training=True):
        """
        Forward pass on the embedding layer.
        :params ids: input of shape (batch, n_seq).
        :params key: random key.
        :params training: if True, apply dropout.
        """
        if self.config["bayesian_emb"]:
            return self.embedding(ids, key, training)
        else:
            return self.embedding(ids, key, training),  0.

class LearnableEmbedding(hk.Module):
    """
    Embeds tokens and positions into an array of shape [n_batch, n_seq, n_hidden].
    """
    def __init__(self, config, vocab_size, hidden_size):
        """
        Build Embedding from configuration.
        :params config: configuration dictionary.
        """
        super().__init__(name="LearnableEmbedding")
        self.config = config
        self.vocab_size=vocab_size
        self.hidden_size = hidden_size

    def __call__(self, token_ids, key, training=True):
        """
        Forward pass on the embedding layer.
        :params token_ids: input of shape (batch, n_seq).
        :params key: random key.
        :params training: if True, apply dropout.
        """
        # Reshape ids
        flat_token_ids = jnp.reshape(token_ids, [token_ids.shape[0]*token_ids.shape[1]])

        # Embed tokens
        flat_token_embeddings = hk.Embed(
            vocab_size=self.vocab_size,
            embed_dim=self.hidden_size
        )(flat_token_ids)

        # After we've embedded our token IDs, we reshape to recover our batch dimension
        embeddings = jnp.reshape(
            flat_token_embeddings,
            [token_ids.shape[0], token_ids.shape[1], -1]
        )

        # Combine our token embeddings with a set of learned positional embeddings
        ### embeddings = token_embeddings + PositionEncoding(self.config)() # Will do outside this

        # Apply layer norm
        ###
        ### embeddings = hk.LayerNorm(
        ###    axis=-1, create_scale=True, create_offset=True
        ### )(embeddings) # Will do outside this function

        # # Apply dropout layer during training
        # if training:
        #     embeddings = hk.dropout(
        #         key,
        #         rate=self.config['embed_dropout_rate'],
        #         x=embeddings
        #     ) # Will do outside this

        return embeddings

class BayesianEmbedding(hk.Module):
    """
    Embeds tokens and positions into an array of shape [n_batch, n_seq, n_hidden].
    Apply Variational Inference to the embedding vectors.
    """
    def __init__(self, config, vocab_size, hidden_size):
        """
        Build Embedding from configuration.
        :params config: configuration dictionary.
        """
        super().__init__(name="BayesianEmbedding")
        self.config = config
        self.vocab_size=vocab_size
        self.hidden_size = hidden_size
        # Posterior weight distribution
        self.w_mean = hk.get_parameter(
            name="w_mean",
            shape=[self.vocab_size, self.hidden_size],
            init=hk.initializers.TruncatedNormal(),
        )
        self.w_rho = hk.get_parameter(
            name="w_rho",
            shape=[self.vocab_size, self.hidden_size],
            init=hk.initializers.RandomNormal(stddev=1e-2, mean=-7)
        )
        self.w_sig = jax.nn.softplus(self.w_rho)
        # Prior weight distribution
        prior_distribution = self.config['emb_prior_distribution']
        prior_params = self.config['emb_prior_params']
        self.prior_w = Prior(self.vocab_size*self.hidden_size, prior_distribution, prior_params)

    def __call__(self, ids, key, training=True):
        """
        Forward pass on the embeddings.
        :params ids: input of shape (batch, n_seq).
        :params key: random key.
        :params training: if True, apply dropout.
        """
        # Split keys
        keys = jax.random.split(key, num=2)

        # Sample embedding matrix from embedding distribution
        eps = jax.random.normal(keys[0], shape=self.w_sig.shape)
        sample_embeddings = self.w_mean + jnp.multiply(self.w_sig, eps)

        # Select embeddings corresponding to input ids, add positional embedding
        # embeddings = jnp.asarray(sample_embeddings)[(ids,)] + PositionEncoding(self.config)()
        # Will do position embeddings outside this
        embeddings = jnp.asarray(sample_embeddings)[(ids,)]

        # Apply layer norm
        # embeddings = hk.LayerNorm(
        #     axis=-1, create_scale=True, create_offset=True,
        # )(embeddings)

        # When training apply dropout
        # if training:
        #     embeddings = hk.dropout(
        #         rng=keys[1],
        #         rate=self.config['embed_dropout_rate'],
        #         x=embeddings
        #     )

        kl_div = self.KL_divergence(
            self.w_mean, self.w_sig**2, self.prior_w.params["loc"], self.prior_w.params["scale"]**2
        )

        return embeddings, kl_div

    def KL_divergence(self, posterior_mean, posterior_cov, prior_mean, prior_cov):
        """
        Compute KL divergence between the Gaussian posterior and prior distributions.
        :params posterior_mean: mean vector of the posterior.
        :params posterior_cov: vector with the diagonal elements of the covariance matrix.
        :params prior_mean: scalar or mean vector of the prior.
        :params prior_cov: scalar with the value of the variation of the isotropic Gaussian prior.
        """
        eps = 1e-9
        d = np.prod(posterior_mean.shape)
        kl = 0.5*(jnp.sum((posterior_cov+(posterior_mean-prior_mean)**2)/prior_cov - jnp.log(posterior_cov+eps)) - d + d*jnp.log(prior_cov))

        return kl

class PositionEncoding(hk.Module):
    """
    A position encoding of shape [n_seq, n_hidden].
    """
    def __init__(self, config):
        """
        Build positional encoding.
        :params config: configuration dictionary.
        """
        super().__init__(name="PositionEncoding")
        self.config = config

    def __call__(self):
        """
        Returns sinusoidal position encoding.
        """
        positional_encoding = np.zeros((self.config["max_length"], self.config["hidden_size"]), dtype=np.float32)
        position = np.arange(0, self.config["max_length"])[:, np.newaxis]
        scale_factor = -np.log(self.config["max_scale"] / self.config["min_scale"]) / (self.config["hidden_size"] // 2 - 1)
        div_term = self.config["min_scale"] * np.exp(np.arange(0, self.config["hidden_size"] // 2) * scale_factor)
        positional_encoding[:, :self.config["hidden_size"] // 2] = np.sin(position * div_term)
        positional_encoding[:, self.config["hidden_size"] // 2: 2 * (self.config["hidden_size"] // 2)] = np.cos(position * div_term)

        return positional_encoding


import statistics
#Splitting the file name into variables
FOLDER = "../swimdata/"

def read_swim_data(filename):
    swimer, age, distance, stroke = filename.removesuffix(".txt").split("-")

    # Retrieving data from file
    with open(FOLDER + filename) as file:
        lines = file.readlines()
        # Remember, that strip remove the break line
        times = lines[0].strip().split(",")

    converts = []

    for t in times:
        if ":" in t:
            minutes, rest = t.split(":")
            seconds, hundredths = rest.split(".")

        else:
            minutes = 0
            seconds, hundredths = t.split(".")

        converts.append((int(minutes) * 60 * 100) + (int(seconds) * 100) + int(hundredths))

    average = statistics.mean(converts)

    round(average/ 100, 2) #86.56, where 86 - seconds, 56 - hundredths

    mins_secs, hundredths = str(round(average / 100, 2)).split(".") # ['86', '58']

    mins_secs = int(mins_secs)

    minutes = mins_secs // 60
    seconds = mins_secs - minutes * 60

    average = str(minutes) + ":" + str(seconds) + "." + hundredths

    #print(average)

    return average, swimer, age, distance, stroke, times


import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

formatter = logging.Formatter("%(asctime)s | %(name)s |  %(levelname)s: %(message)s")

file_handler = logging.FileHandler("log.log")
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)

logger.addHandler(file_handler)
logger.addHandler(stream_handler)


from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route('/user_info/')
def get_user_info():
    return jsonify({'slackUsername':'tshergzeh',
                    'backend':True,
                    'age':21,
                    'bio':'I am a backend developer participating in the HNG9 internship.'})

@app.route('/operate', methods=['POST'])
def operate():
    if not request.json or not 'operation_type' in request.json or not 'x' in request.json or not 'y' in request.json:
        abort(400)
    operation = {
        'operation_type': request.json['operation_type'],
        'x': request.json['x'],
        'y': request.json['y']
    }
    if operation['operation_type'] == 'addition':
        result = operation['x'] + operation['y']
    elif operation['operation_type'] == 'subtraction':
        result = operation['x'] - operation['y']
    elif operation['operation_type'] == 'multiplication':
        result = operation['x'] * operation['y']
    else:
        abort(400)
    return jsonify({'slackUsername': 'tshergzeh',
        'operation_type': operation['operation_type'],
        'result': result
    })

@app.route('/')
def hello_world():
    return 'Hello World!'


import logging
import os
import re

import bs4
from bs4 import BeautifulSoup as bs
import typing
from typing import List, Dict
from datetime import datetime

class DataFormatter:
    """
    Абстрактный класс для задания соответствий между
        получаемыми из html свойствами
        свойствами в БД
        колонками экспортного файла
    """
    pass

class BookDataFormatter(DataFormatter):
    """
    Класс содержит таблицу соответствий между свойствами книги в БД (db), колонок экспортного файла (csv, xlsx)
    и методами парсера класса ParserFromHTML (parser), вынимающими это свойство из html.
    {
    'название_свойства': {
           'parser': 'метод_для_вынимания_свойства_из_html_кода',
           'db': { 'name': 'название_колонки_в_бд',
                    'type': 'тип_колонки_в_бд'
                    },
           'csv': { 'name': 'Название_колонки_в_csv',
                    'method': 'метод_для_форматирования_значения_для_csv'
                    },
            'xlsx': {   'name': 'Название_колонки_в_xlsx',
                        'method': 'метод_для_форматирования_значения_для_xlsx',
                        'order': 'порядок следования в таблице в формате integer'
                    }
           },
    ...
    }
          свойства date, month, year не вынимаются из html стандартным способом,
          поэтому его parser не задан. Они будут вынуты в методе ParserFromHTML.all_books_from_page()

          На ЛЛ есть книги со ссылкой вида /book/book_id и произведения со ссылкой вида /work/work_id.
    """

    common = {
        'author_id': {'parser': 'get_author_id',
                      'db': {'name': 'author_id', 'type': 'INTEGER'},
                      'csv': {'name': 'Cсылка на автора', 'method': 'create_author_link'},
                      'xlsx': {'name': 'Cсылка на автора', 'method': 'create_author_link', 'order' :7, 'column_width':30},
                      },
        'author_name': {'parser': 'get_author_name',
                        'db': {'name': 'author_name', 'type': 'TEXT'},
                        'csv': {'name': 'Автор', },
                        'xlsx': {'name': 'Автор', 'order':2, 'column_width':30 }
                        },
        'book_id': {'parser': 'get_book_id',
                    'db': {'name': 'book_id', 'type': 'INTEGER'},
                    'csv': {'name': 'Ссылка на  книгу', 'method': 'create_book_link'},
                    'xlsx': {'name': 'Ссылка на  книгу', 'method': 'create_book_link', 'order':8, 'column_width':30}
                    },
        'work_id': {'parser': 'get_work_id',
                    'db': {'name': 'work_id', 'type': 'INTEGER'},
                    'csv': {'name': 'Ссылка на произведение', 'method': 'create_work_link'},
                    'xlsx': {'name': 'Ссылка на произведение', 'method': 'create_work_link','order':9, 'column_width':30}
                    },
        'book_name': {'parser': 'get_book_name',
                      'db': {'name': 'book_name', 'type': 'TEXT'},
                      'csv': {'name': 'Название', },
                      'xlsx': {'name': 'Название', 'order':1, 'column_width':30}
                      },
        'common_rating': {'parser': 'get_common_rating',
                          'db': {'name': 'common_rating', 'type': 'REAL'},
                          'csv': {'name': 'Общая оценка', },
                          'xlsx': {'name': 'Общая оценка', 'order':10, 'column_width':5}
                          },
        'picture_url': {'parser': 'get_picture_url',
                        'db': {'name': 'picture_url', 'type': 'TEXT'},
                        'csv': {'name': 'Обложка', 'method': 'create_picture_url'},
                        'xlsx': {'name': 'Обложка', 'method': 'create_picture_url', 'order':12, 'column_width':30}
                        },
        'reader_rating': {'parser': 'get_reader_rating',
                          'db': {'name': 'reader_rating', 'type': 'REAL'},
                          'csv': {'name': 'Моя оценка', },
                          'xlsx': {'name': 'Моя оценка', 'order':3, 'column_width':5}
                          },
        'tags': {'parser': 'get_tags',
                 'db': {'name': 'tags', 'type': 'TEXT'},
                 'csv': {'name': 'Теги', },
                 'xlsx': {'name': 'Теги', 'order':5, 'column_width':20}
                 },
        'review_id': {'parser': 'get_review_id',
                      'db': {'name': 'review_id', 'type': 'INTEGER'},
                      'csv': {'name': 'Ссылка на рецензию', 'method': 'create_review_link'},
                      'xlsx': {'name': 'Ссылка на рецензию', 'method': 'create_review_link', 'order':11, 'column_width':30},
                      },
        'review_text': {'parser': 'get_review_text',
                        'db': {'name': 'review_text', 'type': 'TEXT'},
                        'csv': {'name': 'Рецензия', 'method': 'create_review_text'},
                        'xlsx': {'name': 'Рецензия', 'method': 'create_review_text', 'order':4, 'column_width':100}
                        },
        'date': {'parser': 'not_implemented',
                 'csv': {'name': 'Дата прочтения', },
                 'xlsx': {'name': 'Дата прочтения', 'order':6, 'column_width':15}
                 },
        'month': {'parser': 'not_implemented',
                  'db': {'name': 'month', 'type': 'INTEGER'},
                  },
        'year': {'parser': 'not_implemented',
                 'db': {'name': 'year', 'type': 'INTEGER'},
                 },
        'livelib_id': {'parser': 'not_implemented',
                       'db': {'name': 'livelib_id', 'type': 'INTEGER'},
                       },
        'login': {'parser': 'not_implemented',
                  'db': {'name': 'login', 'type': 'TEXT'},
                  },
        'update_time': {'parser': 'not_implemented',
                        'db': {'name': 'update_time', 'type': 'TEXT'},
                        },
    }

    book_properties_db = ['book_id', 'work_id', 'book_name', 'author_name', 'author_id', 'common_rating', 'picture_url']
    reader_properties_db = ['livelib_id', 'login', 'update_time']
    readbook_properties_db = ['review_text', 'review_id', 'tags', 'reader_rating', 'month', 'year']

    @classmethod
    def all_properties_parser(cls):
        """
        Преобразует таблицу в удобный для ParserFromHTML словарь.
        :return: словарь вида {название_поля1: метод_обработки_поля1, название_поля2: метод_обработки_поля2, }
        :rtype: Dict
        """
        return {i: j['parser'] for i, j in cls.common.items()}

    @classmethod
    def all_properties_db(cls):
        """
        Преобразует таблицу в удобный для DBConnection словарь.
        :return: словарь вида {'название_поля1':'тип_поля1', 'название_поля2':'тип_поля1', ...}
        :rtype: Dict
        """
        result = {}
        for i in cls.common.values():
            if i.get('db'):
                result[i['db']['name']] = i['db']['type']
        return result

    @classmethod
    def all_properties_csv(cls):
        """
        Преобразует таблицу в удобный для CSVConnection словарь
        :return: словарь вида {'author_id': {'name': 'Cсылка на автора', 'method': 'create_author_link'}, {}, ...}
        :rtype: Dict
        """
        result = {}
        for i, j in cls.common.items():
            if j.get('csv'):
                result[i] = j['csv']
        return result

    @classmethod
    def all_properties_xlsx(cls):
        """
        Преобразует таблицу в удобный для XLSXConnection словарь, упорядоченный по заданному порядку
        :return: Словарь вида {'author_id': {'name': 'Cсылка на автора', 'method': 'create_author_link'}, {}, ...}
        :rtype: Dict
        """
        result = {}
        for i, j in cls.common.items():
            if j.get('xlsx'):
                result[i] = j['xlsx']
        sorted_result ={i[0]:i[1] for i in sorted(result.items(), key=lambda x: x[1]['order'])}
        return sorted_result

class Parser:

    @staticmethod
    def _clear_name(s: str) -> str:
        """
        Служебная функция для очистки названий от переносов и лишних пробелов
        """
        s = re.sub(" +", " ", s)
        s = re.sub("\n", "", s)
        return s

class ParserFromHTML(Parser):
    """
    Класс парсинга страниц сайта. Здесь задаются адресация страниц сайта и поиск данных в его верстке.
    """

    @staticmethod
    def reader_prefix(login: str) -> str:
        """
        Возвращает префикс страниц сайта для конкретного читателя.
        :param login: логин читателя
        :type login: str
        :return: префикс страниц сайта для конкретного читателя
        :rtype: str
        """
        return '/reader/' + login

    @staticmethod
    def reader_read_books_page(login: str) -> str:
        """
        Возвращает начальную страницу с книгами, прочитанными читателем
        :param login: логин читателя
        :type login: str
        :return: страница с прочитанными книгами
        :rtype: str
        """
        return ParserFromHTML.reader_read_books_page_by_number(login=login, number=0)

    @staticmethod
    def reader_read_books_page_by_number(login: str, number: int = 0) -> str:
        """
        Возвращает страницу с заданным номером с книгами, прочитанными читателем
        :param login: логин читателя
        :type login: str
        :param number: номер страницы
        :type number: int
        :return: страница с прочитанными книгами
        :rtype: str
        """
        return ParserFromHTML.reader_prefix(login) + '/read/~' + str(number)

    @staticmethod
    def check_404(bsoup: bs4.BeautifulSoup) -> bool:
        """
        Проверяет, не возвращает ли страница штатные 404.
        :param bsoup: текст страницы
        :type bsoup:  bs4.BeautifulSoup
        :return: True, если 404, False иначе
        :rtype: Boolean
        """
        if bsoup.find('title', string='404 @ LiveLib'):
            return True
        else:
            return False

    @staticmethod
    def check_captcha(bsoup: bs4.BeautifulSoup) -> bool:
        """
        Проверяет, не возвращает ли страница капчу на проверку ботов.
        :param bsoup: текст страницы
        :type bsoup:  bs4.BeautifulSoup
        :return: True, если капча, False иначе
        :rtype: Boolean
        """
        if bsoup.find(string='Please confirm that you and not a robot are sending requests'):
            return True
        else:
            return False

    @staticmethod
    def all_books_from_page(bsoup: bs4.BeautifulSoup, formatter: BookDataFormatter = BookDataFormatter) -> List[Dict]:
        """
        Возвращает ифнормацию о всех книгах на данной странице в виде списка словарей.
        Словарь формируется с ключами из BookDataFormatter, соответствующие значения вычисляются
        с помощью функций, указанных там же.
        Исключение - месяц и год прочтения книги формируются в этом методе, это обусловлено версткой.
        :param bsoup: код страницы
        :type bsoup: bs4.BeautifulSoup
        :param formatter:  словарь с перечислением нужных свойств
        :type formatter: BookDataFormatter
        :return: список словарей по каждой книге вида {'property_name': 'property_value'}
        :rtype: List[Dict]
        """
        # в коде страницы внутри блока

        # чередуются блоки
Месяц Год
 и
КНИГА

        # последовательно пойдем по этим блокам, присваивая книгам, следующим за датой, эту дату прочтения
        result = []
        month = None
        year = None
        for block in bsoup.find('div', id='booklist').children:
            # если это блок с месяцем и годом, запоминаем его для добавления в информацию по последующим книгам
            if 'brow-h2' in block['class']:
                date = block.text
                # вытащим месяц (если он есть, для старых книг его может не быть), переведем его в цифру
                month = re.search(r'\D+(?= )', date)
                if month != None:
                    month = month.group()
                    month_numbers = {'январь': 1, 'февраль': 2, 'март': 3, 'апрель': 4, 'май': 5, 'июнь': 6,
                                     'июль': 7, 'август': 8, 'сентябрь': 9, 'октябрь': 10, 'ноябрь': 11, 'декабрь': 12}
                    month = month_numbers.get(month.lower(), None)
                # вытащим год
                year = re.search(r'\d+', date)
                if year != None: year = int(year.group())
            # если это блок с книгой, парсим ее как книгу и вносим месяц и год прочтения в результат
            elif 'book-item-manage' in block['class']:
                book = ParserFromHTML.book(block, formatter)
                book['month'] = month
                book['year'] = year
                result.append(book)
        return result

    @staticmethod
    def book(bsoup: bs4.BeautifulSoup, formatter: BookDataFormatter = BookDataFormatter) -> Dict[str, str]:
        """
        Возвращает словарь с информацией о книге, представленной в заданном коде.
        Словарь формируется с ключами из BookDataFormatter, соответствующие значения вычисляются
        с помощью функций, указанных там же.
        Исключение - месяц и год прочтения книги формируются в методе all_books_from_page, это обусловлено версткой.
        :param bsoup: код с информацией о книге
        :type bsoup: bs4.BeautifulSoup
        :param formatter: словарь с перечислением нужных свойств
        :type formatter: BookDataFormatter
        :return: словарь типа {'property_name': 'property_value'}
        :rtype: Dict[str,str]
        """
        result = {}
        for property_name, parser_function in formatter.all_properties_parser().items():
            try:
                if hasattr(ParserFromHTML, parser_function):
                    result[property_name] = getattr(ParserFromHTML, parser_function)(bsoup)
            except AttributeError:
                logging.exception(f'No parser function {parser_function} is found!', exc_info=True)
        return result

    @staticmethod
    def get_author_name(bsoup: bs4.BeautifulSoup) -> str:
        result = bsoup.find('a', class_='brow-book-author')
        if result and bool(result.text):
            return ParserFromHTML._clear_name(result.text)
        else:
            return None

    @staticmethod
    def get_author_id(bsoup: bs4.BeautifulSoup) -> str:
        author_id = re.compile(r'(?<=/author/)\d+(?=-)')
        link = bsoup.find('a', class_='brow-book-author')
        if link:
            result = re.search(author_id, link.get('href'))
            return int(result.group()) if result else None
        else:
            return None

    @staticmethod
    def get_book_name(bsoup: bs4.BeautifulSoup) -> str:
        result = bsoup.find('a', class_='brow-book-name')
        if result and bool(result.text):
            return Parser._clear_name(result.text)
        else:
            return None

    @staticmethod
    def get_book_id(bsoup: bs4.BeautifulSoup) -> str:
        book_id = re.compile(r'(?<=/book/)\d+(?=-)')
        link = bsoup.find('a', class_='brow-book-name')
        if link:
            result = re.search(book_id, link.get('href'))
            return int(result.group()) if result else None
        else:
            return None

    @staticmethod
    def get_work_id(bsoup: bs4.BeautifulSoup) -> str:
        book_id = re.compile(r'(?<=/work/)\d+(?=-)')
        link = bsoup.find('a', class_='brow-book-name')
        if link:
            result = re.search(book_id, link.get('href'))
            return int(result.group()) if result else None
        else:
            return None

    @staticmethod
    def get_common_rating(bsoup: bs4.BeautifulSoup) -> float:
        """
        Возвращает общую оценку книги.
        :param bsoup: код, вмещающий информацию о книге
        :type bsoup: bs4.BeautifulSoup
        :return: число
        :rtype: float
        """
        result = bsoup.find('div', class_='brow-ratings').find_all('span', class_='rating-book')[1]
        if result and bool(result.text):
            return float(result.text)
        else:
            return None

    @staticmethod
    def get_picture_url(bsoup: bs4.BeautifulSoup) -> str:
        """
        Возвращает ссылку на картинку с обложкой книги.
        :param bsoup: код, вмещающий информацию о книге
        :type bsoup: bs4.BeautifulSoup
        :return: абсолютную ссылку
        :rtype: str
        """
        result = bsoup.find('div', class_='cover-wrapper').find('img').get('data-pagespeed-lazy-src')
        if result:
            return result
        else:
            result = bsoup.find('div', class_='cover-wrapper').find('img').get('src')
            return result if result else None

    @staticmethod
    def get_reader_rating(bsoup: bs4.BeautifulSoup) -> float:
        """
        Возвращает оценку книги читателем.
        :param bsoup: код, вмещающий информацию о книге
        :type bsoup: bs4.BeautifulSoup
        :return: число
        :rtype: float
        """
        result = bsoup.find('div', class_='brow-ratings').find_all('span', class_='rating-book')[0]
        if result and bool(result.text):
            return float(result.text)
        else:
            return None

    @staticmethod
    def get_tags(bsoup: bs4.BeautifulSoup):
        tags = bsoup.find('div', class_='brow-tags')
        result = []
        if tags != None:
            # необходимо проверить, не является ли тег ссылкой на расширенный список тегов (вида 'Еще NN тегов')
            # Если он - ссылка, то пропускаем его.
            # даже если теги скрыты, мы все равно их вытащим из кода страницы.
            more = re.compile(r'^Ещё \d+')
            for i in tags.find_all('a', class_='label-tag'):
                if re.match(more, i.text) == None:
                    result.append(i.text)
        return ';'.join(result)

    @staticmethod
    def get_review_id(bsoup: bs4.BeautifulSoup) -> int:
        result = None
        review_id = re.compile(r'(?<=review-)\d+(?=-full)')
        div = bsoup.find(id=review_id)
        if div != None:
            result = int(re.search(review_id, div['id']).group())
        return result

    @staticmethod
    def get_review_text(bsoup: bs4.BeautifulSoup) -> str:
        result = None
        review_id = re.compile(r'(?<=review-)\d+(?=-full)')
        div = bsoup.find(id=review_id)
        if div != None:
            # сохраняем текст рецензии
            body = ''.join([str(p) for p in div.find('div', itemprop='reviewBody').contents])
            # ищем и сохраняем
            events = div.find('div', class_='event-pad')
            extra = ''.join([str(p) for p in events.contents]) if events != None else ''
            result = body + extra
        return result

    @staticmethod
    def get_paginator(bsoup: bs4.BeautifulSoup) -> List[int]:
        """
        Возвращает список номеров страниц из паджинатора в низу страницы. Если страница единственная, и паджинатора нет,
        то возвращает пустой список.
        :param bsoup: код страницы
        :type bsoup: bs4.BeautifulSoup
        :return: список номеров страниц либо пустой список
        :rtype: List[int]
        """
        paginator = bsoup.find('div', id='booklist-pagination')
        result = []
        # если страница единственная, она же текущая, то возвращаем пустой список ссылок
        if paginator == None:
            return result
        # если страницы есть
        else:
            last_page = paginator.find('a', title='Последняя страница')
            # если не все страницы представлены, но есть ссылка на самую последнюю страницу
            if last_page:
                last_number = int(re.search(r'(?<=~)\d+', last_page['href']).group())
                result = [i for i in range(1, last_number + 1)]
            # если все страницы умещаются в низу страницы (их мало, до пяти штук)
            else:
                result = [int(i) for i in paginator.text.split()]
            return result

class ParserForDB(Parser):
    @staticmethod
    def _prepare_book_for_db(book: Dict, formatter=BookDataFormatter) -> List:
        """
        Преобразует книгу для сохранения в БД в соответствии с BookDataFormatter.
        Нужен в случае, если название колонки в БД отличается от названия свойства парсера или
        требуется предварительная обработка значения свойства.
        :param book: словарь с информацией про книгу вида {'parser_field_name1':'field_value1','parser_field_name2':'field_value2'}
        :type book: Dict
        :param formatter: класс форматтера
        :type formatter: Class
        :return: словарь для сохранения  в БД вида {'db_field_name1':'field_value1', 'db_field_name2':'field_value2', ... }
        :rtype: Dict
        """
        new_book = {}
        for property in formatter.all_properties_db().keys():
            value = book.get(property, None)
            if value == None: value = ''
            new_book[formatter.common[property]['db']['name']] = value
        return new_book

    @staticmethod
    def prepare_books_for_db(books: List[Dict], formatter=BookDataFormatter) -> List:
        """
        Преобразует список книг для сохранения в БД в соответствии с BookDataFormatter.
        Нужен в случае, если название колонки в БД отличается от названия свойства парсера или
        требуется предварительная обработка значения свойства.
        :param books: список книг вида [{'parser_field_name1':'field_value1','parser_field_name2':'field_value2'},{}]
        :type books: List[Dict]
        :param formatter: класс форматтера
        :type formatter: Class
        :return: список для сохранения  в БД вида [{'db_field_name1':'field_value1', 'db_field_name2':'field_value2'}, {}]
        :rtype: List[Dict]
        """
        result = []
        for book in books:
            result.append(ParserForDB._prepare_book_for_db(book, formatter=formatter))
        return result

class ParserForCSV(Parser):
    @staticmethod
    def create_filepath_csv(login: str) -> str:
        """
        Возвращает путь и безопасное имя файла CSV формата 'login-YYYY-MM-DD--HH-MM-SS.csv'.
        Из логина читателя будут удалены небезопасные символы.
        :param login: логин читателя
        :type login: str
        :return:
        :rtype: str
        """
        login = login.translate(str.maketrans('', '', '\/:*?"<>|'))
        filename = login + "-" + datetime.now().strftime("%Y-%m-%d--%H-%M-%S") + '.csv'
        # @todo тут должна задаваться папка для сохранения csv
        return (os.path.join('csv', filename))

class ParserForXLSX(Parser):
    @staticmethod
    def prepare_book_for_xlsx(book: Dict, formatter=BookDataFormatter) -> List:
        """
        Преобразует книгу для сохранения в XLSX в соответствии с BookDataFormatter.
        Нужен в случае, если название колонки в XLSX отличается от названия свойства парсера или
        требуется предварительная обработка значения свойства.
        :param book: словарь с информацией про книгу вида {'parser_field_name1':'field_value1','parser_field_name2':'field_value2'}
        :type book: Dict
        :param formatter: класс форматтера
        :type formatter: Class
        :return: словарь для сохранения  в XLSX вида {'db_field_name1':'field_value1', 'db_field_name2':'field_value2', ... }
        :rtype: Dict
        """
        new_book = {}
        for property in formatter.all_properties_xlsx().keys():
            method = formatter.all_properties_xlsx()[property].get('method', None)
            value = book.get(property, None)
            if value == None:
                value = ''
            elif method and hasattr(ParserForXLSX, method):
                value = getattr(ParserForXLSX,method)(value)
            new_book[property] = value
        # отдельно формируем дату из свойств month и year
        month_numbers = {1:'январь', 2:'февраль', 3:'март', 4:'апрель', 5:'май', 6:'июнь',
                         7:'июль',8: 'август', 9:'сентябрь',10: 'октябрь',11: 'ноябрь', 12: 'декабрь'}
        month = "" if not book['month'] else month_numbers.get(book['month'], '')
        new_book['date'] = " ".join((str(book['year']), month ))
        return new_book

    @staticmethod
    def create_author_link(id):
        return 'https://livelib.ru/author/'+str(id)

    @staticmethod
    def create_book_link(id):
        return 'https://livelib.ru/book/'+str(id)

    @staticmethod
    def create_work_link(id):
        return 'https://livelib.ru/work/'+str(id)

    @staticmethod
    def create_review_link(id):
        return 'https://livelib.ru/review/'+str(id)

    @staticmethod
    def create_review_text(text):
        bsoup = bs4.BeautifulSoup(text,features='lxml')
        result = bsoup.get_text("\n")
        result = result.replace("\n\n", "\n")
        return result


import json
import os

import country_converter as coco
import pandas as pd
from country_converter import country_converter

from scripts.config import PATHS

WEO_YEAR: int = 2023
CAUSES_OF_DEATH_YEAR = 2019
DEBT_YEAR: int = 2023

def get_full_africa_iso3() -> list:
    africa = (
        coco.CountryConverter()
        .data[["ISO3", "continent"]]
        .query("continent == 'Africa'")
        .ISO3.to_list()
    )

    # Add sub saharan Africa
    africa.append("SSA")
    africa.append("SSF")
    africa.append("AFE")
    africa.append("AFW")

    # Add World
    africa.append("WLD")

    # Add Africa
    africa.append("AFR")

    # ADD Global
    africa.append("GLOBAL")

    return africa

def sort_name_first(
    df: pd.DataFrame,
    name: str,
    name_column: str,
    date_column: str,
    keep_current_sorting=True,
):
    if not keep_current_sorting:
        df = df.sort_values([date_column, name_column], ascending=[True, False])

    top = df.query(f"{name_column} == '{name}'").reset_index(drop=True)
    other = df.query(f"{name_column} != '{name}'").reset_index(drop=True)

    return pd.concat([top, other], ignore_index=True)

def base_africa_df():
    """Create a map with geometries for all african countries"""

    return (
        country_converter.CountryConverter()
        .data[["ISO3", "continent"]]
        .rename(columns={"ISO3": "iso_code"})
        .query("continent == 'Africa'")
        .drop(columns="continent")
    )

def _download_wb_regions():
    df = pd.read_excel(
        "http://databank.worldbank.org/" "data/download/site-content/CLASS.xlsx",
        sheet_name="Groups",
    ).rename(
        columns={
            "GroupCode": "group_code",
            "GroupName": "group_name",
            "CountryCode": "iso_code",
            "CountryName": "country_name",
        }
    )
    df.to_csv(f"{PATHS.raw_data}/wb_groupings.csv", index=False)

def read_wb_regions(region_code: str) -> dict:
    """Read World Bank regions from csv file"""

    df = pd.read_csv(f"{PATHS.raw_data}/wb_groupings.csv")

    data = df.groupby("group_code").apply(lambda d: d.iso_code.to_list()).to_dict()

    return data[region_code]

def regions() -> dict:
    north_africa_wb = [
        "DZA",
        "EGY",
        "LBY",
        "MAR",
        "TUN",
    ]

    un_mapping = {
        "Northern Africa": "NAF",
        "Middle Africa": "MAF",
        "Western Africa": "WAF",
        "Eastern Africa": "EAF",
        "Southern Africa": "SAF",
    }

    data = (
        country_converter.CountryConverter()
        .data[["ISO3", "continent", "UNregion"]]
        .rename(columns={"ISO3": "iso_code"})
        .query("continent == 'Africa'")
        .assign(un=lambda d: d.UNregion.map(un_mapping))
    )

    regions_dict = {
        "NAF_WB": north_africa_wb,
        "SSA_WB": data.query("iso_code not in @north_africa_wb").iso_code.to_list(),
        "AFR": data.iso_code.to_list(),
        "SSA_UN": data.query("un != 'NAF'").iso_code.to_list(),
        "AFE_WB": read_wb_regions("AFE"),
        "AFW_WB": read_wb_regions("AFW"),
    }

    # UN regions
    for region in data.un.unique():
        regions_dict[region] = data.query("un == @region").iso_code.to_list()

    return regions_dict

def region_names() -> dict:
    return {
        "NAF_WB": "North Africa (WB)",
        "SSA_WB": "Sub-Saharan Africa (WB)",
        "SSA": "Sub-Saharan Africa (WB exc. high income)",
        "SSF": "Sub-Saharan Africa (WB)",
        "AFE_WB": "Eastern and Southern Africa",
        "AFE": "Eastern and Southern Africa",
        "AFW_WB": "Western and Central Africa",
        "AFW": "Western and Central Africa",
        "AFR": "Africa",
        "SSA_UN": "Sub-Saharan Africa (UN)",
        "NAF": "Northern Africa",
        "MAF": "Middle Africa",
        "WAF": "Western Africa",
        "EAF": "Eastern Africa",
        "SAF": "Southern Africa",
        "WLD": "World",
    }

def clean_wb_overview(df: pd.DataFrame) -> pd.DataFrame:
    """Clean World Bank data for overview charts

    returns a dataframe for a line chart with values for World and SSA
    """

    return (
        df.loc[lambda d: d["iso_code"].isin(["WLD", "SSA"])]
        .pivot(index="date", columns="iso_code", values="value")
        .round(2)
        .reset_index()
        .dropna(subset=["SSA", "WLD"])
        .rename(columns={"SSA": "Sub-Saharan Africa", "WLD": "World"})
    )

def df_to_key_number(
    df: pd.DataFrame,
    indicator_name: str,
    id_column: str,
    value_columns: str | list[str],
) -> dict:
    if isinstance(value_columns, str):
        value_columns = [value_columns]

    return (
        df.assign(indicator=indicator_name)
        .filter(["indicator", id_column] + value_columns, axis=1)
        .groupby(["indicator"])
        .apply(
            lambda x: x.set_index(id_column)[value_columns]
            .astype(str)
            .to_dict(orient="index")
        )
        .to_dict()
    )

def update_key_number(path: str, new_dict: dict) -> None:
    """Update a key number json by updating it with a new dictionary"""

    # Check if the file exists, if not create
    if not os.path.exists(path):
        with open(path, "w") as f:
            json.dump({}, f)

    with open(path, "r") as f:
        data = json.load(f)

    for k in new_dict.keys():
        data[k] = new_dict[k]

    with open(path, "w") as f:
        json.dump(data, f, indent=4)


import requests
import os

account_id = os.getenv('META_API_ACCOUNT_ID')
token = os.getenv("META_API_TOKEN")
region = os.getenv("META_API_REGION")

class Trading():
    def fetch_candlesticks(symbol, timeframe):
        symbol = symbol.replace('/', '')
        symbol = symbol.upper()
        timeframe_map = {
            "1 minute": "1m",
            "1 min": "1m",
            "1min": "1m",
            "M1": "1m",
            "5 minutes": "5m",
            "5 min": "5m",
            "5min": "5m",
            "M5": "1m",
            "15 minutes": "15m",
            "15 min": "15m",
            "15min": "15m",
            "M15": "15m",
            "30 minutes": "30m",
            "30 min": "30m",
            "30min": "30m",
            "M30": "30m",
            "1 hour": "1h",
            "1hour": "1h",
            "1hr": "1h",
            "H1": "1h",
            "4 hours": "4h",
            "4hours": "4h",
            "4 hrs": "4h",
            "H4": "4h",
            "1 day": "1d",
            "1day": "1d",
            "D1": "1d",
            "1 week": "1w",
            "1week": "1w",
            "W1": "1w",
            "1 month": "1mn",
            "1month": "1mn",
            "MN": "1mn"
        }
        # Check if the user input matches any of the keys in the dictionary
        if timeframe in timeframe_map:
            timeframe = timeframe_map[timeframe]
        else:
            # Assume that the user input is already in the correct format
            pass

        url = f"https://mt-market-data-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/historical-market-data/symbols/{symbol}/timeframes/{timeframe}/candles?limit=15"
        headers = {
            "auth-token": token,
            "Content-Type": "application/json"
        }
        response = requests.get(url, headers=headers)
        if response:
            candlesticks = response.json()
            return candlesticks
        else:
            return 'Failed to get candlesticks.'

    def close_trade(position_id) -> None:
        trade_data = {
            'actionType': 'POSITION_CLOSE_ID',
            'positionId': position_id
        }
        headers = {
            "auth-token": token,
            "Content-Type": "application/json"
        }
        url = f"https://mt-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/trade"
        response = requests.post(
            url, headers=headers, json=trade_data)
        response = response.json()
        return response

    def close_all_trades():
        url2 = f"https://mt-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/positions"
        headers = {
            "auth-token": token,
            "Content-Type": "application/json"
        }
        positions = requests.get(url2, headers=headers)
        positions = positions.json()
        responses = []
        for position in positions:
            trade_data = {
                'actionType': 'POSITION_CLOSE_ID',
                'positionId': position['id']
            }
            url = f"https://mt-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/trade"
            response = requests.post(
                url, headers=headers, json=trade_data)
            if response:
                print(f"Successfully closed trade for {position['symbol']}")
            else:
                print(f"Failed to close trade for {position['symbol']}")
            if response:
                responses.append(f"Successfully closed trade for {position['symbol']}")
            else:
                responses.append(f"Failed to close trade for {position['symbol']}")

        if responses:
            return responses
        else:
            return f'No trades to close.'

    def get_positions():
        url2 = f"https://mt-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/positions"
        headers = {
            "auth-token": token,
            "Content-Type": "application/json"
        }
        positions = requests.get(url2, headers=headers)
        if positions:
            positions = positions.json()
            return positions
        else:
            return f'Failed to get positions'

    def get_account_information():
        url = f"https://mt-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/account-information"
        headers = {
            "auth-token": token,
            "Content-Type": "application/json"
        }
        response = requests.get(url, headers=headers)
        if response:
            response = response.json()
            return response
        else:
            return f'Failed to get account information'

    def place_trade(symbol, volume, signal) -> None:
        signal = signal.upper()
        symbol = symbol.upper()
        symbol = symbol.replace('/', '')
        # Place the new trade
        if signal == 'BUY':
            trade_data = {
                'symbol': symbol,
                'actionType': 'ORDER_TYPE_BUY',
                'volume': float(volume),
                'comment': 'Auto-GPT MetaTrader Plugin'
            }
            headers = {
                "auth-token": token,
                "Content-Type": "application/json"
            }
            url = f"https://mt-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/trade"
            response = requests.post(url, headers=headers, json=trade_data)

            response = response.json()
            return response

        elif signal == 'SELL':
            trade_data = {
                'symbol': symbol,
                'actionType': 'ORDER_TYPE_SELL',
                'volume': float(volume),
                'comment': 'Auto-GPT MetaTrader Plugin'
            }
            headers = {
                "auth-token": token,
                "Content-Type": "application/json"
            }
            url = f"https://mt-client-api-v1.{region}.agiliumtrade.ai/users/current/accounts/{account_id}/trade"
            response = requests.post(url, headers=headers, json=trade_data)

            response = response.json()
            return response


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

from flask import request
from flask import session
from flask import redirect
from flask import url_for
from flask import Blueprint
from flask import render_template

from steamcommerce_api.api import user
from steamcommerce_api.api import steam
from steamcommerce_api.api import userrequest
from steamcommerce_api.api import paidrequest
from steamcommerce_api.api import testimonial
from steamcommerce_api.api import notification
from steamcommerce_api.api import creditrequest

import re
import config
import datetime

from oid import oid
from forms import user as user_form
from utils import route_decorators

user_view = Blueprint('views.user', __name__)

@user_view.route('/user/<username>')
@route_decorators.is_logged_in
@route_decorators.is_admin
def user_admin_profile(username):
    try:
        user_data = user.User().get_by_username(username)
    except user.User().model.DoesNotExist:
        error = {
            'title': 'Usuario inexistente',
            'content': 'El usuario no existe :('
        }

        return render_template('views/error.html', **error)

    notifications = notification.Notification().get_for_user(user_data['id'])

    userrequests = userrequest.UserRequest().get_by_user_id(
        user_data['id']
    )

    creditrequests = creditrequest.CreditRequest().get_by_user_id(
        user_data['id']
    )

    paidrequests = paidrequest.PaidRequest().get_by_user_id(
        user_data['id']
    )

    spent_incomes = user.User().get_user_spent_incomes(user_data['id'])

    register_delta = datetime.datetime.now() - (
        user_data.get('register_date') or datetime.datetime(year=2012, month=8, day=1)
    )

    form = user_form.ProfileForm(obj=user_data)

    params = {
        'form': form,
        'user': user_data,
        'userrequests': userrequests,
        'paidrequests': paidrequests,
        'notifications': notifications,
        'creditrequests': creditrequests,
        'spent_incomes': spent_incomes,
        'register_delta': register_delta
    }

    return render_template('views/user/profile.html', **params)

@user_view.route('/login')
@user_view.route('/login/')
@route_decorators.not_logged_in
@oid.loginhandler
def user_login():
    return oid.try_login(config.STEAM_OPENID_URL)

@user_view.route('/registro', methods=['GET', 'POST'])
@user_view.route('/registro/', methods=['GET', 'POST'])
@route_decorators.is_logged_in
@route_decorators.has_no_email
def user_register():
    user_id = session.get('user')
    curr_user = user.User().get_by_id(user_id)

    if request.method == 'GET':
        form = user_form.RegisterForm()

        return render_template(
            'views/user/register.html',
            user=curr_user,
            form=form
        )
    elif request.method == 'POST':
        form = user_form.RegisterForm(request.form)

        if not form.validate():
            return render_template(
                'views/user/register.html',
                user=curr_user,
                form=form
            )

        user.User().set_email(user_id, None, form.email.data)
        session['email'] = form.email.data

        return redirect(url_for('views.store.store_catalog'))

@user_view.route('/logout')
@user_view.route('/logout/')
@route_decorators.is_logged_in
def user_logout():
    try:
        session.pop('user')
    except:
        pass

    try:
        session.pop('admin')
    except:
        pass

    return redirect(url_for('views.store.store_catalog'))

@user_view.route('/perfil', methods=['GET', 'POST'])
@route_decorators.is_logged_in
def user_profile():
    user_id = session.get('user')
    user_data = user.User().get_by_id(user_id)

    notifications = notification.Notification().get_user_top_notifications(
        user_id
    )

    userrequests = userrequest.UserRequest().get_by_user_id(user_id)
    creditrequests = creditrequest.CreditRequest().get_by_user_id(user_id)
    paidrequests = paidrequest.PaidRequest().get_by_user_id(user_id)

    params = {
        'user': user_data,
        'userrequests': userrequests,
        'paidrequests': paidrequests,
        'notifications': notifications,
        'creditrequests': creditrequests
    }

    if request.method == 'GET':
        form = user_form.ProfileForm(obj=user_data)
        params.update({'form': form})

    elif request.method == 'POST':
        form = user_form.ProfileForm(request.form)
        params.update({'form': form})

        if form.validate():
            if user_data['email'] != form.email.data:
                user.User().set_email(
                    user_id,
                    user_data['email'],
                    form.email.data
                )

            name = form.name.data
            last_name = form.last_name.data

            if (
                user_data['name'] != name or
                user_data['last_name'] != last_name
            ):
                user.User().set_name(user_id, name, last_name)

    return render_template('views/user/profile.html', **params)

@user_view.route('/historial/<custom_id:history_identifier>')
@route_decorators.is_logged_in
def user_history(history_identifier):
    user_id = session.get('user')

    request_type = history_identifier['type']
    request_id = int(history_identifier['number'])

    incorrect_request = {
        'title': 'El pedido no corresponde a este usuario',
        'content': u'El pedido no está asociado a esta cuenta'
    }

    if request_type == 'A':
        try:
            userrequest_data = userrequest.UserRequest().get_id(request_id)
        except userrequest.UserRequest().model.DoesNotExist:
            return render_template('views/error.html', **incorrect_request)

        if userrequest_data['user']['id'] != user_id:
            return render_template('views/error.html', **incorrect_request)

        params = {
            'request_type': request_type,
            'request_id': request_id,
            'userrequest': userrequest_data
        }

        return render_template(
            'views/user/user-history.html',
            **params
        )
    elif request_type == 'B':
        try:
            creditrequest_data = creditrequest.CreditRequest().get_id(
                request_id
            )
        except creditrequest.CreditRequest().model.DoesNotExist:
            return render_template('views/error.html', **incorrect_request)

        if creditrequest_data['user']['id'] != user_id:
            return render_template('views/error.html', **incorrect_request)

        params = {
            'request_type': request_type,
            'request_id': request_id,
            'creditrequest': creditrequest_data
        }

        return render_template(
            'views/user/user-history.html',
            **params
        )
    elif request_type == 'C':
        try:
            paidrequest_data = paidrequest.PaidRequest().get_id(request_id)
        except paidrequest.PaidRequest.DoesNotExist:
            return render_template('views/error.html', **incorrect_request)

        if paidrequest_data['user']['id'] != user_id:
            return render_template('views/error.html', **incorrect_request)

        params = {
            'request_type': request_type,
            'request_id': request_id,
            'paidrequest': paidrequest_data
        }

        return render_template(
            'views/user/user-history.html',
            **params
        )

@user_view.route('/notifications/seen/')
@route_decorators.is_logged_in
@route_decorators.as_json
def user_notifications_seen():
    user_id = session.get('user')
    notification.Notification().update_seen(user_id)

    return {'success': True}

@user_view.route('/testimonios/nuevo')
@route_decorators.is_logged_in
def user_testimonials_new():
    return redirect('/')

@user_view.route('/testimonial/skip/', methods=['POST'])
@route_decorators.is_logged_in
@route_decorators.as_json
def user_testimonial_skip():
    user_id = session.get('user')
    testimonial_id = request.form.get('testimonial_id')

    if not testimonial_id:
        return ({'success': False}, 500)

    pending_testimonials = testimonial.Testimonial().get_unsubmited(
        user_id,
        excludes=['all']
    )

    testimonial_id = int(testimonial_id)

    if testimonial_id not in [x['id'] for x in pending_testimonials]:
        return ({'success': False}, 500)

    testimonial.Testimonial().update(**{
        'id': testimonial_id,
        'visible': False
    })

    return {'success': True}

@user_view.route('/testimonial/submit/', methods=['POST'])
@route_decorators.is_logged_in
@route_decorators.as_json
def user_testimonial_submit():
    return {'success': True}

@user_view.route('/wishlist')
@route_decorators.is_logged_in
def user_wishlist():
    return redirect('/')

@user_view.route('/wishlist/retry')
@route_decorators.is_logged_in
def user_wishlist_retry():
    return redirect(url_for('views.user.user_wishlist'))

@user_view.route('/user/cart/')
@route_decorators.is_logged_in
def user_cart():
    return ''

@user_view.route('/user/notifications/')
@route_decorators.is_logged_in
def user_notifications():
    user_id = session.get('user')

    notifications = notification.Notification().get_user_top_notifications(
        user_id,
        excludes=[
            'all',
        ]
    )

    params = {
        'notifications': notifications
    }

    return render_template(
        'views/user/nav-notifications.html',
        **params
    )

@oid.after_login
def steam_after_login(resp):
    user_steam_id = re.findall(
        config.STEAM_IDENTITY_URL_REGEX,
        resp.identity_url,
        re.DOTALL
    )

    if len(user_steam_id) < 1:
        # TODO: Log event

        return redirect(url_for('views.store.store_catalog'))

    try:
        steam_user = user.User().get_by_steam64(user_steam_id[0])
    except user.User().model.DoesNotExist:
        ip_address = request.headers.get(
            'CF-Connecting-IP',
            request.remote_addr
        )

        user_id = user.User().register(user_steam_id[0], ip_address)

        session['user'] = user_id
        session['email'] = None

        return redirect(url_for('views.user.user_register'))

    if not steam_user.email or len(steam_user.email) < 1:
        session['user'] = steam_user.id
        session['email'] = None

        return redirect(url_for('views.user.user_register'))

    if steam_user.is_banned:
        return render_template(
            'views/user/banned.html',
            user=steam_user
        )

    session['user'] = steam_user.id
    session['email'] = steam_user.email

    if steam_user.admin:
        session['admin'] = True

    player_info = steam.Steam().get_player_summaries(user_steam_id[0])

    if player_info:
        user.User().update(**{
            'id': steam_user.id,
            'avatar_url': player_info.get('avatarfull')
        })

    return redirect(
        request.args.get(
            'next',
            url_for('views.store.store_catalog')
        )
    )


import falcon
import ramlfications
import jsonschema

class ParameterChecker(object):
    """Check parameters with RAML."""

    def __init__(self, raml_file_path):
        """Load the RAML file."""
        self._raml = ramlfications.parse(raml_file_path)

    def process_resource(self, request, response, falcon_resource, uri_params):
        """Check parameters in the request.

        This function checks 3 parts:

        1. headers
        2. query parameters
        3. body
          a. json body
          b. form body parameters

        Note that it overrides process_resource instead of process_request
        because request.uri_template maybe None in process_request.
        Please see:
        http://falcon.readthedocs.io/en/stable/api/request_and_response.html#Request.uri_template
        """
        raml_resource = \
            self._get_raml_resource(request.method, request.uri_template)

        if raml_resource is None:
            return

        if raml_resource.headers:
            for header in raml_resource.headers:
                self._check_header(request, header)

        if raml_resource.query_params:
            for query_param in raml_resource.query_params:
                self._check_param(request, query_param)

        if raml_resource.body:
            if request.content_type is None:
                raise falcon.HTTPBadRequest('Bad request', 'No content type')
            matched = False
            for body in raml_resource.body:
                if body.mime_type != request.content_type:
                    continue
                matched = True
                if body.mime_type == 'application/json':
                    self._check_json_body(request, body.schema)
                elif body.mime_type == 'application/x-www-form-urlencoded':
                    for form_param_tuple in body.form_params.items():
                        form_param = self._make_form_param(form_param_tuple)
                        self._check_param(request, form_param)
                else:
                    # No other content type is supported yet
                    matched = False
            if not matched:
                raise falcon.HTTPBadRequest(
                    'Bad request',
                    'Unsupported content type: {}'.format(request.content_type)
                )

    def _get_raml_resource(self, method, uri_template):
        """Get the RAML resource by method and URI template.

        This is the best we can do for now:
        https://github.com/spotify/ramlfications/issues/112
        """
        for raml_resource in self._raml.resources:
            if raml_resource.method is None or raml_resource.path is None:
                continue
            if raml_resource.method.lower() != method.lower():
                continue
            if uri_template != raml_resource.path:
                continue
            return raml_resource
        return None

    def _check_header(self, request, raml_header):
        """Check if the request headers are valid.

        It checks 2 things:

        1. the existence (if required)
        2. the type (if given)

        It raises HTTPMissingHeader and HTTPInvalidHeader,
        respectively.
        """
        header = request.get_header(raml_header.display_name)

        if raml_header.required and header is None:
            raise falcon.HTTPMissingHeader(raml_header.display_name)

        if raml_header.type and header is not None:
            self.check_value_with_raml_type(
                raml_header,
                header,
                falcon.HTTPInvalidHeader
            )

    def _check_param(self, request, raml_param):
        """Check if the request parameters are valid.

        The behavior of this function is like _check_header, but
        for query parameters and body form parameters.
        """
        param = request.get_param(raml_param.name)

        if raml_param.required and param is None:
            raise falcon.HTTPMissingParam(raml_param.name)

        if raml_param.type and param is not None:
            self.check_value_with_raml_type(
                raml_param,
                param,
                falcon.HTTPInvalidParam
            )

    def _check_json_body(self, request, raml_json_body_schema):
        """Check JSON body with jsonschema.

        This function works only if falconraml.JsonTranslator
        is used in the middlewares.
        """
        if 'json' not in request.context:
            raise falcon.HTTPInternalServerError(
                'Internal server error',
                'Please use falconraml.JsonTranslator to parse json body.'
            )

        if type(raml_json_body_schema) is not dict:
            raise falcon.HTTPInternalServerError(
                'Internal server error',
                'Failed to parse jsonschema.'
            )

        request_json_body = request.context['json']

        try:
            jsonschema.validate(request_json_body, raml_json_body_schema)
        except jsonschema.exceptions.ValidationError as e:
            raise falcon.HTTPBadRequest('Bad request body', e.message)

    def check_value_with_raml_type(self, raml_spec, string, exception):
        """Check a string value with a RAML type.

        The listed types are from:
        https://github.com/raml-org/raml-spec/blob/master/versions/raml-08/raml-08.md#type
        """
        if raml_spec.type == 'string':
            # No need to check anything
            pass
        elif raml_spec.type == 'number':
            if not self._can_parse_as_python_type(float, string):
                raise exception('Should be a number.', raml_spec.name)
        elif raml_spec.type == 'integer':
            if not self._can_parse_as_python_type(int, string):
                raise exception('Should be an integer.', raml_spec.name)
        elif raml_spec.type == 'date':
            # Not supported yet
            pass
        elif raml_spec.type == 'boolean':
            if string not in ('true', 'false'):
                raise exception('Should be "true" or "false".', raml_spec.name)
        elif raml_spec.type == 'file':
            # Not supported yet
            pass

    def _can_parse_as_python_type(self, python_type, string):
        """Check if a string can be converted to a python type.

        Currently supports float and int.
        """
        try:
            python_type(string)
            return True
        except ValueError:
            return False

    def _make_form_param(self, param_tuple):
        """Make a FormParameter from a parameter tuple.

        This is a workaround for weird ramlfications parsing:
        https://github.com/spotify/ramlfications/issues/122
        """
        param_name = param_tuple[0]
        param_config = param_tuple[1]

        form_param = ramlfications.parameters.FormParameter(
            param_name,
            {},
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            {},
            [],
        )

        if 'required' in param_config:
            form_param.required = param_config['required']
        if 'type' in param_config:
            form_param.type = param_config['type']

        return form_param


#-*- coding:utf-8 -*-
__author__ = 'liubf'

from django.views.decorators.csrf import csrf_exempt
from django.core.paginator import Paginator
from django.shortcuts import render
from base.utils import MethodUtil as mtu,DateUtil
from base.models import BasPurLog
import datetime;

__EACH_PAGE_SHOW_NUMBER = 10

@csrf_exempt
def purlog(request):
    pageNum = mtu.getReqVal(request,"pageNum","1")
    start = mtu.getReqVal(request,"start")
    end = mtu.getReqVal(request,"end")
    ucode = mtu.getReqVal(request,"ucode","")
    pname = mtu.getReqVal(request,"pname","")

    try:
        karrs = {}
        if not start:
            start = (datetime.date.today().replace(day=1)).strftime("%Y-%m-%d")
        if not end:
            end = datetime.datetime.today().strftime("%Y-%m-%d")

        karrs.setdefault("createtime__gte", "{start} 00:00:00".format(start=start))
        karrs.setdefault("createtime__lte", "{end} 23:59:59".format(end=end))
        karrs.setdefault("ucode__contains", "{ucode}".format(ucode=ucode))
        karrs.setdefault("name__contains", "{pname}".format(pname=pname))

        rlist = BasPurLog.objects.all().filter(**karrs).order_by("-createtime")
    except Exception as e:
        rlist = []
        print(e)

    page = Paginator(rlist, __EACH_PAGE_SHOW_NUMBER, allow_empty_first_page=True).page(int(pageNum))
    result = {"page": page, "pageNum": str(pageNum), "start": start,"end":end,"ucode":ucode,"pname":pname,"qtype_dict":{"1":"查询","2":"下载"}}
    return render(request, "admin/sysConf_retail_purlog.html", result)

def report(request):
    pageNum = mtu.getReqVal(request, "pageNum", "1")
    start = mtu.getReqVal(request, "start")
    end = mtu.getReqVal(request, "end")
    ucode = mtu.getReqVal(request, "ucode", "")
    pname = mtu.getReqVal(request, "pname", "")
    try:
        if not start:
            start = (datetime.date.today().replace(day=1)).strftime("%Y-%m-%d")
        if not end:
            end = datetime.datetime.today().strftime("%Y-%m-%d")

        conn = mtu.getMysqlConn()
        cur = conn.cursor()

        condition = " where 1=1 "
        condition += " and createtime BETWEEN '{start} 00:00:00' AND '{end} 23:59:59'"\
                     .format(start=start,end=end)
        if ucode:
             condition += " and ucode like '%{ucode}%'".format(ucode=ucode)
        if pname:
            condition += " and name like '%{pname}%'".format(pname=pname)

        sql = "SELECT DATE_FORMAT(createtime,'%Y-%m-%d') createtime,`name`,url," \
              "SUM(CASE WHEN qtype = 1 THEN 1 ELSE 0 END) views," \
              "SUM(CASE WHEN qtype = 2 THEN 1 ELSE 0 END) downs " \
              "FROM bas_pur_log {condition} GROUP BY DATE_FORMAT(createtime,'%Y-%m-%d'),`name` "\
              "order by DATE_FORMAT(createtime,'%Y-%m-%d') DESC "\
              .format(condition=condition)

        cur.execute(sql)
        rlist = cur.fetchall()
        mtu.close(conn,cur)
    except Exception as e:
        rlist = []
        print(e)

    page = Paginator(rlist, __EACH_PAGE_SHOW_NUMBER, allow_empty_first_page=True).page(int(pageNum))
    result = {"page": page, "pageNum": str(pageNum),"start": start,"end":end,"ucode":ucode,"pname":pname,}
    return render(request, "admin/sysConf_retail_purlog_report.html", result)


from scipy.spatial import distance as dist
from imutils.video import VideoStream
from imutils import face_utils
from threading import Thread
import numpy as np
import os
os.environ['PYGAME_HIDE_SUPPORT_PROMPT']="hide"
import pygame
import argparse
import imutils
import time
import dlib
import cv2
import matplotlib.gridspec as gridspec
from collections import OrderedDict
from matplotlib import pyplot as plt
import sklearn
from sklearn.metrics import pairwise
from sklearn.metrics.pairwise import euclidean_distances
import multiprocessing

def cal_EAR(eye):
	dist1=dist.euclidean(eye[1],eye[5])
	dist2=dist.euclidean(eye[2],eye[4])
	dist3=dist.euclidean(eye[0],eye[3])

	ear=(dist1+dist2)/(2*dist3)

	return ear

def cal_MAR(m):
	dist4=dist.euclidean(mouth[13],mouth[19])
	dist5=dist.euclidean(mouth[14],mouth[18])
	dist6=dist.euclidean(mouth[15],mouth[17])

	mar=(dist4+dist5+dist6)/3

	return mar

def count(thresholded, segmented):
    chull = cv2.convexHull(segmented)

    extreme_top    = tuple(chull[chull[:, :, 1].argmin()][0])
    extreme_bottom = tuple(chull[chull[:, :, 1].argmax()][0])
    extreme_left   = tuple(chull[chull[:, :, 0].argmin()][0])
    extreme_right  = tuple(chull[chull[:, :, 0].argmax()][0])

    cX = int((extreme_left[0] + extreme_right[0]) / 2)
    cY = int((extreme_top[1] + extreme_bottom[1]) / 2)

    distance = pairwise.euclidean_distances([(cX, cY)], Y=[extreme_left, extreme_right, extreme_top, extreme_bottom])[0]
    maximum_distance = distance[distance.argmax()]

    radius = int(0.8 * maximum_distance)

    circumference = (2 * np.pi * radius)

    circular_roi = np.zeros(thresholded.shape[:2], dtype="uint8")

    cv2.circle(circular_roi, (cX, cY), radius, 255, 1)

    circular_roi = cv2.bitwise_and(thresholded, thresholded, mask=circular_roi)

    (cnts, _) = cv2.findContours(circular_roi.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    count = 0

    for c in cnts:
        (x, y, w, h) = cv2.boundingRect(c)

        if ((cY + (cY * 0.25)) > (y + h)) and ((circumference * 0.25) > c.shape[0]):
            count += 1

    return count

def run_avg(image, aWeight):
    global bg
    if bg is None:
        bg = image.copy().astype("float")
        return

    cv2.accumulateWeighted(image, bg, aWeight)

def segment(image, threshold=25):
    global bg
    diff = cv2.absdiff(bg.astype("uint8"), image)

    thresholded = cv2.threshold(diff, threshold, 255, cv2.THRESH_BINARY)[1]

    cnts, _ = cv2.findContours(thresholded.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    if len(cnts) == 0:
        return
    else:
        segmented = max(cnts, key=cv2.contourArea)
        return (thresholded, segmented)

pygame.mixer.init()

ap=argparse.ArgumentParser()
ap.add_argument("-l","--landmark_predictor",required=True,help="path of landmark predictor")
ap.add_argument("-a","--alarm",type=str,default="",help="path to alarm.wav file")
ap.add_argument("-w","--webcam",type=int,default=0,help="webcam number")

args=vars(ap.parse_args())
print()
print("######### INPUT ARGUMENTS:- #########")
print()
print("Landmark identifier: ",args["landmark_predictor"])
print("Alarm file: ",args["alarm"])
print("Webcam: ",args["webcam"])

top,right,bottom,left=10, 450, 225, 690
aWeight=0.5
num_frames=0
eye_aspect_ratio_threshold=0.3
mouth_aspect_ratio_threshold=20
cont_frames=48
cont_frames_blink=20
cont_frames_yawn=25
count1=0
count2=0
count3=0
bg = None
alarm_trig=False
og_ear=[]

print()
print("######### LOADING FACIAL LANDMARK PREDICTOR #########")
detector=dlib.get_frontal_face_detector()
predictor=dlib.shape_predictor(args["landmark_predictor"])

(leftstart,leftend)=face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rightstart,rightend)=face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
(mstart,mend)=face_utils.FACIAL_LANDMARKS_IDXS["mouth"]

print()
print("######### STARTING VIDEOSTREAM #########")
vs=VideoStream(src=args["webcam"]).start()
time.sleep(1.0)

FACIAL_LANDMARKS_IDXS = OrderedDict([
	("mouth", (48, 68)),
	("right_eyebrow", (17, 22)),
	("left_eyebrow", (22, 27)),
	("right_eye", (36, 42)),
	("left_eye", (42, 48)),
	("nose", (27, 35)),
	("jaw", (0, 17))
])

print()
print("######### INITIALIZING EAR THRESHOLD #########")
print()
print("Please sit in a position you would normally sit while driving for a few seconds.")
while count2<=100:
	frame=vs.read()
	frame=imutils.resize(frame,width=700)
	frame=cv2.flip(frame,1)

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

	gray=cv2.equalizeHist(gray)

	rects=detector(gray,0)

	for rect in rects:
		shape=predictor(gray,rect)
		shape=face_utils.shape_to_np(shape)

		for (name,(i,j)) in face_utils.FACIAL_LANDMARKS_IDXS.items():
			for (x,y) in shape[i:j]:
				cv2.circle(frame,(x,y),1,(0,0,255),-1)

			(x,y,w,h)=cv2.boundingRect(np.array(shape[i:j]))
			region_of_interest=frame[y:y+h,x:x+w]
			region_of_interest=imutils.resize(region_of_interest,width=600,inter=cv2.INTER_CUBIC)

		lefteye=shape[leftstart:leftend]
		righteye=shape[rightstart:rightend]
		mouth=shape[mstart:mend]

		left_ear=cal_EAR(lefteye)
		right_ear=cal_EAR(righteye)

		avg_ear=(left_ear+right_ear)/2

		left_eye_hull=cv2.convexHull(lefteye)
		right_eye_hull=cv2.convexHull(righteye)

		cv2.drawContours(frame,[left_eye_hull],-1,(0,255,0),1)
		cv2.drawContours(frame,[right_eye_hull],-1,(0,255,0),1)

		og_ear.append(avg_ear)

		count2+=1

sum=0.0
for i in range(len(og_ear)):
	sum=sum+og_ear[i]

temp=sum/len(og_ear)
eye_aspect_ratio_threshold=0.83*temp

print()
print("######### EAR THRESHOLD DETERMINED #########")
print()
print("Average EAR of driver: {:.2f}".format(temp))
print("EAR threshold of the driver: {:.2f}".format(eye_aspect_ratio_threshold))
print()
print("If for a continuous of 48 frames the EAR of driver remains below the threshold then alarm is triggered.")
print()
print("Raise your hand in the indicated box to turn the alarm off.")

while True:
	frame=vs.read()
	frame=imutils.resize(frame, width=700)
	frame=cv2.flip(frame,1)

	clone = frame.copy()

	(height, width) = frame.shape[:2]

	roi = frame[top:bottom, right:left]

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

	gray=cv2.equalizeHist(gray)

	gray=cv2.GaussianBlur(gray,(7,7),0)

	gray_roi=cv2.cvtColor(roi,cv2.COLOR_BGR2GRAY)
	gray_roi=cv2.GaussianBlur(gray_roi,(7,7),0)

	rects=detector(gray,0)
	cv2.putText(frame, "Press 'q' to exit", (500, 500),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)

	for rect in rects:
		shape=predictor(gray,rect)
		shape=face_utils.shape_to_np(shape)

		for (name,(i,j)) in face_utils.FACIAL_LANDMARKS_IDXS.items():
			for (x,y) in shape[i:j]:
				cv2.circle(frame,(x,y),1,(0,0,255),-1)

			(x,y,w,h)=cv2.boundingRect(np.array(shape[i:j]))
			region_of_interest=frame[y:y+h,x:x+w]
			region_of_interest=imutils.resize(region_of_interest,width=600,inter=cv2.INTER_CUBIC)

		lefteye=shape[leftstart:leftend]
		righteye=shape[rightstart:rightend]
		mouth=shape[mstart:mend]

		left_ear=cal_EAR(lefteye)
		right_ear=cal_EAR(righteye)

		avg_ear=(left_ear+right_ear)/2

		mar=cal_MAR(mouth)

		left_eye_hull=cv2.convexHull(lefteye)
		right_eye_hull=cv2.convexHull(righteye)
		# mouth_hull=cv2.convexHull(mouth)

		cv2.drawContours(frame,[left_eye_hull],-1,(0,255,0),1)
		cv2.drawContours(frame,[right_eye_hull],-1,(0,255,0),1)
		cv2.drawContours(frame,[mouth],-1,(0, 255, 0), 1)

		if num_frames < 30:
			run_avg(gray_roi, aWeight)
		else:
			hand = segment(gray_roi)
			if hand is not None:
				(thresholded, segmented) = hand
				cv2.drawContours(clone, [segmented + (right, top)], -1, (0, 0, 255))
				cv2.imshow("Thesholded", thresholded)
				x=count(thresholded, segmented)
				if x>3:
					count1=0
					alarm_trig=False
					pygame.mixer.music.stop()

		if avg_ear<eye_aspect_ratio_threshold:
			count1+=1
			if count1>=cont_frames:
				if not alarm_trig:
					alarm_trig=True
					if args["alarm"]!="":
						pygame.mixer.music.load(args["alarm"])
						pygame.mixer.music.play()
						print()

				cv2.putText(frame,"ALERT: DRIVER SLEEPY!!!",(10,30),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)

			elif count1>=cont_frames_blink:
				cv2.putText(frame,"YOU JUST BLINKED",(10,470),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,0,0),2)

		else:
			count1=0
			cv2.putText(frame,"DRIVER IS AWAKE",(10,30),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,255,0),2)

		cv2.putText(frame,"EAR: {:.2f}".format(avg_ear),(10,60),cv2.FONT_HERSHEY_TRIPLEX,0.7,(0,255,0),2)

		if mar>mouth_aspect_ratio_threshold:
			count3+=1
			if count3>=cont_frames_yawn:
				cv2.putText(frame,"YOU JUST YAWNED",(10,500),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,0,0),2)

		cv2.putText(frame,"MAR: {:.2f}".format(mar),(10,90),cv2.FONT_HERSHEY_TRIPLEX,0.7,(0,255,0),2)

		cv2.rectangle(frame, (left, top), (right, bottom), (0,255,0), 2)

		num_frames += 1

		cv2.imshow("Frame",frame)
		key=cv2.waitKey(1) & 0xFF

		if key==ord("q"):
			break
cv2.destroyAllWindows()
vs.stop()


from django.contrib import admin
from django.urls import path
from shop.views import MainPage, AllCategories, OneProduct, OneCategory, \
                       CartAPI, CartAdd, CartRemove, CartDelete, Payment, \
                       CartClean, Search
from django.conf.urls.static import static
from shop_drf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', MainPage.as_view()),
    path('categories', AllCategories.as_view()),
    path('<int:id>', OneProduct().as_view()),
    path('category/<str:name>', OneCategory().as_view()),
    path('cart/', CartAPI().as_view()),
    path('cart_add/', CartAdd().as_view()),
    path('cart_remove/', CartRemove().as_view()),
    path('cart_delete/', CartDelete().as_view()),
    path('cart_clean/', CartClean().as_view()),
    path('payment/', Payment().as_view()),
    path('search/', Search().as_view()),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


import os
from datetime import datetime, timedelta
from aiogram import Bot, Dispatcher, executor, types
from aiogram.types import ReplyKeyboardRemove, ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton, ContentType

button_hi = KeyboardButton('Сливы')
button_hi2 = KeyboardButton('Архивы')
button_hi3 = KeyboardButton('Приватка')
greet_kb = ReplyKeyboardMarkup(resize_keyboard=True)
greet_kb.add(button_hi,button_hi2,button_hi3)

Arhivi = KeyboardButton('Школьницы')
Arhivi2 = KeyboardButton('Милфы')
menu = KeyboardButton('Главное меню')
Arhivis = ReplyKeyboardMarkup(resize_keyboard=True)
Arhivis.add(Arhivi,Arhivi2,menu)

Privatka = KeyboardButton('Купить')
Otzivi = KeyboardButton('Отзывы')
menu = KeyboardButton('Главное меню')
press = ReplyKeyboardMarkup(resize_keyboard=True)
press.add(Privatka,Otzivi,menu)

Pokypka_arhiv = KeyboardButton('Купить Архив со Шк')
menu = KeyboardButton('Главное меню')
arif = ReplyKeyboardMarkup(resize_keyboard=True)
arif.add(Pokypka_arhiv,menu)

Pokypka_arhiv2 = KeyboardButton('Купить Архив со Милфами')
menu = KeyboardButton('Главное меню')
arif2 = ReplyKeyboardMarkup(resize_keyboard=True)
arif2.add(Pokypka_arhiv2,menu)

sub_inline_markup = InlineKeyboardMarkup(row_width=1)
ssilka_oplata = InlineKeyboardButton(text="Месяц приватки 250р", callback_data="submonth")
sub_inline_markup.insert(ssilka_oplata)

sub_inline_shkool_markup = InlineKeyboardMarkup(row_width=1)
ssilka_oplata_shkool = InlineKeyboardButton(text="Покупка архива школьниц", callback_data="shkool")
sub_inline_shkool_markup.insert(ssilka_oplata_shkool)

sub_inline_milfs_markup = InlineKeyboardMarkup(row_width=1)
ssilka_oplata_milfs = InlineKeyboardButton(text="Покупка архива милф", callback_data="milfs")
sub_inline_milfs_markup.insert(ssilka_oplata_milfs)

TOKEN_KASSA = "381764678:TEST:33651"
API_TOKEN = "5220046644:AAEHt4ki_jK3mH8S0ds8-2UNxfSqJ5xZCtw"
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler(commands=['start'])
async def process_start_command(message: types.Message):
    await message.answer("Привет, я бот приват Сливов @slivu97\n<◇>~•~ОБЬЯВЛЕНИЕ~•~<◇>\nБот в ранем доступе! прошу не покупать архивы\nПотратите деньги в пустую.\n<◇>~•~ОБЬЯВЛЕНИЕ~•~<◇>\nВыбери что тебя интересует",reply_markup=greet_kb)

@dp.message_handler(text=['Главное меню'])
async def glav_menu(message: types.Message):
    await message.answer("~~~~Вы_Перешли_В~~~~\n~~~главное меню~~~",reply_markup=greet_kb)

@dp.message_handler(text=['Сливы'])
async def nashi_slivu(message: types.Message):
    await message.answer("Наши сливы\n№1 - @slivu97\n№2 - @slivu96")

@dp.message_handler(text=['Архивы'])
async def arhifs_menu(message: types.Message):
    await message.answer("Есть архивы вот такие:\n№1-Школьницы\n№2-Милфы",reply_markup=Arhivis)

@dp.message_handler(text=['Приватка'])
async def privatochka(message: types.Message):
    await message.answer("Вход в приватку стоит 250р\nУспей пока цены не поднялись",reply_markup=press)

@dp.message_handler(text=['Школьницы'])
async def shk(message: types.Message):
    await message.answer("Архив со шк 1гб Цена 500р", reply_markup=arif)

@dp.message_handler(text=['Милфы'])
async def mifs(message: types.Message):
    await message.answer("Архив со Милфами 1гб Цена 250р",reply_markup=arif2)

@dp.message_handler(text=['Купить Архив со Шк'])
async def arhif_shk(message: types.Message):
    await message.answer("◇ВОТ ИНЛАЙН КНОПКА ДЛЯ ОПЛАТЫ◇", reply_markup=sub_inline_shkool_markup)

@dp.message_handler(text=['Купить Архив со Милфами'])
async def arhif_mifs(message: types.Message):
    await message.answer("◇ВОТ ИНЛАЙН КНОПКА ДЛЯ ОПЛАТЫ◇", reply_markup=sub_inline_milfs_markup)

@dp.message_handler(text=['Рефиральная Ссылка'])
async def ref_silka(message: types.Message):
    await message.answer("Ещё не создана")

@dp.message_handler(text=['Купить'])
async def process_h2_command(message: types.Message):
    await message.answer("◇ВОТ ИНЛАЙН КНОПКА ДЛЯ ОПЛАТЫ◇", reply_markup=sub_inline_markup)

@dp.message_handler(text=['Отзывы'])
async def procss_hi2_command(message: types.Message):
    await message.answer("Лови")
    await bot.send_photo(message.chat.id,photo=open('1.jpg', 'rb'))
    await bot.send_photo(message.chat.id,photo=open('2.jpg', 'rb'))
    await bot.send_photo(message.chat.id,photo=open('3.jpg', 'rb'))

@dp.message_handler(text=['Пополнить'])
async def esli_kupil_privat(message: types.Message):
    await message.answer("◇ВОТ ИНЛАЙН КНОПКА ДЛЯ ОПЛАТЫ◇", reply_markup=sub_inline_markup)

@dp.callback_query_handler(text=['shkool'])
async def submonth(callp: types.CallbackQuery):
    await bot.delete_message(callp.from_user.id, callp.message.message_id)
    await bot.send_invoice(chat_id=callp.from_user.id, title="Покупка архива школьниц", description="Покупка архива со школьницами", payload="month_shkool", provider_token=TOKEN_KASSA, currency="RUB", start_parameter="bot_shk",prices=[{"label": "Руб", "amount": 50000}])

@dp.pre_checkout_query_handler()
async def process_pre_checkout_query(pre_checkout_query: types.PreCheckoutQuery):
    await bot.answer_pre_checkout_query(pre_checkout_query.id, ok=True)

@dp.message_handler(content_types=ContentType.SUCCESSFUL_PAYMENT)
async def process_pay_shk(message: types.Message):
    if message.successful_payment.invoice_payload == "month_shkool":
        await message.answer(f"Держи ссылку\nhttps://mega.nz/folder/vaYHlYTJ#jlFyV7T2uq3-J4X1nenP1A")

@dp.callback_query_handler(text=['milfs'])
async def milfs_arhiv(calls: types.CallbackQuery):
    await bot.delete_message(calls.from_user.id, calls.message.message_id)
    await bot.send_invoice(chat_id=calls.from_user.id, title="Покупка архива милфами", description="Покупка архива с милфами", payload="month_filfs", provider_token=TOKEN_KASSA, currency="RUB", start_parameter="bot_milfs",prices=[{"label": "Руб", "amount": 25000}])

@dp.pre_checkout_query_handler()
async def process_pre_checkout_query(pre_checkout_query: types.PreCheckoutQuery):
    await bot.answer_pre_checkout_query(pre_checkout_query.id, ok=True)

@dp.message_handler(content_types=ContentType.SUCCESSFUL_PAYMENT)
async def process_pay_milf(message: types.Message):
    if message.successful_payment.invoice_payload == "month_filfs":
        await message.answer(f"Держи ссылку\nНа милф")

@dp.callback_query_handler(text=['submonth'])
async def submonth(call: types.CallbackQuery):
    await bot.delete_message(call.from_user.id, call.message.message_id)
    await bot.send_invoice(chat_id=call.from_user.id, title="Покупка привата", description="Покупка доступа к приват каналу", payload="month_sub", provider_token=TOKEN_KASSA, currency="RUB", start_parameter="test_bots",prices=[{"label": "Руб", "amount": 25000}])

@dp.pre_checkout_query_handler()
async def process_pre_checkout_query(pre_checkout_query: types.PreCheckoutQuery):
    await bot.answer_pre_checkout_query(pre_checkout_query.id, ok=True)

@dp.message_handler(content_types=ContentType.SUCCESSFUL_PAYMENT)
async def process_pay(message: types.Message):
    if message.successful_payment.invoice_payload == "month_sub":
        chat_id = -1001554743391
        expire_date = datetime.now()
        timedelta(days=1)
        link = await bot.create_chat_invite_link(chat_id, expire_date.timestamp, 1)
        await message.answer(f"Держи ссылку\n{link.invite_link}")

if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)


#! /usr/bin/env python

import rospy
import cv2
from sensor_msgs.msg import Image, CompressedImage
from std_msgs.msg import String
from cv_bridge import CvBridge
from darknet_ros_msgs.msg import BoundingBoxes, BoundingBox

# Publishes the detected classes
# Total of 12 objects. Create a unique counter for each one.
# When count matches FRAMES_COUNT publish message for the class
FRAMES_COUNT = 25
count = {}
class_pub = rospy.Publisher('/darknet_link/shown_object', String, queue_size=1)
def bboxes_callback(info):
    global count

    detected_classes = [bbox.Class for bbox in info.bounding_boxes]

    # Remove classes that were being counted but were missed this frame
    for k in count.keys():
        if k not in detected_classes:
            del count[k]

    # Count for each occuring class
    for c in detected_classes:
        if c not in count.keys():
            count[c] = 1 # Create counter
        else:
            count[c] += 1 # Increment counter

    for k in count.keys():
        if count[k] == FRAMES_COUNT:
            class_pub.publish(k)
            del count[k]

    print(count)

def capture_and_send_image_to_darknet_ros():
    rospy.init_node("capture_and_send_image_to_darknet_ros")

    pub = rospy.Publisher('/beo/camera/raw_image', Image, queue_size=1)
    #compressed_pub = rospy.Publisher('/beo/camera/compressed_image', CompressedImage, queue_size=1)

    rospy.Subscriber('/darknet_ros/bounding_boxes/', BoundingBoxes, bboxes_callback)

    bridge = CvBridge()

    rate = rospy.Rate(30)

    cap = cv2.VideoCapture(0)

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

        #cv2.imshow("Frame", frame)

        img_msg = bridge.cv2_to_imgmsg(frame, "bgr8")
        pub.publish(img_msg)

        cv2.waitKey(1)

        rate.sleep()

if __name__ == "__main__":
    try:
        capture_and_send_image_to_darknet_ros()
    except rospy.ROSInterruptException:
        pass
    except KeyboardInterrupt:
        pass

    cv2.destroyAllWindows()


from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
from django.contrib.auth.models import User
from django.db import models

DAYS_OF_WEEK = (
	(0, 'Monday'),
	(1, 'Tuesday'),
	(2, 'Wednesday'),
	(3, 'Thursday'),
	(4, 'Friday'),
	(5, 'Saturday'),
	(6, 'Sunday'),
)

class Schedule(models.Model):
	user = models.ForeignKey(User, primary_key=True)

	def __unicode__(self):
		return unicode(self.user)

class Entry(models.Model):
	schedule = models.ForeignKey(Schedule)
	day = models.IntegerField(choices=DAYS_OF_WEEK)
	class_name = models.CharField(max_length=7)
	start = models.TimeField("From")
	end = models.TimeField("To")

	def __unicode__(self):
		return unicode(self.schedule)

	@staticmethod
	def get_objects_by_day(day, schedule=None):
		entries_by_day = []
		entries = Entry.objects.all()
		for entry in entries:
			if schedule == None:
				if entry.day==day:
					entries_by_day.append(entry)
			else:
				if entry.day==day and entry.schedule==schedule:
					entries_by_day.append(entry)
		return entries_by_day


from django.shortcuts import render

# Create your views here.
def index(request):
    meetups = [{
        'title': 'First meetup',
        'location': 'uganda',
        'slug':'first-meetup'
    },
    {
        'title': 'second meetup',
        'location': 'uganda',
        'slug':'second-meetup'
    }
    ]
    return render(request, 'meetups/index.html', {'showmeetups':True,'meetups':meetups})

def meetup_details(request, meetup_slug):
    selected_meetup = {
        'title': 'second meetup',
        'description': 'this is the first meetup'
    }
    return render(
request, 'meetups/meetup-details.html', {
    'meetup_title': selected_meetup['title'],
    'meetup_desc': selected_meetup['description']
}
    )


import os

from menus import *
from filters import FILTER_LIST
from cursor_bubble import CursorPosBubble
import store

import kivy
from kivy.logger import Logger
from kivy.app import App
from kivy.config import Config
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.lang import Builder
import kivy.properties as kp
kivy.require('2.0.0')

class AppMenuALayout(AnchorLayout):
    pass

class MainLayout(FloatLayout):
    pass

class MainWindow(App):
    design_graph = kp.ObjectProperty(DesignGraph())
    graph = kp.ObjectProperty()
    menus = kp.ListProperty([])
    main_wnd_view = kp.ObjectProperty()
    loaded_filters = kp.ListProperty()
    cursor_bubble = kp.ObjectProperty(CursorPosBubble())

    def load_known_filters(self):
        for fclass in FILTER_LIST:
            self.loaded_filters.append(fclass)

    def get_concrete_menu(self, menu_class):
        for menu in self.menus:
            if issubclass(menu.__class__, menu_class):
                return menu

    def on_graph(self, instance, value):
        """change graph widget in desired place"""
        grid = self.main_wnd_view.ids['place_for_graph']
        try:
            grid.remove_widget(grid.children[0])
        except Exception as e:
            Logger.exception(e)
        grid.add_widget(self.graph)
        self.cursor_bubble.graph = self.graph

    def set_menus(self):
        """set list of menus accessible in program"""
        self.menus.clear()
        mainmenu = [w for w in self.main_wnd_view.walk() if issubclass(w.__class__, MainMenu)][0]
        for item in mainmenu.walk():
            try:
                submenu = item.get_submenu()
                if issubclass(submenu.__class__, ContextMenu):
                    submenu.visible = False
                    self.menus.append(submenu)
            except: pass
        self.menus.insert(0, mainmenu)

    def set_graph(self, which_one):
        store.update('current-graph', which_one)
        if which_one == 'visual':
            self.graph = VisualGraph()
        elif which_one == 'design':
            self.graph = self.design_graph
        else:
            raise ValueError(f"The graph {which_one} does not exist.")

    def build(self):
        import store  # important because this create store for first time.
        self.title = "System Filtracji Cyfrowej"
        # utworzenie obiektów opcji w klasie głównej programu
        self.main_wnd_view = Builder.load_file("main_window.kv")
        self.set_graph('design')
        store.add('current-graph', 'design')
        self.load_known_filters()
        DesignMenu.load()
        self.set_menus()
        self.main_wnd_view.add_widget(self.cursor_bubble)
        return self.main_wnd_view

def configure_kivy():
    _path = os.path.dirname(os.path.realpath(__file__))
    # os.environ['KIVY_HOME'] = _path
    Config.read(os.path.join(_path, 'config.ini'))
    Config.set('kivy', 'exit_on_escape', 0)
    Config.set('kivy', 'log_maxfiles', 1)
    # Config.set('kivy', 'log_dir', os.path.join(_path, "logs"))
    Config.set('input', 'mouse', 'mouse, disable_multitouch')
    Config.set('graphics', 'height', 764)
    Config.set('graphics', 'width', 1024)
    Config.set('graphics', 'minimum_height', 600)
    Config.set('graphics', 'minimum_width', 800)
    Config.set('graphics', 'maxfps', 30)
    Config.write()

if __name__ == '__main__':
    configure_kivy()
    MainWindow().run()
    try:
        os.remove(audio.TMP_FILE)
    except Exception as e:
        Logger.info(f"Tmp file cannot be removed {e}")