# %% Admin
from datetime import datetime
import pandas as pd
# from Helper.Connections_Database import *
# from Odin_Interactions.Extraction.ScrapeSubmissions import *

# Initial Processing
def IP_submissiontracking_reshape(Submission_Raw_Df, conn_Object):
    # deleteme, conn_Object= connect_to_odinprod(); Submission_Raw_Df= Submission_Df

    # Extracting the relevant keys
    Temp_EarliestSubmission = datetime.utcfromtimestamp(int(min(Submission_Raw_Df.Submission_UTCCreationTime))).strftime('%Y-%m-%d %H:%M:%S')
    Temp_submissioninfo= pd.read_sql_query("SELECT idsubmission, idsubmission_reddit FROM submission_info "
                                         "WHERE createdatetime >= '{}'".format(Temp_EarliestSubmission), conn_Object)
    Temp_subredditinfo= pd.read_sql_query("SELECT idsubreddit, idsubreddit_reddit FROM subreddit_info", conn_Object)

    Submission_Raw_Df2_FK1= pd.merge(left= Submission_Raw_Df, right= Temp_submissioninfo, how="left",
                                     left_on="Submission_ID", right_on="idsubmission_reddit")
    Submission_Raw_Df2_FK1andFK2= pd.merge(left= Submission_Raw_Df2_FK1, right= Temp_subredditinfo, how="left",
                                 left_on="Subreddit_ID", right_on="idsubreddit_reddit")
    Submission_Raw_Df2= Submission_Raw_Df2_FK1andFK2.copy()
    Submission_Raw_Df2["isclose"]=0
    Submission_Raw_Df2["Submission_Stickied"]= Submission_Raw_Df2["Submission_Stickied"].astype(int)

    Submission_Raw_Df2["lastfetched"] = datetime.utcfromtimestamp(max(Submission_Raw_Df2["Submission_UTCFetchTime"].astype(int))).\
        strftime('%Y-%m-%d %H:%M:%S')

    # Processing the final submissions
    Submission_Raw_Df3= Submission_Raw_Df2[["idsubmission","idsubreddit",
                                           "lastfetched", "Submission_NumComments", "Submission_Score", "Submission_UpvoteRatio","Submission_Stickied", "isclose"]]
    Submission_Raw_Df3.columns= ["idsubmission","idsubreddit",
                                 "lastfetched", "numcomments", "score", "upvoteratio", "stickied", "isclose"]

    processed_SubmissionTracking= Submission_Raw_Df3

    return processed_SubmissionTracking

# Function 1
# This function works towards removing all submissions that have already been closed.
def IP_submissiontracking_exclusions(Submission_Raw_Df, conn_Object):
    # deleteme, conn_Object= connect_to_odinprod(); Submission_Raw_Df= Insertme_SubmissionTracking

    Processing1_1 = Submission_Raw_Df.copy()

    # Extracting Closed Submissions
    Temp_submissioninfo = pd.read_sql_query("SELECT idsubmission FROM submissiontracking WHERE isclose=1 group by idsubmission", conn_Object)
    DontExtract_List = Temp_submissioninfo["idsubmission"].tolist()
    Processing1_1["isclose_Updated"] = Processing1_1["idsubmission"].isin(DontExtract_List).astype(int)

    # Finalizing and Returning
    Processing1_Final = Processing1_1[['idsubmission', 'idsubreddit', 'lastfetched', 'numcomments', 'score',
                                       'upvoteratio', 'stickied', 'isclose_Updated']].copy()
    Processing1_Final.rename(columns={'isclose_Updated': 'isclose'}, inplace=True)

    print("Processing 1 Complete- Excluding Closed Submissions:" +
          "\n- {} of {} submissions has already been closed".format(sum(Processing1_Final["isclose"]),len(Processing1_1)) +
          "\n- {} submissions to process ".format(len(Processing1_Final) - sum(Processing1_Final["isclose"]))
          )

    Processing1_Final= Processing1_Final[Processing1_Final["isclose"]==0]

    return Processing1_Final

# Function 2
def IP_submissiontracking_PotentialClosures(Submission_Raw_Df, conn_Object):
    # conn_Object= conn_odin_obj; Submission_Raw_Df= Insertme_SubmissionTracking2

    Processing2_1 = Submission_Raw_Df.copy()
    Processing2_1["DatabaseExistence"]= "New"

    # Extracting Submissions
    print("Processing 2 Started- Modifying Potential Closures IsClosed:")
    Temp_RedditSubmissions= "'"+ "','".join(str(e) for e in Processing2_1["idsubmission"].dropna().astype(int).tolist())+ "'"
    TempSQL_IsCloseModifier = "SELECT * , 'Exists' as DatabaseExistence FROM submissiontracking WHERE idsubmission IN ({})""".format(Temp_RedditSubmissions)
    PotentialSubmissionsToClose = pd.read_sql_query(TempSQL_IsCloseModifier, conn_Object)

    # %% Looping
    Processing2_2 = pd.concat([PotentialSubmissionsToClose, Processing2_1]).reset_index(drop=True)
    Temp_LoopList = Processing2_2["idsubmission"].unique().tolist()

    Processing2_3 = pd.DataFrame()

    for Temp_SubmissionID_Indice in range(len(Temp_LoopList)):
        if Temp_SubmissionID_Indice % 250 == 0:
            print("-- Looping and Checking {} of {} submissions.".format(Temp_SubmissionID_Indice, len(Temp_LoopList)))

        Temp_SubmissionID = Temp_LoopList[Temp_SubmissionID_Indice]

        # Temp_SubmissionID= "jgkp92"
        Temp_Df = Processing2_2[Processing2_2["idsubmission"] == Temp_SubmissionID].copy()
        Temp_Df["Prcs2_WillClose"] = 0
        # Temp_Df[["Submission_ID", "Submission_LastFetched","Submission_NumComments"]]

        if len(Temp_Df) <= 2:
            Processing2_3 = pd.concat([Processing2_3, Temp_Df])

        else:
            Temp_LastRow = Temp_Df[Temp_Df["numcomments"] ==
                                   (Temp_Df["numcomments"].max())].iloc[0]["lastfetched"]
            TimeDifference = pd.to_datetime(Temp_Df.iloc[-1]["lastfetched"]) - pd.to_datetime(Temp_LastRow)

            if TimeDifference > pd.Timedelta(days=3):
                Temp_Df.at[Temp_Df.index[-1], "Prcs2_WillClose"] = 1
            else:
                pass

            Processing2_3 = pd.concat([Processing2_3, Temp_Df])

    # Finalizing and Returning
    Processing2_4 = Processing2_3[Processing2_3["DatabaseExistence"] == "New"].copy()
    Processing2_4 = Processing2_4.reset_index(drop=True)

    # Printing Information
    Processing2_Final = Processing2_4[['idsubmission', 'idsubreddit', 'lastfetched', 'numcomments', 'score',
                                       'upvoteratio', 'stickied', 'Prcs2_WillClose']].copy()
    Processing2_Final.rename(columns={'Prcs2_WillClose': 'isclose'}, inplace=True)

    print("Processing 2 Complete- Modifying Potential Closures IsClosed:"+
          "\n-- {} submissions still open ".format(len(Submission_Raw_Df))+
          "\n-- {} of {} will be closed moving forward ".format(sum(Processing2_Final["isclose"]), len(Submission_Raw_Df))
          )

    return Processing2_Final


import torch
import matplotlib.pyplot as plt
from PIL import Image

# sum noise to func
x = torch.empty(1000, 1).uniform_(-10,10)
noise = torch.empty(1000,1).normal_()
y = x * 3 + 4
y_noise = y + noise

# linear func
model = torch.nn.Linear(1,1)
loss = torch.nn.L1Loss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01)

#traning
for i in range(1000):
    optimizer.zero_grad()
    pred = model(x)
    l = loss(pred, y_noise)
    l.backward()
    optimizer.step()
for p in model.parameters():
    # 2.990126848220825
    # 3.999316453933716
    print(p.item())
plt.plot(x.numpy(),y_noise.numpy(),'ro')
plt.plot(x.numpy(),model(x).detach().numpy(),'o')
plt.show()

x = torch.empty(1000,1).uniform_(-10,10)
noise = torch.empty(1000,1).normal_(std=2)
y = 3*(x**2)+4
y_noise = y + noise

model = torch.nn.Sequential(
    torch.nn.Linear(1,5), # w*x (1000,1) (1,5)
    torch.nn.ReLU(),
    torch.nn.Linear(5,1),
    torch.nn.ReLU())
loss_func = torch.nn.L1Loss()
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01)

for i in range(10000):
    optimizer.zero_grad()
    pred= model(x)
    loss = loss_func(pred, y_noise)
    loss.backward()
    optimizer.step()

print(model[0])
print(model[2])
plt.figure()
plt.plot(x.numpy(),y_noise.numpy(),'ro')
plt.plot(x.numpy(),model(x).detach().numpy(),'o')
plt.show()

print(torch.ones(1000,5) + torch.randn(5,1))


# Aim:- Python program for finding the smallest element in an array A of size n using Selection Algorithm.

import sys
print("Enter size of an array ")
s=int(input())
i=0
ar=[]

print("Enter array elements ")
while i<s:
	ar.append(int(input()))
	i=i+1

print("Array values you enteres is: ")
print(ar)

for i in range(len(ar)):                # Traverse through all array elements
	min_idx=i                           # Find the minimum element in remaining unsorted array
	for j in range(i+1, len(ar)):
		if ar[min_idx]>ar[j]:
			min_idx=j

			ar[i], ar[min_idx]=ar[min_idx], ar[i]     # Swap the found minimum element with the first element

print("Sorted array")                # Driver Code to test above code
for i in range(len(ar)):
	print("%d"%ar[i]),

print("Smallest Element: %d"%ar[0])
print("Largest Element: %d"%ar[s-1])


from pygame import Surface, draw
import globals
from utility import *

