# PROGRAM sort_array_of_0s_1s_2s:

'''
You are given an integer array containing only 0s, 1s and 2s. Write a solution to sort this array using one scan only.

You need to change in the given array itself. So no need to return or print anything.

Input format:
Line 1 : Integer n (Array Size)
Line 2 : Array elements (separated by space)

Output Format:
Updated array elements (separated by space)

Constraints :
1 <= n <= 10^6

Sample Input:
7
0 1 2 0 2 0 1

Sample Output:
0 0 0 1 1 2 2
'''

#####################################
# Sort Array of 0s 1s and 2s Module #
#####################################

def sort_array_of_0s_1s_2s(arr):
	i, next_zero, next_two = 0, 0, len(arr) - 1
	while i <= next_two:
	# DO
		if arr[i] == 0:
		# THEN
			arr[next_zero], arr[i] = arr[i], arr[next_zero]
			next_zero = next_zero + 1
			i = i + 1
		elif arr[i] == 2:
		# THEN
			arr[next_two], arr[i] = arr[i], arr[next_two]
			next_two = next_two - 1
		else:
			i = i + 1
		# ENDIF;
	# ENDWHILE;
# END sort_array_0s_1s_2s.

################
# Main Program #
################

n = int(input("Input the size of array (or list): \n"))
arr = [int(x) for x in input("Input the elements of array (or list, separated by space): \n").split()]
sort_array_of_0s_1s_2s(arr)
print(*arr)
# END.


# imports:
import os
import sys
import copy
import json
import subprocess

# constants:
TITLE = """
███████╗██╗    ██╗██╗████████╗ ██████╗██╗  ██╗███████╗██████╗
██╔════╝██║    ██║██║╚══██╔══╝██╔════╝██║  ██║██╔════╝██╔══██╗
███████╗██║ █╗ ██║██║   ██║   ██║     ███████║█████╗  ██████╔╝
╚════██║██║███╗██║██║   ██║   ██║     ██╔══██║██╔══╝  ██╔══██╗
███████║╚███╔███╔╝██║   ██║   ╚██████╗██║  ██║███████╗██║  ██║
╚══════╝ ╚══╝╚══╝ ╚═╝   ╚═╝    ╚═════╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝
"""

BUFFER_SIZE = 32
TYPING_DILAY = 0.05

file_path = sys.argv[0]
WORK_DIR = file_path[:len(file_path) - file_path[::-1].find('/')]

with open(os.path.join(WORK_DIR, 'run.command')) as f:
    lines = f.readlines()

PRIME_TYPING_CHANGE_ACTIVATION = [c for c in \
                                  lines[0][lines[0].find("'") + 1: len(lines[0]) - lines[0][::-1].find("'") - 1]]

ACTIVATION_SIZE = len(PRIME_TYPING_CHANGE_ACTIVATION)

CONFIG_JSON_PATH = os.path.join(WORK_DIR, 'language_config.json')
CONVERSION_JSON_PATH = os.path.join(WORK_DIR, 'conversion_chart_ABC_Hebrew.json')

LAYOUT_RETURN_PREFIX = '"KeyboardLayout Name" = '
LAYOUT_RETURN_POSTFIX = ';\n    }\n)'

# apple scripts:
CHANGE_LANGUAGE_SCRIPT = "osascript -e 'tell application \"System Events\" to tell process \"SystemUIServer\" to " \
                         "keystroke space using {control down}' "

GET_CURRENT_LAYOUT_SCRIPT = "defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleSelectedInputSources"

GET_ACTIVE_WINDOW_SCRIPT = "osascript -e 'tell app \"System Events\" to get name of first process whose frontmost is " \
                           "true' "

# functions:
def load_json(path):
    """
    Load a json file.
    :param path: the path to the json file.
    :return: the json file as a dict.
    """
    with open(path) as f:
        return json.load(f)

MAIN_LAYOUT, SECONDARY_LAYOUT = list(load_json(CONVERSION_JSON_PATH).keys())
CONVERSION_PAIRS = load_json(CONVERSION_JSON_PATH)

def run_script(script):
    """
    Run a script and return the output.
    :param script: applescript string to run.
    :return: the output from the activation.
    """
    return subprocess.check_output(script, shell=True).decode('utf-8').strip()

def get_current_layout():
    """
    Get the current keyboard layout.
    :return: the current keyboard layout.
    """

    current_layout = run_script(GET_CURRENT_LAYOUT_SCRIPT)
    return current_layout[current_layout.find(LAYOUT_RETURN_PREFIX) + len(LAYOUT_RETURN_PREFIX):
                          current_layout.find(LAYOUT_RETURN_POSTFIX)]

def convert_typing(layout, stack):
    """
    Convert the typing from one language to another.
    :param stack: text to convert as a list.
    :param layout: current keyboard language.
    :return: the converted text.
    """
    if layout != MAIN_LAYOUT and layout != SECONDARY_LAYOUT:
        return copy.deepcopy(stack)
    else:
        return [CONVERSION_PAIRS[layout][key] if key in CONVERSION_PAIRS[layout] else key
                for key in stack]

SECONDARY_TYPING_CHANGE_ACTIVATION = convert_typing(MAIN_LAYOUT, PRIME_TYPING_CHANGE_ACTIVATION)

def start_message():
    print(TITLE)
    print('=' * 65)
    print(' ' * 25,  'Activities log:')
    print('=' * 65)
    print()


uniform_dist = [0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03]
linear_dist = [0.0525, 0.0475, 0.0425, 0.0375, 0.0325, 0.0275, 0.0225, 0.0175, 0.0125, 0.0075]
plateau_dist = [.30, 0, 0, 0, 0, 0, 0, 0, 0, 0]

r_cadence = 52
r_size = 6
c_size = 1000
c_growth = 2
power_dist = [.20, .133, .0889, .059260, .03951, .02634, .017559, .011706, .007804, .005203, .003468, .002312, .001542, .001028, .000685, .000457, .000305, .000203, .000135, .000090]

import random

def rotate_simulation(dist, r_cadence, r_size, c_size, c_growth, spread, method):

    catalog = add_items([], 0, dist, c_size, spread)
    catalog = rank_items(catalog, method)
    index = c_size

    total_sold = 0
    for _ in range(r_cadence):
        for item in catalog[0:r_size]:
            if random.random() <= item[2]:
                catalog.remove(item)
                total_sold += 1
        catalog = add_items(catalog, index, dist, c_growth, spread)
        index += c_growth
        catalog = rank_items(catalog, method)

    return total_sold

def rank_items(catalog, method):
    if method == "random":
        random.shuffle(catalog)
    elif method == "popular":
        catalog.sort(key=lambda x: x[1], reverse=True)
    elif method == "personal":
        catalog.sort(key=lambda x: x[2], reverse=True)

    return catalog

def add_items(catalog, index, dist, number, spread):
    q, r = divmod(number, len(dist))
    new_items = q*dist + random.sample(dist, r)
    catalog.extend([(index + i, x, x + x*(2*random.random()-1)*spread)
                     for i, x in enumerate(new_items)])

    return catalog


# -*- coding: utf-8 -*-
import re
import pandas as pd

f = open('C:\\Users\\Tariq\\Dropbox (MIT)\\Projects\\3. ITS\\Tweet Topics-Demographics Corr\\all.txt','rb')
gTweets = f.readlines()

gText, lat, lon = [], [], []
for tweet in gTweets:
    gText.append(tweet.decode('utf-8').split('"text": "')[1].split('", "place":')[0])
    lat.append(str(tweet).split('"coordinates": [ ')[1].split(',')[0])
    lon.append(str(tweet).split('"coordinates": [ ')[1].split(',')[1].split(' ]')[0][1:])

time = []
for tweet in gTweets:
    time.append(str(tweet).split('"created_at": "')[1].split('"')[0])

day,month,day_type,time_of_day = [],[],[],[]
for t in time:
    row = t.split()
    day.append(row[0])
    month.append(row[1])
    day_type.append('wkend' if row[0] in ('Thu','Fri','Sat') else 'wkday')
    hour = int(row[3].split(':')[0])
    time_of_day.append('morning' if hour in range(6,12) else 'afternoon' if hour in range(12,18) else 'evening' if hour in range(18,24) else 'early_morning')

temporal_features = pd.DataFrame({'day':day, 'month':month, 'day_type':day_type, 'time_of_day':time_of_day})
# preprocess incoming Geotagged tweets before classifying
for i in range(0,len(gText)):
    gText[i] = gText[i].replace("ـ","")
    gText[i] = re.findall("[ء-غف-ي]+",gText[i])

# keeping words of length 3 and above!
#gText = [[token for token in text if len(token)>= 3] for text in gText]
# keeping tweets with more than 5 words
#gText = [text for text in gText if len(text) > 4]

f2 = open('tweets.txt','wb')
for text in gText:
    f2.write(text.encode('utf-8'))
    f2.write('\n')

Topic Modeling/City Vibes-Correlation with Demographics/preProcessing.py


from collections import OrderedDict
import torch
import torch.nn as nn
import torch.nn.functional as F

""" Skip Connection """

class AdditiveConnection(nn.Module):
    def __init__(self, channel):
        super().__init__()

    def forward(self, x, y):
        return x + y

class ConcatSkipConnection(nn.Module):
    def __init__(self, channel):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv3d(channel * 2, channel, 3, 1, 1),
        )

    def forward(self, x, y):
        return self.conv(torch.cat([x, y], dim=1))

class AdaptiveSkipConnection(nn.Module):
    def __init__(self, channel):
        super().__init__()
        self.conv_weight = nn.Sequential(
            nn.Conv3d(channel * 2, channel, 1),
            nn.Tanh(),
            nn.Conv3d(channel, channel, 3, 1, 1),
            nn.Sigmoid()
        )

    def forward(self, x, y):
        w = self.conv_weight(torch.cat([x, y], dim=1))
        return (1 - w) * x + w * y

""" Channel Attention """

