from dataclasses import field
from rest_framework import serializers
from django.contrib.auth import get_user_model
import requests
import json
from apps.core.models import UserRole

from apps.core.serializers import MyAccountSerializer, UserAppointment, UserSerializer
from apps.profiles.serializers import CounsellorProfileSerializer, ListCounsellorProfileSerializer

from .models import *
from zoom_api_functions import generateToken

# UserRole = get_user_model()

class AppointmentRequestSerializer(serializers.ModelSerializer):
    class Meta:
        model = AppointmentRequest
        fields = '__all__'

class ListAppointmentRequestSerializer(serializers.ModelSerializer):
    requested_by = MyAccountSerializer()
    # counsellor =
    class Meta:
        model = AppointmentRequest
        fields = '__all__'

class CreateAppointmentSerializer(serializers.ModelSerializer):
    appointment_meeting = serializers.ReadOnlyField()
    class Meta:
        model = Appointment
        fields = '__all__'

class ListAppointmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Appointment
        fields = '__all__'

class AppointmentDetailsSerializer(serializers.ModelSerializer):
    user = MyAccountSerializer(read_only=True)
    counsellor = ListCounsellorProfileSerializer(read_only=True)

    class Meta:
        model = Appointment
        fields = '__all__'

class LiveMeetingSerializer(serializers.ModelSerializer):
    zoom_meeting = serializers.ReadOnlyField()
    status = serializers.ReadOnlyField(default='upcoming')
    api_url = serializers.ReadOnlyField(required=False)
    start_meeting_url = serializers.ReadOnlyField(required=False)
    invitation_url = serializers.ReadOnlyField(source='get_meeting_invitation')

    class Meta:
        model = AppointmentMeeting
        fields = '__all__'

class GetAppointmentMeetingSerializer(serializers.ModelSerializer):
    zoom_meeting = serializers.SerializerMethodField()
    status = serializers.ReadOnlyField(default='upcoming')
    join_meeting_url = serializers.ReadOnlyField(source='get_join_meeting_url')
    invitation_url = serializers.ReadOnlyField(source='get_meeting_invitation')
    api_url = serializers.ReadOnlyField(source='get_api_url')

    class Meta:
        model = AppointmentMeeting
        exclude = ('created_by', 'created_date',
                   'last_modified_by', 'last_modified_date',)

    def get_zoom_meeting(self, obj):
        meeting_id = obj.zoom_meeting_id
        # Getting the Zoom Meeting
        headers = {'authorization': 'Bearer %s' % generateToken(),
                   'content-type': 'application/json'}
        r = requests.get(
            f'https://api.zoom.us/v2/meetings/{meeting_id}',
            headers=headers)
        # print(r.json())
        return r.json()

class DashboardSerializer(serializers.ModelSerializer):
        total_counsellor_user = serializers.SerializerMethodField()
        total_business_user = serializers.SerializerMethodField()
        total_customer_user = serializers.SerializerMethodField()

        class Meta:
            model = UserRole
            fields = ['total_counsellor_user', 'total_business_user', 'total_customer_user']

        def get_total_counsellor_user(self, obj):
            return UserRole.objects.filter(user_role__title="Counsellor").count()

        def get_total_business_user(self, obj):
            return UserRole.objects.filter(user_role__title="Business").count()

        def get_total_customer_user(self, obj):
            return UserRole.objects.filter(user_role__title="Customer").count()

class ReportSerializer(serializers.ModelSerializer):
    class Meta:
        model = Report
        fields = '__all__'

class ReportInfoSerializer(serializers.ModelSerializer):
    appointment = AppointmentDetailsSerializer(read_only=True)
    counsellor = ListCounsellorProfileSerializer(read_only=True)
    reported_by = MyAccountSerializer(read_only=True)

    class Meta:
        model = Report
        fields = '__all__'

class FeedbackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Feedback
        fields = '__all__'

class FeedbackInfoSerializer(serializers.ModelSerializer):
    appointment = AppointmentDetailsSerializer(read_only=True)
    counsellor = ListCounsellorProfileSerializer(read_only=True)
    feedback_by = MyAccountSerializer(read_only=True)

    class Meta:
        model = Feedback
        fields = '__all__'


# gets grupy data and runs a plotting function
import matplotlib.pyplot as plt

def GruPlot( prefix, q_labels, gru_data):

	fig, axes = plt.subplots(nrows=1, ncols=1)
	x = []
	lab = []

	for i in xrange( len(q_labels) ):
		lab.append( q_labels[i][1] )
		x.append( q_labels[i][0] )

	plt.setp(axes, xticks=x, xticklabels=lab)
	plt.title(prefix, fontsize=24)
	plt.ylabel(r"$\gamma$", fontsize=20, weight="bold")

	for i in xrange( len(gru_data) ): # 3N columns

		if i != 0:
			plt.plot( gru_data[0] , gru_data[i], 'o' )

	plt.show()

	return 0


import heapq
from collections import defaultdict
from typing import List

start_and_end_times = [[4, 7], [2, 5], [1, 3], [5, 8]]

# test_tuples = [(1, 5), (3, 4), (3, 3), (2, 1), (2, 7), (1, 1)]
# heapq.heapify(test_tuples)

def max_concurrency_best(s):
    """Naive method to solve max_concurrency. Passes all tests!"""
    heap = []
    count = 0
    answer = 0
    heapq.heapify(s)
    if s:
        # from the min start time to the max end time
        for i in range(s[0][0], s[len(s) - 1][1]):
            for start_and_end_time in s:
                if i == start_and_end_time[0]:
                    count += 1
                    if len(heap) < 1:
                        heapq.heappush(heap, count)
                    elif len(heap) == 1:
                        # fast push, then pop
                        heapq.heappushpop(heap, count)
                    else:
                        heapq.heappop(heap)
                elif i == start_and_end_time[1]:
                    count -= 1
        if heap:
            answer = heap[0]
    return answer

def max_concurrency_attempt_1(s):
    """Efficient method to solve max_concurrency. Passes 4 tests."""
    heap = []
    start = 0
    end = 1
    heapq.heapify(s[:])
    if s:
        count = len(s)
        heapq.heappush(heap, s[0])
        for i in range(len(s)):
            top = s[0]
            if top[end] < s[i][start]:
                heapq.heappush(heap, s[i])
                count -= 1
            elif top[end] < s[i][end]:
                # top[end] = s[i][end]
                heapq.heappop(heap)
                heapq.heappush(heap, top)
                count += 1
    else:
        count = 0
    return count

def max_concurrency_attempt_2(s):
    """Efficient method to solve max_concurrency. Doesn't even compile."""
    import heapq
    h = []
    heapq.heappush(h, 10000)
    res = 0
    for (start, end) in s:
        while heapq.nsmallest(1, h)[0] < s:
            heapq.heappop(h)
        res = res + len(h) - 1
        heapq.heappush(h, end)
    return res

def max_concurrency_attempt_3(s):
    """Fails 9 tests."""
    es = []
    for start, end in s:
        es.append((start, -1))
        es.append((end, 1))
    es.sort()
    result = 0
    n = 0
    for start, s in es:
        if s == -1:
            result += n
        n -= s
    return result

def max_concurrency_attempt_4(intervals):
    """Fails all tests."""
    intervals = sorted(intervals)
    first_start, first_end = intervals[0]
    current_intervals = []
    heapq.heappush(current_intervals, first_start)
    overlaps = 0

    for start, end in intervals[1:]:
        if current_intervals:
            if current_intervals[0] < start:
                heapq.heappop(current_intervals)
                overlaps += len(current_intervals)
    return overlaps

def max_concurrency_attempt_5(points):
    """
    If len of intervals is 0 or 1 return immediately. Passes 2 tests.
    """
    if len(points) in [0, 1]:
        return len(points)

    """
    Push all intervals to heap
    """
    q = []
    for point in points:
        heapq.heappush(q, (point[0], point[1]))

    """
    Start with the top element in the heap
    """
    cur = heapq.heappop(q)
    cur_max = cur[1]
    res = []

    while q:
        point = heapq.heappop(q)

        """
        check if the last seen max falls in the new point interval. If it is then change the last seen max
        """
        if point[0] <= cur_max:
            cur_max = min(cur_max, point[1])

        else:
            """
            In this case last seen max doesn't fall in the new point interval. Push last seen max to ans and then res assign to new point end
            """
            res.append(cur_max)
            cur_max = point[1]
    res.append(cur_max)
    return len(res)

def max_concurrency(s):
    concurrent_jobs = 0
    max_jobs = 0
    heap = []
    if s:
        for start, end in s:
            heapq.heappush(heap, end)
            while heap[0] <= start:
                heapq.heappop(heap)
                concurrent_jobs -= 1
            concurrent_jobs += 1
            if concurrent_jobs > max_jobs:
                max_jobs = concurrent_jobs
    return max_jobs

def max_concurrency_attempt_7(self, trips: List[List[int]], capacity: int) -> bool:
    """Does not compile."""
    start = defaultdict(int)
    end = defaultdict(int)
    for trip in trips:
        start[trip[1]] += trip[0]
        end[trip[2]] += trip[0]
    curr = 0
    heapStart = []
    for key, value in start.items():
        heapq.heappush(heapStart, (key, value))
    heapEnd = []
    for key, value in end.items():
        heapq.heappush(heapEnd, (key, value))
    while heapStart:
        if heapEnd[0][0] <= heapStart[0][0]:
            curr -= heapq.heappop(heapEnd)[1]
        else:
            if heapStart[0][1] + curr > capacity:
                return False
            curr += heapq.heappop(heapStart)[1]
    return True

def max_concurrency_attempt_8(s):
    """Passes 4 tests."""
    intervalPoints = []
    for interval in s:
        heapq.heappush(intervalPoints, (interval[0], -1))
        heapq.heappush(intervalPoints, (interval[1], 1))
    maxOverlap = 0
    maxOverlapLocation = 0
    overlaps = 0
    while intervalPoints:
        index, val = heapq.heappop(intervalPoints)
        overlaps -= val
        if overlaps > maxOverlap:
            maxOverlap = overlaps
            maxOverlapLocation = index
    return maxOverlapLocation

def max_concurrency_pre_attempt_9(s):
    """Passes 7 tests."""
    s.sort(key=lambda x: x[1])
    f = 0
    heap = []
    for start, end in s:
        heapq.heappush(heap, -start)
        f += start
        if f >= end:
            f += heapq.heappop(heap)
    return len(heap)

def max_concurrency_attempt_9(s):
    pq = []
    start = 0
    for start_end in sorted(s, key=lambda x: x[1]):
        st, end = start_end[0], start_end[1]
        start += st
        heapq.heappush(pq, -st)
        while start >= end:
            start += heapq.heappop(pq)
    return len(pq)

def max_concurrency_attempt_10(s):
    """Fails all tests."""
    starts, ends = zip(*s)
    overlap = range(max(starts), min(ends) + 1)
    if not overlap:
        return ([], range(min(starts), max(ends) + 1), [])

    less_non_overlap = range(*heapq.nsmallest(2, starts))
    end, start = heapq.nlargest(2, ends)
    greater_non_overlap = range(start + 1, end + 1)
    return (overlap, less_non_overlap, greater_non_overlap)

def max_concurrency_attempt_11(s):
    """Fails all tests."""
    meetings = sorted(s, key=lambda k: k[1])

    heap = [(meetings[0][1], 0)]

    overlaps = {}

    for i in range(1, len(meetings)):
        if meetings[i][0] == heap[0][0]:
            heapq.heappush(heap, (meetings[i][1], i))
        else:
            heapq.heappop(heap)
            heapq.heappush(heap, (meetings[i][1], i))

        if meetings[i][0] <= heap[0][0]:
            p = (meetings[i][0], heap[0][0])
            if p in overlaps:
                overlaps[p] = max(overlaps[p], len(heap))
            else:
                overlaps[p] = len(heap)

    return [x for x, y in overlaps.items() if y == max(overlaps.values())]