class Map:

    def __init__(self, win, map_array, wall_color):
        if not isinstance(win, Surface): raise TypeError("win has to be a Surface object")
        if not is_rgb_color_value(wall_color): raise TypeError("Wall color has to be an RGB color tuple")
        self.validate_map(map_array)
        self.win = win
        self.grid_width = globals.WIN_WIDTH // len(map_array[0])
        self.map_array = map_array
        self.nrows = len(self.map_array)
        self.ncols = len(self.map_array[0])
        self.empty_squares = []
        for i in range(0, self.nrows - 1):
            for j in range(0, self.ncols - 1):
                if self.map_array[i][j] == 0:
                    self.empty_squares.append((i, j))
        self.grid_coordinates = [[(0, 0) for j in range(0, self.ncols)] for i in range(0, self.nrows)]
        self.grid_column_x_values = []
        self.grid_row_y_values = []
        self.get_gridline_coordinates()
        self.wall_color = wall_color
        self.show_gridlines = True

    def validate_map(self, map_array):
        valid_values = (0, 1)
        if not isinstance(map_array, list) and not isinstance(map_array, tuple):
            raise ValueError("Map array has to be a list or tuple")
        if len(set([len(i) for i in map_array])) != 1:
            raise ValueError("Each row has to be the same length in the map array")
        if len(map_array) * 2 != len(map_array[0]):
            raise ValueError("The number of rows has to be half the number of columns")
        for i in map_array:
            if not isinstance(i, list) and not isinstance(i, tuple):
                raise ValueError("Each row has to be a list or tuple in the map array")
            for j in i:
                if j not in valid_values:
                    raise ValueError(f"Each value in the map array must be in {valid_values}")

    def get_gridline_coordinates(self):
        current_x = 0
        current_y = 0
        for i in range(0, self.nrows):
            for j in range(0, self.ncols):
                self.grid_coordinates[i][j] = (current_x, current_y)
                current_x += self.grid_width
            current_x = 0
            current_y += self.grid_width
        for row in self.grid_coordinates:
            for c in row:
                self.grid_column_x_values.append(c[0])
                self.grid_row_y_values.append(c[1])
        self.grid_column_x_values = sorted(list(set(self.grid_column_x_values)))
        self.grid_row_y_values = sorted(list(set(self.grid_row_y_values)))

    def get_grid_position_of_point(self, point):
        if not isinstance(point, Point): raise ValueError("point has to be a Point object")
        closest_column_x_value = get_closest_number(number_list=self.grid_column_x_values, number=point.x)
        closest_row_y_value = get_closest_number(number_list=self.grid_row_y_values, number=point.y)
        column_index = closest_column_x_value // self.grid_width
        row_index = closest_row_y_value // self.grid_width
        # Determine if point is before or after the values
        if closest_column_x_value - point.x > 0:
            column_index -= 1
        if closest_row_y_value - point.y > 0:
            row_index -= 1
        return row_index, column_index

    def get_neighboring_grid_positions(self, grid_position):
        adjacent_grid_coordinates = ((grid_position[0] - 1, grid_position[1] - 1),
                                     (grid_position[0] - 1, grid_position[1]),
                                     (grid_position[0] - 1, grid_position[1] + 1),
                                     (grid_position[0], grid_position[1] - 1),
                                     (grid_position[0], grid_position[1] + 1),
                                     (grid_position[0] + 1, grid_position[1] - 1),
                                     (grid_position[0] + 1, grid_position[1]),
                                     (grid_position[0] + 1, grid_position[1] + 1))
        return adjacent_grid_coordinates

    def get_neighboring_corner_grid_positions(self, grid_position):
        adjacent_grid_coordinates = ((grid_position[0] - 1, grid_position[1] - 1),
                                     (grid_position[0] - 1, grid_position[1] + 1),
                                     (grid_position[0] + 1, grid_position[1] - 1),
                                     (grid_position[0] + 1, grid_position[1] + 1))
        return adjacent_grid_coordinates

    def get_neighboring_edge_grid_positions(self, grid_position):
        adjacent_grid_coordinates = ((grid_position[0] - 1, grid_position[1]),
                                     (grid_position[0], grid_position[1] - 1),
                                     (grid_position[0], grid_position[1] + 1),
                                     (grid_position[0] + 1, grid_position[1]))
        return adjacent_grid_coordinates

    def draw_gridlines(self):
        current_x = 0
        current_y = 0
        # Verical lines
        for i in range(0, self.ncols):
            draw.line(self.win, globals.GREY, (current_x, current_y), (current_x, current_y + globals.WIN_HEIGHT), width=1)
            current_x += self.grid_width
        # Horizontal lines
        current_x = 0
        for i in range(0, self.nrows):
            draw.line(self.win, globals.GREY, (current_x, current_y), (current_x + globals.WIN_WIDTH, current_y), width=1)
            current_y += self.grid_width

    def draw(self):
        current_x = 0
        current_y = 0
        for row in self.map_array:
            for value in row:
                if value == 1:
                    draw.rect(self.win, self.wall_color, (current_x, current_y, self.grid_width, self.grid_width))
                current_x += self.grid_width
            current_x = 0
            current_y += self.grid_width


# Metasearch Main Program
from GoogleResults import google_scrape
from BingResults import bing_scrape
from supporting import struc
from Ranking import approach1
from Ranking import approach2
import matplotlib.pyplot as plt
from AggregatingResults import aggregate
import os

os.environ['http_proxy']=''

query = input('Enter Query : ')
googleResults = google_scrape(query)
bingResults = bing_scrape(query)

uniqueList = aggregate(googleResults,bingResults)

approach1(googleResults,bingResults,uniqueList)
approach2(googleResults,bingResults,uniqueList)

precisionA1 = [0.2,0.3,0.47,0.5,0.48,0.57]
precisionA2 = [0.2,0.4,0.47,0.55,0.56,0.6]

# Mean average precision
MAP1 = sum(precisionA1)/len(precisionA1)
MAP2 = sum(precisionA2)/len(precisionA2)

print('MAP for Approach 1: (Best Rank approach)  = ' + str(MAP1) )
print('MAP for Approach 2:                       = ' + str(MAP2) )

x_coordinates = ["P@5","P@10","P@15","P@20","P@25","P@30"]
y1_coordinates = [0.2,0.3,0.47,0.5,0.48,0.57]
y2_coordinates = [0.2,0.4,0.47,0.55,0.56,0.6]
plt.plot(x_coordinates, y1_coordinates,label='Approach1')
plt.plot(x_coordinates, y2_coordinates,label='Approach2')
plt.xlabel('Precision@N')
plt.ylabel('Precision')
plt.legend()
plt.show()


from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.mail import send_mail
from django.contrib.auth.models import User
from django.db import models

class Event(models.Model):
    title = models.CharField(max_length=255)
    start_date = models.DateTimeField()
    min_people = models.IntegerField()
    max_people = models.IntegerField()
    mission = models.ForeignKey('Mission')
    description = models.TextField(blank=True)

    def __str__(self):
        return "%s (%s)" % (self.title, self.start_date)

    def active_pledges(self):
        return filter(lambda x: x.is_active(),
                      self.pledge_set.all().order_by('timestamp'))

    def can_start(self):
        return len(self.active_pledges()) >= self.min_people

    def free_slots(self):
        return self.max_people - len(self.active_pledges())

    def is_full(self):
        return self.free_slots() <= 0

    def user_has_active_pledge(self, user):
        for pledge in self.active_pledges():
            if pledge.user == user:
                return True
        return False

@receiver(post_save, sender=Event)
def event_post_save_handler(sender, instance, **kwargs):
    body = """There\'s a new daddle event!

%s - %s
%s
%s

http://daddle.zorzar.de/event/%d""" % (instance.mission.title,
                                       instance.title,
                                       instance.start_date,
                                       instance.description,
                                       instance.id)

    for user in User.objects.all():
        if user.email:
            send_mail('[daddle] New daddle event!',
                      body,
                      'zz@zoranzaric.de',
                      [user.email],
                      fail_silently=False)

class Pledge(models.Model):
    event = models.ForeignKey('Event')
    user = models.ForeignKey(User)
    timestamp = models.DateTimeField()
    cancel_timestamp = models.DateTimeField(blank=True, null=True)

    def is_active(self):
        return self.cancel_timestamp == None

@receiver(post_save, sender=Pledge)
def pledge_post_save_handler(sender, instance, **kwargs):
    body = """%s is helping you!

%s - %s
%s
%s

http://daddle.zorzar.de/event/%d""" % (instance.user,
                                       instance.event.mission.title,
                                       instance.event.title,
                                       instance.event.start_date,
                                       instance.event.description,
                                       instance.event.id)

    for pledge in instance.event.pledge_set.all():
        if pledge.user != instance.user and pledge.user.email:
            send_mail('[daddle] Somebody is helping you!',
                      body,
                      'zz@zoranzaric.de',
                      [pledge.user.email],
                      fail_silently=False)

class Mission(models.Model):
    title = models.CharField(max_length=255)

    def __str__(self):
        return self.title


#! /usr/bin/python3
import sys
from utils import clean_line, check_start

def classify(contents, vocab_details, vocab_index):
    """ (str, dict, dict) -> list

    Return the document's topics in order of relevance
    """
    topics = []
    document_hash = {}

    document_words = contents.split(' ')

    for word in document_words:
        assert word != ''

        if word not in vocab_index:
            continue

        word_index = vocab_index[word]
        word_total = vocab_details[word_index]['total']
        word_topics = vocab_details[word_index]['topics']

        for topic in word_topics:
            if topic not in document_hash:
                document_hash[topic] = 0

            document_hash[topic] += \
                vocab_details[word_index]['topics'][topic] / word_total

    keys = []
    for key in document_hash:
        keys.append(key)
    keys.sort()

    topics = list(range(len(keys)))
    for index in range(len(keys)):
        topics[index] = document_hash[keys[index]]

    indices = list(range(len(topics)))
    indices = sorted(indices, key=lambda x: -topics[x])

    return indices

def compare_topics_order(classed, known, amount):
    """ (list, list, int) -> boolean

    Returns true the number of elements in amount are in the correct order
    """
    for index in range(amount):
        if str(classed[index]) != str(known[index]):
            return False

    return True

def compare_topic_slice(classed, known, cutoff):
    """ (list, list, int) -> boolean

    Returns true if both lists contain the same items up to the cutoff
    """

    classed = classed[:cutoff]
    known = known[:cutoff]

    known.sort()
    classed.sort()

    for i in range(cutoff):
        if i == len(known):
            break
        if i == len(classed):
            break
        if str(known[i]) != str(classed[i]):
            return False

    return True

def compare_position_offset(classed, known, offset):
    """ (list, list, int) -> boolean

    Returns true if the elements within the list
    are never more than offset positions away from each other
    """
    num_topics = len(classed)

    for index in range(num_topics):
        correct = False

        for i in range(offset):
            plus = index + i
            minus = index - i

            if not minus < 0:
                if(str(classed[index]) == str(known[minus])):
                    correct = True
                    break

            if not plus >= len(known):
                if(str(classed[index]) == str(known[plus])):
                    correct = True
                    break

        if not correct:
            return False

    return True

def get_vocab_details(vocab_lines, word_assignment_lines):
    overall_hash = {}

    # Process each line of the vocab file
    for index in range(len(vocab_lines)):
        word_hash = {}

        line = vocab_lines[index].strip()

        word_hash['word'] = line
        word_hash['topics'] = {}
        word_hash['total'] = 0
        overall_hash[index] = word_hash

    # process each line of the word assignment file
    for index in range(len(word_assignment_lines)):
        line = word_assignment_lines[index].strip()

        word_topics = line.split(' ')
        word_topics.pop(0)               # remove word amount

        for word_topic in word_topics:
            word_index, topic_index = word_topic.split(':')

            word_index = int(word_index)

            if word_index not in overall_hash:
                print('overall hash does not contain \
                       this word index %d' % word_index)
                exit(1)

            if topic_index in overall_hash[word_index]['topics']:
                overall_hash[word_index]['topics'][topic_index] += 1
            else:
                overall_hash[word_index]['topics'][topic_index] = 1

            overall_hash[word_index]['total'] += 1

    return overall_hash

def get_vocab_index(vocab_lines):
    overall_hash = {}

    for index in range(len(vocab_lines)):
        line = vocab_lines[index].strip()
        overall_hash[line] = index

    return overall_hash

def get_document_topics(gamma_lines):
    return_list = []

    for line in gamma_lines:
        line = line.strip()
        topics = [float(x) for x in line.split()]
        indices = list(range(len(topics)))
        indices = sorted(indices, key=lambda x: -topics[x])

        line = ' '.join(map(str, indices))
        return_list.append(line)

    return return_list