class GlobalAvgPool3d(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        sum = torch.sum(x, dim=(2, 3, 4), keepdim=True)
        return sum / (x.shape[2] * x.shape[3] * x.shape[4])

class SimplifiedChannelAttention(nn.Module):
    def __init__(self, ch):
        super().__init__()
        self.sca = nn.Sequential(
            # nn.AdaptiveAvgPool3d(1),
            GlobalAvgPool3d(),
            nn.Conv3d(ch, ch, kernel_size=1),
            nn.Sigmoid()
        )

    def forward(self, x):
        return self.sca(x) * x

class ChannelAttention(nn.Module):
    def __init__(self, ch):
        super().__init__()
        self.ca = nn.Sequential(
            GlobalAvgPool3d(),
            nn.Conv3d(ch, ch, kernel_size=1),
            nn.ReLU(),
            nn.Conv3d(ch, ch, kernel_size=1),
            nn.Sigmoid()
        )

    def forward(self, x):
        return self.ca(x) * x

""" Mixed Attention Block """

class PositionwiseFeedForward(nn.Module):
    "Implements FFN equation."

    def __init__(self, channel):
        super(PositionwiseFeedForward, self).__init__()
        self.w_1 = nn.Conv3d(channel, channel, kernel_size=1)
        self.w_2 = nn.Conv3d(channel, channel, kernel_size=1)

    def forward(self, x):
        return self.w_2(torch.tanh(self.w_1(x)))

class MAB(nn.Module):
    def __init__(self, channels, enable_ca=True, reverse=False):
        super(MAB, self).__init__()
        self.channels = channels
        self.enable_ca = enable_ca
        self.reverse = reverse
        self.sca = SimplifiedChannelAttention(channels)
        self.ffn_f = PositionwiseFeedForward(channels)
        self.ffn_w = PositionwiseFeedForward(channels)

    def _rnn_step(self, z, f, h):
        h_ = (1 - f) * z if h is None else f * h + (1 - f) * z
        return h_

    def forward(self, inputs):
        h = None
        Z = self.ffn_f(inputs).tanh()
        F = self.ffn_w(inputs).sigmoid()
        h_time = []

        if not self.reverse:
            for time, (z, f) in enumerate(zip(Z.split(1, 2), F.split(1, 2))):
                h = self._rnn_step(z, f, h)
                h_time.append(h)
        else:
            for time, (z, f) in enumerate((zip(
                reversed(Z.split(1, 2)), reversed(F.split(1, 2))
            ))):
                h = self._rnn_step(z, f, h)
                h_time.insert(0, h)

        out = torch.cat(h_time, dim=2)
        if self.enable_ca:
            out = self.sca(out)
        return out

class BiMAB(MAB):
    def __init__(self, channels, enable_ca=True):
        super().__init__(channels, enable_ca, None)
        self.ffn_w2 = PositionwiseFeedForward(channels)

    def forward(self, inputs):
        Z = self.ffn_f(inputs).tanh()
        F1 = self.ffn_w(inputs).sigmoid()
        F2 = self.ffn_w2(inputs).sigmoid()

        h = None
        hsl = []
        hsr = []
        zs = Z.split(1, 2)

        for time, (z, f) in enumerate(zip(zs, F1.split(1, 2))):
            h = self._rnn_step(z, f, h)
            hsl.append(h)

        h = None
        for time, (z, f) in enumerate((zip(reversed(zs), reversed(F2.split(1, 2))))):
            h = self._rnn_step(z, f, h)
            hsr.insert(0, h)

        hsl = torch.cat(hsl, dim=2)
        hsr = torch.cat(hsr, dim=2)

        out = hsl + hsr
        if self.enable_ca:
            out = self.sca(out)
        return out

""" Mixed Attention Network """

class Encoder(nn.Module):
    def __init__(self, channels, num_half_layer, sample_idx, Attn=None):
        super(Encoder, self).__init__()
        self.layers = nn.ModuleList()
        for i in range(num_half_layer):
            if i not in sample_idx:
                encoder_layer = nn.Sequential(OrderedDict([
                    ('conv', nn.Conv3d(channels, channels, 3, 1, 1, bias=False)),
                    ('attn', Attn(channels, reverse=i % 2 == 1)) if Attn else None
                ]))
            else:
                encoder_layer = nn.Sequential(OrderedDict([
                    ('conv', nn.Conv3d(channels, channels * 2, 3, (1, 2, 2), 1, bias=False)),
                    ('attn', Attn(channels * 2, reverse=i % 2 == 1)) if Attn else None
                ]))
                channels *= 2
            self.layers.append(encoder_layer)

    def forward(self, x, xs):
        num_half_layer = len(self.layers)
        for i in range(num_half_layer - 1):
            x = self.layers[i](x)
            xs.append(x)
        x = self.layers[-1](x)
        return x

class Decoder(nn.Module):
    def __init__(self, channels, num_half_layer, sample_idx, Fusion=None, Attn=None):
        super(Decoder, self).__init__()

        self.layers = nn.ModuleList()
        self.enable_fusion = Fusion is not None

        if self.enable_fusion:
            self.fusions = nn.ModuleList()
            ch = channels
            for i in reversed(range(num_half_layer)):
                fusion_layer = Fusion(ch)
                if i in sample_idx:
                    ch //= 2
                self.fusions.append(fusion_layer)

        for i in reversed(range(num_half_layer)):
            if i not in sample_idx:
                decoder_layer = nn.Sequential(OrderedDict([
                    ('conv', nn.ConvTranspose3d(channels, channels, 3, 1, 1, bias=False)),
                    ('attn', Attn(channels, reverse=i % 2 == 0)) if Attn else None
                ]))
            else:
                decoder_layer = nn.Sequential(OrderedDict([
                    ('up', nn.Upsample(scale_factor=(1, 2, 2), mode='trilinear', align_corners=True)),
                    ('conv', nn.Conv3d(channels, channels // 2, 3, 1, 1, bias=False)),
                    ('attn', Attn(channels // 2, reverse=i % 2 == 0)) if Attn else None
                ]))
                channels //= 2
            self.layers.append(decoder_layer)

    def forward(self, x, xs):
        num_half_layer = len(self.layers)
        x = self.layers[0](x)
        for i in range(1, num_half_layer):
            if self.enable_fusion:
                x = self.fusions[i](x, xs.pop())
            else:
                x = x + xs.pop()
            x = self.layers[i](x)
        return x

class MAN(nn.Module):
    def __init__(
        self,
        in_channels=1,
        channels=16,
        num_half_layer=5,
        sample_idx=[1, 3],
        Attn=MAB,
        BiAttn=BiMAB,
        Fusion=AdaptiveSkipConnection,
    ):
        super(MAN, self).__init__()

        self.head = nn.Sequential(
            nn.Conv3d(in_channels, channels, 3, 1, 1, bias=False),
            BiAttn(channels) if BiAttn else None
        )

        self.encoder = Encoder(channels, num_half_layer, sample_idx, Attn)
        self.decoder = Decoder(channels * (2**len(sample_idx)), num_half_layer, sample_idx,
                               Fusion=Fusion, Attn=Attn)

        self.tail = nn.Sequential(
            nn.ConvTranspose3d(channels, in_channels, 3, 1, 1, bias=True),
            BiAttn(in_channels) if BiAttn else None
        )

    def forward(self, x):
        xs = [x]
        out = self.head(xs[0])
        xs.append(out)
        out = self.encoder(out, xs)
        out = self.decoder(out, xs)
        out = out + xs.pop()
        out = self.tail(out)
        out = out + xs.pop()
        return out

""" Model Variants """

def man():
    net = MAN(1, 16, 5, [1, 3])
    net.use_2dconv = False
    net.bandwise = False
    return net

def man_m():
    net = MAN(1, 12, 5, [1, 3])
    net.use_2dconv = False
    net.bandwise = False
    return net

def man_s():
    net = MAN(1, 8, 5, [1, 3])
    net.use_2dconv = False
    net.bandwise = False
    return net

def man_b():
    net = MAN(1, 24, 5, [1, 3])
    net.use_2dconv = False
    net.bandwise = False
    return net

def man_deep():
    net = MAN(1, 16, 7, [1, 3, 5])
    net.use_2dconv = False
    net.bandwise = False
    return net

""" Baseline """

def baseline():
    net = MAN(1, 16, 5, [1, 3], Attn=None, BiAttn=None, Fusion=None)
    net.use_2dconv = False
    net.bandwise = False
    return net


from django.db import models
from exploreuser.models import ExUser
from django.template.defaultfilters import slugify
from datetime import datetime, timezone

# Create your models here.
class Post(models.Model):
	user = models.ForeignKey(ExUser, on_delete=models.CASCADE)
	title = models.CharField(max_length=50)
	describtion = models.TextField()
	timestamp = models.DateTimeField(auto_now=True)

def get_image_path(instance, filename):
	user = instance.post.user
	title = instance.post.title
	slug = slugify(title)

	return "post_images/%s/%s-%s"%(user, slug, filename)

class PostImages(models.Model):
	post = models.ForeignKey(Post, on_delete=models.CASCADE, default=None)
	image = models.ImageField(upload_to=get_image_path, verbose_name='Image')

class Hashtags(models.Model):
	tag = models.CharField(max_length=32, unique=True)
	post = models.ManyToManyField(Post)

class Comments(models.Model):
	user = models.ForeignKey(ExUser, on_delete=models.CASCADE)
	text = models.CharField(max_length=200)
	on_post = models.ForeignKey(Post, on_delete=models.CASCADE)
	added_time = models.DateTimeField(auto_now_add=True)

	class Meta:
		ordering = ['added_time']

	def diff_time(self):
		now = datetime.now(timezone.utc)
		diff = now - self.added_time
		diff_in_sec = diff.total_seconds()

		if diff_in_sec < 60:
			td = 'Just now'
		elif diff_in_sec >= 60 and diff_in_sec < 3600:
			minute = divmod(diff_in_sec, 60)[0]

			if minute > 1:
				td = '%d minutes ago'%(minute)
			else:
				td = '1 minute ago'

		elif diff_in_sec >= 3600 and diff_in_sec < 86400:
			hours = divmod(diff_in_sec, 3600)[0]

			if hours > 1:
				td = '%d hours ago'%(hours)
			else:
				td = '1 hour ago'

		elif diff_in_sec >= 86400 and diff_in_sec < 604800:
			days = divmod(diff_in_sec, 86400)[0]

			if days > 1:
				td = '%d days ago'%(days)
			else:
				td = '1 day ago'

		else:
			td = self.added_time.strftime('%d %b, %Y')

		return td

class PostRating(models.Model):
	post = models.ForeignKey(Post, on_delete=models.CASCADE)
	user = models.ForeignKey(ExUser, on_delete=models.CASCADE)
	rating = models.IntegerField(null=True)

class PostHit(models.Model):
	max_permitted_hit = 20
	post = models.ForeignKey(Post, on_delete=models.CASCADE)
	hits = models.IntegerField(default=0)
	user = models.ForeignKey(ExUser, on_delete=models.CASCADE)
	last_viewed = models.DateTimeField(auto_now=True)


from core.exceptions import ErrorWhenParsing
from misc.constants import (OPENING_BRACKET, EJF_FOUND_BUFFERS, CLOSING_BRACKET, OPENING_BRACE,
                      CLOSING_BRACE, EJF_NO_BUFFERS_FOUND)
class EventJsonFormat:
    def __init__(self):
        self.event_json = None
        self.sender = None

    def get_event_json(self):
        return self.event_json

    def get_sender(self):
        return self.sender

    def _parse_line_with_event_json_format(self, line_with_event_json_format):
        # Skip first the characters
        line_with_event_json_format = line_with_event_json_format[3:]
        index_of_opening_bracket = line_with_event_json_format.index(OPENING_BRACKET)
        index_of_closing_bracket = line_with_event_json_format.index(CLOSING_BRACKET)
        index_of_opening_brace = line_with_event_json_format.index(OPENING_BRACE)
        index_of_closing_brace = line_with_event_json_format.index(CLOSING_BRACE)

        self.sender = line_with_event_json_format[index_of_opening_bracket+1:index_of_closing_bracket]
        self.event_json = line_with_event_json_format[index_of_opening_brace:index_of_closing_brace+1]

    def parse(self,event_json_format_data):
        """
            (WmiTrace) LogDump for Logger Id 0x21
            Reading Buffer   1 /   4
            Reading Buffer   2 /   4
            Reading Buffer   3 /   4
            Reading Buffer   4 /   4
            Found Buffers: 4 Messages: 2, sorting entries
            [0]0AB4.0AF4::  131804496926295220 [Microsoft-Windows-Shell-NotificationCenter/ActionCenterButtonStateOnLaunching/]{"messageState": 0, "notificationState": 1}
            Total of 2 Messages from 4 Buffers
        """
        line_with_event_json_format = ""
        index = 0
        index_of_found_buffers = -1
        for line in event_json_format_data.split("\n"):
            if EJF_FOUND_BUFFERS in line.lower():
                index_of_found_buffers = index
                break
            elif EJF_NO_BUFFERS_FOUND in line.lower():
                self.sender = "<NO_DATA_FOUND>"
                self.event_json = "<NO_DATA_FOUND>"
                return
            else:
                index += 1
        if index_of_found_buffers == -1:
            raise ErrorWhenParsing("\" Found buffers\" wasn't found in the Json event format provided: {}".format(event_json_format_data))
        line_with_event_json_format = event_json_format_data.split("\n")[index_of_found_buffers+1]

        self._parse_line_with_event_json_format(line_with_event_json_format)

    def __str__(self):
        output = ""
        for key, value in self.__dict__.items():
            output += "{}: {}\n".format(key,value)
        return output


import pickle
from io import BytesIO
from unittest import TestCase

import numpy as np
from numpy.testing import assert_array_almost_equal
from scipy import linalg
from nose.tools import assert_true

from pykalman import KalmanFilter
from pykalman.datasets import load_robot

class KalmanFilterTests(object):
    """All of the actual tests to check against an implementation of the usual
    Kalman Filter. Abstract so that sister implementations can re-use these
    tests.
    """

    def test_kalman_sampling(self):
        kf = self.KF(
            self.data.transition_matrix,
            self.data.observation_matrix,
            self.data.transition_covariance,
            self.data.observation_covariance,
            self.data.transition_offsets,
            self.data.observation_offset,
            self.data.initial_state_mean,
            self.data.initial_state_covariance)

        (x, z) = kf.sample(100)
        assert_true(x.shape == (100, self.data.transition_matrix.shape[0]))
        assert_true(z.shape == (100, self.data.observation_matrix.shape[0]))

    def test_kalman_filter_update(self):
        kf = self.KF(
            self.data.transition_matrix,
            self.data.observation_matrix,
            self.data.transition_covariance,
            self.data.observation_covariance,
            self.data.transition_offsets,
            self.data.observation_offset,
            self.data.initial_state_mean,
            self.data.initial_state_covariance)

        # use Kalman Filter
        (x_filt, V_filt) = kf.filter(X=self.data.observations)

        # use online Kalman Filter
        n_timesteps = self.data.observations.shape[0]
        n_dim_obs, n_dim_state = self.data.observation_matrix.shape
        kf2 = self.KF(n_dim_state=n_dim_state, n_dim_obs=n_dim_obs)
        x_filt2 = np.zeros((n_timesteps, n_dim_state))
        V_filt2 = np.zeros((n_timesteps, n_dim_state, n_dim_state))
        for t in range(n_timesteps - 1):
            if t == 0:
                x_filt2[0] = self.data.initial_state_mean
                V_filt2[0] = self.data.initial_state_covariance
            (x_filt2[t + 1], V_filt2[t + 1]) = kf2.filter_update(
                x_filt2[t], V_filt2[t],
                observation=self.data.observations[t + 1],
                transition_matrix=self.data.transition_matrix,
                transition_offset=self.data.transition_offsets[t],
                transition_covariance=self.data.transition_covariance,
                observation_matrix=self.data.observation_matrix,
                observation_offset=self.data.observation_offset,
                observation_covariance=self.data.observation_covariance
            )
        assert_array_almost_equal(x_filt, x_filt2)
        assert_array_almost_equal(V_filt, V_filt2)

    def test_kalman_filter(self):
        kf = self.KF(
            self.data.transition_matrix,
            self.data.observation_matrix,
            self.data.transition_covariance,
            self.data.observation_covariance,
            self.data.transition_offsets,
            self.data.observation_offset,
            self.data.initial_state_mean,
            self.data.initial_state_covariance)

        (x_filt, V_filt) = kf.filter(X=self.data.observations)
        assert_array_almost_equal(
            x_filt[:500],
            self.data.filtered_state_means[:500],
            decimal=7
        )
        assert_array_almost_equal(
            V_filt[:500],
            self.data.filtered_state_covariances[:500],
            decimal=7
        )

    def test_kalman_predict(self):
        kf = self.KF(
            self.data.transition_matrix,
            self.data.observation_matrix,
            self.data.transition_covariance,
            self.data.observation_covariance,
            self.data.transition_offsets,
            self.data.observation_offset,
            self.data.initial_state_mean,
            self.data.initial_state_covariance)

        x_smooth = kf.smooth(X=self.data.observations)[0]
        assert_array_almost_equal(
            x_smooth[:501],
            self.data.smoothed_state_means[:501],
            decimal=7
        )

    def test_kalman_fit(self):
        # check against MATLAB dataset
        kf = self.KF(
            self.data.transition_matrix,
            self.data.observation_matrix,
            self.data.initial_transition_covariance,
            self.data.initial_observation_covariance,
            self.data.transition_offsets,
            self.data.observation_offset,
            self.data.initial_state_mean,
            self.data.initial_state_covariance,
            em_vars=['transition_covariance', 'observation_covariance'])

        loglikelihoods = np.zeros(5)
        for i in range(len(loglikelihoods)):
            loglikelihoods[i] = kf.loglikelihood(self.data.observations)
            kf.em(X=self.data.observations, n_iter=1)

        assert_true(np.allclose(loglikelihoods, self.data.loglikelihoods[:5]))

        # check that EM for all parameters is working
        kf.em_vars = 'all'
        n_timesteps = 30
        for i in range(len(loglikelihoods)):
            kf.em(X=self.data.observations[0:n_timesteps], n_iter=1)
            loglikelihoods[i] = kf.loglikelihood(self.data.observations[0:n_timesteps])
        for i in range(len(loglikelihoods) - 1):
            assert_true(loglikelihoods[i] < loglikelihoods[i + 1])

    def test_kalman_initialize_parameters(self):
        self.check_dims(5, 1, {'transition_matrices': np.eye(5)})
        self.check_dims(1, 3, {'observation_offsets': np.zeros(3)})
        self.check_dims(2, 3, {'transition_covariance': np.eye(2),
                          'observation_offsets': np.zeros(3)})
        self.check_dims(3, 2, {'n_dim_state': 3, 'n_dim_obs': 2})
        self.check_dims(4, 1, {'initial_state_mean': np.zeros(4)})

    def check_dims(self, n_dim_state, n_dim_obs, kwargs):
        kf = self.KF(**kwargs)
        (transition_matrices, transition_offsets, transition_covariance,
         observation_matrices, observation_offsets, observation_covariance,
         initial_state_mean, initial_state_covariance) = (
            kf._initialize_parameters()
        )
        assert_true(transition_matrices.shape == (n_dim_state, n_dim_state))
        assert_true(transition_offsets.shape == (n_dim_state,))
        assert_true(transition_covariance.shape == (n_dim_state, n_dim_state))
        assert_true(observation_matrices.shape == (n_dim_obs, n_dim_state))
        assert_true(observation_offsets.shape == (n_dim_obs,))
        assert_true(observation_covariance.shape == (n_dim_obs, n_dim_obs))
        assert_true(initial_state_mean.shape == (n_dim_state,))
        assert_true(
            initial_state_covariance.shape == (n_dim_state, n_dim_state)
        )

    def test_kalman_pickle(self):
        kf = self.KF(
            self.data.transition_matrix,
            self.data.observation_matrix,
            self.data.transition_covariance,
            self.data.observation_covariance,
            self.data.transition_offsets,
            self.data.observation_offset,
            self.data.initial_state_mean,
            self.data.initial_state_covariance,
            em_vars='all')

        # train and get log likelihood
        X = self.data.observations[0:10]
        kf = kf.em(X, n_iter=5)
        loglikelihood = kf.loglikelihood(X)

        # pickle Kalman Filter
        store = BytesIO()
        pickle.dump(kf, store)
        clf = pickle.load(BytesIO(store.getvalue()))

        # check that parameters came out already
        np.testing.assert_almost_equal(loglikelihood, kf.loglikelihood(X))

class KalmanFilterTestSuite(TestCase, KalmanFilterTests):
    """Class that nose can pick up on to actually run Kalman Filter tests
    against default implementation.
    """

    def setUp(self):
        self.KF = KalmanFilter
        self.data = load_robot()


# coding:utf-8

import sqlite3
import time
import datetime

class DB:
    def __init__(self):
        self.Start()
        self.CreatTable()
        self.Close()
        # print(self.id)

    def Start(self, path='sql.db'):
        self.conn = sqlite3.connect(path)
        self.cursor = self.conn.cursor()

    def CreatTable(self):
        try:
            sql = '''
            CREATE TABLE IF NOT EXISTS `ocr`(
               `id` INTEGER PRIMARY KEY,
               `user` VARCHAR(100) NOT NULL,
               `score` INTEGER UNSIGNED NOT NULL,
               `update_date` TIMESTAMP
            );
            '''
            self.cursor.execute(sql)
            return 1
        except Exception as e:
            print('>> Creat Error:', e)
            return 0

    def Insert(self, user, score):
        try:
            sql = '''
            INSERT INTO ocr ( id, user, score, update_date )
            VALUES
            (NULL, ?, ?, ?);
           '''
            self.Start()
            self.cursor.execute(sql, (user, score, datetime.datetime.now()))
            self.conn.commit()
            self.Close()
            return 1
        except Exception as e:
            print('>> Insert Error:', e)
            return 0

    def Select(self, id):
        self.Start()
        self.cursor.execute('''SELECT * from ocr WHERE id=(?);''', (id,))
        res = self.cursor.fetchall()
        self.Close()
        return res

    def Close(self):
        self.cursor.close()
        self.conn.close()

    def SelectALL(self):
        self.Start()
        sql = "SELECT * from ocr;"
        self.cursor.execute(sql)
        res = self.cursor.fetchall()
        self.Close()
        return res

if __name__ == '__main__':
    db = DB()
    db.Insert('1', '4')
    res = db.SelectALL()
    print(res)


import socket
from server import *

# Server variables for setting up a connection
SERVER = socket.gethostbyname(socket.gethostname()) # SERVER is used for server IP address
PORT1 = 8000                                        # PORT1 - port number. Server port used to provide unique code to clients
PORT2 = 8001                                        # PORT2 - port number. Server port used to receive message from clients
MSG_LENGTH = 1024                                   # MSG_LENGTH - max size of message
FORMAT = 'utf-8'                                    # FORMAT - text format

# Server start
s = Server(SERVER, PORT1, PORT2, FORMAT, MSG_LENGTH)
try:
    s.start_server()
    input()
    s.shutdown_server()
except Exception as e:
    print(f"{e} :(")


def quickSort(alist):
    quickSortHelper(alist, 0, len(alist) - 1)

    return alist

def quickSortHelper(alist, first, last):
    if first < last:
        splitpoint = partition(alist, first, last)
        quickSortHelper(alist, first, splitpoint - 1)
        quickSortHelper(alist, splitpoint + 1, last)

def partition(alist, first, last):
    splitValue = alist[first]
    leftmark = first + 1
    rightmark = last
    done = False

    while not done:
        while leftmark <= rightmark and alist[leftmark] <= splitValue:
            leftmark = leftmark + 1

        while rightmark >= leftmark and alist[rightmark] >= splitValue:
            rightmark = rightmark - 1

        if rightmark < leftmark:
            done = True
        else:
            alist[leftmark], alist[rightmark] = alist[rightmark], alist[leftmark]

    alist[first], alist[rightmark] = alist[rightmark], alist[first]

    return rightmark

alist = [18, 56, 32, 4, 88, 23, 66, 12, 32, 7, 31]
print(quickSort(alist))
'''
时间复杂度为O(nlog n)
根据中值选取相关，极端情况下为O(n^2)，加上递归开销，不如冒泡
'''


"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = None):
        self.val = val
        self.neighbors = neighbors if neighbors is not None else []
"""

class Solution:
    def cloneGraph(self, node: 'Node') -> 'Node':
        if node is None:
            return None
        if node.neighbors == []:
            return Node(node.val, None)

        # created placeholder map val->new_nodes
        queue = deque([node])
        clones = {}
        while queue:
            og = queue.popleft()
            for nei in og.neighbors:
                if nei.val not in clones:
                    clone = Node(nei.val, [])
                    clones[nei.val] = clone
                    queue.append(nei)

        # add neighbors to things in map
        queue = deque([node])
        visited = set([node.val])
        while queue:
            og = queue.popleft()

            for nei in og.neighbors:
                clones[og.val].neighbors.append(clones[nei.val])
                if nei.val not in visited:
                    visited.add(nei.val)
                    queue.append(nei)

        return clones[node.val]


from bs4 import BeautifulSoup
import sqlite3

con = sqlite3.connect("bookmarks.db")
con.execute("CREATE TABLE IF NOT EXISTS bookmarked_videos(id INTEGER PRIMARY KEY, video_id TEXT UNIQUE, title TEXT, timestamp INTEGER)")
con.commit()

file = open("bookmarks.html")
soup = BeautifulSoup(file, 'html.parser')
file.close()

for a in soup.find_all('a'):
    url = a['href']
    if 'youtube' in url and 'watch' in url:
        split = url.split("v=")
        if len(split) > 1:
            title = a.string
            title_split = title.split(" - YouTube")
            try:
                video_id = split[1][:11]
                title = title_split[0]
                timestamp = a['add_date']
                con.execute("INSERT INTO bookmarked_videos (video_id, title, timestamp) VALUES (?, ?, ?) ON CONFLICT(video_id) DO UPDATE SET title = excluded.title, timestamp = excluded.timestamp WHERE bookmarked_videos.timestamp >= excluded.timestamp", (video_id, title, timestamp))
                con.commit()
            except:
                print(split[1][:11] + " " + title_split[0] + " " + a['add_date'])

con.close()


"""This module reproduces the content of the course in
streamlit, section 2"""
import streamlit as st
import pandas as pd
import numpy as np

# You can display almost anything just by passing it to
# st.write()

st.write("Hello world")
st.write("Welcome to Streamlit App APIs")
st.write(1234)
df=pd.DataFrame({
    "first_column":[1,2,3,4,5],
    "second_column":["a","b","c","d","e"],
    "third_column":[12.1,12.34,12.33,15.1, 66]
}
)
st.write(df)
st.write(np.array([1,2,3,4]))

## --------- MAGIC ---------------#
st.write("Magic commands")
df1=pd.DataFrame({'col1':[1,2,3]})

df1

x=10

x

st.button("Rerun")


import asyncio
import json
from typing import Optional

import aiohttp

from . import graphql_ws_consumer

class GraphqlWsTransport:
    """Transport interface for the `GraphqlWsClient`."""

    # Default timeout for the WebSocket messages.
    TIMEOUT: float = 60.0

    async def connect(self, timeout: Optional[float] = None) -> None:
        """Connect to the server."""
        raise NotImplementedError()

    async def send(self, message: dict) -> None:
        """Send message."""
        raise NotImplementedError()

    async def receive(self, timeout: Optional[float] = None) -> dict:
        """Receive message."""
        raise NotImplementedError()

    async def disconnect(self, timeout: Optional[float] = None) -> None:
        """Disconnect from the server."""
        raise NotImplementedError()

    async def wait_disconnect(self, timeout: Optional[float] = None) -> None:
        """Wait server to close the connection."""
        raise NotImplementedError()

class GraphqlWsTransportAiohttp(GraphqlWsTransport):
    """Transport based on AIOHTTP WebSocket client.

    Args:
        url: WebSocket GraphQL endpoint.
        cookies: HTTP request cookies.
        headers: HTTP request headers.

    """

    def __init__(self, url, cookies=None, headers=None):
        """Constructor. See class description for details."""
        # Server URL.
        self._url = url
        # HTTP cookies.
        self._cookies = cookies
        # HTTP headers.
        self._headers = headers
        # AIOHTTP connection.
        self._connection: aiohttp.ClientWebSocketResponse
        # A task which processes incoming messages.
        self._message_processor: asyncio.Task
        # A queue for incoming messages.
        self._incoming_messages: asyncio.Queue = asyncio.Queue()

    async def connect(self, timeout: Optional[float] = None) -> None:
        """Establish a connection with the WebSocket server.

        Returns:
            `(True, <chosen-subprotocol>)` if connection accepted.
            `(False, None)` if connection rejected.

        """
        connected = asyncio.Event()
        self._message_processor = asyncio.create_task(
            self._process_messages(connected, timeout or self.TIMEOUT)
        )
        await asyncio.wait(
            [connected.wait(), self._message_processor],
            return_when=asyncio.FIRST_COMPLETED,
        )
        if self._message_processor.done():
            # Make sure to raise an exception from the task.
            self._message_processor.result()
            raise RuntimeError(f"Failed to connect to the server: {self._url}!")

    async def send(self, message: dict) -> None:
        """Send message."""
        assert self._connection is not None, "Client is not connected!"
        await self._connection.send_str(json.dumps(message))

    async def receive(self, timeout: Optional[float] = None) -> dict:
        """Wait and receive a message from the WebSocket connection.

        Method fails if the connection closes.

        Returns:
            The message received as a `dict`.

        """
        # Make sure there's no an exception to raise from the task.
        if self._message_processor.done():
            self._message_processor.result()

        # Wait and receive the message.
        try:
            payload = await asyncio.wait_for(
                self._incoming_messages.get(), timeout or self.TIMEOUT
            )
            assert isinstance(payload, str), "Non-string data received!"
            return dict(json.loads(payload))
        except asyncio.TimeoutError as ex:
            # See if we have another error to raise inside.
            if self._message_processor.done():
                self._message_processor.result()
            raise ex

    async def disconnect(self, timeout: Optional[float] = None) -> None:
        """Close the connection gracefully."""
        await self._connection.close(code=1000)
        try:
            await asyncio.wait_for(
                asyncio.shield(self._message_processor), timeout or self.TIMEOUT
            )
            self._message_processor.result()
        except asyncio.TimeoutError:
            pass
        finally:
            if not self._message_processor.done():
                self._message_processor.cancel()
                try:
                    await self._message_processor
                except asyncio.CancelledError:
                    pass

    async def wait_disconnect(self, timeout: Optional[float] = None) -> None:
        """Wait server to close the connection."""
        raise NotImplementedError()

    async def _process_messages(self, connected, timeout):
        """Process messages coming from the connection.

        Args:
            connected: Event for reporting that connection established.
            timeout: Connection timeout in seconds.

        """
        session = aiohttp.ClientSession(cookies=self._cookies, headers=self._headers)
        async with session as session:
            connection = session.ws_connect(
                self._url,
                protocols=[graphql_ws_consumer.GRAPHQL_WS_SUBPROTOCOL],
                timeout=timeout,
            )
            async with connection as self._connection:
                if (
                    self._connection.protocol
                    != graphql_ws_consumer.GRAPHQL_WS_SUBPROTOCOL
                ):
                    raise RuntimeError(
                        f"Server uses wrong subprotocol: {self._connection.protocol}!"
                    )
                connected.set()
                async for msg in self._connection:
                    await self._incoming_messages.put(msg.data)
                    if msg.type == aiohttp.WSMsgType.CLOSED:
                        break


import sys
import numpy as np
import pandas as pd

# potential connection by resolved inconsistencies
pd_result = pd.read_csv(
    '/home/jyoun/Jason/Research/KIDS/manuscript_preparation/before_after_incon/find_path/result.txt',
    sep='\t',
    index_col=False,
    names=['index', 'node1', 'node2', 'node3', 'node4'])

# train data
pd_train = pd.read_csv(
    '/home/jyoun/Jason/Research/KIDS/manuscript_preparation/before_after_incon/find_path/train_original.txt',
    sep='\t',
    names=['Subject', 'Predicate', 'Object', 'Label'])

for column in ['Subject', 'Predicate', 'Object']:
    pd_train[column] = pd_train[column].apply(lambda x: x.replace('#SEMICOLON#', ':'))
    pd_train[column] = pd_train[column].apply(lambda x: x.replace('#SPACE#', ' '))
    pd_train[column] = pd_train[column].apply(lambda x: x.replace('#COMMA#', ','))

# entities
pd_entities = pd.read_csv(
    '/home/jyoun/Jason/Research/KIDS/kg_constructor/output/entity_full_names.txt',
    sep='\t',
    names=['entity_full_name'])

entities = pd_entities['entity_full_name'].tolist()

molecular_function = [entity.split(':')[-1] for entity in entities if 'concept:molecular_function' in entity]
biological_process = [entity.split(':')[-1] for entity in entities if 'concept:biological_process' in entity]
antibiotic = [entity.split(':')[-1] for entity in entities if 'concept:antibiotic' in entity]
cellular_component = [entity.split(':')[-1] for entity in entities if 'concept:cellular_component' in entity]

# scores
pd_original_score = pd.read_csv(
    '/home/jyoun/Jason/Research/KIDS/manuscript_preparation/before_after_incon/compare_pra/final_original/instance/test/scores/confers#SPACE#resistance#SPACE#to#SPACE#antibiotic',
    sep='\t',
    names=['score', 'path_exists'])

pd_without_resolved_score = pd.read_csv(
    '/home/jyoun/Jason/Research/KIDS/manuscript_preparation/before_after_incon/compare_pra/final_without_resolved/instance/test/scores/confers#SPACE#resistance#SPACE#to#SPACE#antibiotic',
    sep='\t',
    names=['score', 'path_exists'])

# reason
reason = []
with open('/home/jyoun/Jason/Research/KIDS/manuscript_preparation/before_after_incon/compare_pra/final_original/instance/test/predictions/confers#SPACE#resistance#SPACE#to#SPACE#antibiotic.reasons') as file:
    for line in file:
        line = line.replace('#SPACE#', ' ')
        line = line.replace('#SEMICOLON#', ':')
        line = line.replace('#COMMA#', ',')

        if line == '\n':
            continue

        line = line.replace('\n', '')
        if '\t' not in line:
            sub = line.split('$')[-1]
        else:
            items = line.split('\t')
            obj = items[1].split('$')[-1]
            models = sorted([item.split('=')[0] for item in items[2:]])
            models = ', '.join(models)

            reason.append([sub, obj, models])

pd_reason = pd.DataFrame(reason, columns=['Subject', 'Object', 'models'])

###########
# process #
###########

def check_model(node1, node2, node3, node4):
    index = (pd_train['Subject'] == node1)
    index &= (pd_train['Object'] == node2)
    selected = pd_train[index]
    predicates = selected['Predicate'].tolist()

    if not (('has' in predicates) or ('is involved in' in predicates) or ('upregulated by antibiotic' in predicates)):
        return ''

    if node2 in molecular_function:
        return '0'
    elif node2 in biological_process:
        return '1'
    elif node2 in antibiotic:
        index = (pd_train['Subject'] == node3)
        index &= (pd_train['Object'] == node2)
        selected = pd_train[index]

        predicates = selected['Predicate'].tolist()

        model_str = []

        if 'upregulated by antibiotic' in predicates:
            index = (pd_train['Subject'] == node3)
            index &= (pd_train['Object'] == node4)
            selected = pd_train[index]

            if selected['Predicate'].tolist() == 'confers resistance to antibiotic':
                model_str.append('3')

        if 'confers resistance to antibiotic' in predicates:
            index = (pd_train['Subject'] == node3)
            index &= (pd_train['Object'] == node4)
            selected = pd_train[index]

            if 'upregulated by antibiotic' in selected['Predicate'].tolist():
                model_str.append('4')

            if 'confers resistance to antibiotic' in selected['Predicate'].tolist():
                model_str.append('5')

        return ' '.join(model_str)

pd_result['model'] = ''
pd_result['model'] = pd_result.apply(lambda row: check_model(row['node1'], row['node2'], row['node3'], row['node4']), axis=1)
pd_result = pd_result[pd_result['model'] != '']

subject_dict = pd_result.groupby('index')['node1'].apply(lambda x: list(set(x))[0]).to_dict()
object_dict = pd_result.groupby('index')['node4'].apply(lambda x: list(set(x))[0]).to_dict()

pd_result_models = pd_result.groupby('index')['model'].apply(lambda x: ', '.join(sorted(list(set(x)))))
pd_result_models = pd_result_models.reset_index()

pd_result_models['Subject'] = pd_result_models['index'].apply(lambda x: subject_dict[x])
pd_result_models['Object'] = pd_result_models['index'].apply(lambda x: object_dict[x])

chosen_index = []

for index, row in pd_result_models.iterrows():
    select_index = (pd_reason['Subject'] == row['Subject'])
    select_index &= (pd_reason['Object'] == row['Object'])

    selected = pd_reason[select_index]

    all_models = selected['models'].tolist()[0].split(', ')
    result_models = row['model'].split(', ')

    flag = False
    for model in result_models:
        if model in all_models:
            flag = True

    if flag:
        chosen_index.append(row['index'])

pd_original_score_selected = pd_original_score.iloc[chosen_index]['score']
pd_without_resolved_score_selected = pd_without_resolved_score.iloc[chosen_index]['score']

percent_increase = pd_original_score_selected.sub(pd_without_resolved_score_selected)
percent_increase = percent_increase.divide(pd_without_resolved_score_selected)
percent_increase = percent_increase.multiply(100)
percent_increase = percent_increase.replace([np.inf, -np.inf], np.nan)

percent_increase.to_csv('percent_increase.txt', index=False)

print(percent_increase.tail(50))
print()
print(percent_increase.mean())
print(percent_increase.std())
print()

pd_original_score_selected = pd_original_score.drop(chosen_index)['score']
pd_without_resolved_score_selected = pd_without_resolved_score.drop(chosen_index)['score']

percent_increase = pd_original_score_selected.sub(pd_without_resolved_score_selected)
percent_increase = percent_increase.divide(pd_without_resolved_score_selected)
percent_increase = percent_increase.multiply(100)
percent_increase = percent_increase.replace([np.inf, -np.inf], np.nan)

print(percent_increase.mean())
print(percent_increase.std())


''' C-2.28
The PredatoryCreditCard class of Section 2.4.1 provides a process month
method that models the completion of a monthly cycle. Modify the class
so that once a customer has made ten calls to charge in the current month,
each additional call to that function results in an additional $1 surcharge.
'''

class CreditCard:
    def __init__(self, customer, bank, acnt, limit, balance=0):
        self._customer = customer
        self._bank = bank
        self._account = acnt
        self._limit = limit
        self._balance = balance

    def get_customer(self):
        return self._customer

    def get_bank(self):
        return self._bank

    def get_account(self):
        return self._account

    def get_limit(self):
        return self._limit

    def get_balance(self):
        return self._balance

    def charge(self, price):
        if not isinstance(price, (int, float)):
            raise TypeError('Price must be a number.')
        elif price + self._balance > self._limit:
            return False
        else:
            self._balance += price
            return True

    def make_payment(self, amount):
        if not isinstance(amount, (int, float)):
            raise TypeError('Amount must be a number.')
        elif amount < 0:
            raise ValueError('Amount cannot be negative.')
        else:
            self._balance -= amount

class PredatoryCreditCard(CreditCard):
    MAX_CHARGES = 10

    def __init__(self, customer, bank, acnt, limit, apr):
        super().__init__(customer, bank, acnt, limit)
        self._apr = apr
        self._charge_count = 0

    def charge(self, price):
        success = super().charge(price)
        if not success:
            self._balance += 5
        else:
            self._charge_count += 1
            if self._charge_count > PredatoryCreditCard.MAX_CHARGES:
                self._balance += 1
        return success

    def process_month(self):
        if self._balance > 0:
            monthly_factor = pow(1+self._apr, 1/12)
            self._balance *= monthly_factor
        self._charge_count = 0  # resets at the begining of each month

if __name__ == '__main__':
    wallet = PredatoryCreditCard('John Bowman', 'California Savings', '5391 0375 9387 5309', 2500, 8)

    for val in range(15):
        wallet.charge(100)

    print(wallet.get_balance())


#https://www.codechef.com/JULY18B/problems/NMNMX

from functools import reduce
import operator as op

#efficient factorial = PRECOMPUTE FACTORIALS ;)
#Ref https://stackoverflow.com/questions/4941753/is-there-a-math-ncr-function-in-python
#AC in PyPy

fact={}

fact[0]=1

for i in range(1,5001):
	fact[i]=fact[i-1]*i

def ncr(n, r):
	if(r>n):
		return 0
	return fact[n] // fact[n-r] // fact[r]

def expoGivenI(n,k,i,precomputed):
	#returns the number of combinations in which element is not the global minimum
	#total no of combos in which a particular element is always present - noOfWaysInWhichThatElementIsMin- noOfWaysInWhichThatElementIsMax
	e= precomputed- ncr(n-i-1,k-1)-ncr(i,k-1)
	return e

t=int(raw_input())

while(t!=0):
	t-=1
	n,k=[int(x) for x in raw_input().split()]
	a=[int(x) for x in raw_input().split()]
	a=sorted(a)
	middle_eles=[]
	for i in range(1,n-1):
		middle_eles.append(a[i])

	exponents=[ncr(n-2,k-2)]  #n-2Ck-2 is the expo of the second number
	mid=n//2
	precomputed=ncr(n-1,k-1) #total no of combos in which a particular element is always present
	for index in range(2,mid):
		exponents.append(expoGivenI(n,k,index,precomputed))

	mirror=exponents[::-1]

	if(n%2!=0):
		#n happens to be odd
		#calculate middle element
		exponents.append(expoGivenI(n,k,mid,precomputed))

	exponents+=mirror

	products=[]
	for i in range(n-2):
		p=pow(middle_eles[i],exponents[i],10**9+7) #mid[i] ^ expo
		products.append(p)

	ans=reduce(op.mul,products,1)

	print(pow(ans,1,10**9+7))


from datetime import datetime, timedelta, timezone
import urllib.parse
import mimetypes
import sys
import boto3

def lambda_handler(event, context):

    # S3 Client
    s3 = boto3.resource('s3')

    # Timezone (JST)
    JST = timezone(timedelta(hours=+9), 'JST')

    # Set time
    now = datetime.now(JST)
    time = "{0:%Y%m%d%-H%M%S}".format(now)
    filename = now.strftime("lambda.log_%Y%m%d")

    # Get file.
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')

    # Check MIME type.
    bucket_name = 'frombk'
    s3.Bucket(bucket_name).download_file(key, '/tmp/' + key)
    mime = mimetypes.guess_type('/tmp/' + key)[0]

    # Download log
    bucket_name = 'detbk'

    try:
        s3.Bucket(bucket_name).download_file(filename, '/tmp/' + filename)
    except:
        # make blank file
        with open('/tmp/' + filename,"w"):pass

    # Make Temporaly.
    with open('/tmp/' + filename, "a") as file:
        message = key + "," + str(mime)  + "," +  str(time)
        file.write(message + '\n')

    # upload to S3
    bucket_name = 'detbk'
    s3.Bucket(bucket_name).upload_file('/tmp/' + filename, filename)

    return


"""
Command line Python tool for file conversion from Moire markup language to other
formats, such as HTML, TeX, etc.
"""
import logging
import sys
from argparse import ArgumentParser, Namespace

from moire.moire import Moire
import moire.default  # noqa: F401

__author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru"

def main():
    logging.basicConfig(level=logging.INFO, format="%(message)s")

    parser: ArgumentParser = ArgumentParser()

    parser.add_argument("-i", "--input", help="Moire input file", required=True)
    parser.add_argument("-o", "--output", help="output file")
    parser.add_argument("-f", "--format", help="output format", required=True)

    options: Namespace = parser.parse_args(sys.argv[1:])

    with open(options.input, "r") as input_file:
        converter: Moire = getattr(
            sys.modules["moire.default"], options.format
        )()
        converter.file_name = options.input
        output: str = converter.convert(input_file.read())

    if not output:
        logging.fatal("Fatal: output was no produced.")
        sys.exit(1)

    if options.output:
        with open(options.output, "w+") as output_file:
            output_file.write(output)
            logging.info(f"Converted to {options.output}.")
    else:
        sys.stdout.write(output)

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""
Created on Thu Jan 5 17:03:36 2023

@author: prach
"""

"""
CLUSTERING PART STARTS
"""

# import necessary modules
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import cluster
import sklearn.metrics as skmet

# function to read file
def readFile(x):
    '''
        This function is used to read csv file in original form and then
        filling 'nan' values by '0' to avoid disturbance in data visualization
        and final results.

        Parameters
        ----------
        x : csv filename

        Returns
        -------
        ghg_grow : variable for storing csv file

    '''
    ghg_grow = pd.read_csv("ghg-emissions.csv");
    ghg_grow = pd.read_csv(x)
    ghg_grow = ghg_grow.fillna(0.0)
    return ghg_grow

# calling readFile function to display dataframe
ghg_grow = readFile("ghg-emissions.csv")

print("\nGHG-emission Growth: \n", ghg_grow)

# dropping particular columns which are not required to clean data
ghg_grow = ghg_grow.drop(['unit', '1989'], axis=1)

print("\nGHG-emission Growth after dropping columns: \n", ghg_grow)

# transpose dataframe
ghg_grow = pd.DataFrame.transpose(ghg_grow)

print("\nTransposed GHG-emission Growth: \n",ghg_grow)

# populating header with header information
header1 = ghg_grow.iloc[0].values.tolist()

ghg_grow.columns = header1

print("\nGHG-emission Growth Header: \n", ghg_grow)

# remove first two rows from dataframe
ghg_grow = ghg_grow.iloc[2:]

print("\nGHG-emission Growth after selecting particular rows: \n", ghg_grow)

# creating a dataframe for two columns to store original values
pop_ex = ghg_grow[["India","Australia"]].copy()

# extracting maximum and minmum value from new dataframe
max_val = pop_ex.max()

min_val = pop_ex.min()

pop_ex = (pop_ex - min_val) / (max_val - min_val) # operation of min and max

print("\nMin and Max operation on GHG-emission Growth: \n", pop_ex)

# set up clusterer and number of clusters
ncluster = 6

kmeans = cluster.KMeans(n_clusters=ncluster)

# fitting the data where the results are stored in kmeans object
kmeans.fit(pop_ex)

labels = kmeans.labels_ # labels is number of associated clusters

# extracting estimated cluster centres
cen = kmeans.cluster_centers_

print("\nCluster Centres: \n", cen)

# calculate the silhoutte score
print("\nSilhoutte Score: \n",skmet.silhouette_score(pop_ex, labels))

# plot using the labels to select colour
plt.figure(figsize=(10.0, 10.0))

col = ["tab:red", "tab:pink", "tab:green", "tab:blue", "tab:brown", \
       "tab:cyan", "tab:orange", "tab:black", "tab:olive", "tab:gray"]

# loop over the different labels
for l in range(ncluster):
    plt.plot(pop_ex[labels==l]["India"], pop_ex[labels==l]["Australia"],
             marker="o", markersize=3, color=col[l])

# display cluster centres
for ic in range(ncluster):
    xc, yc = cen[ic,:]
    plt.plot(xc, yc, "dk", markersize=10)

plt.xlabel("India")

plt.ylabel("Australia")

plt.show()

print("\nCentres: \n", cen)

df_cen = pd.DataFrame(cen, columns=["India", "Australia"])

print(df_cen)

df_cen = df_cen * (max_val - min_val) + max_val

pop_ex = pop_ex * (max_val - min_val) + max_val
# print(df_ex.min(), df_ex.max())

print("\nDataframe Centre: \n", df_cen)

# plot using the labels to select colour
plt.figure(figsize=(10.0, 10.0))

col = ["tab:blue", "tab:orange", "tab:green", "tab:red", "tab:purple", "tab:brown", \
"tab:pink", "tab:gray", "tab:olive", "tab:cyan"]

for l in range(ncluster): # loop over the different labels
    plt.plot(pop_ex[labels==l]["India"], pop_ex[labels==l]["Australia"], "o", markersize=3, color=col[l])

# show cluster centres
plt.plot(df_cen["India"], df_cen["Australia"], "dk", markersize=10)

plt.xlabel("India")

plt.ylabel("Australia")

plt.title("GHG-emission Growth(%)")

plt.show()

print("\nCentres: \n", cen)

# In[ ]:

"""
CURVE FIT PART STARTS
"""

# import necessary modules
# import numpy as np
import pandas as pd
import scipy.optimize as opt
import matplotlib.pyplot as plt
#import errors as err

# function to read file
def readFile(y):
    '''
        This function is used to read csv file in original form and then
        filling 'nan' values by '0' to avoid disturbance in data visualization
        and final results.

        Parameters
        ----------
        x : csv filename

        Returns
        -------
        air_pop : variable for storing csv file

    '''
    air_pop = pd.read_csv("Air_pollution.csv");
    air_pop = pd.read_csv(y)
    air_pop = air_pop.fillna(0.0)
    return air_pop

# calling readFile function to display dataframe
air_pop = readFile("Air_pollution.csv")

print("\nAir_pollution: \n", air_pop)

# converting to dataframe
air_pop = pd.DataFrame(air_pop)

# transpose dataframe
air_pop = air_pop.transpose()

print("\nTransposed Air_pollution: \n", air_pop)

# populating header with header information
header2 = air_pop.iloc[0].values.tolist()

air_pop.columns = header2

print("\nAir_pollution Header: \n", air_pop)

# select particular column
air_pop = air_pop["Bahamas, The"]

print("\nAir_pollution after selecting particular column: \n", air_pop)

# rename column
air_pop.columns = ["AIR_P"]

print("\nRenamed Air_pollution: \n", air_pop)

# extracting particular rows
air_pop = air_pop.iloc[5:]

air_pop = air_pop.iloc[:-1]

print("\nAIR_P after selecting particular rows: \n", air_pop)

# resetn index of dataframe
air_pop = air_pop.reset_index()

print("\nAir_pollution reset index: \n", air_pop)

# rename columns
air_pop = air_pop.rename(columns={"index": "Year", "Bahamas, The": "AIR_P"} )

print("\nAir_pollution after renamed columns: \n", air_pop)

print(air_pop.columns)

# plot line graph
air_pop.plot("Year", "AIR_P",     )

plt.legend()

plt.title("Air_pollution")

plt.show()

# curve fit with exponential function
def exponential(s, q0, h):
    '''
        Calculates exponential function with scale factor n0 and growth rate g.
    '''
    s = s - 1960.0
    x = q0 * np.exp(h*s)
    return x

# performing best fit in curve fit
print(type(air_pop["Year"].iloc[1]))

air_pop["Year"] = pd.to_numeric(air_pop["Year"])

print("\nAir_pollution Type: \n", type(air_pop["Year"].iloc[1]))

param, covar = opt.curve_fit(exponential, air_pop["Year"], air_pop["AIR_P"],
p0=(4.978423, 0.03))

# plotting best fit
air_pop["fit"] = exponential(air_pop["Year"], *param)

air_pop.plot("Year", ["AIR_P", "fit"], label=["New AIR_P", "New Fit"])

plt.legend()

plt.title("Air_pollution")

plt.show()

# predict fit for future years
year = np.arange(1960, 2031)

print("\nForecast Years: \n", year)

forecast = exponential(year, *param)

plt.figure()

plt.plot(air_pop["Year"], air_pop["AIR_P"], label="AIR_P")

plt.plot(year, forecast, label="Forecast")

plt.xlabel("Year")

plt.ylabel("AIR_P")

plt.title("Air_pollution")

plt.legend()

plt.show()

# err_ranges function
def err_ranges(x, exponential, param, sigma):
    '''
        Calculates the upper and lower limits for the function, parameters and
        sigmas for single value or array x. Functions values are calculated for
        all combinations of +/- sigma and the minimum and maximum is determined.
        Can be used for all number of parameters and sigmas >=1.

        This routine can be used in assignment programs.
    '''
    import itertools as iter

    # initiate arrays for lower and upper limits
    lower = exponential(x, *param)
    upper = lower

    uplow = []   # list to hold upper and lower limits for parameters
    for p,s in zip(param, sigma):
        pmin = p - s
        pmax = p + s
        uplow.append((pmin, pmax))

    pmix = list(iter.product(*uplow))

    for p in pmix:
        y = exponential(x, *p)
        lower = np.minimum(lower, y)
        upper = np.maximum(upper, y)
        print("\nLower: \n", lower)
        print("\nUpper: \n", upper)
    return lower, upper


import jwt
from datetime import datetime, timedelta

def decrypt_token(token,jwt_key):

    try:
        data = jwt.decode(
            token,
            jwt_key,
            algorithms=['HS256']
        )
        return data
    except Exception as e:
        return None


import logging

#logのフォーマットを変えることができる
formatter = '%(levelname)s:%(message)s'
#下のコマンドはlogの日時を表示させる。
formatter = '%(asctime)s:%(message)s'

# デフォルトではwarning以上しか出力されない。
#basicConfigのlevelの設定により、ファイル(test.log)にinfoまで出力された。
#filenameを指定することで別ファイルに保存可能
logging.basicConfig(filename='test.log',level=logging.INFO,format=formatter)

logging.critical('critical')
logging.error('error')
logging.warning('warning')
#formatを使わなくても以下のように式展開が可能になる。
logging.info('info　%s %s','test1','test2')
logging.debug('debug')

"""
>
CRITICAL:root:critical
ERROR:root:error
WARNING:root:warning
INFO:root:info　test1 test2
"""


# -*- coding: utf-8 -*-
# @Time    : 2018/10/23 20:04
# @Author  : Wang Xin
# @Email   : wangxin_buaa@163.com

import torch
import torch.nn as nn

class MaskedMSELoss(nn.Module):
    def __init__(self):
        super(MaskedMSELoss, self).__init__()

    def forward(self, pred, target):
        assert pred.dim() == target.dim(), "inconsistent dimensions"
        valid_mask = (target > 0).detach()
        diff = target - pred
        diff = diff[valid_mask]
        self.loss = (diff ** 2).mean()
        return self.loss

class MaskedL1Loss(nn.Module):
    def __init__(self):
        super(MaskedL1Loss, self).__init__()

    def forward(self, pred, target):
        assert pred.dim() == target.dim(), "inconsistent dimensions"
        valid_mask = (target > 0).detach()
        diff = target - pred
        diff = diff[valid_mask]
        self.loss = diff.abs().mean()
        return self.loss

class berHuLoss(nn.Module):
    def __init__(self):
        super(berHuLoss, self).__init__()

    def forward(self, pred, target):
        assert pred.dim() == target.dim(), "inconsistent dimensions"

        huber_c = torch.max(pred - target)
        huber_c = 0.2 * huber_c

        valid_mask = (target > 0).detach()
        diff = target - pred
        diff = diff[valid_mask]
        diff = diff.abs()

        huber_mask = (diff > huber_c).detach()

        diff2 = diff[huber_mask]
        diff2 = diff2 ** 2

        self.loss = torch.cat((diff, diff2)).mean()

        return self.loss

class ScaleInvariantError(nn.Module):
    """
    Scale invariant error defined in Eigen's paper!
    """

    def __init__(self, lamada=0.5):
        super(ScaleInvariantError, self).__init__()
        self.lamada = lamada
        return

    def forward(self, y_true, y_pred):
        first_log = torch.log(torch.clamp(y_pred, min, max))
        second_log = torch.log(torch.clamp(y_true, min, max))
        d = first_log - second_log
        loss = torch.mean(d * d) - self.lamada * torch.mean(d) * torch.mean(d)
        return loss

class probabilisticOrdLoss(nn.SmoothL1Loss):
    def __init__(self,args):
        super(probabilisticOrdLoss, self).__init__()
        self.loss = 0.0
        self.args = args

    def forward(self,ord_labels,target):
        """
        :param ord_labels: ordinal labels for each position of Image I.
        :param target:     the ground_truth discreted using SID strategy.
        :return: ordinal loss
        """
        N, C, H, W = ord_labels.size()
        ord_num = C
        if torch.cuda.is_available() and self.args.gpu:
            K = torch.zeros((N, C, H, W), dtype=torch.int).cuda()
            for i in range(ord_num):
                if i <=  target:
                    K[:, i, :, :] = K[:, i, :, :] + torch.ones((N, H, W), dtype=torch.int).cuda()
        else:
            K = torch.zeros((N, C, H, W), dtype=torch.int)
            for i in range(ord_num):
                if i <= target:
                    K[:, i, :, :] = K[:, i, :, :] + i * torch.ones((N, H, W), dtype=torch.int)
        return super().forward(ord_labels,K)

class ordLoss(nn.Module):
    """
    Ordinal loss is defined as the average of pixelwise ordinal loss F(h, w, X, O)
    over the entire image domain:
    """

    def __init__(self,args):
        super(ordLoss, self).__init__()
        self.loss = 0.0
        self.args = args

    def forward(self, ord_labels, target):
        """
        :param ord_labels: ordinal labels for each position of Image I.
        :param target:     the ground_truth discreted using SID strategy.
        :return: ordinal loss
        """
        # assert pred.dim() == target.dim()
        # invalid_mask = target < 0
        # target[invalid_mask] = 0

        N, C, H, W = ord_labels.size()
        ord_num = C
        # print('ord_num = ', ord_num)

        self.loss = 0.0

        # for k in range(ord_num):
        #     '''
        #     p^k_(w, h) = e^y(w, h, 2k+1) / [e^(w, h, 2k) + e^(w, h, 2k+1)]
        #     '''
        #     p_k = ord_labels[:, k, :, :]
        #     p_k = p_k.view(N, 1, H, W)
        #
        #     '''
        #     对每个像素而言，
        #     如果k小于l(w, h), log(p_k)
        #     如果k大于l(w, h), log(1-p_k)
        #     希望分类正确的p_k越大越好
        #     '''
        #     mask_0 = (target >= k).detach()   # 分类正确
        #     mask_1 = (target < k).detach()  # 分类错误
        #
        #     one = torch.ones(p_k[mask_1].size())
        #     if torch.cuda.is_available():
        #         one = one.cuda()
        #     self.loss += torch.sum(torch.log(torch.clamp(p_k[mask_0], min = 1e-7, max = 1e7))) \
        #                  + torch.sum(torch.log(torch.clamp(one - p_k[mask_1], min = 1e-7, max = 1e7)))

        # faster version
        if torch.cuda.is_available() and self.args.gpu:
            K = torch.zeros((N, C, H, W), dtype=torch.int).cuda()
            for i in range(ord_num):
                K[:, i, :, :] = K[:, i, :, :] + i * torch.ones((N, H, W), dtype=torch.int).cuda()
        else:
            K = torch.zeros((N, C, H, W), dtype=torch.int)
            for i in range(ord_num):
                K[:, i, :, :] = K[:, i, :, :] + i * torch.ones((N, H, W), dtype=torch.int)

        mask_0 = (K <= target).detach() # Mask all pixel < rank K as 0
        mask_1 = (K > target).detach()

        one = torch.ones(ord_labels[mask_1].size())
        if torch.cuda.is_available() and self.args.gpu:
            one = one.cuda()
            # mask_0 = mask_0.detach()
            # mask_1 = mask_1.detach()

        self.loss += torch.sum(torch.log(torch.clamp(ord_labels[mask_0], min=1e-8, max=1e8))) \
                     + torch.sum(torch.log(torch.clamp(one - ord_labels[mask_1], min=1e-8, max=1e8)))

        # del K
        # del one
        # del mask_0
        # del mask_1

        N = N * H * W
        self.loss /= (-N)  # negative
        return self.loss


# 221003
# 프로그래머스 24060번 알고리즘 수업 - 병합 정렬 1
# 분류: 재귀
# 난이도: 실버 4
# https://www.acmicpc.net/problem/24060
# 한줄 평: 병합 정렬은 middle을 어디서 나누느냐에 따라 중간 과정이 많이 바뀜...주의해야 할 듯
from math import ceil
from collections import deque

def merge(front, back):
    global cnt, answer
    front, back = deque(front), deque(back)
    res = []
    while front or back:
        if front and back:
            if front[0] <= back[0]:
                res.append(front.popleft())
            else:
                res.append(back.popleft())
        elif front:
            res.append(front.popleft())
        elif back:
            res.append(back.popleft())
        if cnt < k:             # cnt가 k일때까지만 집계해주기
            cnt += 1
            answer = res[-1]
        # print(cnt, answer)
    return res

def merge_sort(l):
    if len(l) <= 1:
        return l
    mid = ceil(len(l) / 2)      # list가 홀수면 front가 더 많도록 middle을 설정
    left = l[:mid]
    right = l[mid:]
    front = merge_sort(left)
    back = merge_sort(right)
    return merge(front, back)

if __name__ == "__main__":
    n, k = map(int, input().split())
    l = list(map(int, input().split()))
    cnt, answer = 0, 0
    result = merge_sort(l)
    a = -1 if cnt != k else answer      # cnt가 k가 안됐으면 조건에 부합하지 않으니 -1
    print(a)


"""3. Write a function that takes two objects as parameters and returns
    True if they are the same object, and False if not.
"""

class Widget:
    def __init__(self, name, size):
        self.name = name
        self.size = size
        print(f"Widget {self} created!")

def is_same(a, b):
    return a is b

widget1 = Widget("Bonk", 44)
widget2 = Widget("Bonk", 44)
widget3 = Widget("Conk", 22)
same_widget = widget1

print(is_same(widget1, widget2)) #False (2 Objects with same Properties)
print(is_same(widget1, widget3)) #False
print(is_same(same_widget, widget1)) #True


import torch
import numpy as np

# ## Variable     我们需要能够构建计算图的 tensor，这就是 Variable。
# tensor 是 PyTorch 中的完美组件，但是构建神经网络还远远不够，我们需要能够构建计算图的 tensor，这就是 Variable。
# Variable 是对 tensor 的封装，操作和 tensor 是一样的，但是每个 Variabel都有三个属性，
# Variable 中的 tensor本身`.data`，对应 tensor 的梯度`.grad`以及这个 Variable 是通过什么方式得到的`.grad_fn`

# 通过下面这种方式导入 Variable
from torch.autograd import Variable

x_tensor = torch.randn(10, 5)
y_tensor = torch.randn(10, 5)

# 将 tensor 变成 Variable
x = Variable(x_tensor, requires_grad=True)  # 默认 Variable 是不需要求梯度的，所以我们用这个方式申明需要对其进行求梯度
y = Variable(y_tensor, requires_grad=True)
z = torch.sum(x + y)

print(z.data)
print(z.grad_fn)   ## 上面我们打出了 z 中的 tensor 数值，同时通过`grad_fn`知道了其是通过 Sum 这种方式得到的

z.backward()    #自动求导
print(x.grad)   # 求 x 和 y 的梯度
print(y.grad)
# 通过`.grad`我们得到了 x 和 y 的梯度，这里我们使用了 PyTorch 提供的自动求导机制，


from multiprocessing import Process

from .config import Config
from .dht.DHTServer import DHTServer
from .util.common import get_logger

logger = get_logger("logger_dht_main")

# 启动多进程
def start_processes(id):
    logger.info("DHT网络进程{0}运行成功 !!! 绑定地址 ------> {1}:{2}".format(id, Config.BIND_IP, Config.BIND_PORT + id))
    dht_server = DHTServer(Config.BIND_IP, Config.BIND_PORT + id, id)
    dht_server.start()
    dht_server.auto_send_find_node()

# 启动多进程服务
def start_server():
    processes = []
    for id in range(Config.MAX_PROCESSES):
        processes.append(Process(target=start_processes, args=(id,)))

    for p in processes:
        p.start()

    for p in processes:
        p.join()


import uvicorn

from fastapi import FastAPI

from src.api_v1 import router as router_v1

app = FastAPI(
    title="ITPC test task"
)

app.include_router(
    router=router_v1,
    prefix="/api/v1"
)

if __name__ == '__main__':
    uvicorn.run("src.main:app", reload=True)


import matplotlib.pyplot as plt

def pie_chart(pokedex = []):
    """
    Task 27: Create a Pie Chart showing pokemon from pokedex sorted by their generation

    Access the pokedex, sort out pokemon by generation and plot this data in a
    pie chart format. Add labels to clearly identify each generation.

    :param pokedex: list of pokemon
    :return: None
    """
    p_dict = {}# {"1":3, "2": 1, "7":2}
    for pokemon in pokedex:
        p_dict[pokemon[11]] = p_dict.get(pokemon[11], 0) + 1
    p_labels = [f"Generation {x}" for x in p_dict.keys()] #List comprehension
    plt.pie(p_dict.values(), labels=p_labels, autopct="%.0f%%")
    plt.title("Pokemon by Generation")
    plt.show()

def bar_chart(pokedex = []):
    """
    Task 28: Create a Bar Chart showing pokemon from pokedex sorted by their type

    Access the pokedex, sort out pokemon by type and plot this data in a
    bar chart format. Add axis labels and main title.

    :param pokedex: list of pokemon
    :return: None
    """
    diction = {} # {"Bug": 1, "Water": 7}
    for pokemon in pokedex:
        diction[pokemon[2]] = diction.get(pokemon[2], 0) + 1
    plt.bar(diction.keys(), diction.values(), color = "r")
    print(diction)
    plt.title("Pokemon sorted by type")
    plt.xlabel("Type of Pokemon")
    plt.ylabel("Frequency")
    plt.savefig("types.png")


"""
Created on Wed Feb 17 13:27:55 2021

@author: William Callender

This program downloads data about the current progress of COVID-19 vaccinations
in the United States to project the total number of vaccinations going forward.
It does this by getting data about the number of vaccinations per day since
vaccines first became approved. It then runs linear regression over that data
to determine how fast the number of daily vaccinations is increasing. It
integrates this projection and accounts for the current number of people fully
vaccinated and the fact that both vaccines require 2 shots for full
vaccination. It shows this with some graphs and a crude projection for when the
US could be fully vaccinated.

It creates 2 csv files and 2 new optional png files every day.

The data is sourced (by default) from the Our World in Data COVID-19 repository
under the
[Creative Commons BY license](https://creativecommons.org/licenses/by/4.0/).
This code is licensed likewise.

I cannot predict the future, and neither can this program. These projections
were created as a way for me to be less bored while inside, and should not be
used in place of projections provided by experts. They should be used merely
for entertainment purposes or for learning about coding, not for anything where
the accuracy of projections is important. By using this code you acknowledge
that I am not responsible for any harm caused by its misuse.
"""

# change this line to True to have the program always overwrite without asking
defaultReplace = False
# change the filename for the vaccination data
fname = 'vaccinations.csv'
# the url to download the raw data from
url = 'https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.csv'
# should the program keep a log of its projections?
shouldLogProjections = True
# filename for the log, should end in .csv
logfile = 'projections.csv'
# should output plots as png?
saveFigs = True

import wget
from os import remove, path
import csv
from scipy.stats import linregress as linreg
from scipy.integrate import simps
from datetime import date, timedelta
from matplotlib import pyplot as plt
from numpy import linspace

replace = False
filename = fname
if path.exists(fname) and not defaultReplace:
    c = ''
    while c.lower() != 'y' and c != 'n':
        print(f'Should the existing {fname} be replaced by updated data? (y/n)')
        c = input()
    replace = c.lower() == 'y'
elif not path.exists(fname):
    print(f'No existing data at {fname}, downloading... ', end='')
    filename = wget.download(url, out=fname)
    print('done!')

if replace:
    try:
        remove(fname)
        print('Removed existing file')
        print('Downloading new data... ', end='')
        filename = wget.download(url, out=fname)
        print('done!')
    except FileNotFoundError:
        if not defaultReplace:
            print(f"Unexpected FileNotFoundError. Will continue with execution assuming file {fname} doesn't exist")
    except:
        print('Unknown error')
        raise

dates = []
dailyVaccinations = []
peopleFullyVaccinated = []

with open(filename, 'r') as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        if row[1] == 'USA':
            if not row[7] == '':
                dailyVaccinations.append(int(row[7]))
                dates.append(date.fromisoformat(row[2]))
            if not row[5] == '':
                peopleFullyVaccinated.append(int(row[5]))

peopleFullyVaccinatedToday = max(peopleFullyVaccinated)
days = [(d - dates[0]).days for d in dates]

res = linreg(days, dailyVaccinations)
m, b, r2 = (res.slope, res.intercept, res.rvalue**2)
samples = 1000
projectTo = 240
x = linspace(min(days), projectTo, samples)
yhat = [m*xi + b for xi in x]
# divide by 2 because shots require 2 doses :( but then add everyone who's already vaccinated :)
projectedVaccinations = [(simps(yhat[:i], x[:i]) / 2) + peopleFullyVaccinatedToday for i in range(1, len(x))]
crossover = 0
for i, v in enumerate(projectedVaccinations):
    if v > 330e6:
        crossover = min(days) + (i/samples)*projectTo
        break
crossoverDate = dates[0] + timedelta(days=crossover)
plt.scatter(days, dailyVaccinations, label='True daily vaccinations')
plt.plot(x, yhat, color='r', label=f'y = {round(m,3)}x + {round(b,3)}')
plt.legend()
plt.xlabel(f'Number of days since {dates[0]}')
plt.ylabel('Number of daily vaccinations')
plt.title(f'Projection of daily vaccinations from {date.today()}')
if saveFigs:
    plt.savefig('Projected daily vaccinations ' + str(date.today()))
plt.show()
plt.close()
plt.plot(x[1:], projectedVaccinations, label='Projected Full Vaccinations')
plt.plot(x[1:], [330e6 for _ in range(len(projectedVaccinations))], label='Total US Population (330 million)')
plt.legend()
plt.xlabel(f'Number of days since {dates[0]}')
plt.ylabel('Number of full vaccinations')
plt.title(f'Projection of full vaccinations from {date.today()}')
if saveFigs:
    plt.savefig('Projected total vaccinations ' + str(date.today()))
plt.show()
plt.close()
if crossover == 0:
    print('This projects not all US citizens will be vaccinated within the timeframe')
else:
    print('This projects all US citizens may be vaccinated by', crossoverDate.strftime('%B %d, %Y'))
    print("Please note that this doesn't factor in vaccine skepticism, an upper limit to daily vaccinations, and other unforseen challenges. This projection is beyond optimistic, but it's probably reasonable to assume that the general population will be allowed to request vaccines by this date, even if they're difficult to get.")

if shouldLogProjections:
    todayAlreadyExists = False
    if not path.exists(logfile):
        print(f'Log not found at {logfile}, creating it')
        with open(logfile, 'w', newline='') as f:
            writer = csv.writer(f)
            writer.writerow(['Current Date', 'Projected Full Vaccination Date'])
    else:
        with open(logfile, 'r') as f:
            reader = csv.reader(f)
            if list(reader)[-1][0] == str(date.today()):
                todayAlreadyExists = True
                print('Data from today already exists, not adding to log')
    if not todayAlreadyExists:
        with open(logfile, 'a', newline='') as f:
            writer = csv.writer(f)
            writer.writerow([str(date.today()), str(crossoverDate)])
            print(f'Appending data from today to {logfile}')


import sqlite3
import threading as td
import wx

from forsteri.interface import data as idata
from forsteri.interface import sql as isql

"""
Constant Declarations
"""

"""
Frame Class
"""
class LinkFrame(wx.Frame):
    """
    """

    def __init__(self, *args, **kwargs):
        """
        Initialize the frame.

        Args:
          *args (): Any arguments to be passed directly to the super's
            constructor.
          **kwargs (): Any keyword arguments to be passed to the super's
            constructor.

        Returns:
          LinkFrame
        """

        ## Frame
        # Initialize by the parent's constructor.
        super(LinkFrame, self).__init__(*args, **kwargs)

        # Create the master panel.
        masterPanel = wx.Panel(self)

        # Create the master sizer.
        masterSizer = wx.BoxSizer(wx.VERTICAL)

        ## List Control
        # Create the list control.
        self.linkList = wx.ListCtrl(masterPanel, size=(300, 200),
            style=wx.LC_REPORT|wx.LC_HRULES|wx.LC_VRULES|wx.BORDER_SUNKEN)

        # Add columns to the list control.
        self.linkList.InsertColumn(0, "Old", width=145)
        self.linkList.InsertColumn(1, "New", width=145)

        # Bind the selection of an item to a function.
        self.linkList.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onSelected)
        self.linkList.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.onSelected)
        self.linkList.Bind(wx.EVT_LEFT_DCLICK, self.onEdit)

        ## Manipulate Buttons
        # Create the manipulate sizer.
        manipSizer = wx.BoxSizer(wx.HORIZONTAL)

        # Create the buttons.
        self.addButton = wx.Button(masterPanel, id=wx.ID_ADD)
        self.editButton = wx.Button(masterPanel, id=wx.ID_EDIT)
        self.deleteButton = wx.Button(masterPanel, id=wx.ID_DELETE)

        # Add the buttons to the manipulate sizer.
        manipSizer.AddMany([self.addButton, (5, 0), self.editButton, (5, 0),
            self.deleteButton])

        # Bind button presses to functions.
        self.addButton.Bind(wx.EVT_BUTTON, self.onAdd)
        self.editButton.Bind(wx.EVT_BUTTON, self.onEdit)
        self.deleteButton.Bind(wx.EVT_BUTTON, self.onDelete)

        ## Finish Buttons
        # Create the finish sizer.
        finishSizer = wx.BoxSizer(wx.HORIZONTAL)

        # Create the buttons.
        okButton = wx.Button(masterPanel, id=wx.ID_OK)
        cancelButton = wx.Button(masterPanel, id=wx.ID_CANCEL)

        # Set the ok button to be the dafault button.
        okButton.SetDefault()

        # Add the buttons to the finish sizer.
        finishSizer.AddMany([okButton, (5, 0), cancelButton])

        # Bind the button presses to function.
        okButton.Bind(wx.EVT_BUTTON, self.onOK)
        cancelButton.Bind(wx.EVT_BUTTON, self.onCancel)

        ## Key Bindings
        # Create a new id for selecting all.
        selectAllId = wx.NewId()

        # Bind the id to a function.
        self.Bind(wx.EVT_MENU, self.selectAll, id=selectAllId)

        # Create a new accelerator table and set it to the frame.
        accelT = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord("A"), selectAllId)])
        self.SetAcceleratorTable(accelT)

        ## Frame Operations
        # Add everything to the master sizer.
        masterSizer.AddSpacer(10)
        masterSizer.Add(self.linkList, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER,
            border=5)
        masterSizer.Add(manipSizer, flag=wx.TOP|wx.ALIGN_CENTER, border=10)
        masterSizer.AddSpacer(9)
        masterSizer.Add(wx.StaticLine(masterPanel, size=(312, 2)),
            flag=wx.ALIGN_CENTER)
        masterSizer.AddSpacer(9)
        masterSizer.Add(finishSizer, flag=wx.RIGHT|wx.BOTTOM|wx.ALIGN_RIGHT,
            border=5)

        # Open a connection to the database.
        self.connection = sqlite3.connect(isql.MASTER)
        self.connection2 = sqlite3.connect(idata.MASTER)

        # Update the displayed list.
        self.initializeList(None)

        # Set the sizer for the master panel.
        masterPanel.SetSizer(masterSizer)

        # Bind closing the frame to a function.
        self.Bind(wx.EVT_CLOSE, self.onClose)

        # Set window properties.
        self.SetSize((328, 333))
        self.SetTitle("Link Products")
        self.Centre()
        self.Show(True)

    """
    Event Handlers
    """
    def initializeList(self, event):
        """
        """

        # Get the list of links.
        links = isql.getLinks(self.connection)

        # Iterate over the list and add each to the control.
        index = 0
        for (old, new) in links:
            # Add the items to the list control.
            self.linkList.InsertStringItem(index, old)
            self.linkList.SetStringItem(index, 1, new)

            # Increment the index.
            index += 1

    def updateList(self, event):
        """
        """

        # Get the list of links.
        links = isql.getLinks(self.connection)

        # Remove all items from the list control.
        self.linkList.DeleteAllItems()

        # Update the selected colors.
        self.onSelected(event)

        # Iterate over the list and add each to the control.
        index = 0
        for (old, new) in links:
            # Add the items to the list control.
            self.linkList.InsertItem(index, old)
            self.linkList.SetItem(index, 1, new)

            # Increment the index.
            index += 1

    def onSelected(self, event):
        """
        """

        # If multiple products are selected, set the edit and delete buttons
        # to be yellow.
        if self.linkList.GetSelectedItemCount() > 1:
            self.editButton.Disable()
            self.deleteButton.SetBackgroundColour("Yellow")
        # If only one product is selected, set the edit and delete buttons
        # to be the default color.
        else:
            self.editButton.Enable()
            self.deleteButton.SetBackgroundColour(wx.NullColour)

    def selectAll(self, event):
        """
        """

        # Iterate through the items in the list selecting each.
        for i in range(0, self.linkList.GetItemCount()):
            self.linkList.Select(i)

    def onAdd(self, event):
        """
        """

        # Create the dialog box.
        linkDlg = LinkDialog(self, title="Add Link")

        # Show the link dialog box.
        if linkDlg.ShowModal() == wx.ID_CANCEL:
            return

        # Get the selections from the dialog boxes.
        (old, new) = linkDlg.getSelection()

        # Destroy the dialog box.
        linkDlg.Destroy()

        # If either input is an empty string, show an error.
        if old == '' or new == '':
            errorDialog = wx.MessageDialog(self,
                "One of the entries was empty.", "Error", wx.OK|wx.ICON_ERROR)
            errorDialog.ShowModal()

            return

        # Add the link to the database.
        isql.addLink(old, new, self.connection)

        # Add the data link.
        idata.linkData(old, new, self.connection2)

        # Update the link list.
        self.updateList(event)

    def onEdit(self, event):
        """
        """

        # Create the dialog box.
        linkDlg = LinkDialog(self, title="Add Link")

        # Get the selected data.
        index = self.linkList.GetFirstSelected()

        # If nothing is selected, send an error.
        if index == -1:
            errorDialog = wx.MessageDialog(self, "No item was selected.",
                "Error", wx.OK|wx.ICON_ERROR)
            errorDialog.ShowModal()

            return

        # Get the string value of the old product.
        old1 = self.linkList.GetItemText(index)
        new1 = self.linkList.GetItemText(index, 1)

        # Set the text in the link dialog.
        linkDlg.setSelection(old1, new1)

        # Show the link dialog box.
        if linkDlg.ShowModal() == wx.ID_CANCEL:
            return

        # Get the selections from the dialog boxes.
        (old2, new2) = linkDlg.getSelection()

        # Destroy the dialog box.
        linkDlg.Destroy()

        # If either input is an empty string, show an error.
        if old2 == '' or new2 == '':
            errorDialog = wx.MessageDialog(self,
                "One of the entries was empty.", "Error", wx.OK|wx.ICON_ERROR)
            errorDialog.ShowModal()

            return

        # Edit the link in the database.
        if old1 == old2 and new1 == new2:
            pass
        elif old1 != old2 and new1 == new2:
            isql.setLink(old2, new2, 1, self.connection)
            idata.unlinkData(old1, new1, self.connection2)
            idata.linkData(old2, new2, self.connection2)
        elif old1 == old2 and new1 != new2:
            isql.setLink(old2, new2, 2, self.connection)
            idata.unlinkData(old1, new1, self.connection2)
            idata.linkData(old2, new2, self.connection2)
        else:
            isql.setLink(old2, new2, old1, self.connection)
            idata.unlinkData(old1, new1, self.connection2)
            idata.linkData(old2, new2, self.connection2)

        # Update the link list
        self.updateList(event)

    def onDelete(self, event):
        """
        """

        # Get the selected data.
        index = self.linkList.GetFirstSelected()

        # If nothing is selected, send an error.
        if index == -1:
            errorDialog = wx.MessageDialog(self, "No item was selected.",
                "Error", wx.OK|wx.ICON_ERROR)
            errorDialog.ShowModal()

            return False

        # Get the string value of the old product.
        old = self.linkList.GetItemText(index)
        new = self.linkList.GetItemText(index, 1)

        # Iterate until all selected are removed.
        run = True
        while run:
            # Remove the link from the database.
            isql.removeLink(old, new, self.connection)

            # Remove the data link.
            idata.unlinkData(old, new, self.connection2)

            # Get the next index.
            index = self.linkList.GetNextSelected(index)

            # If there is no next index stop the loop.
            if index == -1:
                run = False
            else:
                old = self.linkList.GetItemText(index)
                new = self.linkList.GetItemText(index, 1)

        # Update the link list.
        self.updateList(event)

    def onOK(self, event):
        """
        """

        # Commit and close the database.
        self.connection.commit()
        self.connection.close()
        self.connection2.commit()
        self.connection2.close()

        self.Close()

    def onCancel(self, event):
        """
        """

        # Close the database.
        self.connection.close()
        self.connection2.close()

        self.Close()

    def onClose(self, event):
        """
        """

        self.Destroy()