# print(max_concurrency(start_and_end_times))
# start_time, end_time = start_and_end_time[0], start_and_end_time[1]
# overlap = min(end_time)


from appFile import request, app, ma, cross_origin
from models.index import db, Events, Timeline
from flask import jsonify
from controllers.auth import JWTcheck

class EventSchema(ma.Schema):
  class Meta:
    fields = ('id', 'name', 'info', 'timeline_id', 'day', 'month', 'year', 'time', 'date_created')

event_schema = EventSchema()

@app.route('/addEvent', methods=['POST'])
@cross_origin()
@JWTcheck
def addEvent(data):
  info = request.json['info']
  name = request.json['name']
  timeline_id = request.json['timeline_id']
  day = request.json['day']
  month = request.json['month']
  year = request.json['year']
  time = request.json['time']

  new_event = Events(name, info, timeline_id, day, month, year, time)

  db.session.add(new_event)
  db.session.commit()
  return event_schema.jsonify(new_event)

@app.route('/getEvents', methods=['POST'])
@cross_origin()
@JWTcheck
def getEvents(data):
  timelineID = request.json['timeline_id']

  if (Timeline.query.filter_by(id=timelineID).first().user_id!=data['user']):
    return jsonify(message='You do not own this timeline'), 403

  events = Events.query.filter_by(timeline_id=timelineID).all()

  output = []
  for element in events:
    output.append({'name':element.name, 'id':element.id, 'info':element.info, 'day':element.day, 'month':element.month, 'year':element.year, 'time':element.time})

  return jsonify(output)

@app.route('/eventEdit', methods=['PATCH'])
@cross_origin()
@JWTcheck
def eventEditInfo(data):
  id = request.json['id']
  info = request.json['info']
  name = request.json['name']
  day = request.json['day']
  month = request.json['month']
  year = request.json['year']
  time = request.json['time']

  event = Events.query.filter_by(id=id).first()

  if (Timeline.query.filter_by(id=event.timeline_id).first().user_id!=data['user']):
    return jsonify(message='You do not own this timeline'), 403

  event.info = info
  event.name = name
  event.day = day
  event.month = month
  event.year = year
  event.time = time
  db.session.commit()

  return jsonify({'name':event.name,'info':event.info, 'day':event.day, 'month':event.month, 'year':event.year, 'time':event.time, 'id':event.id})


def function_names(open_file_handler):
    '''
    This function takes in an open_file_handler (python file) and will scan
    though it to find function names within the file.
    :param open_file_handler: io.TextIOWrapper, a file handler in the read mode
    :return: list of strings
    '''
    # Two lists, one of file text, other (empty) with found fn names
    text_list = open_file_handler.readlines()
    found_func_names = []
    # Iterate through list, if def is found, strip it, split string at (
    for text in text_list:
        if ("def " in text):
            text = text.lstrip("def ")
            func_name = text.rsplit("(")
            # add the name to the found fn list
            found_func_names.append(func_name[0])
    # Return the list of found functions
    return found_func_names

def justified(open_file_handler):
    '''
    Function takes in an open_file_handler, and will scan through the files to
    see if the entire file is left-justified. If the line starts with a space,
    this function will return False. Otherwise, it will return True.
    :param open_file_handler: io.TextIOWrapper, opened in Read mode
    :return: Boolean
    '''
    flag = True
    # Read the initial line
    text = open_file_handler.readline()
    # Iterate through the lines in the text, if flag is false, stop
    while(flag and text):
        # If we find a space at the begining of the word, set the flag to false
        if(text.startswith(" ")):
            flag = False
        # Read the next line for the loop
        text = open_file_handler.readline()
    return flag


import os
import requests
import shutil
import boto3
from PIL import Image
import urllib.request

access_key_src = os.environ.get("AWS_ACCESS_KEY_ID")
secret_key_src = os.environ.get("AWS_SECRET_ACCESS_KEY")
region_name = os.environ.get("AWS_REGION_NAME")
bucket_name = os.environ.get("AWS_MEDIA_BUCKET_NAME")
bucket_folder = os.environ.get("AWS_BUCKET_BASE_FOLDER","")

def convert_image_name(old_name, append_name):
    names = old_name.split(".")
    extension = names[1]
    new_name = names[0] + "-" + append_name + "." + extension
    return new_name

def create_thumb_s3(image_file):
    s3 = boto3.resource('s3', region_name=region_name,
                        aws_access_key_id=access_key_src,
                        aws_secret_access_key=secret_key_src)
    bucket = s3.Bucket(bucket_name)

    if not os.path.exists("__sized__/products"):
        os.makedirs("__sized__/products")

    keys = {
        "products": [
            ("product_gallery", "thumbnail__540x540"),
            ("product_gallery_2x", "thumbnail__1080x1080"),
            ("product_small", "thumbnail__60x60"),
            ("product_small_2x", "thumbnail__120x120"),
            ("product_list", "thumbnail__255x255"),
            ("product_list_2x", "thumbnail__510x510"),
        ]
    }
    for output in keys['products']:
        values = output[1].split("__")
        if len(values) != 2:
            return
        output_size_str = values[1].split("x")
        output_size = tuple(list(map(int, output_size_str)))

        img = Image.open(image_file)

        img.thumbnail(output_size)
        image_path_thumb = convert_image_name(
            image_file.replace("images", "__sized__/products"),
            values[0] + "-" + values[1])

        img.save(image_path_thumb)

        new_image_name = bucket_folder+image_path_thumb.replace(
            "app/media/", "")

        bucket.upload_file(image_path_thumb, new_image_name,
                           ExtraArgs={"ContentType": "image/webp"})

        os.remove(image_path_thumb)

    os.remove(image_file)

    pass

    """download image from url
    """

def download_image(url):
    fileName = url.split("/")[-1]
    fileName = os.path.join("images", fileName)
    path = os.path.dirname(fileName)
    if not os.path.exists(path):
        os.makedirs(path)
    opener = urllib.request.URLopener()
    opener.addheader('User-Agent', 'Upload media service')
    fileName, headers = opener.retrieve(url, fileName)
    # fileName = opener.retrieve(url, fileName)
    return fileName


import pandas as pd, numpy as np
import re
import pickle
dataset = pd.read_csv("Restaurant_Reviews.csv")

dataset['Review']

import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
corpus = []
for i in range(0, 1000):
  review = re.sub('[^a-zA-Z]', ' ', dataset['Review'][i])
  review = review.lower()
  review = review.split()
  ps = PorterStemmer()
  all_stopwords = stopwords.words('english')
  all_stopwords.remove('not')
  review = [ps.stem(word) for word in review if not word in set(all_stopwords)]
  review = ' '.join(review)
  corpus.append(review)

from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer(max_features = 1500)
X = cv.fit_transform(corpus).toarray()
y = dataset.iloc[:, -1].values

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.30, random_state=42)

# Creating a pickle file for the CountVectorizer
pickle.dump(cv, open('cv-transform.pkl', 'wb'))

from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB(alpha=0.2)
classifier.fit(X_train, y_train)

y_pred = classifier.predict(X_test)
print(np.concatenate((y_pred.reshape(len(y_pred),1), y_test.reshape(len(y_test),1)),1))

from sklearn.metrics import confusion_matrix, accuracy_score
cm = confusion_matrix(y_test, y_pred)
print(cm)
accuracy_score(y_test, y_pred)

pickle.dump(classifier,open('model.pkl','wb'))


from PIL import Image
import PIL.ImageOps
from shutil import move

def alpha_channel_upscale(inpath, outpath, workingImage, settings):
    """Opens the current working image as well as the original image, resizes (BICUBIC) the original image and copies the alpha channel"""
    originalImage = Image.open(workingImage.originalPath)
    if originalImage.mode != 'RGBA':
        # No alpha channel existed in the original image, so no need to do anything
        # Move the file to the outpath
        move(inpath, outpath)
        return True

    currentImage = Image.open(inpath)

    resizedImage = originalImage.resize(currentImage.size, Image.BICUBIC)

    # Extract the alpha channel
    alpha = resizedImage.split()[-1]
    currentImage.putalpha(alpha)

    currentImage.save(outpath, 'PNG')

    return True