def main():
    check_start('./test_doc_guess_algorithm.py <folder> <output> <num_topics>', 4)

    # Input naming
    folder = sys.argv[1]
    output = sys.argv[2]
    num_topics = int(sys.argv[3])

    topic_order_count = [0] * num_topics
    topic_feeling_count = [0] * num_topics
    topic_offset_count = [0] * num_topics

    # File allocation
    format_file = folder + '/initial.formatted'
    vocab_file = folder + '/initial.vocab'
    word_assignment_file = folder + '/out/word-assignments.dat'
    gamma_file = folder + '/out/final.gamma'

    # Read in required data
    with open(vocab_file) as data_file:
        vocab_lines = data_file.readlines()

    with open(word_assignment_file) as data_file:
        word_assignment_lines = data_file.readlines()

    with open(format_file) as data_file:
        format_lines = data_file.readlines()

    with open(gamma_file) as data_file:
        gamma_lines = data_file.readlines()

    vocab_details = get_vocab_details(vocab_lines, word_assignment_lines)
    topic_lines = get_document_topics(gamma_lines)
    vocab_index = get_vocab_index(vocab_lines)

    num_docs = len(format_lines)

    for index in range(len(format_lines)):
        line = format_lines[index]
        line = line.strip()

        known_topics = topic_lines[index].strip().split(' ')
        document_contents = line.split('|~|')[3]
        document_contents = clean_line(document_contents)
        classed_doc = classify(document_contents, vocab_details, vocab_index)

        if len(classed_doc) == 0:
            print(document_contents)
            continue

        if index % 1000 == 0 and index != 0:
            print('Snapshot: ' + str(index))
            for i in range(1, num_topics):
                print('\tTopics correct position %d: %s' % (i, str(topic_order_count[i] / index)))
                print('\tTopics within range %d: %s' % (i, str(topic_feeling_count[i] / index)))
                print('\tTopics within offset %d: %s' % (i, str(topic_offset_count[i] / index)))

        for i in range(1, len(classed_doc)):
            if compare_topics_order(classed_doc, known_topics, i):
                topic_order_count[i] += 1

            if compare_topic_slice(classed_doc, known_topics, i):
                topic_feeling_count[i] += 1

            if compare_position_offset(classed_doc, known_topics, i):
                topic_offset_count[i] += 1

    out_ptr = open(output, 'w')

    out_ptr.write('Number of documents: ' + str(num_docs) + '\n')
    for i in range(num_topics):
        out_ptr.write('Topics correct position %d: %s\n' % (i, str(topic_order_count[i] / num_docs)))
        out_ptr.write('Topics within range %d: %s\n' % (i, str(topic_feeling_count[i] / num_docs)))
        out_ptr.write('Topics within offset %d: %s\n' % (i, str(topic_offset_count[i] / num_docs)))

if __name__ == '__main__':
    main()


from gsy_e.models.strategy.scm.external.forecast_mixin import SCMForecastExternalMixin
from gsy_e.models.strategy.scm.load import SCMLoadProfileStrategy

class ForecastSCMLoadStrategy(SCMForecastExternalMixin, SCMLoadProfileStrategy):
    """External SCM Load strategy"""

    # def _update_energy_requirement(self, _area):
    #     """Overwrite method that sets the energy requirement in the state."""

    def update_energy_forecast(self) -> None:
        """Set energy forecast for future markets."""
        for slot_time, energy_kWh in self.energy_forecast_buffer.items():
            if slot_time >= self.owner.current_market_time_slot:
                self.state.set_desired_energy(energy_kWh * 1000, slot_time, overwrite=True)
                self.state.update_total_demanded_energy(slot_time)

    def update_energy_measurement(self) -> None:
        """Set energy measurement for past markets."""
        for slot_time, energy_kWh in self.energy_measurement_buffer.items():
            if slot_time < self.owner.current_market_time_slot:
                self.state.set_energy_measurement_kWh(energy_kWh, slot_time)


from dataclasses import dataclass, field
from collections import namedtuple
from typing import Dict
from pptx import Presentation

from .my_slide import MySlide

@dataclass
class MyPresentation:
    """
    Represents a PowerPoint presentation.

    Attributes:
        filepath (str): The file path of the PowerPoint presentation.
        explanations (namedtuple): Named tuple to store slide explanations. Defaults to None.
        slides (Dict[int, MySlide]): Dictionary to store slide objects. Defaults to None.
    """

    filepath: str
    explanations: namedtuple = None
    slides: Dict[int, MySlide] = field(default_factory=dict)

    def parse(self):
        """
        Parses the PowerPoint presentation to extract slide data.

        Creates instances of the MySlide class for each slide and stores them in the self.slides dictionary.
        """
        try:
            prs = Presentation(f"{self.filepath}")
        except Exception as e:
            print(f"Error: {e}")
            return

        for slide_number, slide in enumerate(prs.slides, start=1):
            slide_obj = prs.slides[slide_number - 1]  # Access slide object using slide number - 1

            # Extract text from text boxes on the slide
            slide_text_boxes = [
                run.text.strip()
                for shape in slide_obj.shapes
                if shape.has_text_frame
                for paragraph in shape.text_frame.paragraphs
                for run in paragraph.runs
                if run.text.strip()
            ]

            # Ignore the slide if there is no text
            if not slide_text_boxes:
                continue

            # Create a MySlide object and store it in the slides dictionary
            self.slides[slide_number] = MySlide(slide_number, slide_text_boxes)


import argparse
import numpy as np
import matplotlib.pyplot as plt
from pprint import pprint
from reach import ReachDatabase, load
from scipy.interpolate import Rbf

def evaluate(positions, scores, func, eps=None):
    rbf = Rbf(positions[:, 0], positions[:, 1], positions[:, 2], scores, function=func, epsilon=eps)
    Ainv = np.linalg.inv(rbf.A)
    e = rbf.nodes / np.diag(Ainv)
    return np.linalg.norm(e, ord=1)/len(e)

def main():
    parser = argparse.ArgumentParser(
        description="Calculate and display the errors generated by varying parametrizations of RBF interpolation")
    parser.add_argument(type=str, dest="db_file", help="Filepath of the reach database")
    parser.add_argument('--max_eps', type=float, default=1.0, help="Maximum value of epsilon to sample")
    parser.add_argument('--n_eps_samples', type=int, default=50, help="Number of epsilon values to sample on [5e-3, max_eps]")
    args = parser.parse_args()

    # Load database from ROS message
    db = load(args.db_file)
    result = db.results[-1]

    positions = np.array([r.goal()[0:3, 3] for r in result])
    scores = np.array([r.score for r in result])

    # Evaluate the functions that use the epsilon parameter over a range of values
    epsilon = np.linspace(0.0005, args.max_eps, args.n_eps_samples)
    functions_eps = ['multiquadric', 'inverse', 'gaussian']
    error_eps = np.empty((len(functions_eps), len(epsilon)))
    for i, func in enumerate(functions_eps):
        for j, eps in enumerate(epsilon):
            error_eps[i, j] = evaluate(positions, scores, func, eps)

    # Evaluate the functions that do not use epsilon
    functions_no_eps = ['thin_plate', 'linear', 'cubic', 'quintic']
    error_no_eps = np.empty((len(functions_no_eps), len(epsilon)))
    for i, func in enumerate(functions_no_eps):
        error_no_eps[i] = np.repeat(evaluate(positions, scores, func), len(epsilon))

    # Combine the results
    functions = functions_eps + functions_no_eps
    error = np.vstack([error_eps, error_no_eps])

    # Print the error for each method and its corresponding epsilon value
    print('Method - Error - Epsilon')
    pprint(list(zip(functions, zip(np.min(error, axis=1), epsilon[np.argmin(error, axis=1)]))))

    # Plot the results
    _,ax = plt.subplots()
    lines = ax.plot(epsilon, error.T)
    for i, line in enumerate(lines):
        line.set_label(functions[i])
    ax.scatter(epsilon[np.argmin(error, axis=1)], np.min(error, axis=1))
    ax.set(
        xlabel='Epsilon',
        ylabel='Error'
    )
    ax.grid()
    ax.legend()
    plt.show()

if __name__ == '__main__':
    main()


#!/usr/bin/python3
from playlist_class import Playlist
from songs_class import Song
import mutagen
import os
import datetime

class MusicCrawler:

    def __init__(self, dir_path=os.path.expanduser("~/Music")):
        self.dir_path = dir_path
        self.song_lst = []
        self.songtypes = ('.ogg', '.mp3', '.flac')
        self.find_songs()

    def find_songs(self):
        for root, dirs, files in os.walk(self.dir_path):
            for fn in files:
                path = os.path.join(root, fn)
                if fn.endswith(self.songtypes):
                    song = mutagen.File(path, easy=True)
                    self.song_lst.append(Song(song['title'][0], song['artist'][0], song['album'][0], str(datetime.timedelta(seconds=int(song.info.length))), path))

    def generate_playlist(self, plname="", shuff=False, repp=True):
        gn_plist = Playlist(name=plname, shuffle=shuff, repeat=repp)
        for s in self.song_lst:
            gn_plist.add_song(s)
        return gn_plist


from fixtures.request import Request

# функция для поиска папки
def search_folder(access_token):
    response = Request("Search Folder").send_request(method="GET",
                       url="https://www.googleapis.com/drive/v3/files",
                       params={"q": "name='python' and mimeType='application/vnd.google-apps.folder'",
                               "fields": "files(id)",
                               "access_token": f"{access_token}"})
    return response


from os import path
from typing import List, Tuple

import pytorch_lightning as pl
import torch
import torchmetrics
from torch.nn import functional as F

from et4el.embedder import ELMO_EMBEDDINGS_DIM, ELMoPretrainedEmbedder
from et4el.encoder import MentionEncoder, SentenceEncoder, SimpleDecoder
from et4el.utils import MentionHandler, Mentions, load_vocab_dict

PATH_TO_VOCAB = path.normpath(path.join(path.dirname(__file__), "ontology/conll_categories.txt"))

class FineGrainedEntityTyper(pl.LightningModule):
    def __init__(self,
                 learning_rate=2e-3,
                 mention_dropout=0.5,
                 input_dropout=0.5,
                 rnn_dim=50,
                 cnn_dim=50,
                 mask_dim=50,
                 attention_dim=100,
                 answer_num=60000,
                 max_mention_length=10,
                 max_context_length=50,
                 threshold=0.5,
                 **_kwargs):
        super().__init__()
        self.save_hyperparameters()

        self.learning_rate = learning_rate

        self.answer_num = answer_num
        self.threshold = threshold

        embeddings_dim = ELMO_EMBEDDINGS_DIM
        output_dim = 2 * rnn_dim + embeddings_dim + cnn_dim

        self.pre_handler = MentionHandler(max_mention_length, max_context_length)
        self.embedder = ELMoPretrainedEmbedder(self.device)
        self.sentence_encoder = SentenceEncoder(input_dropout, rnn_dim, embeddings_dim, mask_dim, attention_dim)
        self.mention_encoder = MentionEncoder(mention_dropout, cnn_dim, embeddings_dim, attention_dim)
        self.decoder = SimpleDecoder(output_dim, answer_num)

        self.answer2id = load_vocab_dict(PATH_TO_VOCAB, vocab_max_size=self.answer_num)
        self.id2answer = {v: k for k, v in self.answer2id.items()}

        self.f1 = torchmetrics.F1(num_classes=answer_num, threshold=threshold, average="macro")

    @staticmethod
    def add_model_specific_args(parent_parser):
        parser = parent_parser.add_argument_group("FineGrainedEntityTyper")
        parser.add_argument("--mention-dropout", type=float, default=0.5)
        parser.add_argument("--input-dropout", type=float, default=0.5)
        parser.add_argument("--rnn-dim", type=int, default=50)
        parser.add_argument("--cnn-dim", type=int, default=50)
        parser.add_argument("--mask-dim", type=int, default=50)
        parser.add_argument("--attention-dim", type=int, default=100)
        parser.add_argument("--answer-num", type=int, default=60000)
        parser.add_argument("--max-mention-length", type=int, default=10)
        parser.add_argument("--max-context-length", type=int, default=50)
        parser.add_argument("--threshold", type=float, default=0.5)
        return parent_parser

    def to(self, *args, **kwargs):
        out = torch._C._nn._parse_to(*args, **kwargs)
        self.embedder.to(device=out[0])
        return super().to(*args, **kwargs)

    def _get_logits(self, mentions):
        """
        1. Get ELMo Embeddings
        2. Encode Sentence
        3. Encode Mention (word level and char level)
        4. Concat and decode all three vectors v = [s, m_word, m_char]
        """
        mentions = self.pre_handler.prepare_mentions(mentions)
        embeddings = self.embedder.embed(mentions)
        sequence_rep = self.sentence_encoder(mentions, embeddings)
        mention_rep = self.mention_encoder(mentions, embeddings)

        representation = torch.cat((sequence_rep, mention_rep), 1)
        logits = self.decoder(representation)
        return logits

    def forward(self, mentions: Mentions):
        logits = self._get_logits(mentions)
        outputs = torch.sigmoid(logits)

        # Decode predictions to categories
        predictions: List[List[Tuple[str, float]]] = []
        for output in outputs:
            output_indices = (output > self.threshold).nonzero().squeeze(1)
            if len(output_indices) == 0:
                output_indices = torch.argmax(output, dim=0, keepdim=True)
            predicted_categories = [(self.id2answer[i.item()], output[i].item()) for i in output_indices]
            predictions.append(predicted_categories)
        return predictions

    def on_train_start(self):
        self.logger.log_hyperparams(self.hparams)

    def training_step(self, batch, batch_idx):
        mentions, categories_batch = batch

        # Encode target categories to target tensor
        targets = torch.zeros([len(categories_batch), self.answer_num], device=self.device)
        for i, categories in enumerate(categories_batch):
            answer_ids = [self.answer2id[c] for c in categories if c in self.answer2id]
            for answer_idx in answer_ids:
                targets[i, answer_idx] = 1

        logits = self._get_logits(mentions)
        loss = F.binary_cross_entropy_with_logits(logits, targets)

        self.log("train_loss", loss)
        return loss

    def _eval_step(self, batch):
        mentions, categories_batch = batch

        # Encode target categories to target tensor
        targets = torch.zeros([len(categories_batch), self.answer_num], dtype=torch.int, device=self.device)
        for i, categories in enumerate(categories_batch):
            answer_ids = [self.answer2id[c] for c in categories if c in self.answer2id]
            for answer_idx in answer_ids:
                targets[i, answer_idx] = 1

        logits = self._get_logits(mentions)
        outputs = torch.sigmoid(logits)
        return outputs, targets

    def validation_step(self, batch, batch_idx):
        return self._eval_step(batch)

    def validation_epoch_end(self, results):
        # results = List[(outputs, targets) from each validation_step]
        outputs = torch.cat([outputs for outputs, targets in results])  # .permute(1, 0)
        targets = torch.cat([targets for outputs, targets in results])  # .permute(1, 0)
        accuracy = self.f1(outputs, targets)
        self.log("validation_accuracy", accuracy, prog_bar=True)

    def test_step(self, batch, batch_idx):
        return self._eval_step(batch)

    def test_epoch_end(self, results):
        # results = List[(outputs, targets) from each test_step]
        outputs = torch.cat([outputs for outputs, targets in results])  # .permute(1, 0)
        targets = torch.cat([targets for outputs, targets in results])  # .permute(1, 0)
        accuracy = self.f1(outputs, targets)
        self.log("test_accuracy", accuracy, prog_bar=True)

    def configure_optimizers(self):
        optimizer = torch.optim.Adam(self.parameters(), lr=self.learning_rate)
        return optimizer