"""
"""
class LinkDialog(wx.Dialog):
    """
    """

    def __init__(self, *args, **kwargs):
        """
        """

        # Initialize by the parent's constructor.
        super(LinkDialog, self).__init__(*args, **kwargs)

        # Create the master panel.
        masterPanel = wx.Panel(self)

        # Create the master sizer.
        masterSizer = wx.BoxSizer(wx.VERTICAL)

        # Create the box sizers.
        oldSizer = wx.BoxSizer(wx.HORIZONTAL)
        newSizer = wx.BoxSizer(wx.HORIZONTAL)

        # Create the static text.
        oldLabel = wx.StaticText(masterPanel, label="Old Product")
        newLabel = wx.StaticText(masterPanel, label="New Product")

        # Create the old and new text entries.
        self.oldEntry = wx.TextCtrl(masterPanel, size=(150, -1))
        self.newEntry = wx.TextCtrl(masterPanel, size=(150, -1))

        # Add the label and entries to the sizers.
        oldSizer.AddMany([oldLabel, (5, 0), self.oldEntry])
        newSizer.AddMany([newLabel, (5, 0), self.newEntry])

        # Get the choices for auto complete.
        links = self.getChoices()

        # Set the auto complete for the text entries.
        self.oldEntry.AutoComplete(links)
        self.newEntry.AutoComplete(links)

        # Create the finish sizer.
        finishSizer = wx.BoxSizer(wx.HORIZONTAL)

        # Create the finish buttons.
        okButton = wx.Button(masterPanel, id=wx.ID_OK)
        cancelButton = wx.Button(masterPanel, id=wx.ID_CANCEL)

        # Set the OK button to be the dafault button.
        okButton.SetDefault()

        # Add the finish buttons to the sizer.
        finishSizer.AddMany([okButton, (5, 0), cancelButton])

        # Add the text and combo box to the sizer.
        masterSizer.AddSpacer(10)
        masterSizer.Add(oldSizer, flag=wx.LEFT|wx.BOTTOM|wx.RIGHT|
            wx.ALIGN_RIGHT, border=5)
        masterSizer.Add(newSizer, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_RIGHT,
            border=5)
        masterSizer.Add(wx.StaticLine(masterPanel, size=(240, 20)),
            flag=wx.ALIGN_CENTER)
        masterSizer.Add(finishSizer, flag=wx.RIGHT|wx.BOTTOM|wx.ALIGN_RIGHT,
            border=5)

        # Set the master sizer.
        masterPanel.SetSizer(masterSizer)

        # Set the size of the window.
        self.SetSize((250, 150))

    def getChoices(self):
        """
        """

        # Get the list of variables.
        links = isql.getAttribute("product")

        # Extract only the first column.
        links = [link[0] for link in links]

        return links

    def getSelection(self):
        """
        """

        # Get the value of the text entries.
        old = self.oldEntry.GetValue()
        new = self.newEntry.GetValue()

        return old, new

    def setSelection(self, old, new):
        """
        """

        # Set the value of the text entries.
        self.oldEntry.SetValue(old)
        self.newEntry.SetValue(new)

        return True

"""
Start Application
"""
def main():
    """
    When the file is called independently create and display the manager frame.
    """

    app = wx.App()
    LinkFrame(None, style=wx.DEFAULT_FRAME_STYLE)#^wx.RESIZE_BORDER)
    app.MainLoop()

if __name__ == '__main__':
    main()