def primeNumb():
    testNum = int(input("Enter an integer to test for prime: "))
    if testNum > 1:
        for i in range(2,testNum):
            #print(i)
            if (testNum % i) == 0:
                print(testNum, "is not a prime number")
                print(i,"times",testNum//i,"is",testNum)
                break
        else:
            print(testNum, "is a prime number",i)
    else:
        print("You must enter an integer.")

def stampa():
    print ("ecco quello che cercavi")

if __name__ == "__main__":
    stampa()


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def searchBST(self, root:TreeNode, val: int) -> TreeNode:
        while root:
            if root.val == val:
                return root
            elif root.val < val:
                root = root.right
            else:
                root = root.left
        return None

    #Implement recursive approach
    def searchBSTRecursively(self, root: TreeNode, val) -> TreeNode:
        if not root:
            return None

        while root:
            if root.val == val:
                return root
            elif val > root.val:
                return self.searchBSTRecursively(root.right, val)
            else:
                return self.searchBSTRecursively(root.left, val)


"""Test the A-priori, position-based and hybrid method in freqsubseq.py. """

import unittest
from freqsubseq import initialized_tree, candidates, run_apriori
from freqsubseq import assign_pattern_index, initialized_queue
from freqsubseq import candidate_mappings, run_position
from freqsubseq import number_of_freq_subseq
from freqsubseq import frequent_patterns, Counter

class AuxReader:
    """Auxiliary reader to set up test cases."""

    def __init__(self, seqs):
        """Initiate reader with a collection of sequences."""
        self.seqs = seqs

    def items(self):
        """Return a generator of sequences that are stored."""
        for seq in self.seqs:
            yield seq

class AlgorithmTestCase(unittest.TestCase):
    def setUp(self):
        seq = 'ACGATTCGATCG'
        num = 2
        self.data = AuxReader([seq for _ in range(num)])
        self.thrd = 4
        self.min_len = 1
        self.max_len = 3
        self.ground_truth = {('A', 6), ('C', 6), ('G', 6), ('T', 6), ('AT', 4),
                             ('CG', 6), ('GA', 4), ('TC', 4), ('CGA', 4),
                             ('GAT', 4), ('TCG', 4)}

    def test_initialized_tree(self):
        m = 2
        tree = initialized_tree(self.data, m)

        # Check the edgelist of the tree
        el_true = {('', 'A'), ('', 'C'), ('', 'G'), ('', 'T'), ('A', 'AC'),
                   ('A', 'AT'), ('C', 'CG'), ('G', 'GA'), ('T', 'TT'),
                   ('T', 'TC')}
        el = {(parent.seq, child.seq)
              for parent in tree.all_nodes()
              for child in parent.all_children()}
        self.assertEqual(el, el_true)

        # Check the counts for leaves
        counts_true = {('AC', 2), ('AT', 4), ('CG', 6), ('GA', 4), ('TT', 2),
                       ('TC', 4)}
        counts = {(node.seq, node.count) for node in tree.nodes_at_level(m)}
        self.assertEqual(counts, counts_true)

    def test_candidates(self):
        m = 2
        tree = initialized_tree(self.data, m)
        cand_true = {'ATC', 'CGA', 'GAT', 'TCG'}
        cand = set(candidates(tree, m+1, self.thrd))
        self.assertEqual(cand, cand_true)

    def test_run_apriori(self):
        m = 2
        tree = initialized_tree(self.data, m)
        run_apriori(self.data, tree, m+1, self.thrd)

        # Check the edgelist of the tree
        el_true = {('', 'A'), ('', 'C'), ('', 'G'), ('', 'T'), ('A', 'AC'),
                   ('A', 'AT'), ('C', 'CG'), ('G', 'GA'), ('T', 'TT'),
                   ('T', 'TC'), ('AT', 'ATC'), ('CG', 'CGA'), ('GA', 'GAT'),
                   ('TC', 'TCG')}
        el = {(parent.seq, child.seq)
              for parent in tree.all_nodes()
              for child in parent.all_children()}
        self.assertEqual(el, el_true)

        # Check the counts for the candidate patterns
        counts_true = {('ATC', 2), ('CGA', 4), ('GAT', 4), ('TCG', 4)}
        counts = {(node.seq, node.count) for node in tree.nodes_at_level(m+1)}
        self.assertEqual(counts, counts_true)

    def test_assign_pattern_index(self):
        m = 2
        tree = initialized_tree(self.data, m)
        assign_pattern_index(tree, m, self.thrd)
        has_idx_ture = {('AC', False), ('AT', True), ('CG', True),
                        ('GA', True), ('TT', False), ('TC', True)}
        has_idx = {(node.seq, hasattr(node, 'idx'))
                   for node in tree.nodes_at_level(m)}
        self.assertEqual(has_idx, has_idx_ture)

    def test_initialized_queue(self):
        m = 2
        tree = initialized_tree(self.data, m)
        assign_pattern_index(tree, m, self.thrd)
        idx = {seq: tree.pattern(seq).idx
               for seq in ['AT', 'CG', 'GA', 'TC']}
        queue_true = [(0, 1, idx['CG']), (0, 2, idx['GA']), (0, 3, idx['AT']),
                      (0, 5, idx['TC']), (0, 6, idx['CG']), (0, 7, idx['GA']),
                      (0, 8, idx['AT']), (0, 9, idx['TC']), (0, 10, idx['CG'])]
        queue_true += [(1, 1, idx['CG']), (1, 2, idx['GA']), (1, 3, idx['AT']),
                       (1, 5, idx['TC']), (1, 6, idx['CG']), (1, 7, idx['GA']),
                       (1, 8, idx['AT']), (1, 9, idx['TC']), (1, 10, idx['CG'])]
        queue = initialized_queue(self.data, tree, m, self.thrd)
        self.assertEqual(queue, queue_true)

    def test_cadidate_mappings(self):
        m = 2
        tree = initialized_tree(self.data, m)
        assign_pattern_index(tree, m, self.thrd)
        idx = {seq: tree.pattern(seq).idx
               for seq in ['AT', 'CG', 'GA', 'TC']}

        idx_set = {0, 1, 2, 3}
        mapping_true = {('ATC', (idx['AT'], idx['TC'])),
                        ('CGA', (idx['CG'], idx['GA'])),
                        ('GAT', (idx['GA'], idx['AT'])),
                        ('TCG', (idx['TC'], idx['CG']))}
        mapping = set()
        for seq, indices, cand_idx in candidate_mappings(tree, m+1, self.thrd):
            idx_set.remove(cand_idx)
            mapping.add((seq, indices))
        self.assertEqual(len(idx_set), 0)
        self.assertEqual(mapping, mapping_true)

    def test_run_position(self):
        m = 2
        tree = initialized_tree(self.data, m)
        assign_pattern_index(tree, m, self.thrd)
        queue = initialized_queue(self.data, tree, m, self.thrd)
        run_position(queue, tree, m+1, self.thrd)
        idx = {seq: tree.pattern(seq).idx
               for seq in ['ATC', 'CGA', 'GAT', 'TCG']}

        # Check queue
        queue_true = [(0, 1, idx['CGA']), (0, 2, idx['GAT']),
                      (0, 5, idx['TCG']), (0, 6, idx['CGA']),
                      (0, 7, idx['GAT']), (0, 8, idx['ATC']), (0, 9, idx['TCG'])]
        queue_true += [(1, 1, idx['CGA']), (1, 2, idx['GAT']),
                       (1, 5, idx['TCG']), (1, 6, idx['CGA']),
                       (1, 7, idx['GAT']), (1, 8, idx['ATC']), (1, 9, idx['TCG'])]
        self.assertEqual(queue, queue_true)

        # Check counts in the tree
        counts_true = {('ATC', 2), ('CGA', 4), ('GAT', 4), ('TCG', 4)}
        counts = {(node.seq, node.count) for node in tree.nodes_at_level(m+1)}
        self.assertEqual(counts, counts_true)

    def test_number_of_freq_subseq(self):
        m = 1
        tree = initialized_tree(self.data, m)
        num = number_of_freq_subseq(tree, m, self.thrd)
        self.assertEqual(num, 24)

    def test_frequent_patterns(self):
        # A-priori
        counter = Counter()
        results = frequent_patterns(self.data, self.min_len, self.max_len,
                                    self.thrd, method='apriori',
                                    counter=counter)
        self.assertEqual(set(results), self.ground_truth)
        self.assertEqual(counter.count, 3)

        # Position-based method
        counter = Counter()
        results = frequent_patterns(self.data, self.min_len, self.max_len,
                                    self.thrd, method='position',
                                    counter=counter)
        self.assertEqual(set(results), self.ground_truth)
        self.assertEqual(counter.count, 2)

        # Hybrid method
        counter = Counter()
        results = frequent_patterns(self.data, self.min_len, self.max_len,
                                    self.thrd, method='hybrid',
                                    counter=counter)
        self.assertEqual(set(results), self.ground_truth)
        self.assertEqual(counter.count, 2)

if __name__ == '__main__':
    unittest.main()


import re

from utils import logger

BIO_PATTERN = re.compile(r'\[(.+?)\](_[A-Z]{3}_)')
BIO_BEGIN = re.compile(r'_[A-Z]{3}_\[')
BIO_END = re.compile(r'\]_[A-Z]{3}_')

def pre_process(text):
    text = BIO_PATTERN.sub(r'\2[\1]\2', text)
    i = 0
    res = []
    label = ''
    is_begin = False
    is_inner = False
    length = len(text)
    while i < length:
        c = text[i]
        if '_' == c and i + 5 < length and BIO_BEGIN.fullmatch(text, i, i + 6):
            label = text[i + 1:i + 4]
            i += 6
            is_begin = True
            is_inner = True
            continue
        if ']' == c and i + 5 < length and BIO_END.fullmatch(text, i, i + 6) and is_inner:
            i += 6
            is_inner = False
            continue

        if is_begin:
            res.append([c, f'B-{label}'])
            is_begin = False
        elif is_inner:
            res.append([c, f'I-{label}'])
        else:
            res.append([c, 'O'])
        i += 1
    return res

def post_process(text, predict):
    res = []
    end_idx = len(text) - 1
    for i in range(end_idx):
        token = text[i]
        label1 = predict[i]
        label2 = predict[i + 1]
        if 'O' == label1:
            res.append(token)
        else:
            if label1.startswith('B-'):
                res.append('[')
            res.append(token)
            if not label2.startswith('I-'):
                res.append(f']_{label1[2:5]}_')
    token = text[end_idx]
    label1 = predict[end_idx]
    if label1.startswith('B-'):
        res.append('[')
    res.append(token)
    if 'O' != label1:
        res.append(f']_{label1[2:5]}_')
    return ''.join(res)

if __name__ == '__main__':
    text = '我喷了[chanel]_PRO_香水，在[澳大利亚]_LOC_吃着[肯德基]_COM_炸鸡'
    bio = pre_process(text)
    labeled = post_process([char[0] for char in bio], [char[1] for char in bio])
    logger.info(text)
    logger.info(bio)
    logger.info(labeled)
    logger.info(f'check status: {text == labeled}')


import json
import pandas as pd
import numpy as np

def processing_title(title):
    return title.upper()

def processing_author(author):
    return author.title()

def processing_discount(discount):
    try:
        discount = discount.replace('%dcto', '')
        return int(discount)
    except ValueError:
        return 0

def processing_price_now(price):
    try:
        price = price.replace('.','')[2:]
        return int(price)
    except ValueError:
        return np.nan

def processing_price_before(row):
    if row['Discount'] == 0:
        return row['Price now']
    else:
        price = row['Price before'].replace('.','')[2:]
        return int(price)

def processing_info(info):
    info = info.split(',')
    info_sorted = [i.strip().upper() for i in info]
    return info_sorted

def extracting_editorial(info_sorted):
    editorial = info_sorted[0]
    return editorial

def extracting_year(info_list):
    for i in info_list:
        if i.isdigit() and len(i) == 4:
            return i
    return np.nan

def process_data(df):

    df['Title'] = df['Title'].apply(processing_title)

    df['Author'] = df['Author'].apply(processing_author)

    df['Discount'] = df['Discount'].apply(processing_discount)

    df['Price now'] = df['Price now'].apply(processing_price_now)

    df['Price before'] = df.apply(processing_price_before, axis=1)

    df['Info_p'] = df['Info'].apply(processing_info)

    df['Editorial'] = df['Info_p'].apply(extracting_editorial)

    df['Year'] = df['Info_p'].apply(extracting_year)
    df['Year'] = df['Year'].fillna(0).astype('int64')

    df = df.drop(['Info', 'Info_p'], axis='columns')

    return df

if __name__ == "__main__":

    data_json = r"E:\Practicas\Proyects\book_tracker_buddy\data\buscabooks.json"
    with open(data_json) as file:
        books = json.load(file)

    df = pd.DataFrame(books)
    df = process_data(df)

    data_csv = r"E:\Practicas\Proyects\book_tracker_buddy\data\buscabooks_process.csv"
    df.to_csv(data_csv, index=False)


# Fails: 251.py
# Autors: Dmitrijs Doronins

import Tkinter as tk

root= tk.Tk()

root.title("Mana Bilde")

w = tk.Canvas(root, width=600, height=400, bg="#abc")

w.pack()

linija = w.create_line(50,100,400,300,width='5',fill='#FF0')

root.mainloop()


import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

import dgl
from dgl.base import DGLError
from dgl.ops import edge_softmax
import dgl.function as fn

class Identity(nn.Module):
    """A placeholder identity operator that is argument-insensitive.
    (Identity has already been supported by PyTorch 1.2, we will directly
    import torch.nn.Identity in the future)
    """

    def __init__(self):
        super(Identity, self).__init__()

    def forward(self, x):
        """Return input"""
        return x

class MsgLinkPredictor(nn.Module):
    """Predict Pair wise link from pos subg and neg subg
    use message passing.

    Use Two layer MLP on edge to predict the link probability

    Parameters
    ----------
    embed_dim : int
        dimension of each each feature's embedding

    Example
    ----------
    >>> linkpred = MsgLinkPredictor(10)
    >>> pos_g = dgl.graph(([0,1,2,3,4],[1,2,3,4,0]))
    >>> neg_g = dgl.graph(([0,1,2,3,4],[2,1,4,3,0]))
    >>> x = torch.ones(5,10)
    >>> linkpred(x,pos_g,neg_g)
    (tensor([[0.0902],
         [0.0902],
         [0.0902],
         [0.0902],
         [0.0902]], grad_fn=<AddmmBackward>),
    tensor([[0.0902],
         [0.0902],
         [0.0902],
         [0.0902],
         [0.0902]], grad_fn=<AddmmBackward>))
    """

    def __init__(self, emb_dim):
        super(MsgLinkPredictor, self).__init__()
        self.src_fc = nn.Linear(emb_dim, emb_dim)
        self.dst_fc = nn.Linear(emb_dim, emb_dim)
        self.out_fc = nn.Linear(emb_dim, 1)

    def link_pred(self, edges):
        src_hid = self.src_fc(edges.src['embedding'])
        dst_hid = self.dst_fc(edges.dst['embedding'])
        score = F.relu(src_hid+dst_hid)
        score = self.out_fc(score)
        return {'score': score}

    def forward(self, x, pos_g, neg_g):
        # Local Scope?
        pos_g.ndata['embedding'] = x
        neg_g.ndata['embedding'] = x

        pos_g.apply_edges(self.link_pred)
        neg_g.apply_edges(self.link_pred)

        pos_escore = pos_g.edata['score']
        neg_escore = neg_g.edata['score']
        return pos_escore, neg_escore

class TimeEncode(nn.Module):
    """Use finite fourier series with different phase and frequency to encode
    time different between two event

    ..math::
        \Phi(t) = [\cos(\omega_0t+\psi_0),\cos(\omega_1t+\psi_1),...,\cos(\omega_nt+\psi_n)]

    Parameter
    ----------
    dimension : int
        Length of the fourier series. The longer it is ,
        the more timescale information it can capture

    Example
    ----------
    >>> tecd = TimeEncode(10)
    >>> t = torch.tensor([[1]])
    >>> tecd(t)
    tensor([[[0.5403, 0.9950, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000,
          1.0000, 1.0000]]], dtype=torch.float64, grad_fn=<CosBackward>)
    """

    def __init__(self, dimension):
        super(TimeEncode, self).__init__()

        self.dimension = dimension
        self.w = torch.nn.Linear(1, dimension)
        self.w.weight = torch.nn.Parameter((torch.from_numpy(1 / 10 ** np.linspace(0, 9, dimension)))
                                           .double().reshape(dimension, -1))
        self.w.bias = torch.nn.Parameter(torch.zeros(dimension).double())

    def forward(self, t):
        t = t.unsqueeze(dim=2)
        output = torch.cos(self.w(t))
        return output

class MemoryModule(nn.Module):
    """Memory module as well as update interface

    The memory module stores both historical representation in last_update_t

    Parameters
    ----------
    n_node : int
        number of node of the entire graph

    hidden_dim : int
        dimension of memory of each node

    Example
    ----------
    Please refers to examples/pytorch/tgn/tgn.py;
                     examples/pytorch/tgn/train.py

    """

    def __init__(self, n_node, hidden_dim):
        super(MemoryModule, self).__init__()
        self.n_node = n_node
        self.hidden_dim = hidden_dim
        self.reset_memory()

    def reset_memory(self):
        self.last_update_t = nn.Parameter(torch.zeros(
            self.n_node).float(), requires_grad=False)
        self.memory = nn.Parameter(torch.zeros(
            (self.n_node, self.hidden_dim)).float(), requires_grad=False)

    def backup_memory(self):
        """
        Return a deep copy of memory state and last_update_t
        For test new node, since new node need to use memory upto validation set
        After validation, memory need to be backed up before run test set without new node
        so finally, we can use backup memory to update the new node test set
        """
        return self.memory.clone(), self.last_update_t.clone()

    def restore_memory(self, memory_backup):
        """Restore the memory from validation set

        Parameters
        ----------
        memory_backup : (memory,last_update_t)
            restore memory based on input tuple
        """
        self.memory = memory_backup[0].clone()
        self.last_update_t = memory_backup[1].clone()

    # Which is used for attach to subgraph
    def get_memory(self, node_idxs):
        return self.memory[node_idxs, :]

    # When the memory need to be updated
    def set_memory(self, node_idxs, values):
        self.memory[node_idxs, :] = values

    def set_last_update_t(self, node_idxs, values):
        self.last_update_t[node_idxs] = values

    # For safety check
    def get_last_update(self, node_idxs):
        return self.last_update_t[node_idxs]

    def detach_memory(self):
        """
        Disconnect the memory from computation graph to prevent gradient be propagated multiple
        times
        """
        self.memory.detach_()

class MemoryOperation(nn.Module):
    """ Memory update using message passing manner, update memory based on positive
    pair graph of each batch with recurrent module GRU or RNN

    Message function
    ..math::
        m_i(t) = concat(memory_i(t^-),TimeEncode(t),v_i(t))

    v_i is node feature at current time stamp

    Aggregation function
    ..math::
        \bar{m}_i(t) = last(m_i(t_1),...,m_i(t_b))

    Update function
    ..math::
        memory_i(t) = GRU(\bar{m}_i(t),memory_i(t-1))

    Parameters
    ----------

    updater_type : str
        indicator string to specify updater

        'rnn' : use Vanilla RNN as updater

        'gru' : use GRU as updater

    memory : MemoryModule
        memory content for update

    e_feat_dim : int
        dimension of edge feature

    temporal_dim : int
        length of fourier series for time encoding

    Example
    ----------
    Please refers to examples/pytorch/tgn/tgn.py
    """

    def __init__(self, updater_type, memory, e_feat_dim, temporal_encoder):
        super(MemoryOperation, self).__init__()
        updater_dict = {'gru': nn.GRUCell, 'rnn': nn.RNNCell}
        self.memory = memory
        memory_dim = self.memory.hidden_dim
        self.temporal_encoder = temporal_encoder
        self.message_dim = memory_dim+memory_dim + \
            e_feat_dim+self.temporal_encoder.dimension
        self.updater = updater_dict[updater_type](input_size=self.message_dim,
                                                  hidden_size=memory_dim)
        self.memory = memory

    # Here assume g is a subgraph from each iteration
    def stick_feat_to_graph(self, g):
        # How can I ensure order of the node ID
        g.ndata['timestamp'] = self.memory.last_update_t[g.ndata[dgl.NID]]
        g.ndata['memory'] = self.memory.memory[g.ndata[dgl.NID]]

    def msg_fn_cat(self, edges):
        src_delta_time = edges.data['timestamp'] - edges.src['timestamp']
        time_encode = self.temporal_encoder(src_delta_time.unsqueeze(
            dim=1)).view(len(edges.data['timestamp']), -1)
        ret = torch.cat([edges.src['memory'], edges.dst['memory'],
                         edges.data['feats'], time_encode], dim=1)
        return {'message': ret, 'timestamp': edges.data['timestamp']}

    def agg_last(self, nodes):
        timestamp, latest_idx = torch.max(nodes.mailbox['timestamp'], dim=1)
        ret = nodes.mailbox['message'].gather(1, latest_idx.repeat(
            self.message_dim).view(-1, 1, self.message_dim)).view(-1, self.message_dim)
        return {'message_bar': ret.reshape(-1, self.message_dim), 'timestamp': timestamp}

    def update_memory(self, nodes):
        # It should pass the feature through RNN
        ret = self.updater(
            nodes.data['message_bar'].float(), nodes.data['memory'].float())
        return {'memory': ret}

    def forward(self, g):
        self.stick_feat_to_graph(g)
        g.update_all(self.msg_fn_cat, self.agg_last, self.update_memory)
        return g

class EdgeGATConv(nn.Module):
    '''Edge Graph attention compute the graph attention from node and edge feature then aggregate both node and
    edge feature.

    Parameter
    ==========
    node_feats : int
        number of node features

    edge_feats : int
        number of edge features

    out_feats : int
        number of output features

    num_heads : int
        number of heads in multihead attention

    feat_drop : float, optional
        drop out rate on the feature

    attn_drop : float, optional
        drop out rate on the attention weight

    negative_slope : float, optional
        LeakyReLU angle of negative slope.

    residual : bool, optional
        whether use residual connection

    allow_zero_in_degree : bool, optional
        If there are 0-in-degree nodes in the graph, output for those nodes will be invalid
        since no message will be passed to those nodes. This is harmful for some applications
        causing silent performance regression. This module will raise a DGLError if it detects
        0-in-degree nodes in input graph. By setting ``True``, it will suppress the check
        and let the users handle it by themselves. Defaults: ``False``.

    '''

    def __init__(self,
                 node_feats,
                 edge_feats,
                 out_feats,
                 num_heads,
                 feat_drop=0.,
                 attn_drop=0.,
                 negative_slope=0.2,
                 residual=False,
                 activation=None,
                 allow_zero_in_degree=False):
        super(EdgeGATConv, self).__init__()
        self._num_heads = num_heads
        self._node_feats = node_feats
        self._edge_feats = edge_feats
        self._out_feats = out_feats
        self._allow_zero_in_degree = allow_zero_in_degree
        self.fc_node = nn.Linear(
            self._node_feats, self._out_feats*self._num_heads)
        self.fc_edge = nn.Linear(
            self._edge_feats, self._out_feats*self._num_heads)
        self.attn_l = nn.Parameter(torch.FloatTensor(
            size=(1, self._num_heads, self._out_feats)))
        self.attn_r = nn.Parameter(torch.FloatTensor(
            size=(1, self._num_heads, self._out_feats)))
        self.attn_e = nn.Parameter(torch.FloatTensor(
            size=(1, self._num_heads, self._out_feats)))
        self.feat_drop = nn.Dropout(feat_drop)
        self.attn_drop = nn.Dropout(attn_drop)
        self.leaky_relu = nn.LeakyReLU(negative_slope)
        self.residual = residual
        if residual:
            if self._node_feats != self._out_feats:
                self.res_fc = nn.Linear(
                    self._node_feats, self._out_feats*self._num_heads, bias=False)
            else:
                self.res_fc = Identity()
        self.reset_parameters()
        self.activation = activation

    def reset_parameters(self):
        gain = nn.init.calculate_gain('relu')
        nn.init.xavier_normal_(self.fc_node.weight, gain=gain)
        nn.init.xavier_normal_(self.fc_edge.weight, gain=gain)
        nn.init.xavier_normal_(self.attn_l, gain=gain)
        nn.init.xavier_normal_(self.attn_r, gain=gain)
        nn.init.xavier_normal_(self.attn_e, gain=gain)
        if self.residual and isinstance(self.res_fc, nn.Linear):
            nn.init.xavier_normal_(self.res_fc.weight, gain=gain)

    def msg_fn(self, edges):
        ret = edges.data['a'].view(-1, self._num_heads,
                                   1)*edges.data['el_prime']
        return {'m': ret}

    def forward(self, graph, nfeat, efeat, get_attention=False):
        with graph.local_scope():
            if not self._allow_zero_in_degree:
                if (graph.in_degrees() == 0).any():
                    raise DGLError('There are 0-in-degree nodes in the graph, '
                                   'output for those nodes will be invalid. '
                                   'This is harmful for some applications, '
                                   'causing silent performance regression. '
                                   'Adding self-loop on the input graph by '
                                   'calling `g = dgl.add_self_loop(g)` will resolve '
                                   'the issue. Setting ``allow_zero_in_degree`` '
                                   'to be `True` when constructing this module will '
                                   'suppress the check and let the code run.')

            nfeat = self.feat_drop(nfeat)
            efeat = self.feat_drop(efeat)

            node_feat = self.fc_node(
                nfeat).view(-1, self._num_heads, self._out_feats)
            edge_feat = self.fc_edge(
                efeat).view(-1, self._num_heads, self._out_feats)

            el = (node_feat*self.attn_l).sum(dim=-1).unsqueeze(-1)
            er = (node_feat*self.attn_r).sum(dim=-1).unsqueeze(-1)
            ee = (edge_feat*self.attn_e).sum(dim=-1).unsqueeze(-1)
            graph.ndata['ft'] = node_feat
            graph.ndata['el'] = el
            graph.ndata['er'] = er
            graph.edata['ee'] = ee
            graph.apply_edges(fn.u_add_e('el', 'ee', 'el_prime'))
            graph.apply_edges(fn.e_add_v('el_prime', 'er', 'e'))
            e = self.leaky_relu(graph.edata['e'])
            graph.edata['a'] = self.attn_drop(edge_softmax(graph, e))
            graph.edata['efeat'] = edge_feat
            graph.update_all(self.msg_fn, fn.sum('m', 'ft'))
            rst = graph.ndata['ft']
            if self.residual:
                resval = self.res_fc(nfeat).view(
                    nfeat.shape[0], -1, self._out_feats)
                rst = rst + resval

            if self.activation:
                rst = self.activation(rst)

            if get_attention:
                return rst, graph.edata['a']
            else:
                return rst

class TemporalEdgePreprocess(nn.Module):
    '''Preprocess layer, which finish time encoding and concatenate
    the time encoding to edge feature.

    Parameter
    ==========
    edge_feats : int
        number of orginal edge feature

    temporal_encoder : torch.nn.Module
        time encoder model
    '''

    def __init__(self, edge_feats, temporal_encoder):
        super(TemporalEdgePreprocess, self).__init__()
        self.edge_feats = edge_feats
        self.temporal_encoder = temporal_encoder

    def edge_fn(self, edges):
        t0 = torch.zeros_like(edges.dst['timestamp'])
        time_diff = edges.data['timestamp'] - edges.src['timestamp']
        time_encode = self.temporal_encoder(
            time_diff.unsqueeze(dim=1)).view(t0.shape[0], -1)
        edge_feat = torch.cat([edges.data['feats'], time_encode], dim=1)
        return {'efeat': edge_feat}

    def forward(self, graph):
        graph.apply_edges(self.edge_fn)
        efeat = graph.edata['efeat']
        return efeat

class TemporalTransformerConv(nn.Module):
    def __init__(self,
                 edge_feats,
                 memory_feats,
                 temporal_encoder,
                 out_feats,
                 num_heads,
                 allow_zero_in_degree=False,
                 layers=1):
        '''Temporal Transformer model for TGN and TGAT

        Parameter
        ==========
        edge_feats : int
            number of edge features

        memory_feats : int
            dimension of memory vector

        temporal_encoder : torch.nn.Module
            compute fourier time encoding

        out_feats : int
            number of out features

        num_heads : int
            number of attention head

        allow_zero_in_degree : bool, optional
            If there are 0-in-degree nodes in the graph, output for those nodes will be invalid
            since no message will be passed to those nodes. This is harmful for some applications
            causing silent performance regression. This module will raise a DGLError if it detects
            0-in-degree nodes in input graph. By setting ``True``, it will suppress the check
            and let the users handle it by themselves. Defaults: ``False``.
        '''
        super(TemporalTransformerConv, self).__init__()
        self._edge_feats = edge_feats
        self._memory_feats = memory_feats
        self.temporal_encoder = temporal_encoder
        self._out_feats = out_feats
        self._allow_zero_in_degree = allow_zero_in_degree
        self._num_heads = num_heads
        self.layers = layers

        self.preprocessor = TemporalEdgePreprocess(
            self._edge_feats, self.temporal_encoder)
        self.layer_list = nn.ModuleList()
        self.layer_list.append(EdgeGATConv(node_feats=self._memory_feats,
                                           edge_feats=self._edge_feats+self.temporal_encoder.dimension,
                                           out_feats=self._out_feats,
                                           num_heads=self._num_heads,
                                           feat_drop=0.6,
                                           attn_drop=0.6,
                                           residual=True,
                                           allow_zero_in_degree=allow_zero_in_degree))
        for i in range(self.layers-1):
            self.layer_list.append(EdgeGATConv(node_feats=self._out_feats*self._num_heads,
                                               edge_feats=self._edge_feats+self.temporal_encoder.dimension,
                                               out_feats=self._out_feats,
                                               num_heads=self._num_heads,
                                               feat_drop=0.6,
                                               attn_drop=0.6,
                                               residual=True,
                                               allow_zero_in_degree=allow_zero_in_degree))

    def forward(self, graph, memory, ts):
        graph = graph.local_var()
        graph.ndata['timestamp'] = ts
        efeat = self.preprocessor(graph).float()
        rst = memory
        for i in range(self.layers-1):
            rst = self.layer_list[i](graph, rst, efeat).flatten(1)
        rst = self.layer_list[-1](graph, rst, efeat).mean(1)
        return rst


import unittest

from datetime import date
from sqlalchemy import inspect, func, Numeric
from src.modelo.actividad import Actividad
from src.modelo.gasto import Gasto
from src.modelo.viajero import Viajero, ActividadViajero
from src.modelo.declarative_base import Session, engine, Base
from src.logica.Logica_mock import object_as_dict

Base.metadata.create_all(engine)

class MostrarGastosActividadTestCase(unittest.TestCase):

    def setUp(self):

        ''' Se puebla la base de datos para las pruebas'''

        self.session = Session()

        busqueda_actividad = self.session.query(Actividad).all()
        for actividad in busqueda_actividad:
            self.session.delete(actividad)

        busqueda_viajero = self.session.query(Viajero).all()
        for viajero in busqueda_viajero:
            self.session.delete(viajero)

        busqueda_gasto = self.session.query(Gasto).all()
        for gasto in busqueda_gasto:
            self.session.delete(gasto)

        busqueda_av = self.session.query(ActividadViajero).all()
        for av in busqueda_av:
            self.session.delete(av)
        self.session.commit()

        #  Crear actividades y agregarlas a la base de datos con add y commit
        self.actividad_1 = Actividad("Paseo a la Playa")
        self.actividad_2 = Actividad("Caminata")
        self.session.add(self.actividad_1)
        self.session.add(self.actividad_2)
        self.session.commit()

        # Crear los viajeros y agregarlos a la base de datos con add y commit
        self.viajero_1 = Viajero("Juan", "Perez")
        self.viajero_2 = Viajero("Rosa", "Garcia")
        self.viajero_3 = Viajero("Luis", "Mora")
        self.viajero_4 = Viajero("Ana", "Zavala")
        self.session.add(self.viajero_1)
        self.session.add(self.viajero_2)
        self.session.add(self.viajero_3)
        self.session.add(self.viajero_4)
        self.session.commit()

        # Crear los gastos.  Note que el atributo fecha en este momento es String.

        self.gasto_1 = Gasto("Transporte", 100, '21-01-2021')
        self.gasto_2 = Gasto("Comida", 200, '22-01-2021')
        self.gasto_3 = Gasto("Bebida", 90, '23-01-2021')
        self.gasto_4 = Gasto("Fiesta",120,'24-01-2021')
        self.gasto_5 = Gasto("Transporte", 150, '28-01-2021')
        self.session.add(self.gasto_1)
        self.session.add(self.gasto_2)
        self.session.add(self.gasto_3)
        self.session.add(self.gasto_4)
        self.session.add(self.gasto_5)
        self.session.commit()

        #  Crea las relaciones entre actividad y viajero (cuales son los viajeros asociados a cada actividad)

        self.actividad_1.viajeros = [self.viajero_1, self.viajero_2, self.viajero_3, self.viajero_4]
        self.actividad_2.viajeros = [self.viajero_2]

        # Crea las relaciones entre actividad y gasto *(cuales son los gastos de cada actividad)

        self.actividad_1.gastos = [self.gasto_1, self.gasto_2, self.gasto_3, self.gasto_4]
        self.actividad_2.gastos = [self.gasto_5]

        # Crea las relaciones entre viajero y gastos (que viajero realizo cada gasto)

        self.viajero_1.gastos = [self.gasto_1, self.gasto_3]
        self.viajero_2.gastos = [self.gasto_2, self.gasto_5]
        self.viajero_3.gastos = [self.gasto_4]
        self.viajero_4.gastos = []
        self.session.commit()

        # Cierra la sesion
        self.session.close()

    def test_mostrar_gastos_actividad(self):
        self.session = Session()
        self.act_id = 1

        self.viajeross = self.session.query(Viajero).all()

        self.viajeros1 = []
        for viajero in self.viajeross:
            self.viajeros1.append(object_as_dict(viajero))

        self.gastos1 = self.session.query(Gasto).join(Actividad).filter(Gasto.actividad == self.act_id).all()
        self.gastos = []
        for gasto in self.gastos1:
            self.gastos.append(object_as_dict(gasto))
        for g in self.gastos:
            vid = g.get("viajero")
            for viajero in self.viajeros1:
                if viajero['id'] == vid:
                    g["Nombre"] = viajero['nombre']
                    g["Apellido"] = viajero['apellido']

        # Mostrar que la lista en la base de datos es la misma que fue insertada

        self.lista_gastos = [{'id': 1, 'concepto': 'Transporte', 'valor': 100, 'fecha': '21-01-2021', 'actividad': 1, 'viajero': 1, 'Nombre': 'Juan', 'Apellido': 'Perez'}, {'id': 2, 'concepto': 'Comida', 'valor': 200, 'fecha': '22-01-2021', 'actividad': 1, 'viajero': 2, 'Nombre': 'Rosa', 'Apellido': 'Garcia'}, {'id': 3, 'concepto': 'Bebida', 'valor': 90, 'fecha': '23-01-2021', 'actividad': 1, 'viajero': 1, 'Nombre': 'Juan', 'Apellido': 'Perez'}, {'id': 4, 'concepto': 'Fiesta', 'valor': 120, 'fecha': '24-01-2021', 'actividad': 1, 'viajero': 3, 'Nombre': 'Luis', 'Apellido': 'Mora'}]
        self.assertListEqual(self.lista_gastos, self.gastos)

    def tearDown(self):
        session = Session()

        session.close()


import argparse
import cv2
import logging as log

import sys
import time
import socket
import paho.mqtt.client as mqtt
import json
import math
import os

from inference import Network

# Set the MQTT server environment variables
HOSTNAME = socket.gethostname()
IPADDRESS = socket.gethostbyname(HOSTNAME)
MQTT_HOST = IPADDRESS
MQTT_PORT = 1884
MQTT_KEEPALIVE_INTERVAL = 60

def connect_mqtt():

    client = mqtt.Client()
    client.connect(MQTT_HOST, MQTT_PORT, MQTT_KEEPALIVE_INTERVAL)

    return client

def get_args():

    # Create the parser object
    parser = argparse.ArgumentParser()

    # Create the arguments
    # Required
    parser.add_argument("-m", "--model", required = True, type = str, help = "The location of model .xml file")
    parser.add_argument("-i", "--input", required = True, type = str, help = "The path to input image or video")

    # Optional
    parser.add_argument("-d", "--device", default = "CPU", type =str, help = "To specify target device used for inference, CPU, GPU, VPU etc.")
    parser.add_argument("-l", "--cpu_extension", required = False, type = str, default = None, help = "MKLDNN (CPU)-targeted custom layers. Absolute path to a shared library")
    parser.add_argument("-pt", "--prob_threshold", default = 0.5, type = float, help = "Probability threshold for detections filtering")
    parser.add_argument("-c", "--color", default = "GREEN", type = str, help = "The color of the bounding boxes to draw; RED, GREEN or BLUE")
    parser.add_argument("-at", "--alert_time", default = 15.0, type = float, help = "The duration people stay in the frame")

    args = parser.parse_args()

    return args

def preprocessing(frame, batch, channel, height, width):

    # Resize to model's input w x h
    p_frame = cv2.resize(frame, (width, height))

    # Transpose the layout from hwc to chw
    p_frame = p_frame.transpose((2, 0, 1))

    # Reshape to model's shape n x c x h x w
    p_frame = p_frame.reshape((batch, channel, height, width))

    return p_frame

def infer_on_stream(args, client):

    # Set flag for the input
    single_image_mode = False

    # Instantiate current inference request
    cur_request_id = 0

    # Initialize the plugin
    plugin = Network()

    # Load model, and get the input shape
    plugin.load_model(args.model, args.device, cur_request_id, args.cpu_extension)
    n, c, h, w = plugin.get_input_shape()

    ### Checking for the feed input file
    # CAM
    if args.input == 'CAM':
        input_stream = 0

    # Image
    elif args.input.endswith('.jpg') or args.input.endswith('.bmp') :
        single_image_mode = True
        input_stream = args.input

    # Video
    else:
        input_stream = args.input
        assert os.path.isfile(args.input), "Specified input file doesn't exist"

    # Create the VideoCapture object, and have it opened
    cap = cv2.VideoCapture(input_stream)

    if input_stream:
        cap.open(args.input)

    if not cap.isOpened():
        log.error("ERROR! Unable to open video source")
    ###

    # Grab the dimension of width and height
    global initial_w, initial_h
    initial_w = cap.get(3)
    initial_h = cap.get(4)

    # Set initial parameters
    temp = 0
    fp = 0
    last_count = 0
    total_count = 0
    duration = 0

    # Iterate the frame until the video ends
    while cap.isOpened():
        flag, frame = cap.read()
        if not flag:
            break
        key_pressed = cv2.waitKey(60)

        # Preprocessing
        p_frame = preprocessing(frame, n, c, h, w)

        # Perform async_inference
        plugin.exec_net(cur_request_id, p_frame)
        inf_start = time.time()

        # Get the output result
        if plugin.wait(cur_request_id) == 0:
            result = plugin.extract_output(cur_request_id)
            det_time = time.time() - inf_start

            # Draw the bounding box
            frame, current_count, d, fp = draw_boxes(frame, result, args, temp, fp)

            # Print the inference time
            inf_time_message = "Inference time: {:.3f}ms".format(det_time * 1000)
            cv2.putText(frame, inf_time_message, (15, 15), cv2.FONT_HERSHEY_COMPLEX, 0.5, (200, 10, 10), 1)

            ### People Counting ###
            # When new person enters into the frame
            if current_count > last_count: # New entry
                start_time = time.time()
                total_count = total_count + current_count - last_count
                client.publish("person", json.dumps({"total": total_count}))

            if current_count < last_count:
                duration = int(time.time() - start_time)
                client.publish("person/duration", json.dumps({"duration": duration}))

            # To check lost frames for false positive cases
            lost_info = "Lost frame: %d" %(fp - 1)
            cv2.putText(frame, lost_info, (15, 30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (200, 10, 10), 1)

            # Warning if people staying time > alert time
            if duration >= args.alert_time:
                cv2.putText(frame, 'CAUTION! Staying longer than ' + str(args.alert_time) + ' seconds', (15, 45), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)

            client.publish("person", json.dumps({"count": current_count}))
            last_count = current_count

            temp = d
            ###----------------###

            # Break if escape key is pressed
            if key_pressed == 27:
                break

        # Send the information to FFmpeg server
        sys.stdout.buffer.write(frame)
        sys.stdout.flush()

        # Image mode
        if single_image_mode:
            cv2.imwrite('output_image.jpg', frame)

    # Release all. Destroy OpenCV windows, and disconnect the MQTT
    cap.release()
    cv2.destroyAllWindows()
    client.disconnect()

def draw_boxes(frame, result, args, x, k):

    # Customize the color space of bounding box, if not assign default will be 'GREEN'
    colors = {"BLUE": (255, 0, 0), "GREEN": (0, 255, 0), "RED": (0, 0, 255)}
    if args.color:
        draw_color = colors.get(args.color)
    else:
        draw_color = colors["GREEN"]

    current_count = 0
    distance = x

    for obj in result[0][0]:
        conf = obj[2]
        if conf >= args.prob_threshold:
            xmin = int(obj[3] * initial_w)
            ymin = int(obj[4] * initial_h)
            xmax = int(obj[5] * initial_w)
            ymax = int(obj[6] * initial_h)
            class_id = int(obj[1])

            # If the probability threshold is crossed, then count the people, and draw the bounding box
            current_count += 1
            cv2.rectangle(frame, (xmin, ymin), (xmax, ymax), draw_color, 3)

            det_label = str(class_id)
            cv2.putText(frame, "label: " + det_label + ' ' + str(round(obj[2] * 100, 1)) + ' %', (xmin, ymin - 7), cv2.FONT_HERSHEY_COMPLEX, 0.6, draw_color, 2)
            enter_time = time.time()

            # To calculate the distance
            c_y = frame.shape[0] / 2
            c_x = frame.shape[1] / 2

            mid_y = (ymin + ymax) / 2
            mid_x = (xmin + xmax) / 2

            distance =  math.sqrt(math.pow(mid_x - c_x, 2) +  math.pow(mid_y - c_y, 2) * 1.0)
            k = 0

    if current_count < 1:
        k += 1

    if distance > 0 and k < 15:
        current_count = 1
        k += 1
        if k > 100:
            k = 0

    return frame, current_count, distance, k

def main():
    args = get_args()
    client = connect_mqtt()
    infer_on_stream(args, client)

if __name__ == "__main__":
    main()


"""EJERCICIO 3
El día juliano correspondiente a una fecha es un número entero que indica los días que han
transcurrido desde el 1 de enero del año indicado. Queremos crear un programa principal que
al introducir una fecha nos diga el día juliano que corresponde. Para ello podemos hacer las
siguientes subrutinas:
 LeerFecha: Nos permite leer por teclado una fecha (día, mes y año).
 DiasDelMes: Recibe un mes y un año y nos dice los días de ese mes en ese año.
 EsBisiesto: Recibe un año y nos dice si es bisiesto.
 Calcular_Dia_Juliano: recibe una fecha y nos devuelve el día juliano."""
from datetime import datetime

def leer_fecha():
    try:
        n1=int(input("Introduce un día del mes: "))
        n2=int(input ("Introduce un mes de en formato numérico, 1 para Enero y 12 para diciembre: "))
        n3=int(input ("Introduce un año: "))

        if n1<1 or n1>31 or n2<1 or n2>13:
            return "La fecha introducida no es correcta"

        elif (n2==11 or n2==4 or n2==6 or n2==9 or n2==2) and n1>30:
            return  "La fecha introducida no es correcta"

        elif n2==2 and n1>29:
            return  "La fecha introducida no es correcta"

        elif n2==2 and n3%4!=0 and n1>28:
            return "La fecha introducida no es correcta"

        elif n2==2 and (n3%4==0 and n3%100==0 and n3%400!=0) and n1>28:
            return"La fecha introducida no es correcta"
        else:
            #return "La fecha introducida es correcta"
            return n1,n2,n3

    except:
        "Sólo se admiten enteros"

    #return n1,n2,n3

def dias_del_mes():
    treinta=[11,4,6,9]
    treinta_y_uno=[1,3,5,7,8,10,12]
    try:
        dia,mes,anho=leer_fecha()
    except:
        print("Los valores introducidos no son correctos")
    if mes in treinta:
        n1=30
    elif mes in treinta_y_uno:
        n1=31
    elif mes==2:
        if anho%4==0:
            if anho%100==0 and anho%400!=0:
                n1=28
            else:
                n1=29
        else:
            n1=28
    else:
        print("Los meses sólo van del 1 al 12")
        exit()
    print ("Los días de ese mes en ese año son "+ str(n1))
    return n1

def es_bisiesto():
    dia,mes,anho=leer_fecha()
    bandera=True
    if anho%4==0:
         if anho%100==0 and anho%400!=0:
             print ("El año "+str(anho)+" no es bisiesto")
         else:
              print("El año "+str(anho)+" es bisiesto")
              bandera=False
    else:
        print ("El año "+str(anho)+" no es bisiesto")

def calcular_dia_juliano():
    try:
        dia,mes,anho=leer_fecha()
        d1=str(anho)+'-01-01'
        d2=str(anho)+'-'+str(mes)+'-'+str(dia)
        d1 = datetime.strptime(d1, "%Y-%m-%d")
        d2 = datetime.strptime(d2, "%Y-%m-%d")
        resultado= abs((d2 - d1).days)
    except:
        resultado="Los valores introducidos no son correctos"

    return resultado

print (calcular_dia_juliano())


from __future__ import absolute_import, division, print_function,\
    with_statement

import collections
import errno
import socket
import logging
import ssl
import sys

from tornado import ioloop
from tornado.log import gen_log
from tornado.netutil import ssl_wrap_socket, ssl_match_hostname, \
    SSLCertificateError
from tornado import stack_context

from datetime import timedelta

try:
    from tornado.platform.posix import _set_nonblocking
except ImportError:
    _set_nonblocking = None

# These errnos indicate that a non-blocking operation must be retried
# at a later time. On most platforms they're the same value, but on
# some they differ.
_ERRNO_WOULDBLOCK = (errno.EWOULDBLOCK, errno.EAGAIN)

# These errnos indicate that a connection has been abruptly terminated.
# They should be caught and handled less noisily than other errors.
_ERRNO_CONNRESET = (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE)

# Nice constant for enabling debug output
import sys

_SHOULD_LOG_DEBUG_OUTPUT = gen_log.isEnabledFor(logging.DEBUG)

class StreamClosedError(IOError):
    """Exception raised by `IOStream` methods when the stream is closed.

    Note that the close callback is scheduled to run *after* other
    callbacks on the stream (to allow for buffered data to be processed),
    so you may see this error before you see the close callback.
    """
    pass

class WriteQueue(object):

    def __init__(self):
        self._last_send_idx = 0
        self._write_queue = collections.deque()

    def has_next(self):
        return len(self._write_queue) > 0

    def next(self):
        if self.has_next():
            return (self._write_queue[0], self._last_send_idx)
        return None

    def clear(self):
        self._write_queue.clear()

    def append(self, src):
        self._write_queue.append(src)

    def advance(self, bytes_to_advance):
        next_src = self._write_queue[0]

        if bytes_to_advance + self._last_send_idx >= len(next_src):
            self._write_queue.popleft()
            self._last_send_idx = 0
        else:
            self._last_send_idx += bytes_to_advance

class IOHandler(object):

    def __init__(self, io_loop=None):
        # Bind to the eventloop
        self._io_loop = io_loop or ioloop.IOLoop.current()

        # Error tracking
        self.error = 0

        # Callbacks
        self._connect_cb = None
        self._close_cb = None
        self._read_cb = None
        self._write_cb = None

        # TODO:Review - Is this a good idea?
        self._error_cb = None

    def reading(self):
        raise NotImplementedError()

    def writing(self):
        raise NotImplementedError()

    def closed(self):
        raise NotImplementedError()

    def read(self, callback):
        raise NotImplementedError()

    def write(self, src, callback=None):
        raise NotImplementedError()

    def connect(self, address, callback=None):
        raise NotImplementedError()

    def close(self):
        raise NotImplementedError()

class FileDescriptorHandle(object):

    def __init__(self, fd, io_loop):
        assert fd is not None
        assert io_loop is not None

        self.fd = fd
        self._io_loop = io_loop
        self._event_interest = None

    def is_reading(self):
        return self._event_interest & self._io_loop.READ

    def is_writing(self):
        return self._event_interest & self._io_loop.WRITE

    def set_handler(self, event_handler):
        """initialize the ioloop event handler"""
        assert event_handler is not None and callable(event_handler)
        self._event_interest = self._io_loop.ERROR

        with stack_context.NullContext():
            self._io_loop.add_handler(
                self.fd,
                event_handler,
                self._event_interest)

    def remove_handler(self):
        self._io_loop.remove_handler(self.fd)

    def disable_reading(self):
        """
        Alias for removing the read interest from the event handler.
        """
        if _SHOULD_LOG_DEBUG_OUTPUT:
            gen_log.debug('Halting read events for stream(fd:{})'.format(
                self.fd))
        self._drop_event_interest(self._io_loop.READ)

    def disable_writing(self):
        """
        Alias for removing the send interest from the event handler.
        """
        if _SHOULD_LOG_DEBUG_OUTPUT:
            gen_log.debug('Halting write events for stream(fd:{})'.format(
                self.fd))
        self._drop_event_interest(self._io_loop.WRITE)

    def resume_reading(self):
        """
        Alias for adding the read interest to the event handler.
        """
        if _SHOULD_LOG_DEBUG_OUTPUT:
            gen_log.debug('Resuming recv events for stream(fd:{})'.format(
                self.fd))
        self._add_event_interest(self._io_loop.READ)

    def resume_writing(self):
        """
        Alias for adding the send interest to the event handler.
        """
        if _SHOULD_LOG_DEBUG_OUTPUT:
            gen_log.debug('Resuming send events for stream(fd:{})'.format(
                self.fd))
        self._add_event_interest(self._io_loop.WRITE)

    def _add_event_interest(self, event_interest):
        """Add io_state to poller."""
        if not self._event_interest & event_interest:
            self._event_interest = self._event_interest | event_interest
            self._io_loop.update_handler(self.fd, self._event_interest)

    def _drop_event_interest(self, event_interest):
        """Stop poller from watching an io_state."""
        if self._event_interest & event_interest:
            self._event_interest = self._event_interest & (~event_interest)
            self._io_loop.update_handler(self.fd, self._event_interest)

class SocketIOHandler(IOHandler):

    def __init__(self, sock, io_loop=None, recv_chunk_size=4096):
        super(SocketIOHandler, self).__init__(io_loop)

        # Socket init
        self._socket = sock

        # Set socket options
        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._socket.setblocking(0)

        # Initialize our handling of the FD events
        self.handle = FileDescriptorHandle(self._socket.fileno(), self._io_loop)
        self.handle.set_handler(self._handle_events)

        # Flow control vars
        self._connecting = False
        self._closing = False

        # Writing and reading management
        self._write_queue = WriteQueue()

        self._recv_chunk_size = recv_chunk_size
        self._recv_buffer = bytearray(self._recv_chunk_size)

    def on_done_writing(self, callback=None):
        """
        Sets a callback for completed send events and then sets the send
        interest on the event handler.
        """
        if not self._closing:
            assert callback is None or callable(callback)
            self._write_cb = stack_context.wrap(callback)

    def on_close(self, callback):
        """
        Sets a callback to be called after this stream closes.
        """
        if not self._closing:
            assert callback is None or callable(callback)
            self._close_cb = stack_context.wrap(callback)

    def on_error(self, callback):
        """
        Sets a callback to be called after this stream closes.
        """
        if not self._closing:
            assert callback is None or callable(callback)
            self._error_cb = stack_context.wrap(callback)

    def reading(self):
        """Returns True if we are currently receiving from the stream."""
        return not self.closed() and self.handle.is_reading()

    def writing(self):
        """Returns True if we are currently writing to the stream."""
        return not self.closed() and self._write_queue.has_next()

    def closed(self):
        return self._closing or self._socket is None

    def read(self, callback):
        """
        Sets a callback for read events and then sets the read interest on
        the event handler.
        """
        self._assert_not_closed()

        assert callback is None or callable(callback)
        self._read_cb = stack_context.wrap(callback)
        self.handle.resume_reading()

    def write(self, msg, callback=None):
        self._assert_not_closed()

        if not isinstance(msg, basestring) and not isinstance(msg, bytearray):
            raise TypeError("bytes/bytearray/unicode/str objects only")

        # Append the data for writing - this should not copy the data
        self._write_queue.append(msg)
        # Enable writing on the FD
        self.handle.resume_writing()
        # Set our callback - writing None to the method below is okay
        self.on_done_writing(callback)

    def connect(self, address, callback=None):
        self._connecting = True

        try:
            self._socket.connect(address)
        except socket.error as e:
            if (e.args[0] != errno.EINPROGRESS and e.args[0] not in _ERRNO_WOULDBLOCK):
                gen_log.warning("Connect error on fd %d: %s", self.handle.fd, e)
                self.close()
                return

        self._on_connect_cb = stack_context.wrap(callback)
        self.handle.resume_writing()

    def close(self):
        if not self._closing:
            if self._write_queue.has_next():
                self.on_done_writing(self._close)
            else:
                self._close()

            self._closing = True

    def _close(self):
        """Close this stream."""
        if self._socket is not None:
            gen_log.debug('Closing stream(fd: {})'.format(self.handle.fd))

            self.handle.remove_handler()

            self._socket.close()
            self._socket = None

            if self._close_cb:
                self._run_callback(self._close_cb)

    def _assert_not_closed(self):
        if self.closed():
            raise StreamClosedError('Stream closing or closed.')

    def _do_read(self, recv_buffer):
        return self._socket.recv_into(recv_buffer, self._recv_chunk_size)

    def _do_write(self, send_buffer):
        return self._socket.send(send_buffer)

    def _handle_events(self, fd, events):
        #gen_log.debug('Handle event for stream(fd: {})'.format(self.handle.fd))

        if self._socket is None:
            gen_log.warning("Got events for closed stream %d", fd)
            return

        try:
            if self._socket is not None and events & self._io_loop.READ:
                self.handle_read()

            if self._socket is not None and events & self._io_loop.WRITE:
                if self._connecting:
                    self.handle_connect()
                else:
                    self.handle_write()

            if not self.closed() and events & self._io_loop.ERROR:
                self.handle_error(
                    self._socket.getsockopt(
                        socket.SOL_SOCKET, socket.SO_ERROR))
        except Exception:
            self.close()
            raise

    def handle_error(self, error):
        try:
            if self._error_cb is not None:
                callback = self._error_cb
                self._error_cb = None
                self._run_callback(callback, error)

            if error not in _ERRNO_CONNRESET:
                gen_log.warning("Error on stream(fd:%d) caught: %s",
                                self.handle.fd, errno.errorcode[error])
        finally:
            # On error, close the FD
            self.close()

    def handle_read(self):
        try:
            read = self._do_read(self._recv_buffer)

            if read is not None:
                if read > 0 and self._read_cb:
                    self._run_callback(self._read_cb, self._recv_buffer[:read])
                elif read == 0:
                    self.close()
        except (socket.error, IOError, OSError) as ex:
                if ex.args[0] not in _ERRNO_WOULDBLOCK:
                    self.handle_error(ex.args[0])

    def handle_write(self):
        if self._write_queue.has_next():
            try:
                msg = None

                while self._write_queue.has_next():
                    msg, offset = self._write_queue.next()
                    sent = self._do_write(msg[offset:])
                    self._write_queue.advance(sent)
            except (socket.error, IOError, OSError) as ex:
                if ex.args[0] in _ERRNO_WOULDBLOCK:
                    self._write_queue.appendleft(msg)
                else:
                    self._write_queue.clear()
                    self.handle_error(ex.args[0])
        else:
            self.handle.disable_writing()

            if self._write_cb:
                callback = self._write_cb
                self._write_cb = None
                self._run_callback(callback)

    def handle_connect(self):
        if self._on_connect_cb is not None:
            callback = self._on_connect_cb
            self._on_connect_cb = None
            self._run_callback(callback)

        self._connecting = False

    def _run_callback(self, callback, *args, **kwargs):
        """Wrap running callbacks in try/except to allow us to
        close our socket."""

        try:
            # Use a NullContext to ensure that all StackContexts are run
            # inside our blanket exception handler rather than outside.
            with stack_context.NullContext():
                callback(*args, **kwargs)
        except Exception as ex:
            gen_log.error("Uncaught exception: %s", ex)

            # Close the socket on an uncaught exception from a user callback
            # (It would eventually get closed when the socket object is
            # gc'd, but we don't want to rely on gc happening before we
            # run out of file descriptors)
            self.close()

            # Re-raise the exception so that IOLoop.handle_callback_exception
            # can see it and log the error
            raise

class SSLSocketIOHandler(SocketIOHandler):
    """A utility class to write to and read from a non-blocking SSL socket.

    If the socket passed to the constructor is already connected,
    it should be wrapped with::

    ssl.wrap_socket(sock, do_handshake_on_connect=False, **kwargs)

    before constructing the `SSLSocketIOHandler`. Unconnected sockets will be
    wrapped when `SSLSocketIOHandler.connect` is finished.
    """
    def __init__(self, *args, **kwargs):
        """The ``ssl_options`` keyword argument may either be a dictionary
        of keywords arguments for `ssl.wrap_socket`, or an `ssl.SSLContext`
        object.
        """
        self._ssl_options = kwargs.pop('ssl_options', {})
        super(SSLSocketIOHandler, self).__init__(*args, **kwargs)
        self._ssl_accepting = True
        self._handshake_reading = False
        self._handshake_writing = False
        self._ssl_on_connect_cb = None
        self._server_hostname = None

        # If the socket is already connected, attempt to start the handshake.
        try:
            self._socket.getpeername()
        except socket.error:
            pass
        else:
            # Indirectly start the handshake, which will run on the next
            # IOLoop iteration and then the real IO event_interest will be set in
            # _handle_events.
            self.handle.resume_writing()

    def reading(self):
        return self._handshake_reading or super(SSLSocketIOHandler, self).reading()

    def writing(self):
        return self._handshake_writing or super(SSLSocketIOHandler, self).writing()

    def _do_ssl_handshake(self):
        # Based on code from test_ssl.py in the python stdlib
        try:
            self._handshake_reading = False
            self._handshake_writing = False
            self._socket.do_handshake()
        except ssl.SSLError as err:
            if err.args[0] == ssl.SSL_ERROR_WANT_READ:
                self._handshake_reading = True
                return
            elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
                self._handshake_writing = True
                return
            elif err.args[0] in (ssl.SSL_ERROR_EOF,
                                 ssl.SSL_ERROR_ZERO_RETURN):
                self.close()
                return
            elif err.args[0] == ssl.SSL_ERROR_SSL:
                try:
                    peer = self._socket.getpeername()
                except Exception:
                    peer = '(not connected)'
                gen_log.warning("SSL Error on %d %s: %s",
                                self.handle.fd, peer, err)
                self.close()
                return
            raise
        except socket.error as err:
            if err.args[0] in _ERRNO_CONNRESET:
                self.close()
                return
        except AttributeError:
            # On Linux, if the connection was reset before the call to
            # wrap_socket, do_handshake will fail with an
            # AttributeError.
            self.close()
            return
        else:
            self._ssl_accepting = False
            if not self._verify_cert(self._socket.getpeercert()):
                self.close()
                return
            if self._ssl_on_connect_cb is not None:
                callback = self._ssl_on_connect_cb
                self._ssl_on_connect_cb = None
                self._run_callback(callback)

    def _verify_cert(self, peercert):
        """Returns True if peercert is valid according to the configured
        validation mode and hostname.

        The ssl handshake already tested the certificate for a valid
        CA signature; the only thing that remains is to check
        the hostname.
        """
        if isinstance(self._ssl_options, dict):
            verify_mode = self._ssl_options.get('cert_reqs', ssl.CERT_NONE)
        elif isinstance(self._ssl_options, ssl.SSLContext):
            verify_mode = self._ssl_options.verify_mode

        assert verify_mode in (ssl.CERT_NONE, ssl.CERT_REQUIRED, ssl.CERT_OPTIONAL)

        if verify_mode == ssl.CERT_NONE or self._server_hostname is None:
            return True
        cert = self._socket.getpeercert()
        if cert is None and verify_mode == ssl.CERT_REQUIRED:
            gen_log.warning("No SSL certificate given")
            return False
        try:
            ssl_match_hostname(peercert, self._server_hostname)
        except SSLCertificateError:
            gen_log.warning("Invalid SSL certificate", )
            return False
        else:
            return True

    def handle_read(self):
        if self._ssl_accepting:
            self._do_ssl_handshake()
        else:
            super(SSLSocketIOHandler, self).handle_read()

    def handle_write(self):
        if self._ssl_accepting:
            self._do_ssl_handshake()
        else:
            super(SSLSocketIOHandler, self).handle_write()

    def connect(self, address, callback=None, server_hostname=None):
        # Save the user's callback and run it after the ssl handshake
        # has completed.
        self._ssl_on_connect_cb = stack_context.wrap(callback)
        self._server_hostname = server_hostname

        super(SSLSocketIOHandler, self).connect(address, callback=None)

    def handle_connect(self):
        # When the connection is complete, wrap the socket for SSL
        # traffic. Note that we do this by overriding handle_connect
        # instead of by passing a callback to super().connect because
        # user callbacks are enqueued asynchronously on the IOLoop,
        # but since _handle_events calls handle_connect immediately
        # followed by handle_write we need this to be synchronous.
        self._socket = ssl_wrap_socket(self._socket, self._ssl_options,
                                       server_hostname=self._server_hostname,
                                       do_handshake_on_connect=False)
        super(SSLSocketIOHandler, self).handle_connect()

    def _do_read(self, recv_buffer):
        if self._ssl_accepting:
            # If the handshake hasn't finished yet, there can't be anything
            # to read (attempting to read may or may not raise an exception
            # depending on the SSL version)
            return -1

        try:
            bytes = self._socket.read(self._recv_chunk_size)
            read = len(bytes)
            recv_buffer[:read] = bytes

            return read
        except ssl.SSLError as e:
            # SSLError is a subclass of socket.error, so this except
            # block must come first.
            if e.args[0] == ssl.SSL_ERROR_WANT_READ:
                return -1
            else:
                raise

    def _do_write(self, send_buffer):
        return self._socket.send(send_buffer)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
---------------------------------------------------------------------------------------------------
calc_razao_curva

DOCUMENT ME!

revision 0.2  2015/nov  mlabru
pep8 style conventions

revision 0.1  2014/nov  mlabru
initial version (Linux/Python)
---------------------------------------------------------------------------------------------------
"""
__version__ = "$revision: 0.2$"
__author__ = "mlabru, sophosoft"
__date__ = "2015/11"

# < imports >--------------------------------------------------------------------------------------

# python library
# import logging
import math

# model
from ...newton import defs_newton as ldefs

# < module data >----------------------------------------------------------------------------------

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

# -------------------------------------------------------------------------------------------------

def calc_razao_curva(f_atv, ff_pto_x, ff_pto_y, f_cine_data):
    """
    ajusta a razão de curva da aeronave

    @param f_atv: pointer para aeronave
    @param ff_pto_x: coordenada X do ponto
    @param ff_pto_y: coordenada Y do ponto
    @param f_cine_data: pointer para pilha
    """
    # logger
    # M_LOG.info("calc_razao_curva:>>")

    # verifica parâmetros de entrada
    assert f_atv
    assert f_cine_data

    # verifica condições para execução (II)
    if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv):

        # cai fora...
        return False

    # curva pela esquerda ?
    if f_atv.f_atv_raz_crv < 0:

        # determina a proa
        lf_proa = f_atv.f_trf_pro_atu - 90.

    # senão, pela direita
    else:
        # determina a proa
        lf_proa = f_atv.f_trf_pro_atu - 270.

    # proa negativa ?
    if lf_proa < 0:

        # normaliza a proa
        lf_proa += 360.

    # converte para radianos
    lf_proa = math.radians(lf_proa)

    # calcula o raio de curva
    f_cine_data.f_raio_curva = abs(f_atv.f_atv_vel_gnd / math.radians(f_atv.f_atv_raz_crv))

    # calcula o centro de curva (x, y)
    lf_ccurva_x = f_atv.f_trf_x + (f_cine_data.f_raio_curva * math.sin(lf_proa))
    lf_ccurva_y = f_atv.f_trf_y + (f_cine_data.f_raio_curva * math.cos(lf_proa))

    # calcula a distância do ponto em relação ao centro da curva (x, y)
    lf_dst_pto_cc_x = ff_pto_x - lf_ccurva_x
    lf_dst_pto_cc_y = ff_pto_y - lf_ccurva_y

    # calcula a distância do ponto em relação ao centro da curva (em linha reta)
    f_cine_data.f_dst_pto_cc = math.sqrt((lf_dst_pto_cc_x ** 2) + (lf_dst_pto_cc_y ** 2))

    # calcula a nova razão curva
    if f_cine_data.f_dst_pto_cc < f_cine_data.f_raio_curva:

        # ajusta a razão ?
        if f_cine_data.v_ajusta_razao:

            # calcula a razão de curva
            lf_raz_crv = abs(f_atv.f_atv_vel_gnd / math.radians(f_cine_data.f_dst_pto_cc))

            if (lf_raz_crv > 0) and (lf_raz_crv <= 9.1961):

                if f_atv.f_atv_raz_crv < 0.:
                    f_atv.f_atv_raz_crv = -lf_raz_crv

                else:
                    f_atv.f_atv_raz_crv = lf_raz_crv

            else:
                f_atv.f_atv_raz_crv *= -1.

        else:
            f_atv.f_atv_raz_crv *= -1.

    # logger
    # M_LOG.info("calc_razao_curva:<<")

# < the end >--------------------------------------------------------------------------------------


from typing import List
from .. import DeviceModel, _template_env
from . import signed_weight

class IntegratorModel(DeviceModel):
    ng_spice_model_name = 'int'

    def __init__(
        self,
        model_name: str,
        in_offset: float = 0.0,
        gain: float = 1.0,
        out_lower_limit: float = -10.0,
        out_upper_limit: float = 10.0,
        limit_range: float = 1e-6,
        out_ic: float = 0.0,
        comments: List[str] = ['integrator'],
    ):
        super().__init__(
            model_name,
            comments=comments,
            in_offset=in_offset,
            gain=gain,
            out_lower_limit=out_lower_limit,
            out_upper_limit=out_upper_limit,
            out_ic=out_ic,
            limit_range=limit_range,
        )
        # indicate that this model has a verilog-ams implementation
        self.verilog_ams = True

    def get_ngspice(self):
        return _template_env.get_template('ngspice/model.cir.j2').render(
            {
                'model_instance_name': self.model_name,
                'model_name': self.ng_spice_model_name,
                'parameters': self.parameters,
            }
        )

    def get_verilog_ams(self):
        return _template_env.get_template('verilog_ams/integrator.vams.j2').render(
            {
                'module_instance_name': self.model_name,
                'model_name': self.ng_spice_model_name,
                'parameters': {
                    'in_offset': {
                        'active': float(self.parameters['in_offset']) != 0.0,
                        'magnitude': float(self.parameters['in_offset']),
                        'sign': ['+', '-'][float(self.parameters['in_offset']) < 0],
                    },
                    'gain': float(self.parameters['gain']),
                    'out_lower_limit': signed_weight(
                        float(self.parameters['out_lower_limit'])
                    ),
                    'out_upper_limit': signed_weight(
                        float(self.parameters['out_upper_limit'])
                    ),
                    'limit_range': signed_weight(float(self.parameters['limit_range'])),
                    'out_ic': {
                        'magnitude': abs(float(self.parameters['out_ic'])),
                        'sign': ['+', '-'][float(self.parameters['out_ic']) < 0],
                    },
                },
                'description': 'A simplistic integrator model',
                'terminals': ['in', 'out'],
            }
        )


from werkzeug.utils import secure_filename
import sqlite3
import json
import os

class DatabaseHelper:
    """
    This help to manage databases.
    """

    def __init__(self) -> None:
        pass

    def save_image(self, main_dir: str, user_token: str, images: dict) -> bool:
        """
        save_image() will save given images to given path.

        Args:
            main_dir (str): Main directory
            user_token (str): Sub directory (image directory)
            images (dict): Set of images

        Returns:
            bool:  Return code (False -> Failed, True -> Success)
        """
        try:
            os.mkdir(f"{main_dir}/{user_token}")

            for img in images:
                img_name, img_ext = os.path.splitext(
                    secure_filename(images[img].filename)
                )

                images[img].filename = f"{img}{img_ext}"

                location = os.path.join(main_dir, user_token, images[img].filename)

                images[img].save(location)

            return True  # Success

        except Exception as e:
            print(f"An Error occured : {e}")

            return False  # Failure


# 서로 다른 N개의 자연수의 합이 S라고 한다. S를 알 때, 자연수 N의 최댓값은 얼마일까?

s = int(input())

l = 1
r = s
answer = 0

while l <= r:

    mid = (l+r)//2

    add = mid*(mid+1)//2

    if add <= s:
        l = mid + 1
        answer = mid

    elif add > s:
        r = mid - 1

print(answer)


import torch
import gym
from model import Model
from collections import deque
import numpy as np
from env_wrapper import FlappyBirdEnv

env = FlappyBirdEnv(render_mode = "human")

policy = Model(4, 2)
def reinforce(policy, n_training_episodes, max_t, gamma, print_every):
    is_pick = True
    scores_deque = deque(maxlen=100)
    scores = []
    for i_episode in range(1, n_training_episodes+1):
        saved_log_probs = []
        rewards = []
        state, info = env.reset()
        # Line 4 of pseudocode
        for t in range(max_t):
            # print(state)
            # import ipdb; ipdb.set_trace()
            pick = np.random.uniform()

            action, log_prob = policy.act(torch.tensor(state))
            saved_log_probs.append(log_prob)
            # if is_pick and pick <= 0.1:
            #     state, reward, done, _ = env.step(env.action_space.sample())
            # else:
            state, reward, done, _ = env.step(action)

            rewards.append(reward)
            if done:
                break
        scores_deque.append(sum(rewards))
        scores.append(sum(rewards))

        returns = deque(maxlen=max_t)
        n_steps = len(rewards)

        for t in range(n_steps)[::-1]:
            disc_return_t = (returns[0] if len(returns)>0 else 0)
            returns.appendleft( gamma*disc_return_t + rewards[t]   )

        eps = np.finfo(np.float32).eps.item()
        returns = torch.tensor(returns, dtype = torch.float32)
        returns = (returns - returns.mean()) / (returns.std() + eps)

        policy_loss = []
        for log_prob, disc_return in zip(saved_log_probs, returns):
            policy_loss.append(-log_prob * disc_return)

        # print(policy_loss)
        policy_loss = torch.cat(policy_loss).sum()

        policy.optimizer.zero_grad()
        policy_loss.backward()
        policy.optimizer.step()

        if i_episode % print_every == 0:
            print('Episode {}\tAverage Score: {:.2f}'.format(i_episode, np.mean(scores_deque)))
        if i_episode % print_every == 200:
            is_pick = False

    return scores

reinforce(
    policy=policy,
    n_training_episodes=1000,
    max_t = 500,
    gamma = 0.98,
    print_every=100
    )


from ..db import db_client
from ..schemas.profile_schema import Profile

table = db_client.client.table("chats")

def create_new_chat(uuid: str, member_uuid: str):
    return table.insert({
        "member_a": uuid,
        "member_b": member_uuid,
    }).execute()

def get_user_chats(uuid: str):
    member_a =  table.select("*").eq("member_a", uuid).execute().data
    member_b =  table.select("*").eq("member_b", uuid).execute().data
    merged = member_a + member_b
    return merged