import fiona
import geopandas as gpd
import pandas as pd
from shapely import LineString, MultiPoint, ops
from tqdm import tqdm

class FixLineGeometry:

    def __init__(self: 'FixLineGeometry', path: str, crs: int = 3826) -> None:
        '''
        The initial settings of FixLineGeometry.

        Parameters
        --------
        path: str
            The file path of the shapefile.

        crs: int
            Targeted crs for the following modifications.
        '''
        geom = fiona.open(path)

        if (geom.schema['geometry'] == 'LineString'):   # Ref: https://gis.stackexchange.com/questions/457106/check-geometry-type-of-shapefile-with-geopandas

            self.NETWORK = gpd.read_file(path, encoding = 'utf-8').to_crs(crs)

        else:

            raise ValueError(f'Invalid geometry type: expect LineString but get {geom.schema["geometry"]}')

    def debug(

            self: 'FixLineGeometry',
            auto_fix: bool = True,
            threshold: float = 1.0,
            savefile_path: str = r'.',
            savefile_name: str = 'fixed'

        ) -> gpd.GeoDataFrame:
        '''
        List all not properly connected polylines.

        Parameters
        --------
        auto_fix: bool
            Whether to fix unconnected vetices or not. Default to be `False`.

        threshold: float
            The threshold to check whether the lines should be connected or not.
            For example, two non-connected vortex within 1 meters with threshold set to 1 meters would be regarded as unconnected.

        savefile_path: str
            The folder corrected shapefile should be placed at.

        savefile_name: str
            The name of the corrected shapefile.
        '''

        def to_MultiPoint(feature: LineString) -> MultiPoint:
            '''
            Convert LineString into MultiPoint object; only apply to one row so use it with `lambda`.

            Parameters
            --------
            feature: shapely.LineString
                The linestring object needs converting into multipoint.

            Returns
            --------
            result: shapely.MultiPoint
                The multipoint version of original feature.
            '''

            return MultiPoint(feature.coords)

        multi_point_NETWORK = self.NETWORK.copy()
        # Convert the linestring into multipoint. / 將線轉換為複數點
        multi_point_NETWORK['geometry'] = self.NETWORK.apply(lambda L: to_MultiPoint(L['geometry']), axis = 1)

        problem_case = gpd.GeoDataFrame()

        # For auto fix mode / 自動修復模式用
        if (auto_fix):

            # Explode the multipoint so we can find out the point where the distance of any two line is smaller then threshold. /
            # 將複數點轉換成單一點，這樣才能個別檢查在哪一點任意兩條線的距離小於閥值。
            single_point_series = multi_point_NETWORK['geometry'].explode(index_parts = True).copy()
            # Perform buffer on every point with the radius using threshold. / 對每一點執行以閥值為半徑的環域。
            single_point_buffer = single_point_series.buffer(threshold)

            for (i, item) in tqdm(single_point_buffer.items(), 'Traversing every vertices', len(single_point_series)):

                # Find the linestrings which intersect the point buffer, or the linestring within the distance of threshold near the point. /
                # 找出和點環域有交集的線，即與點的直線距離在閥值內的線。
                close_NETWORK = self.NETWORK[self.NETWORK['geometry'].intersects(item)].copy()
                # Find the line itself. Since the single points were converted from multipoints, which were extracted from the linestrings, /
                # there will always be the original line in the result. /
                # 找出線本身。由於每一單點是由複數點轉換而來，而複數點是線上的每一頂點，因此必定會搜尋到原始的線。
                close_NETWORK['self'] = close_NETWORK['geometry'].geom_equals(self.NETWORK.at[i[0], 'geometry'])
                # Find the linestings touching but not crossing the original line. / 找出碰觸但未超出原始線的線。
                close_NETWORK['touch'] = close_NETWORK['geometry'].touches(self.NETWORK.at[i[0], 'geometry'])

                def check_within1(idx: tuple, feature: LineString) -> bool:
                    '''
                    Check the current point is within the linestring; only apply to one row so use it with `lambda`.

                    Parameters
                    --------
                    idx: tuple
                        The current index of the base point in `single_point_series` (the point we want to check within).

                    feature: shapely.LineString
                        The linestring to compare with the base point.

                    Returns
                    --------
                    result: bool
                        Whether the point is within the linestring.
                    '''

                    base_point = single_point_series[idx[0]][idx[1]]
                    ref_multipoint = to_MultiPoint(feature)

                    return base_point.within(ref_multipoint)

                # Find out whether the intersection point of any two linestrings are correctly placed. /
                # Note that this only catch the point between the start and finish of the line; /
                # Remaing case have been catched by previous `touch`. /
                # 確認任意兩線交會處的頂點有正確的疊合。這只適用在線的端點外的情況，端點的連接情況已在`touch`欄位確認。
                close_NETWORK['within'] = close_NETWORK.apply(lambda L: check_within1(i, L['geometry']), axis = 1)

                # Exclude the record if any of these columns are `True`: self, touch & within. /
                # This means the record is connect correctly with the line which the point buffer belongs to. /
                # 排除以下任意為真的欄位：self、touch 和 within，這代表這筆紀錄的線與點環域所屬的線有正確連接上。
                close_NETWORK = close_NETWORK.query('(self == False) & (touch == False) & (within == False)').copy()
                # Drop the column we don't need anymore. / 刪除接下來用不到的欄位。
                close_NETWORK.drop(['self', 'touch', 'within'], axis = 1, inplace = True)

                # Record problem pairs / 記錄未正確連接的線組合。
                if (len(close_NETWORK) > 0):

                    geom_idx = close_NETWORK.columns.get_loc('geometry')
                    close_NETWORK.insert(loc = geom_idx,     column = 'nbr_idx0', value = i[0])
                    close_NETWORK.insert(loc = geom_idx + 1, column = 'nbr_idx1', value = i[1])
                    close_NETWORK.insert(loc = geom_idx + 2, column = 'nbr_name', value = self.NETWORK.at[i[0], 'name'])

                    if ('section' in self.NETWORK.columns):

                        close_NETWORK.insert(loc = geom_idx + 3, column = 'nbr_sctn', value = self.NETWORK.at[i[0], 'section'])
                        close_NETWORK.insert(loc = geom_idx + 4, column = 'nbr_poin', value = single_point_series[i[0]][i[1]])

                    else:

                        close_NETWORK.insert(loc = geom_idx + 3, column = 'nbr_poin', value = single_point_series[i[0]][i[1]])

                    problem_case = pd.concat([problem_case, close_NETWORK]).copy()

        # For non auto fix mode; basically same as above but use a more simple calculaing method. /
        # CANNOT EXCLUDE GENERAL INTERSECTIONS! USE AUTO FIX MODE FOR THE PURPOSE.
        # 非自動修復模式用；基本上和自動修復模式相同，但使用較簡單的算法。無法排除兩條交會點在線段中間的點，即使正確也將視為錯誤。
        else:

            multi_point_buffer = multi_point_NETWORK.copy()
            multi_point_buffer['geometry'] = multi_point_NETWORK['geometry'].buffer(threshold)

            for (i, row) in tqdm(multi_point_buffer.iterrows(), 'Traversing every line', len(multi_point_buffer)):

                close_NETWORK = self.NETWORK[self.NETWORK['geometry'].intersects(row['geometry'])].copy()
                close_NETWORK['self'] = close_NETWORK['geometry'].geom_equals(self.NETWORK.at[i, 'geometry'])
                close_NETWORK['touch'] = close_NETWORK['geometry'].touches(self.NETWORK.at[i, 'geometry'])

                close_NETWORK = close_NETWORK.query('(touch == False) & (self == False)').copy()
                close_NETWORK.drop(['self', 'touch'], axis = 1, inplace = True)

                if (len(close_NETWORK) > 0):

                    geom_idx = close_NETWORK.columns.get_loc('geometry')
                    close_NETWORK.insert(loc = geom_idx,     column = 'nbr_idx0', value = i)
                    close_NETWORK.insert(loc = geom_idx + 1, column = 'nbr_name', value = self.NETWORK.at[i, 'name'])

                    if ('section' in self.NETWORK.columns):

                        close_NETWORK.insert(loc = geom_idx + 2, column = 'nbr_sctn', value = self.NETWORK.at[i, 'section'])

                    problem_case = pd.concat([problem_case, close_NETWORK]).copy()

        # Append new index to all problem cases. / 為所有錯誤的線組合添加新的索引。
        problem_case.reset_index(inplace = True)

        problem_NETWORK = gpd.GeoDataFrame()
        duplicate_filter = set()

        # Remove the duplicates. Since the function iterrated all point buffer, any incorrectly connected network would append new pairs to the `problem_case`. /
        # If there are two incorrectly connected lines, there will be two records where one of the item is a reversed verion of another one. /
        # 移除重複的線組合。由於上方的方式迭代了每一個點環域，任何未正確連接的線皆會產生一次記錄，導致記錄的數量是實際問題的兩倍；/
        # 舉例來說，甲線的A點和乙線的B點距離在閥值內，迭代完成後將會出現 (甲, 乙) 和 (乙, 甲) 的組合，其中一組會是另一組的相反。
        for (i, row) in tqdm(problem_case.iterrows(), 'Removing duplicate networks', len(problem_case)):

            item = (row['index'], row['nbr_idx0'])

            # If the record doesn't exist in the `duplicate_filter` yet, add it and its reversed version so next time its reversed version will be omitted. /
            # 若該筆記錄尚未存在於 `duplicate_filter`中，將其與其相反版本加入，如此一來其相反版本將不會被加入。
            if ((item not in duplicate_filter) & (item[::-1] not in duplicate_filter)):

                duplicate_filter.add(item)
                duplicate_filter.add(item[::-1])

                # ... so that `problem_NETWORK` will not have duplictes. /
                # ……因此 `problem_NETWORK` 中不會有重複的紀錄。
                problem_NETWORK = pd.concat([problem_NETWORK, problem_case.loc[[i]]]).copy()

        if (not auto_fix):

            return problem_NETWORK

        else:

            fixed_point_series = single_point_series.copy()

            # Find the nearest point of the two lines and change the coordinates. / 找出兩條線相交的最近點並將其校正。
            for (i, row) in tqdm(problem_NETWORK.iterrows(), 'Searching nearest vertices', len(problem_NETWORK)):

                host_point = row['nbr_poin']
                guest_line = multi_point_NETWORK.at[row['index'], 'geometry']

                (query, nearest) = ops.nearest_points(host_point, guest_line)

                guest_point = single_point_series[single_point_series == nearest]
                guest_index = guest_point.index

                fixed_point_series[guest_index] = host_point

            # Flatten the multi-index series. Since it was originally exploded from multipoint, /
            # it is related to the linestring in original NETWORK dataframe./
            # 移除 series 的複數索引。由於其複數索引來自多點，因此新的索引和NETWORK中的線的索引相連。
            fixed_point_series = fixed_point_series.droplevel(1, axis = 0)

            fixed_point_list = list()

            # Implode the series so the series is made of multipoint. / 重新將單點組裝回多點。
            for (i, item) in fixed_point_series.items():

                if (len(fixed_point_list) == i):

                    fixed_point_list.append([item])

                else:

                    fixed_point_list[i].append(item)

            fixed_line_list = list()

            # Convert multipoint into linestring / 將多點轉換成線。
            for multi_point in fixed_point_list:

                fixed_line_list.append(LineString(multi_point))

            # Replace old NETWORK's geometry. / 替換掉舊 NETWORK 中的幾何。
            fixed_NETWORK = self.NETWORK.copy()
            fixed_NETWORK['geometry'] = fixed_line_list

            # Export to shapefile. / 輸出shapefile檔案。
            fixed_NETWORK.to_file(f'{savefile_path}\\{savefile_name}.shp', encoding = 'utf-8')

            return problem_NETWORK

    def plot(self: 'FixLineGeometry'):
        '''
        Plot the map of the shapefile.
        '''
        basemap = self.NETWORK.plot(color = 'lightgrey', linewidth = 0.75)
        basemap.set_axis_off()
        basemap.set_title('Network Map')

    # Properties

    @property
    def NETWORK(self: 'FixLineGeometry') -> gpd.GeoDataFrame:
        '''
        The network GeoDataFrame of the file.
        '''
        return self._NETWORK

    @NETWORK.setter
    def NETWORK(self: 'FixLineGeometry', value):
        '''
        Set the network GeoDataFrame.
        '''
        self._NETWORK = value


# The implementation is adopted from UHDM work, made publicly available under the Apache 2.0 License
# source code avaiable via https://github.com/CVMI-Lab/UHDM/
import torch
import torch.nn as nn
import torch.nn.functional as F

class my_model(nn.Module):

    def __init__(
        self,
        en_feature_num,
        en_inter_num,
        de_feature_num,
        de_inter_num,
        sam_number=1,
    ):
        super(my_model, self).__init__()
        self.encoder = Encoder(
            feature_num=en_feature_num,
            inter_num=en_inter_num,
            sam_number=sam_number)
        self.decoder = Decoder(
            en_num=en_feature_num,
            feature_num=de_feature_num,
            inter_num=de_inter_num,
            sam_number=sam_number)

    def forward(self, x):
        y_1, y_2, y_3 = self.encoder(x)
        out_1, out_2, out_3 = self.decoder(y_1, y_2, y_3)
        return out_1, out_2, out_3

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                m.weight.data.normal_(0.0, 0.02)
                if m.bias is not None:
                    m.bias.data.normal_(0.0, 0.02)
            if isinstance(m, nn.ConvTranspose2d):
                m.weight.data.normal_(0.0, 0.02)

class Decoder(nn.Module):

    def __init__(self, en_num, feature_num, inter_num, sam_number):
        super(Decoder, self).__init__()
        self.preconv_3 = conv_relu(4 * en_num, feature_num, 3, padding=1)
        self.decoder_3 = Decoder_Level(feature_num, inter_num, sam_number)
        self.preconv_2 = conv_relu(
            2 * en_num + feature_num, feature_num, 3, padding=1)
        self.decoder_2 = Decoder_Level(feature_num, inter_num, sam_number)
        self.preconv_1 = conv_relu(
            en_num + feature_num, feature_num, 3, padding=1)
        self.decoder_1 = Decoder_Level(feature_num, inter_num, sam_number)

    def forward(self, y_1, y_2, y_3):
        x_3 = y_3
        x_3 = self.preconv_3(x_3)
        out_3, feat_3 = self.decoder_3(x_3)
        x_2 = torch.cat([y_2, feat_3], dim=1)
        x_2 = self.preconv_2(x_2)
        out_2, feat_2 = self.decoder_2(x_2)
        x_1 = torch.cat([y_1, feat_2], dim=1)
        x_1 = self.preconv_1(x_1)
        out_1 = self.decoder_1(x_1, feat=False)
        return out_1, out_2, out_3

class Encoder(nn.Module):

    def __init__(self, feature_num, inter_num, sam_number):
        super(Encoder, self).__init__()
        self.conv_first = nn.Sequential(
            nn.Conv2d(
                12, feature_num, kernel_size=5, stride=1, padding=2,
                bias=True), nn.ReLU(inplace=True))
        self.encoder_1 = Encoder_Level(
            feature_num, inter_num, level=1, sam_number=sam_number)
        self.encoder_2 = Encoder_Level(
            2 * feature_num, inter_num, level=2, sam_number=sam_number)
        self.encoder_3 = Encoder_Level(
            4 * feature_num, inter_num, level=3, sam_number=sam_number)

    def forward(self, x):
        x = F.pixel_unshuffle(x, 2)
        x = self.conv_first(x)
        out_feature_1, down_feature_1 = self.encoder_1(x)
        out_feature_2, down_feature_2 = self.encoder_2(down_feature_1)
        out_feature_3 = self.encoder_3(down_feature_2)
        return out_feature_1, out_feature_2, out_feature_3

class Encoder_Level(nn.Module):

    def __init__(self, feature_num, inter_num, level, sam_number):
        super(Encoder_Level, self).__init__()
        self.rdb = RDB(
            in_channel=feature_num, d_list=(1, 2, 1), inter_num=inter_num)
        self.sam_blocks = nn.ModuleList()
        for _ in range(sam_number):
            sam_block = SAM(
                in_channel=feature_num,
                d_list=(1, 2, 3, 2, 1),
                inter_num=inter_num)
            self.sam_blocks.append(sam_block)
        if level < 3:
            self.down = nn.Sequential(
                nn.Conv2d(
                    feature_num,
                    2 * feature_num,
                    kernel_size=3,
                    stride=2,
                    padding=1,
                    bias=True), nn.ReLU(inplace=True))
        self.level = level

    def forward(self, x):
        out_feature = self.rdb(x)
        for sam_block in self.sam_blocks:
            out_feature = sam_block(out_feature)
        if self.level < 3:
            down_feature = self.down(out_feature)
            return out_feature, down_feature
        return out_feature

class Decoder_Level(nn.Module):

    def __init__(self, feature_num, inter_num, sam_number):
        super(Decoder_Level, self).__init__()
        self.rdb = RDB(feature_num, (1, 2, 1), inter_num)
        self.sam_blocks = nn.ModuleList()
        for _ in range(sam_number):
            sam_block = SAM(
                in_channel=feature_num,
                d_list=(1, 2, 3, 2, 1),
                inter_num=inter_num)
            self.sam_blocks.append(sam_block)
        self.conv = conv(
            in_channel=feature_num, out_channel=12, kernel_size=3, padding=1)

    def forward(self, x, feat=True):
        x = self.rdb(x)
        for sam_block in self.sam_blocks:
            x = sam_block(x)
        out = self.conv(x)
        out = F.pixel_shuffle(out, 2)
        if feat:
            feature = F.interpolate(x, scale_factor=2, mode='bilinear')
            return out, feature
        else:
            return out

class DB(nn.Module):

    def __init__(self, in_channel, d_list, inter_num):
        super(DB, self).__init__()
        self.d_list = d_list
        self.conv_layers = nn.ModuleList()
        c = in_channel
        for i in range(len(d_list)):
            dense_conv = conv_relu(
                in_channel=c,
                out_channel=inter_num,
                kernel_size=3,
                dilation_rate=d_list[i],
                padding=d_list[i])
            self.conv_layers.append(dense_conv)
            c = c + inter_num
        self.conv_post = conv(
            in_channel=c, out_channel=in_channel, kernel_size=1)

    def forward(self, x):
        t = x
        for conv_layer in self.conv_layers:
            _t = conv_layer(t)
            t = torch.cat([_t, t], dim=1)
        t = self.conv_post(t)
        return t

class SAM(nn.Module):

    def __init__(self, in_channel, d_list, inter_num):
        super(SAM, self).__init__()
        self.basic_block = DB(
            in_channel=in_channel, d_list=d_list, inter_num=inter_num)
        self.basic_block_2 = DB(
            in_channel=in_channel, d_list=d_list, inter_num=inter_num)
        self.basic_block_4 = DB(
            in_channel=in_channel, d_list=d_list, inter_num=inter_num)
        self.fusion = CSAF(3 * in_channel)

    def forward(self, x):
        x_0 = x
        x_2 = F.interpolate(x, scale_factor=0.5, mode='bilinear')
        x_4 = F.interpolate(x, scale_factor=0.25, mode='bilinear')
        y_0 = self.basic_block(x_0)
        y_2 = self.basic_block_2(x_2)
        y_4 = self.basic_block_4(x_4)
        y_2 = F.interpolate(y_2, scale_factor=2, mode='bilinear')
        y_4 = F.interpolate(y_4, scale_factor=4, mode='bilinear')
        y = self.fusion(y_0, y_2, y_4)
        y = x + y
        return y

class CSAF(nn.Module):

    def __init__(self, in_chnls, ratio=4):
        super(CSAF, self).__init__()
        self.squeeze = nn.AdaptiveAvgPool2d((1, 1))
        self.compress1 = nn.Conv2d(in_chnls, in_chnls // ratio, 1, 1, 0)
        self.compress2 = nn.Conv2d(in_chnls // ratio, in_chnls // ratio, 1, 1,
                                   0)
        self.excitation = nn.Conv2d(in_chnls // ratio, in_chnls, 1, 1, 0)

    def forward(self, x0, x2, x4):
        out0 = self.squeeze(x0)
        out2 = self.squeeze(x2)
        out4 = self.squeeze(x4)
        out = torch.cat([out0, out2, out4], dim=1)
        out = self.compress1(out)
        out = F.relu(out)
        out = self.compress2(out)
        out = F.relu(out)
        out = self.excitation(out)
        out = F.sigmoid(out)
        w0, w2, w4 = torch.chunk(out, 3, dim=1)
        x = x0 * w0 + x2 * w2 + x4 * w4
        return x

class RDB(nn.Module):

    def __init__(self, in_channel, d_list, inter_num):
        super(RDB, self).__init__()
        self.d_list = d_list
        self.conv_layers = nn.ModuleList()
        c = in_channel
        for i in range(len(d_list)):
            dense_conv = conv_relu(
                in_channel=c,
                out_channel=inter_num,
                kernel_size=3,
                dilation_rate=d_list[i],
                padding=d_list[i])
            self.conv_layers.append(dense_conv)
            c = c + inter_num
        self.conv_post = conv(
            in_channel=c, out_channel=in_channel, kernel_size=1)

    def forward(self, x):
        t = x
        for conv_layer in self.conv_layers:
            _t = conv_layer(t)
            t = torch.cat([_t, t], dim=1)
        t = self.conv_post(t)
        return t + x

class conv(nn.Module):

    def __init__(self,
                 in_channel,
                 out_channel,
                 kernel_size,
                 dilation_rate=1,
                 padding=0,
                 stride=1):
        super(conv, self).__init__()
        self.conv = nn.Conv2d(
            in_channels=in_channel,
            out_channels=out_channel,
            kernel_size=kernel_size,
            stride=stride,
            padding=padding,
            bias=True,
            dilation=dilation_rate)

    def forward(self, x_input):
        out = self.conv(x_input)
        return out

class conv_relu(nn.Module):

    def __init__(self,
                 in_channel,
                 out_channel,
                 kernel_size,
                 dilation_rate=1,
                 padding=0,
                 stride=1):
        super(conv_relu, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(
                in_channels=in_channel,
                out_channels=out_channel,
                kernel_size=kernel_size,
                stride=stride,
                padding=padding,
                bias=True,
                dilation=dilation_rate), nn.ReLU(inplace=True))

    def forward(self, x_input):
        out = self.conv(x_input)
        return out


import sys
import os

def part1(file_name):
    max_calories = 0
    current_calories = 0
    with open(file_name, 'r') as f:
        for line in f:
            if line == "\n":
                max_calories = max(max_calories, current_calories)
                current_calories = 0
            else:
                current_calories += int(line)
        max_calories = max(max_calories, current_calories)
    return max_calories

def part2(file_name):
    curr_calories = 0
    callories_arr = []
    with open(file_name, 'r') as f:
        for line in f:
            if line == "\n":
                callories_arr.append(curr_calories)
                curr_calories = 0
            else:
                curr_calories += int(line)
        callories_arr.append(curr_calories)
    # return sum of 3 highest values from callories_arr
    return sum(sorted(callories_arr)[-3:])

if __name__ == "__main__":
    file_name = "input.txt"
    if len(sys.argv) > 1 and os.path.isfile(sys.argv[1]):
        file_name = sys.argv[1]
    print("Results for file: {}".format(file_name))
    print("Part 1: {}".format(part1(file_name)))
    print("Part 2: {}".format(part2(file_name)))


import csv
import time
import sys

states = []
statesPop = 0

def delay_print(s):
    for c in s:
        sys.stdout.write( '%s' % c )
        sys.stdout.flush()
        time.sleep(0.03)
    print()

def menu():
    delay_print("Welcome to the NSA's US States database, please choose an option:")
    delay_print("1 - Print all data.")
    delay_print("2 - Select data.")
    delay_print("3 - Quit.")

with open ("USStates.txt") as csvfile:
    statesCsv = csv.reader(csvfile, delimiter = ",")
    for row in statesCsv:
        states.append(row)

listLength = len(states)

print("--------------------------------------")
for i in range(listLength):
    print("|{0:15}|{1:4}|{2:15}|".format(states[i][0], states[i][1].center(4), states[i][3]))
print("--------------------------------------")

for x in range(listLength):
    statesPop = statesPop + int(states[x][4])

print("Total population: " + str(statesPop))


import numpy as np
import Calculator as calc
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider

# true - Earth, false - Oscillator
Earth = True
Oscillator = False

choose_field = Earth  # тут выбирать, что рисовать - гравитационное, или осциллятор
# настройка параметров ниже - в функции set_params

# constants:
R = 6371000.0  # Earth radius
G = 6.673e-11  # C
M = 5.9742e24  # C

global step_t
global total_time

global m
global w

global r0
global vr_0

def trans(x, y):
    r_temp = np.sqrt(x**2 + y**2)
    temp_2 = y / r_temp
    if temp_2 > 1:
        temp_3 = np.pi / 2
    elif temp_2 < -1:
        temp_3 = -np.pi / 2
    else:
        temp_3 = np.arcsin(temp_2)

    if temp_3 >= 0:
        temp = x / r_temp
        if temp > 1:
            hi = 0.0
        elif temp < -1:
            hi = np.pi
        else:
            hi = np.arccos(temp)
    else:
        temp = x / r_temp
        if temp > 1:
            hi = 0.0
        elif temp < -1:
            hi = np.pi
        else:
            hi = 2 * np.pi - np.arccos(temp)
    return r_temp, hi

def gravitational_planet_potential(x):
    if x < R:
        return 5e-20
    return -m * M * G / x

def gravitational_planet_force_2D(r_vec):
    A = -m * M * G
    if r_vec[0]**2 + r_vec[1]**2 <= R**2:
        return np.array([0, 0])

    arr_r, arr_hi = trans(r_vec[0], r_vec[1])
    return np.array([A * np.cos(arr_hi) / arr_r**2,
                     A * np.sin(arr_hi) / arr_r**2])

def potent_oscillator(r_mod):
    return m * w * r_mod ** 2 / 2

def oscillator_force_2D(r_vec):
    return np.array([-m * w * r_vec[0], -m * w * r_vec[1]])

global U_
global Force

def set_params(mode=Earth):
    global m
    global r0
    global vr_0
    global U_
    global Force
    global w
    global total_time
    global step_t

    if mode:  # здесь настраиваются начальные параметры для 2д случая гравитационного поля
        m = 1000
        vr_0 = np.array([-4000.0, 0.0])
        total_time = 100000
        step_t = 100.0
        r0 = np.array([R + 2 * R, R + 3 * R])
        U_ = gravitational_planet_potential
        Force = gravitational_planet_force_2D
    else:  # здесь настраиваются начальные параметры для 2д случая поля осциллятора
        m = 1.67e-27
        vr_0 = np.array([-2.0, 0.0])
        w0 = 3
        w = w0**2
        total_time = 5
        step_t = 1e-3
        r0 = np.array([2.0, 1.0])
        U_ = potent_oscillator
        Force = oscillator_force_2D

def update(val):
    t, r, v = calc.eqSolut(func_, m, r0, vr_0, 0, total_time_slider.val, step_t)
    r_x = [r[i][0] for i in range(0, len(r))]
    r_y = [r[i][1] for i in range(0, len(r))]
    v_x = [v[i][0] for i in range(0, len(v))]
    v_y = [v[i][1] for i in range(0, len(v))]

    r_norm = [np.linalg.norm(r[i]) for i in range(0, len(r))]
    v_mod, fi_in_v = [trans(v_x[i], v_y[i])[0] for i in range(0, len(v))], \
                     [trans(v_x[i], v_y[i])[1] for i in range(0, len(v))]
    E_full = [(v_mod[i]) ** 2 * m / 2 + U_(r_norm[i]) for i in range(0, len(r_norm))]

    v_fi = [v_mod[i] * np.sqrt(abs(1 - (np.dot(v[i], r[i]) / np.linalg.norm(v[i]) / np.linalg.norm(r[i])) ** 2)) for i in range(0, len(v_mod))]
    x_eff = [(np.linalg.norm(r[i])) for i in range(0, len(v_fi))]
    U_eff = [U_(x_eff[i]) + v_fi[i] ** 2 * m / 2 for i in range(0, len(v_fi))]

    line_xy.set_xdata(r_x)
    line_xy.set_ydata(r_y)

    line_tv.set_xdata(t)
    line_tv.set_ydata(v_x)

    line_tr.set_xdata(t)
    line_tr.set_ydata(r_x)

    line_rE.set_xdata(r_norm)
    line_rE.set_ydata(E_full)

    line_Uef.set_xdata(x_eff)
    line_Uef.set_ydata(U_eff)

    fg.canvas.draw_idle()

# init
set_params(choose_field)  # true - Earth, false - oscillator
func_ = Force

t, r, v = calc.eqSolut(func_, m, r0, vr_0, 0, total_time, step_t)

r_x = [r[i][0] for i in range(0, len(r))]
r_y = [r[i][1] for i in range(0, len(r))]
v_x = [v[i][0] for i in range(0, len(v))]
v_y = [v[i][1] for i in range(0, len(v))]

fg = plt.figure(figsize=(12, 7))
plt.subplot(221)
line_tr, = plt.plot(t, r_x, label='r')
plt.title('Coordinate_x_main')
plt.xlabel('t')
plt.ylabel('r')
plt.grid()

plt.subplot(222)
line_tv, = plt.plot(t, v_x, label='v')
plt.title('Speed_ x')
plt.xlabel('t')
plt.ylabel('v')
plt.grid()

plt.subplot(223)
if choose_field:
    circle1 = plt.Circle((0, 0), R, color='r', fill=True)
    ax = plt.gca()
    ax.add_patch(circle1)
line_xy, = plt.plot(r_x, r_y, label='Y(x)')
plt.title('y(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.grid()

r_norm = [np.linalg.norm(r[i]) for i in range(0, len(r))]
v_mod, fi_in_v = [trans(v_x[i], v_y[i])[0] for i in range(0, len(v))], \
                 [trans(v_x[i], v_y[i])[1] for i in range(0, len(v))]
E_full = [(v_mod[i]) ** 2 * m / 2 + U_(r_norm[i]) for i in range(0, len(r_norm))]

#v_fi = [v_mod[i] / np.tan(fi_in_v[i]) for i in range(0, len(v_mod))]
v_fi = [v_mod[i] * np.sqrt(abs(1 - (np.dot(v[i], r[i]) / np.linalg.norm(v[i]) / np.linalg.norm(r[i]))**2)) for i in range(0, len(v_mod))]

x_eff = [(np.linalg.norm(r[i])) for i in range(0, len(v_fi))]
U_eff = [U_(x_eff[i]) + v_fi[i]**2 * m / 2 for i in range(0, len(v_fi))]

plt.subplot(224)
line_Uef, = plt.plot(x_eff, U_eff, label='U')
line_rE, = plt.plot(r_norm, E_full, 'r-.', label='particle Energy')
plt.title('Energy')
plt.xlabel('r')
plt.ylabel('E')
plt.grid()

ax_total_time = plt.axes([0.1, 0.025, 0.8, 0.0125])
total_time_slider = Slider(
    ax=ax_total_time,
    label="t",
    valmin=0,
    valmax=10 * total_time,
    valinit=total_time,
    valstep=1
)
total_time_slider.on_changed(update)

plt.show()


from abc import (
    ABC,
    abstractmethod,
)
from sys import stderr
from typing import Union
from pathlib import Path

from loguru import logger as _Logger

from .. import get_bot_config

class AbstractLogger(ABC):
    @abstractmethod
    def info(self, msg):
        ...

    @abstractmethod
    def error(self, msg):
        ...

    @abstractmethod
    def debug(self, msg):
        ...

    @abstractmethod
    def warn(self, msg):
        ...

    @abstractmethod
    def plugin(self, msg):
        ...

    @abstractmethod
    def exception(self, msg):
        ...

    @abstractmethod
    def bot(self, msg, **kwargs):
        ...

    @abstractmethod
    def success(self, msg):
        pass

class Logger(AbstractLogger):
    __logger: _Logger

    def __init__(self) -> None:
        debug: bool = get_bot_config('debug')
        self.__logger = _Logger
        # {thread.name} {file}:{module}.{function} {line}|
        time_fmt = "{time:HH:mm:ss}"  # {time:YYYY-MM-DD HH:mm:ss.SSS}
        fmt = "|<green>" \
              + time_fmt \
              + "</green>|<level>{level.icon}</level>|<level>{message}</level>"
        self.__logger.remove()
        self.__logger.add(
            stderr,
            format=fmt,
            enqueue=False,
            level=10 if debug else 15
        )
        try:
            self.__logger.level("DEBUG ", no=10, color="<light-black>",
                                icon="💡")
            self.__logger.level("INFO ", no=15, color="<fg #FFFFFF>", icon="  ")
            self.__logger.level("GROUP", no=15, color="<g>", icon="👪")
            self.__logger.level("FRIEND", no=15, color="<g>", icon="🙎")  # →←⇨⇦
            self.__logger.level("TEMP", no=15, color="<g>", icon="👤")
            self.__logger.level("PLUGIN", no=20, color="<c>", icon="🧩")
            self.__logger.level("SUCCESS ", no=25, color="<g><b>", icon="✔")
            self.__logger.level("WARNING ", no=30, color="<y><b>", icon="⚠")
            self.__logger.level("ERROR ", no=35, color="<r><b>", icon="❌")
            self.__logger.level("CRITICAL ", no=40, color="<fg #FC3F3F><b>",
                                icon="☠")
            self.__logger.level("ORDER ", no=15, color="<light-black>",
                                icon="👉")
        except TypeError:
            ...

    def log_to_file(self, path: Union[str, Path] = None):
        from os import environ
        project_path = Path(environ.get('PROJECT_PATH'))
        config = get_bot_config('log')

        log_path = project_path.joinpath(
            config['sink'] if path is None else path
        ).resolve()

        if not all([log_path.exists(), log_path.is_dir()]):
            self.warn(f"'{log_path}' does not exist.")
            log_path.mkdir()

        config.pop('sink')
        self.__logger.add(
            sink=f"{log_path.__str__()}/file.log",
            level=10,
            **config
        )

    def debug(self, msg):
        return self.__logger.log("DEBUG ", msg)

    def info(self, msg):
        return self.__logger.log("INFO ", msg)

    def plugin(self, msg):
        return self.__logger.log("PLUGIN", msg)

    def success(self, msg):
        return self.__logger.log("SUCCESS ", msg)

    def warn(self, msg):
        return self.__logger.log("WARNING ", msg)

    def error(self, msg):
        return self.__logger.log("ERROR ", msg)

    def exception(self, msg):
        return self.__logger.exception(msg)

    def critical(self, msg):
        return self.__logger.log("CRITICAL ", msg)

    def bot(self, msg, **kwargs):
        def cut_length(string: str, length: int, fillChar: str = ' ') -> str:
            string = str(string)
            real_len = 0
            chinese_n = 0
            char_n = 0
            for char in string:
                is_chinese = len(char.encode('utf-8')) == 3
                chinese_n += 1 if is_chinese else 0
                real_len += 2 if is_chinese else 1
                char_n += 1
                if real_len > length:
                    char_n -= 1 if is_chinese else 0
                    return string[:char_n] + '.' * (real_len - length + 2)
            return string.center(length - chinese_n, fillChar)

        receive = kwargs.get('receive')
        message_type = kwargs.get('type')
        target = kwargs.get('target')
        header = '{}({}) '.format(
            cut_length(target.group.name, 12),
            cut_length(target.group.id, 9)
        ) if any([
            all([receive, message_type == 'group']),
            message_type == 'temp']
        ) else ''
        level = "GROUP" if message_type == 'group' else (
            'FRIEND' if message_type == 'friend' else 'TEMP')
        try:
            return self.__logger.opt(colors=True, capture=True).log(
                level,
                f"<light-blue>{header}</>" +
                f"<light-cyan>{target.name}({target.id})</> <light-red>" +
                ("->" if receive else "<-") + "</> " + msg
            )
        except Exception as e:
            print(receive, message_type, target)
            raise e

    def order(self, name, msg):
        return self.__logger.opt(colors=True) \
            .log("ORDER ", f"<light-cyan>{name}</>:<g>{msg}</>")


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('document', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='CredibilityModel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('hub', models.FloatField(default=1)),
                ('auth', models.FloatField(default=0)),
                ('source_score', models.FloatField(default=0)),
                ('credibility', models.FloatField(default=1)),
                ('document', models.OneToOneField(null=True, to='document.Document')),
                ('outgoing', models.ManyToManyField(to='credibility.CredibilityModel', related_name='incoming')),
            ],
        ),
        migrations.CreateModel(
            name='SourceModel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('document_source', models.TextField(max_length=400)),
                ('source_correct', models.FloatField(default=0)),
                ('total', models.FloatField(default=0)),
            ],
        ),
        migrations.AddField(
            model_name='credibilitymodel',
            name='source',
            field=models.ForeignKey(null=True, to='credibility.SourceModel', related_name='credibility_models'),
        ),
    ]


'''
date: 2019-07-20
'''

for test_case in range(1, int(input())+1):
    seq = [input() for _ in range(5)]
    leng = [len(s) for s in seq]

    res = ""
    for j in range(max(leng)):
        for i in range(5):
            if leng[i] > j:
                res += seq[i][j]

    print("#{} {}".format(test_case, res))


program = open("./inputs/d10.txt", 'r').read().splitlines()

def part1():
    program_copy = program.copy()
    X = 1
    valid_cycles = [20, 60, 100, 140, 180, 220]

    cycle = 1
    signal_strength_sum = 0
    wait_cycle = False
    while cycle <= 220:
        # during cycle
        if cycle in valid_cycles:
            signal_strength_sum += cycle * X

        # after cycle
        if wait_cycle:
            # we waited a cycle
            X += int(program_copy[0].split()[1])
            program_copy.pop(0)
            wait_cycle = False
        else:
            if program_copy[0] != "noop":
                wait_cycle = True
            else:
                program_copy.pop(0)

        cycle += 1

    return signal_strength_sum

def part2():
    program_copy = program.copy()
    X = 1 # also the middle of the sprite
    display = ""

    wrap_cycles = [40, 80, 120, 160, 200, 240]
    cycle = 1
    crt_pos = 0
    wait_cycle = False
    while cycle <= 240:
        # during cycle - draw pixel
        if crt_pos > 39:
            crt_pos %= 40

        if X - 1 == crt_pos or X == crt_pos or X + 1 == crt_pos:
            display += '#'
        else:
            display += '.'

        # after cycle
        if wait_cycle:
            X += int(program_copy[0].split()[1])
            program_copy.pop(0)
            wait_cycle = False
        else:
            if program_copy[0] != "noop":
                wait_cycle = True
            else:
                program_copy.pop(0)

        if cycle in wrap_cycles:
            display += '\n'

        cycle += 1
        crt_pos += 1

    return display

print(f"Part 1: {part1()}")
print(f"Part 2:\n{part2()}")


import boto3
import os

class S3PDFDownloader():

    def __init__(self, bucket_names):
        """Searching and downloading files in the specified buckets.

        Args:
            bucket_names (List):
                a list of bucket names to search
                the search orders is the same as the name orders in the list

        Examples:
            >>> downloader = S3PDFDownloader(['ai2-s2-pdfs', 'ai2-s2-pdfs-private'])
            >>> downloader.check_paper(test_sha)
            >>> res = downloader.download_paper(test_sha, 'papers/')
            >>> # res not False - Successful download returns the bucket_name
            >>> # res is False  - File not found on the s3 buckets

        """
        self.bucket_names = bucket_names
        self.s3 = boto3.client('s3')

    @staticmethod
    def _construct_prefix(paper_sha):
        return f"{paper_sha[:4]}/{paper_sha[4:]}.pdf"

    def check_paper(self, paper_sha):
        """Check if a paper sha exists in the buckets.

        Args:
            paper_sha (str): paper sha without `.pdf`

        Returns:
            [str or bool]:
                returns the bucket name if found,
                otherwise returns False.
        """
        for bucket_name in self.bucket_names:
            res = self.s3.list_objects_v2(
                Bucket=bucket_name,
                Prefix=self._construct_prefix(paper_sha),
            )
            if res['KeyCount'] > 0:
                return bucket_name

        return False

    def download_paper(self, paper_sha, save_path):
        """Download a paper from the buckets.

        Args:
            paper_sha (str): paper sha without `.pdf`

        Returns:
            [str or bool]:
                returns the bucket name if found
                and downloaded, otherwise returns False.
        """
        bucket_name = self.check_paper(paper_sha)

        if bucket_name:
            self.s3.download_file(bucket_name, self._construct_prefix(
                paper_sha), os.path.join(save_path, paper_sha+'.pdf'))

        return bucket_name


# 给定一个 n × n 的二维矩阵表示一个图像。
#
#  将图像顺时针旋转 90 度。
#
#  说明：
#
#  你必须在原地旋转图像，这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
#
#  示例 1:
#
#  给定 matrix =
# [
#   [1,2,3],
#   [4,5,6],
#   [7,8,9]
# ],
#
# 原地旋转输入矩阵，使其变为:
# [
#   [7,4,1],
#   [8,5,2],
#   [9,6,3]
# ]
#
#
#  示例 2:
#
#  给定 matrix =
# [
#   [ 5, 1, 9,11],
#   [ 2, 4, 8,10],
#   [13, 3, 6, 7],
#   [15,14,12,16]
# ],
#
# 原地旋转输入矩阵，使其变为:
# [
#   [15,13, 2, 5],
#   [14, 3, 4, 1],
#   [12, 6, 8, 9],
#   [16, 7,10,11]
# ]
#
#  Related Topics 数组
#  👍 560 👎 0

# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 顺时针旋转90度
        # 先转置矩阵，然后翻转每一行
        size = len(matrix[0])
        for i in range(size):
            for j in range(i,size):
                matrix[j][i], matrix[i][j] = matrix[i][j], matrix[j][i]

        # 翻转每一行
        for i in range(size):
            matrix[i].reverse()


# Solution using double BFS
class Solution:
    def findLadders(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: List[List[str]]
        """

        def construct_paths(source, dest, tree):
            if source == dest:
                return [[source]]
            return [[source] + path for succ in tree[source]
                                    for path in construct_paths(succ, dest, tree)]

        def add_path(tree, word, neigh, is_forw):
            if is_forw: tree[word]  += neigh,
            else:       tree[neigh] += word,

        def bfs_level(this_lev, oth_lev, tree, is_forw, words_set):
            if not this_lev: return False
            if len(this_lev) > len(oth_lev):
                return bfs_level(oth_lev, this_lev, tree, not is_forw, words_set)
            for word in (this_lev | oth_lev):
                words_set.discard(word)
            next_lev, done = set(), False
            while this_lev:
                word = this_lev.pop()
                for c in string.ascii_lowercase:
                    for index in range(len(word)):
                        neigh = word[:index] + c + word[index+1:]
                        if neigh in oth_lev:
                            done = True
                            add_path(tree, word, neigh, is_forw)
                        if not done and neigh in words_set:
                            next_lev.add(neigh)
                            add_path(tree, word, neigh, is_forw)
            return done or bfs_level(next_lev, oth_lev, tree, is_forw, words_set)

        if endWord not in wordList:
            return []
        tree, path, paths = collections.defaultdict(list), [beginWord], []
        is_found = bfs_level(set([beginWord]), set([endWord]), tree, True, set(wordList))
        return construct_paths(beginWord, endWord, tree)


"""
"============================================================================
"File:        aws_dl.py
"Description: Python aws ocumentation reader (under development).
"Author: Marcin Katulski ( marcin.katulski@gmail.com )
"
"============================================================================
"""
import re
import codecs
import urllib
from bs4 import BeautifulSoup

class DownloadDoc:
    def __init__(self, url, doc,  proxy={} ):
        self._url = url
        self._doc = doc
        self._proxy = proxy
        self._linkList = {}

    def downloadList( self, fname ):
        print("Downloading: .... {0}".format(self._url+self._doc))
        self._site = urllib.urlopen( self._url+self._doc, proxies=self._proxy )
        html = self._site.read()
        self._listSoup = BeautifulSoup( html )
        print("Searching list of types ...")
        div = self._listSoup.find_all("div",{"class":"highlights"})

        if len(div)==1:
            print("Processing types ...")
            refList = div[0].find_all("a")

            for i in refList:
                 if i.text!="AWS::CloudFormation::Init":
                    if i.attrs.has_key("href"):
                        print("{0}".format(i.text))
                    self._linkList[ i.text ]={}
                    site = urllib.urlopen( self._url+i.attrs["href"],
                            proxies=self._proxy )
                    text = site.read()
                    sp = BeautifulSoup( text )
                    dvs = sp.find_all("div",{"class":"section"})
                    p = dvs[0].findChildren("p", recursive=False)
                    self._linkList[ i.text ]["doc"] =""
                    for j in p:
                        self._linkList[ i.text ]["doc"] += re.sub("[\"']", " ",
                                j.text+"\\n")
                    hr=dvs[0].findChildren("div",{"class":"section"})
                    self._linkList[ i.text ]["properties"] = {}
                    if len(hr)==0:
                        continue
                    hr=hr[0].find_all("a")
                    for prop in hr:
                        if self._linkList[i.text]["properties"].has_key(
                                prop.text ):
                            continue
                        if re.match('\w+\s+', prop.text  )is not None:
                            continue
                        "Try to load description for parameters"
                        dvsx = dvs[0].find_all("div", {"class":"variablelist"})
                        term = ""
                        for xvsd in dvsx:
                           span= xvsd.find_all("span", {"class":"term"}, text=prop.text)
                           if len(span) !=0:
                               term=span[0].findParent().findNextSibling()
                               break
                        self._linkList[ i.text
                                ]["properties"][prop.text]=re.sub("[\"']"," ",
                                        re.sub("<.*?>","",re.sub("</p>",'\\n',"{0}".format(term))))

            with codecs.open(fname, "wb" , encoding='utf8' ) as file:
                file.write("let g:AWSTypes=")
                s=str(self._linkList)
                s=re.sub("'", '"',s)
                s=re.sub("u\"","\"",s)
                file.write(s)

if __name__ == "__main__":
    doc = DownloadDoc("http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/","aws-template-resource-type-ref.html")
    doc.downloadList( "./AWSTypes.vim" )


# 연습문제 19. BMI 계산기 BMI Calculator

weight = float(input("How many kilograms do you weigh? "))
height = float(input("How tall are you in meters? "))

bmi = weight / (height * height)

health_guide = ""

if bmi < 18.5:
	health_guide += "underweight. You should see your doctor."
elif bmi >= 18.5 and bmi < 25:
	health_guide += "within the ideal weight range."
elif bmi >= 25:
	health_guide += "overweight. You should see your doctor."

print("Your BMI is {}\nYou are {}".format(bmi, health_guide))


from random import random

def main():
    printIntro()
    probA , porbB , n = getInputs()
    winsA , winsB = simNGame(n,probA, porbB)
    printSummary(n,winsA, winsB)

def printIntro():
    print("This progra sumulate a game of racquetball between two")
    print("player called A and B , the ability of each other is")
    print("indicated by a probability that")
    print("The player wins the point when serving, Player A always")
    print("has the first serve.")
def getInputs():
    a = eval(input("What is the prob player A wins  a serve?"))
    b = eval(input("What is the prob player B wins  a serve?"))
    n = eval(input("How many game to simulate ?"))
    return a, b ,n

def simNGame(n,probA, porbB):

    winsA =0
    winsB = 0

    for i in range(n):
        scoreA ,scoreB = simOneGame(probA, porbB)
        if scoreA > scoreB:
            winsA = winsA + 1
        else:
            winsB = winsB + 1

    return winsA , winsB

#Simulate a single game
def simOneGame(probA, probB):
    serving = "A"
    scoreA = 0
    scoreB = 0

    while not gameOver(scoreA, scoreB):
        if serving == "A":
            if random() < probA:
                scoreA = scoreA + 1
            else:
                serving = "B"

        else :
            if random() < probB:
                scoreB = scoreB + 1
            else:
                serving = "A"
    return scoreA ,scoreB

def gameOver(a,b) :
    return a == 15 or b ==  15

def printSummary(n,winsA, winsB):

    print("Games simulation {}".format(n))
    print("Wins for A :{0},{1:0.1%}".format(winsA, winsA/n))
    print("Wins for B :{0},{1:0.1%}".format(winsB, winsB/n))


import matplotlib.pyplot as plt
import numpy as np
from IPython.display import Audio, display
import soundfile as sf

import librosa
import parselmouth
from parselmouth import praat

from os import listdir
from os.path import isfile, join
import re

def plot_specgram_from_wave(waveform, sample_rate, title="Spectrogram", xlim=None):
    waveform = waveform.numpy()

    num_channels, num_frames = waveform.shape

    figure, axes = plt.subplots(num_channels, 1)
    if num_channels == 1:
        axes = [axes]
    for c in range(num_channels):
        axes[c].specgram(waveform[c], Fs=sample_rate)
        if num_channels > 1:
            axes[c].set_ylabel(f'Channel {c+1}')
        if xlim:
            axes[c].set_xlim(xlim)
    figure.suptitle(title)
    plt.show(block=False)

def plot_specgram(spec, sample_rate, title="Spectrogram", xlim=None):
    num_freq, num_frames = spec.shape
    time_axis = np.arange(0, num_frames) / num_frames
    freq_axis = np.arange(0, num_freq) * sample_rate/2/num_freq
    figure, axes = plt.subplots(1, 1)
    axes.pcolormesh(time_axis, freq_axis, spec[:, :], cmap='viridis')
    axes.set_xlim(xlim)
    figure.suptitle(title)
    plt.show(block=False)

def plot_waveform(waveform, sample_rate, title="Waveform", xlim=None, ylim=None):
    waveform = waveform.numpy()

    num_channels, num_frames = waveform.shape
    time_axis = np.arange(0, num_frames) / sample_rate

    figure, axes = plt.subplots(num_channels, 1)
    if num_channels == 1:
        axes = [axes]
    for c in range(num_channels):
        axes[c].plot(time_axis, waveform[c], linewidth=1)
        axes[c].grid(True)
        if num_channels > 1:
            axes[c].set_ylabel(f'Channel {c+1}')
        if xlim:
            axes[c].set_xlim(xlim)
        if ylim:
            axes[c].set_ylim(ylim)
    figure.suptitle(title)
    plt.show(block=False)

def print_stats(waveform, sample_rate=None, src=None):
    if src:
        print("-" * 10)
        print("Source:", src)
        print("-" * 10)
    if sample_rate:
        print("Sample Rate:", sample_rate)
    print("Shape:", tuple(waveform.shape))
    print("Dtype:", waveform.dtype)
    print(f" - Max:     {waveform.max().item():6.3f}")
    print(f" - Min:     {waveform.min().item():6.3f}")
    print(f" - Mean:    {waveform.mean().item():6.3f}")
    print(f" - Std Dev: {waveform.std().item():6.3f}")
    print()
    print(waveform)
    print()

def play_audio(waveform, sample_rate):
    waveform = waveform.numpy()

    num_channels, num_frames = waveform.shape
    if num_channels == 1:
        display(Audio(waveform[0], rate=sample_rate))
    elif num_channels == 2:
        display(Audio((waveform[0], waveform[1]), rate=sample_rate))
    else:
        raise ValueError(
            "Waveform with more than 2 channels are not supported.")

# Features extraction

def specToAudio(x):
    return librosa.core.spectrum.griffinlim(x)  # to test

def f0(sound, gender):
    '''
    Measure voice pitch
    '''
    if gender == 'male':
        f0min = 50
        f0max = 200

    else:
        f0min = 150
        f0max = 350

    # create a praat pitch object
    pitch = praat.call(sound, "To Pitch", 0.0, f0min, f0max)
    pitch_values = pitch.selected_array['frequency']

    return pitch_values

def f0_array(x_train, gender):
    f0_list = []  # list of list, since pitch_values is a list
    for i in range(x_train.shape[0]):
        pitch_values = f0(x_train[i], gender)
        f0_list.append(pitch_values)

    return np.array(f0_list)

def extract_formants(sound, gender):
    '''
    Extract 3 first formants with Praat's functions thanks to Python's parselmouth
    '''
    time_step = 0  # time between the centres of consecutive analysis frames
    max_nb_formants = 5  # number of formants extracted per frame
    # formant_ceiling: maximum frequency of the formant search range, in Hertz
    window_length = 0.025  # duration of the analysis window (s)
    pre_emphasis = 50

    if gender == 'male':
        f0min = 75
        f0max = 600
        # An average adult male speaker has a vocal tract length that requires an average ceiling of 5000 Hz
        formant_ceiling = 5000

    else:  # gender == 'female'
        f0min = 75
        f0max = 600
        # An average adult female speaker has a vocal tract length that requires an average ceiling of 5500 Hz
        formant_ceiling = 5500

    # First, compute the occurrences of periodic instances in the signal:
    pointProcess = praat.call(
        sound, "To PointProcess (periodic, cc)", f0min, f0max)

    # Then, compute the formants:
    formants = praat.call(sound, "To Formant (burg)", time_step,
                          max_nb_formants, formant_ceiling, window_length, pre_emphasis)

    # And finally assign formant values with times where they make sense (periodic instances):
    numPoints = praat.call(pointProcess, "Get number of points")
    f1_list = []
    f2_list = []
    f3_list = []
    for point in range(0, numPoints):
        point += 1
        t = praat.call(pointProcess, "Get time from index", point)
        f1 = praat.call(formants, "Get value at time", 1, t, 'Hertz', 'Linear')
        f2 = praat.call(formants, "Get value at time", 2, t, 'Hertz', 'Linear')
        f3 = praat.call(formants, "Get value at time", 3, t, 'Hertz', 'Linear')
        f1_list.append(f1)
        f2_list.append(f2)
        f3_list.append(f3)

    # # Create a matrix of formants
    # formant_tuple = (np.array(f1_list), np.array(f2_list), np.array(f3_list))
    # formants = np.vstack(formant_tuple)
    # # We should check that nan values appear in the same places
    # formants = formants[~np.isnan(formants)]

    frt = f1_list + f2_list + f3_list

    return np.array(frt), numPoints

def formants_array(x_train, gender):
    formants_list = []  # list of list, since pitch_values is a list
    for i in range(x_train.shape[0]):
        formants_list.append(extract_formants(x_train[i], gender))

    return np.array(formants_list)


# -*- coding: utf-8 -*-
"""
Created on Sun Jun 21 13:28:00 2020

@author: Matador
"""

import os

cwd = os.getcwd()
cwd = cwd[0:len(cwd) - 11]
os.chdir(cwd)

from import_data import get, coeff
from sklearn.model_selection import train_test_split,LeaveOneOut,KFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import confusion_matrix
from sklearn import metrics
import matplotlib.pyplot as plt
import numpy as np

#%% mostrar el rendimiento del sistema
if not os.path.exists('resultados/knn'):
    os.makedirs('resultados/knn')
data, target = get('data' ,random  = 2)
for i in range(3):

    random = i
    X_train, X_test, y_train, y_test = get("cross",random)
    k_range = range(1,13,2)
    acc = []
    acc1 = []
    print(i)
    sens = []
    pre =[]
    for j in k_range:

        knn = KNeighborsClassifier(n_neighbors = j)
        knn.fit(X_train,y_train)

        y_pred = knn.predict(X_test)
        y_pred1 = knn.predict(X_train)

        acc.append(metrics.accuracy_score(y_pred,y_test))
        acc1.append(metrics.accuracy_score(y_pred1,y_train))
        auxs,auxp = coeff(X_test, y_test, knn)

        sens.append(auxs)
        pre.append(auxp)

    plt.figure()
    plt.title("resultado generados con knn con random state de " + str(random))
    plt.xlabel("# vecinos")
    plt.ylabel('accurency')
    plt.plot(k_range,acc)
    plt.plot(k_range,acc1)
    plt.legend(["test","training"])
    plt.show()

    plt.savefig('resultados/knn/knn_resul '+ str(random) +' .png')

    plt.figure()
    plt.plot(k_range,sens)
    plt.plot(k_range,pre)
    plt.title('sensibilidad y especifidad con random ' +str(random))
    plt.xlabel('# vecinos')
    plt.show()
    plt.legend(['sensibilidad','especificidad'])
    plt.savefig('resultados/knn/knn_seesp '+ str(random) +' .png')

    plt.close('all')