import timm
import torch.nn as nn
from torchinfo import summary

import config

class SETIModel(nn.Module):
    def __init__(self, model_name: str, pretrained: bool = True) -> None:
        super(SETIModel, self).__init__()
        self.model_name = model_name
        self.model = timm.create_model(
            model_name=self.model_name, pretrained=pretrained, in_chans=1
        )
        if config.MODEL_NAME.startswith("rexnet"):
            self.input_fc = self.model.head.fc.in_features
            self.model.head.fc = nn.Linear(
                in_features=self.input_fc, out_features=1, bias=True
            )
        elif config.MODEL_NAME.startswith("efficientnet"):
            self.input_fc = self.model.classifier.in_features
            self.model.classifier = nn.Linear(
                in_features=self.input_fc, out_features=1, bias=True
            )
        elif config.MODEL_NAME.startswith("resnet"):
            self.input_fc = self.model.fc.in_features
            self.model.fc = nn.Linear(
                in_features=self.input_fc, out_features=1, bias=True
            )
        else:
            raise NotImplementedError("Model head has not been modified.")

    def forward(self, x):
        return self.model(x)

def model_details(model, x):
    print("Model summary:")
    summary(
        model,
        input_size=(config.BATCH_SIZE, 1, config.SIZE, config.SIZE),
        verbose=1,
    )
    print(f"Output size: {model(x).shape}")

if __name__ == "__main__":
    import torch

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = SETIModel(model_name=config.MODEL_NAME)
    model = model.to(device)
    x = torch.rand(16, 1, config.SIZE, config.SIZE)
    x = x.to(device)
    model_details(model, x)


# BOJ No.1339
# 단어 수학

n=int(input())
words=[]
alphabet='abcdefghijklmnopqrstuvwxyz'
for _ in range(n):
    word=input()
    words.append(list(word))
dicts={x:0 for x in alphabet.upper()}
# 알파벳의 자리 수에 해당하는 만큼 10의 거듭제곱 수를 더해줌
for i in range(len(words)):
    words[i]=words[i][::-1]
    for j in range(len(words[i])):
        dicts[words[i][j]]+=10**j
result=0
lst=[]

for value in dicts.values():
    lst.append(value)
lst.sort(reverse=True)
m=9
# 1~9까지 값의 크기 순으로 분배
while m>0:
    for i in lst:
        result+=i*m
        m-=1
print(result)


from PyQt4 import QtGui, QtCore
import random

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8

    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class RoiInputBox(QtGui.QWidget):
    def __init__(self, roi, controller):
        super(RoiInputBox, self).__init__()

        self.controller = controller

        self.setMinimumHeight(100)

        self.name = roi.name  #"roi_{0:s}".format(roi.name)
        self.roi_name = roi.name
        self.color = (random.randint(25, 200), random.randint(25, 200), random.randint(25, 200))

        self.setObjectName(_fromUtf8(self.name))

        self.vertLO_input_box = QtGui.QVBoxLayout(self)
        self.vertLO_input_box.setObjectName(_fromUtf8("vertLO_input_box"))

        self.lbl_name = QtGui.QLabel(self)
        self.lbl_name.setObjectName(_fromUtf8("lbl_name"))
        self.lbl_name.setAutoFillBackground(True)
        color_string = "rgb({0:s},{1:s},{2:s})".format(str(self.color[0]), str(self.color[1]), str(self.color[2]))
        self.lbl_name.setStyleSheet("QLabel {{color: {0:s}; }}".format(color_string))
        self.vertLO_input_box.addWidget(self.lbl_name)

        self.gridLO_set_roi = QtGui.QGridLayout()
        self.gridLO_set_roi.setObjectName(_fromUtf8("gridLO_set_roi"))
        # spin box x start
        self.spinBox_roi_x1 = QtGui.QSpinBox(self)
        self.spinBox_roi_x1.setMaximum(9999)
        self.spinBox_roi_x1.setObjectName(_fromUtf8("spinBox_x_start"))
        self.gridLO_set_roi.addWidget(self.spinBox_roi_x1, 0, 1, 1, 1)
        # spin box x end
        self.spinBox_roi_x2 = QtGui.QSpinBox(self)
        self.spinBox_roi_x2.setMaximum(9999)
        self.spinBox_roi_x2.setObjectName(_fromUtf8("spinBox_x_end"))
        self.gridLO_set_roi.addWidget(self.spinBox_roi_x2, 0, 3, 1, 1)
        # spin box y start
        self.spinBox_roi_y1 = QtGui.QSpinBox(self)
        self.spinBox_roi_y1.setMaximum(9999)
        self.spinBox_roi_y1.setObjectName(_fromUtf8("spinBox_y_start"))
        self.gridLO_set_roi.addWidget(self.spinBox_roi_y1, 1, 1, 1, 1)
        # spin box y end
        self.spinBox_roi_y2 = QtGui.QSpinBox(self)
        self.spinBox_roi_y2.setMaximum(9999)
        self.spinBox_roi_y2.setObjectName(_fromUtf8("spinBox_y_end"))
        self.gridLO_set_roi.addWidget(self.spinBox_roi_y2, 1, 3, 1, 1)
        # label x start
        self.lbl_roi_x_start = QtGui.QLabel(self)
        self.lbl_roi_x_start.setObjectName(_fromUtf8("lbl_roi_x_start"))
        self.gridLO_set_roi.addWidget(self.lbl_roi_x_start, 0, 0, 1, 1)
        # label x end
        self.lbl_roi_x_end = QtGui.QLabel(self)
        self.lbl_roi_x_end.setObjectName(_fromUtf8("lbl_roi_x_end"))
        self.gridLO_set_roi.addWidget(self.lbl_roi_x_end, 0, 2, 1, 1)
        # label y start
        self.lbl_roi_y_start = QtGui.QLabel(self)
        self.lbl_roi_y_start.setObjectName(_fromUtf8("lbl_roi_y_start"))
        self.gridLO_set_roi.addWidget(self.lbl_roi_y_start, 1, 0, 1, 1)
        # label y end
        self.lbl_roi_y_end = QtGui.QLabel(self)
        self.lbl_roi_y_end.setObjectName(_fromUtf8("lbl_roi_y_end"))
        self.gridLO_set_roi.addWidget(self.lbl_roi_y_end, 1, 2, 1, 1)
        # add grid_layout_set_roi to vertical layout of tab
        self.vertLO_input_box.addLayout(self.gridLO_set_roi)

    def get_values(self):
        x1 = self.spinBox_roi_x1.value()
        y1 = self.spinBox_roi_y1.value()
        x2 = self.spinBox_roi_x2.value()
        y2 = self.spinBox_roi_y2.value()
        return x1, y1, x2, y2

    def connect_widgets(self, controller):
        self.connect(self.spinBox_roi_x1, QtCore.SIGNAL("valueChanged(int)"), self.send_value_change_x1)
        self.connect(self.spinBox_roi_x2, QtCore.SIGNAL("valueChanged(int)"), self.send_value_change_x2)
        self.connect(self.spinBox_roi_y1, QtCore.SIGNAL("valueChanged(int)"), self.send_value_change_y1)
        self.connect(self.spinBox_roi_y2, QtCore.SIGNAL("valueChanged(int)"), self.send_value_change_y2)
        return

    def send_value_change_x1(self):
        self.controller.change_roi_value(self, "x1")

    def send_value_change_x2(self):
        self.controller.change_roi_value(self, "x2")

    def send_value_change_y1(self):
        self.controller.change_roi_value(self, "y1")

    def send_value_change_y2(self):
        self.controller.change_roi_value(self, "y2")

    def retranslate_roi_input_box(self):
        self.lbl_name.setText(_translate("tracker_main_widget", self.name, None))
        self.lbl_roi_y_end.setText(_translate("tracker_main_widget", "Y End", None))
        self.lbl_roi_x_end.setText(_translate("tracker_main_widget", "X End", None))
        self.lbl_roi_x_start.setText(_translate("tracker_main_widget", "X Start", None))
        self.lbl_roi_y_start.setText(_translate("tracker_main_widget", "Y Start", None))


class Solution:
    def powers(self, n, p, ip, M):
        pw = 1
        invpw = 1
        ppow = []
        invppow = []
        for _ in range(n):
            ppow.append(pw)
            invppow.append(invpw)
            pw = (pw * p) % M
            invpw = (invpw * ip) % M
        return ppow, invppow

    def hashes(self, s, p, M):
        n = len(s)
        h = [0] * (n + 1)
        for i in range(n):
            h[i + 1] = (h[i] + self.ppow[i] * (ord(s[i]) - ord('a'))) % M
        return h

    def distinctEchoSubstrings(self, text: str) -> int:
        n = len(text)
        M = 10 ** 9 + 9
        p = 31
        self.ppow, self.invppow = self.powers(n + 1, p, pow(p, M - 2, M), M)
        subhash = lambda h, i, j: (self.invppow[i] * (h[j + 1] + M - h[i])) % M
        hashes = self.hashes(text, p, M)
        res = set()
        for i in range(n):
            for j in range(i, (i + n) // 2):
                if subhash(hashes, i, j) == subhash(hashes, j + 1, 2 * j - i + 1):
                    res.add(text[i:j+1])
        return len(res)


# %%
from typing import Optional, Union
import pandas as pd
import numpy as np
import requests, re, os

from concurrent.futures import ProcessPoolExecutor

class Decrypter:
    """Simple MCMC decryption algorithm using random walk"""
    def __init__(self, text_url: str,
                       allowable_chars: str = r"[a-zA-Z0-9\s]",
                       allow_uppercase:bool = False,
                       max_workers: Optional[int] = None,
                       **kwargs) -> None:

        self.reference_text_url = text_url
        self.allowable_chars    = allowable_chars
        self.allow_uppercase    = allow_uppercase
        self.max_workers        = max_workers if max_workers is not None else os.cpu_count()
        self.kwargs             = kwargs

        self.reference_text     = self.get_text()
        self.reference_text     = self.clean_text(self.reference_text)

    def get_text(self) -> str:
        """Retrieves text from given url

        Returns:
            str: text from url
        """
        r = requests.get(self.reference_text_url)
        return r.text

    def clean_text(self, text:str) -> str:
        """Removes non-allowable characters from text

        Args:
            text (str): text to clean

        Returns:
            str: cleaned text
        """

        #Find the substring that marks the end of the text
        start_substring = re.search(r"\*\*\* START OF THE PROJECT GUTENBERG EBOOK ", text).end()
        end_substring   = re.search(r"\*\*\* END OF THE PROJECT GUTENBERG EBOOK ", text).start()
        text            = text[start_substring:end_substring]

        #If uppercase are not allowed, turn them into lowercase
        if not self.allow_uppercase:
            text = text.lower()

        #Remove non-allowable characters
        text = re.sub(self.invert_regex_pattern(), "", text)

        #Convert all whitespace to single space
        text = re.sub(r"\s+", " ", text)

        return text

    def invert_regex_pattern(self, pattern: Optional[str] = None) -> str:
        """Inverts the given regex pattern. Only works with simple regex patterns

        Args:
            pattern (Optional[str], optional): Simple regex pattern to invert. Defaults to None.

        Returns:
            str: inverted regex pattern
        """
        if pattern is None:
            pattern = self.allowable_chars

        pattern = re.sub(r"\[", r"[^", pattern)
        return pattern

    def generate_transition_matrix(self, text: str, initialized_dataframe:pd.DataFrame) -> pd.DataFrame:
        """Generates transition matrix from text

        Args:
            text (str): text to generate transition matrix from

        Returns:
            pd.DataFrame: transition matrix
        """

        #Iterate through each character in the text.
        for i in range(len(text) - 1):
            initialized_dataframe.loc[text[i], text[i+1]] += 1

        return initialized_dataframe

    def get_charset(self, text:str, sorted:bool = False) -> Union[set[str], list[str]]:
        """Gets the charset of the given text

        Args:
            text (str): text to get charset for

        Returns:
            set: charset
        """
        return_set = set(text)
        if sorted:
            return_set = list(return_set)
            return_set.sort()

        return return_set

    def generate_transition_matrix_from_text(self) -> None:
        """Generates transition matrix from text

        Returns:
            pd.DataFrame: transition matrix
        """
        #Check if the transition matrix has already been generated
        if hasattr(self, "transition_matrix"):
            return

        #Generate a set of all characters in the text then sort them
        self.charset    = self.get_charset(self.reference_text, sorted=True)

        #Create a dataframe with the characters as the columns and the characters as the rows
        transition_matrix = pd.DataFrame(0, index=self.charset, columns=self.charset)

        #Begin preparations for multiprocessing to speed up the process

        #Create a list of the text to be split up into chunks
        chunk_length = int(np.ceil(len(self.reference_text) / self.max_workers))

        text_chunks = [
            self.reference_text[i * chunk_length : (i + 1)  * chunk_length]
            for i in range(self.max_workers)
        ]

        #Create a list of the dataframes to be used for multiprocessing
        dataframes = [transition_matrix.copy() for _ in range(self.max_workers)]

        #Start multiprocessing
        with ProcessPoolExecutor(max_workers=self.max_workers) as executor:
            dataframe_list = executor.map(self.generate_transition_matrix, text_chunks, dataframes)

        #Combine the dataframes
        for dataframe in dataframe_list:
            transition_matrix += dataframe

        #Add the transitions between the chunks
        for i in range(self.max_workers - 1):
            transition_matrix.loc[text_chunks[i][-1], text_chunks[i+1][0]] += 1

        self.transition_matrix = transition_matrix

        #Normalize the transition matrix so that each row sums to 1 and replace nan values with 0
        self.transition_matrix = self.transition_matrix.div(self.transition_matrix.sum(axis=1), axis=0).fillna(0)

        #Take the log of the transition matrix with a hard bottom of the lowest non-zero value in the matrix minus 20
        transition_matrix       = self.transition_matrix.to_numpy()
        nonzero_values          = transition_matrix[transition_matrix > 0]
        min_value               = np.log(np.min(nonzero_values))
        self.transition_matrix  = np.log(self.transition_matrix).clip(min_value - 20)

        return

    def find_cypher(self, text:str, max_iterations:int = 10_000) -> dict:
        """Finds the cypher for the given text

        Args:
            text (str): text to find cypher for
            max_iterations (int, optional): Maximum number of iterations to run. Defaults to 100.
            max_plausibility (float, optional): Maximum plausibility of the cypher. Defaults to 0.99.

        Returns:
            dict: cypher
        """
        self.text = text
        #Generate the transition matrix, protecting against multiprocess loops in Windows
        if __name__ == "__main__":
            self.generate_transition_matrix_from_text()

        text_charset = self.get_charset(text)

        #Generate a cypher, then calculate its plausibility
        cypher              = self.generate_map(text_charset)
        cypher.plausibility = self.calculate_plausibility(cypher)

        #Keep track of the best cypher found so far as per the plausibility. This will be the cypher that is returned
        self.best_cypher = cypher

        for i in range(max_iterations):
            #Generate the cypher based on the current cypher and calculate its plausibility
            new_cypher              = self.generate_map(text_charset, cypher.copy())
            new_cypher.plausibility = self.calculate_plausibility(new_cypher)

            #If the new cypher is better than the current best cypher, replace it
            if new_cypher.plausibility >= cypher.plausibility:
                cypher = new_cypher
                #If it's also better than the best cypher found so far, replace that too
                if cypher.plausibility >= self.best_cypher.plausibility:
                    self.best_cypher = cypher
            else:
                #If the new cypher is worse than the current cypher, flip a coin with acceptance P(new_cypher) / P(current_cypher)
                #If heads, replace the current cypher with the new one even if it's worse than the current cypher. This will
                #help the algorithm to break out of local minima
                uniform_value = np.random.uniform(0, 1)
                div = np.exp(new_cypher.plausibility - cypher.plausibility)
                if uniform_value < div:
                    cypher = new_cypher

            #Every 1000 iterations, print out the current best cypher
            if i % 1000 == 0:
                print(f"Iteration {i} - Plausibility: {self.best_cypher.plausibility}")
                print(self.best_cypher.decode(text))

        return self.best_cypher, self.best_cypher.decode(text)

    def calculate_plausibility(self, cypher_map:'Cypher') -> float:
        """Test the plausibility of the given map

        Args:
            map (dict): map to test

        Returns:
            float: plausibility of the map
        """
        #Calculate the plausibility of the cypher, starting as if the first character is a space
        plausability = 0
        text = " " + self.text

        for i, char in enumerate(text[:-1]):
            first_char      = cypher_map[char]
            second_char     = cypher_map[text[i+1]]
            plausability   += self.transition_matrix.loc[first_char, second_char]

        return plausability

    def generate_map(self, text_charset:set[str], cypher_map:Optional['Cypher'] = None) -> 'Cypher':
        """Generates or updates the map

        Args:
            map (Optional[dict], optional): map to update. Defaults to None.

        Returns:
            dict: map
        """
        #If the map is not given, generate a random map assigning each character to a random character without replacement
        if cypher_map is None:
            cypher_map = {}
            # #The initial charset should primarily focus on the text charset, but should also include the allowable charset
            charset = [char for char in text_charset] + [char for char in self.charset if char not in text_charset]
            charset_copy = [x for x in charset]
            for char in charset_copy:
                random_char = np.random.choice(charset)
                cypher_map[char] = random_char
                charset.remove(random_char)
            cypher_map = Cypher(cypher_map)
        else:
            #Otherwise make one swap by picking the first character from the charset and the second character from the cypher map
            char1           = np.random.choice(list(text_charset))
            cypher_keys     = [char for char in cypher_map.keys() if char != char1]
            char2           = np.random.choice(cypher_keys)

            cypher_map.swap_chars(char1, char2)

        return cypher_map

class Cypher:
    def __init__(self, cypher_map:dict[str, str], invert_map:bool = False) -> None:
        if invert_map:
            self.cypher_map = self.invert_map(cypher_map)
        else:
            self.cypher_map     = cypher_map
        self.plausibility   = None

    @staticmethod
    def invert_map(dictionary: dict) -> dict:
        return {v: k for k, v in dictionary.items()}

    def decode(self, text:str) -> str:
        """Encodes the given text using the cypher map

        Args:
            text (str): text to encode

        Returns:
            str: encoded text
        """
        encoded_text = ""
        for char in text:
            encoded_text += self.cypher_map[char]
        return encoded_text

    def encode(self, text:str) -> str:
        """Decodes the given text using the cypher map

        Args:
            text (str): text to decode

        Returns:
            str: decoded text
        """
        decoded_text = ""
        char_map = self.invert_map(self.cypher_map)
        for char in text:
            decoded_text += char_map[char]
        return decoded_text

    def __getitem__(self, char:str) -> str:
        return self.cypher_map[char]

    def __setitem__(self, char:str, value:str) -> None:
        self.cypher_map[char] = value

    def swap_chars(self, char1:str, char2:str) -> None:
        """Swaps the characters in the cypher map

        Args:
            char1 (str): first character
            char2 (str): second character
        """
        self.cypher_map[char1], self.cypher_map[char2] = self.cypher_map[char2], self.cypher_map[char1]

    def __eq__(self, other:'Cypher') -> bool:
        return self.cypher_map == other.cypher_map

    def copy(self) -> 'Cypher':
        """Returns a copy of the cypher

        Returns:
            Cypher: copy of the cypher
        """
        new_cypher = Cypher(self.cypher_map.copy())
        new_cypher.plausibility = self.plausibility
        return new_cypher

    def keys(self) -> list[str]:
        """Returns the keys of the cypher map

        Returns:
            list[str]: keys of the cypher map
        """
        return list(self.cypher_map.keys())

# %%
if __name__ == "__main__":
    dc = Decrypter(r"https://www.gutenberg.org/files/2600/2600-0.txt")
    encoded_text = 'g afpa ham gag afpag1qga7wag1paz9pwg7 mac1pg1phag7wam fnpha7mag1pa27mdag aw900phag1pawn7mxwaqmdaqhh cwa 0a 9ghqxp 9wa0 hg9mpa hag agqepaqh2waqxq7mwgaqawpqa 0agh 9fnpw' #Harder test text
    # encoded_text = "mg zt gk fgm mg zt miam ol mit jwtlmogf citmitk mol fgzstk of mit dofr mg lwyytk mit lsoful afr akkgcl gy gwmkautgwl ygkmwft gk mg maqt akdl auaoflm a lta gy mkgwzstl afr zb ghhglofu tfr mitd mg rot mg lstth" #Easy test text
    cypher, decoded_text = dc.find_cypher(encoded_text, max_iterations = 100_000, )
# %%
# dc.find_cypher(encoded_text)


import pickle
from hyperopt import fmin, tpe, hp, STATUS_OK, Trials
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from fastsklearnfeature.candidates.CandidateFeature import CandidateFeature
from fastsklearnfeature.candidates.RawFeature import RawFeature
from fastsklearnfeature.transformations.OneHotTransformation import OneHotTransformation
from typing import List

def create_min_curve(losses, test):
	min_losses = [losses[0]]
	test_equi = [test[0]]
	for l in np.arange(1, len(losses)):
		if min_losses[-1] > losses[l]:
			min_losses.append(losses[l])
			test_equi.append(test[l])
		else:
			min_losses.append(min_losses[-1])
			test_equi.append(test_equi[-1])
	return min_losses, test_equi

#all_features_200: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_new2.p", "rb"))

#all_features_200: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_step.p", "rb"))

all_features_200: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_new.p", "rb"))

#raw_first: Trials = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/trials_new.p", "rb"))

numeric_representations: List[CandidateFeature] = pickle.load(open("/home/felix/phd/feature_constraints/experiment1/features.p", "rb"))

name2feature = {}
name2id = {}
feature_names = []
for f in range(len(numeric_representations)):
	name2feature[str(numeric_representations[f])] = numeric_representations[f]
	name2id[str(numeric_representations[f])] = f
	feature_names.append(str(numeric_representations[f]))

losses = np.array([r['loss'] for r in all_features_200.results])
#losses_raw = [r['loss'] for r in raw_first.results]

complexities = np.zeros(len(losses))
feature_count = np.zeros(len(numeric_representations))

feature_scores = []

for t in range(len(numeric_representations)):
	feature_scores.append([])

for k,v in all_features_200.vals.items():
	for i in range(len(losses)):
		if v[i]:
			if k in name2feature:
				complexities[i] += name2feature[k].get_complexity()
				feature_count[name2id[k]] += 1
				feature_scores[name2id[k]].append(all_features_200.results[i]['loss'])

'''
test = [r['test'] for r in all_features_200.results]
test_raw = [r['test'] for r in raw_first.results]
'''

feature_score_average = []
feature_score_stddev = []
for trial_losses in feature_scores:
	feature_score_average.append(np.average(trial_losses))
	feature_score_stddev.append(np.std(trial_losses))

feature_score_average = np.array(feature_score_average)
feature_score_stddev = np.array(feature_score_stddev)

ids = np.argsort(feature_score_average)

fig, ax = plt.subplots()
barlist= plt.bar(range(len(numeric_representations)), feature_score_average[ids], yerr=feature_score_stddev[ids])

for f_id in ids:
	fname = feature_names[f_id]
	if fname in all_features_200.best_trial['misc']['vals'] and all_features_200.best_trial['misc']['vals'][fname][0]:
		barlist[f_id].set_color('red')
	else:
		barlist[f_id].set_color('blue')

plt.xticks(range(len(numeric_representations)), np.array(feature_names)[ids], rotation='vertical')
plt.margins(0.2)
# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=0.5)
plt.show()

ids = np.argsort(feature_count*-1)

fig, ax = plt.subplots()
barlist= plt.bar(range(len(numeric_representations)), feature_count[ids])

for f_id in ids:
	fname = feature_names[f_id]
	if fname in all_features_200.best_trial['misc']['vals'] and all_features_200.best_trial['misc']['vals'][fname][0]:
		barlist[f_id].set_color('red')
	else:
		barlist[f_id].set_color('blue')

plt.xticks(range(len(numeric_representations)), np.array(feature_names)[ids], rotation='vertical')
plt.margins(0.2)
# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=0.5)
plt.show()

test = 1.0 - np.array([r['test'] for r in all_features_200.results])

ids = np.argsort(complexities)

plt.plot(complexities[ids], losses[ids], color='red', label='cv error')
plt.plot(complexities[ids], test[ids], color='blue', label='test error')
plt.xlabel('Complexity')
plt.ylabel('Loss (1.0 - AUC)')

leg = plt.legend(loc='best', ncol=1, mode="expand", shadow=True, fancybox=True)
leg.get_frame().set_alpha(0.5)

plt.show()

plt.plot(range(len(complexities)), complexities, color='red')
plt.xlabel('Trials')
plt.ylabel('Complexity')

leg = plt.legend(loc='best', ncol=1, mode="expand", shadow=True, fancybox=True)
leg.get_frame().set_alpha(0.5)

plt.show()


import fintech.accounts as accounts
import pymysql

def write_account_transaction_to_db(filename, account):
    print('Starting write of DB example')

    # Open database connection
    connection = pymysql.connect('localhost', 'user', 'password', 'accounts')

    # prepare a cursor object using cursor() method
    cursor = connection.cursor()

    try:
        # Execute INSERT command
        account_number = account.account_number
        name = account.account_holder
        cursor.execute(
            "INSERT INTO acc_info (idacc_info, name) " +
            "VALUES (" + account_number + ", '" + name + "')")
        # Commit the changes to the database

        # Write out the transactions
        for transaction in account.history:
            id = transaction.id
            action = transaction.action
            amount = transaction.amount
            statement = "INSERT into transactions (idtransactions, type, amount, account) VALUES (" + str(id) + ", '" + action + "', " + str(amount) + ", " + str(account_number) + ")"
            print(statement)
            cursor.execute(statement)
        connection.commit()
    except Exception as exp:
        # Something went wrong
        # rollback the changes
        print(exp)
        connection.rollback()

    # Close the database connection
    connection.close()

    print('Done Write DB Example')

print('Starting')
acc = accounts.CurrentAccount('123', 'John', 10.05, 100.0)
acc.deposit(23.45)
acc.withdraw(12.33)

print('Writing Account Transactions')
write_account_transaction_to_db('accounts.xlsx', acc)

print('Done')


import datetime
from yahooquery import Ticker
import matplotlib.pyplot as plt
import pandas as pd

today = datetime.datetime.strptime(str(datetime.date.today()),'%Y-%m-%d').date()

from_date = datetime.datetime.strptime("2021-01-06", "%Y-%m-%d").date()

print(f'Collecting data from {from_date} - {today}')
#end_date = date_1 + datetime.timedelta(days=10)
to_date = from_date
spy = Ticker('spy')
li = []
while to_date < today:
    to_date = from_date + datetime.timedelta(days=7)
    print(f'{from_date} - {to_date}')
    temp_df = spy.history(start=from_date, end=to_date, interval="5m")

    li.append(temp_df)
    from_date = to_date

spy_data = pd.concat(li)
outfile = open("spy_data.csv", 'wb')
spy_data.to_csv(outfile, sep='\t', encoding='utf-8')
outfile.close()


#BOJ 10844번

# IDEA
# [자릿수][나올숫자]
# 0인 경우 / 9인 경우는 전의 특정 자릿수만 보면됨

n = int(input())
dp = [ [0] * 10 for _ in range(n)]

for i in range(1,10) :
    dp[0][i] = 1

for i in range(1,n) :
    for j in range( 0 , 10 ) :
        if j == 0 :
            dp[i][j] = dp[i-1][1]
        elif j == 9 :
            dp[i][j] = dp[i-1][8]
        else :
            dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1]

answer = 0
for temp in dp[n-1] :
    answer += temp % 1000000000
print( answer % 1000000000 )


from PyQt5.QtWidgets import (
  QPushButton, QDialog, QLabel,
  QFileDialog, QLineEdit, QDialogButtonBox,
  QFormLayout, QVBoxLayout, QWidget, QSpinBox
)
from .common_gui import accept_and_finish
from logic.train_network import train

class TrainWindow(QDialog):
  def __init__(self, parent):
    super().__init__(parent)
    self.setWindowTitle("Train neural network")
    self.layout = QFormLayout()
    self.setup_form()
    self.setup_end_buttons()
    self.setLayout(self.layout)
    self.exec()

  def setup_form(self):
    form = QWidget(self)
    form_layout = QFormLayout()
    label_processed_midi = QLabel('Select processed midi')
    self.processed_midi_input = QLineEdit()
    self.processed_midi_input.setReadOnly(True)
    form_layout.addRow(label_processed_midi, self.processed_midi_input)

    browser_button_midi = QPushButton('Browser...')
    browser_button_midi.setObjectName('BrowserButton')
    browser_button_midi.pressed.connect(self.set_processed_midi)
    form_layout.addWidget(browser_button_midi)

    label_weights_folder = QLabel('Select neural network weights folder')
    self.weights_folder_input = QLineEdit()
    self.weights_folder_input.setReadOnly(True)
    form_layout.addRow(label_weights_folder, self.weights_folder_input)

    browser_button_wights = QPushButton('Browser...')
    browser_button_wights.setObjectName('BrowserButton')
    browser_button_wights.pressed.connect(self.set_weights_folder)
    form_layout.addWidget(browser_button_wights)

    label_output_midi = QLabel('Number of epochs')
    label_output_midi.setObjectName('QLabelRow')
    self.epochs = QSpinBox()
    self.epochs.setObjectName('QSpinBox')
    self.epochs.setRange(1, 999999)
    self.epochs.setValue(8)
    form_layout.addRow(label_output_midi, self.epochs)

    form.setLayout(form_layout)
    self.layout.addWidget(form)

  def setup_end_buttons(self):
    buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
    buttonBox.accepted.connect(self.end_dialog)
    buttonBox.rejected.connect(self.reject)
    self.layout.addWidget(buttonBox)

  def end_dialog(self):
    accept_and_finish([
      self.processed_midi_input.text(),
      self.weights_folder_input.text(),
      self.epochs.value()
    ], train, self)

  def set_processed_midi(self):
    self.processed_midi_input.setText(
      QFileDialog.getOpenFileName (None, 'Select processed midi file')[0]
    )

  def set_weights_folder(self):
    directory_list = QFileDialog.getExistingDirectory(None, "Select weights Directory")
    print(directory_list)
    if directory_list:
      self.weights_folder_input.setText(directory_list)


import logging
import sqlalchemy as sa

from datetime import datetime, timedelta

from pyramid.threadlocal import get_current_request
from sqlalchemy.dialects.postgresql import JSON
from ziggurat_foundations.models.base import BaseModel

from appenlight.models import Base, get_db_session, Datastores
from appenlight.lib.enums import ReportType
from appenlight.lib.rule import Rule
from appenlight.lib.redis_keys import REDIS_KEYS
from appenlight.models.report import REPORT_TYPE_MATRIX

log = logging.getLogger(__name__)

class ReportGroup(Base, BaseModel):
    __tablename__ = "reports_groups"
    __table_args__ = {"implicit_returning": False}

    id = sa.Column(sa.BigInteger(), nullable=False, primary_key=True)
    resource_id = sa.Column(
        sa.Integer(),
        sa.ForeignKey(
            "applications.resource_id", onupdate="CASCADE", ondelete="CASCADE"
        ),
        nullable=False,
        index=True,
    )
    priority = sa.Column(
        sa.Integer, nullable=False, index=True, default=5, server_default="5"
    )
    first_timestamp = sa.Column(
        sa.DateTime(), default=datetime.utcnow, server_default=sa.func.now()
    )
    last_timestamp = sa.Column(
        sa.DateTime(), default=datetime.utcnow, server_default=sa.func.now()
    )
    error = sa.Column(sa.UnicodeText(), index=True)
    grouping_hash = sa.Column(sa.String(40), default="")
    triggered_postprocesses_ids = sa.Column(JSON(), nullable=False, default=list)
    report_type = sa.Column(sa.Integer, default=1)
    total_reports = sa.Column(sa.Integer, default=1)
    last_report = sa.Column(sa.Integer)
    occurences = sa.Column(sa.Integer, default=1)
    average_duration = sa.Column(sa.Float, default=0)
    summed_duration = sa.Column(sa.Float, default=0)
    read = sa.Column(sa.Boolean(), index=True, default=False)
    fixed = sa.Column(sa.Boolean(), index=True, default=False)
    notified = sa.Column(sa.Boolean(), index=True, default=False)
    public = sa.Column(sa.Boolean(), index=True, default=False)

    reports = sa.orm.relationship(
        "Report",
        lazy="dynamic",
        backref="report_group",
        cascade="all, delete-orphan",
        passive_deletes=True,
        passive_updates=True,
    )

    comments = sa.orm.relationship(
        "ReportComment",
        lazy="dynamic",
        backref="report",
        cascade="all, delete-orphan",
        passive_deletes=True,
        passive_updates=True,
        order_by="ReportComment.comment_id",
    )

    assigned_users = sa.orm.relationship(
        "User",
        backref=sa.orm.backref(
            "assigned_reports_relation",
            lazy="dynamic",
            order_by=sa.desc(sa.text("reports_groups.id")),
        ),
        passive_deletes=True,
        passive_updates=True,
        secondary="reports_assignments",
        order_by="User.user_name",
    )

    stats = sa.orm.relationship(
        "ReportStat",
        lazy="dynamic",
        backref="report",
        passive_deletes=True,
        passive_updates=True,
    )

    last_report_ref = sa.orm.relationship(
        "Report",
        uselist=False,
        primaryjoin="ReportGroup.last_report " "== Report.id",
        foreign_keys="Report.id",
        cascade="all, delete-orphan",
        passive_deletes=True,
        passive_updates=True,
    )

    def __repr__(self):
        return "<ReportGroup id:{}>".format(self.id)

    def get_report(self, report_id=None, public=False):
        """
        Gets report with specific id or latest report if id was not specified
        """
        from .report import Report

        if not report_id:
            return self.last_report_ref
        else:
            return self.reports.filter(Report.id == report_id).first()

    def get_public_url(self, request, _app_url=None):
        url = request.route_url("/", _app_url=_app_url)
        return (url + "ui/report/%s") % self.id

    def run_postprocessing(self, report):
        """
        Alters report group priority based on postprocessing configuration
        """
        request = get_current_request()
        get_db_session(None, self).flush()
        for action in self.application.postprocess_conf:
            get_db_session(None, self).flush()
            rule_obj = Rule(action.rule, REPORT_TYPE_MATRIX)
            report_dict = report.get_dict(request)
            # if was not processed yet
            if (
                rule_obj.match(report_dict)
                and action.pkey not in self.triggered_postprocesses_ids
            ):
                action.postprocess(self)
                # this way sqla can track mutation of list
                self.triggered_postprocesses_ids = self.triggered_postprocesses_ids + [
                    action.pkey
                ]

        get_db_session(None, self).flush()
        # do not go out of bounds
        if self.priority < 1:
            self.priority = 1
        if self.priority > 10:
            self.priority = 10

    def get_dict(self, request):
        instance_dict = super(ReportGroup, self).get_dict()
        instance_dict["server_name"] = self.get_report().tags.get("server_name")
        instance_dict["view_name"] = self.get_report().tags.get("view_name")
        instance_dict["resource_name"] = self.application.resource_name
        instance_dict["report_type"] = self.get_report().report_type
        instance_dict["url_path"] = self.get_report().url_path
        instance_dict["front_url"] = self.get_report().get_public_url(request)
        del instance_dict["triggered_postprocesses_ids"]
        return instance_dict

    def es_doc(self):
        return {
            "_id": str(self.id),
            "group_id": str(self.id),
            "resource_id": self.resource_id,
            "error": self.error,
            "fixed": self.fixed,
            "public": self.public,
            "read": self.read,
            "priority": self.priority,
            "occurences": self.occurences,
            "average_duration": self.average_duration,
            "summed_duration": self.summed_duration,
            "first_timestamp": self.first_timestamp,
            "last_timestamp": self.last_timestamp,
            "type": "report_group",
            "join_field": {"name": "report_group"},
        }

    def set_notification_info(self, notify_10=False, notify_100=False):
        """
        Update redis notification maps for notification job
        """
        current_time = datetime.utcnow().replace(second=0, microsecond=0)
        # global app counter
        key = REDIS_KEYS["counters"]["reports_per_type"].format(
            self.report_type, current_time
        )
        redis_pipeline = Datastores.redis.pipeline()
        redis_pipeline.incr(key)
        redis_pipeline.expire(key, 3600 * 24)
        # detailed app notification for alerts and notifications
        redis_pipeline.sadd(REDIS_KEYS["apps_that_had_reports"], self.resource_id)
        redis_pipeline.sadd(
            REDIS_KEYS["apps_that_had_reports_alerting"], self.resource_id
        )
        # only notify for exceptions here
        if self.report_type == ReportType.error:
            redis_pipeline.sadd(REDIS_KEYS["apps_that_had_reports"], self.resource_id)
            redis_pipeline.sadd(
                REDIS_KEYS["apps_that_had_error_reports_alerting"], self.resource_id
            )
        key = REDIS_KEYS["counters"]["report_group_occurences"].format(self.id)
        redis_pipeline.incr(key)
        redis_pipeline.expire(key, 3600 * 24)
        key = REDIS_KEYS["counters"]["report_group_occurences_alerting"].format(self.id)
        redis_pipeline.incr(key)
        redis_pipeline.expire(key, 3600 * 24)

        if notify_10:
            key = REDIS_KEYS["counters"]["report_group_occurences_10th"].format(self.id)
            redis_pipeline.setex(key, 3600 * 24, 1)
        if notify_100:
            key = REDIS_KEYS["counters"]["report_group_occurences_100th"].format(
                self.id
            )
            redis_pipeline.setex(key, 3600 * 24, 1)

        key = REDIS_KEYS["reports_to_notify_per_type_per_app"].format(
            self.report_type, self.resource_id
        )
        redis_pipeline.sadd(key, self.id)
        redis_pipeline.expire(key, 3600 * 24)
        key = REDIS_KEYS["reports_to_notify_per_type_per_app_alerting"].format(
            self.report_type, self.resource_id
        )
        redis_pipeline.sadd(key, self.id)
        redis_pipeline.expire(key, 3600 * 24)
        redis_pipeline.execute()

    @property
    def partition_id(self):
        return "rcae_r_%s" % self.first_timestamp.strftime("%Y_%m")

    def partition_range(self):
        start_date = self.first_timestamp.date().replace(day=1)
        end_date = start_date + timedelta(days=40)
        end_date = end_date.replace(day=1)
        return start_date, end_date

def after_insert(mapper, connection, target):
    if not hasattr(target, "_skip_ft_index"):
        data = target.es_doc()
        data.pop("_id", None)
        Datastores.es.index(target.partition_id, "report", data, id=target.id)

def after_update(mapper, connection, target):
    if not hasattr(target, "_skip_ft_index"):
        data = target.es_doc()
        data.pop("_id", None)
        Datastores.es.index(target.partition_id, "report", data, id=target.id)

def after_delete(mapper, connection, target):
    query = {"query": {"term": {"group_id": target.id}}}
    # delete by query
    Datastores.es.delete_by_query(
        index=target.partition_id, doc_type="report", body=query, conflicts="proceed"
    )

sa.event.listen(ReportGroup, "after_insert", after_insert)
sa.event.listen(ReportGroup, "after_update", after_update)
sa.event.listen(ReportGroup, "after_delete", after_delete)


def setup():
    background(220)
    size(600,600)
    stroke(245)
    strokeWeight(50)
    noFill()
    square(0,0,600)

    translate(0,70)

    font = createFont("Montserrat-Black.otf", 42)
    font2 = createFont("Montserrat-Medium.otf", 35)
    textFont(font)
    fill(30)
    text("ETIQUETTE DU MONDE", 43, 140)

    textFont(font2)
    text("ETIQUETTE MAGIC NO. 1", 85, 260)
    text("DE KEMPTON MOONEY",87, 300)
    text("- 22 02 2022 -", 183, 340)
    text("HOMMAGE A MANZONI", 85, 380)

    saveFrame("output.png")


import pandas as pd
import wget
import multiprocessing

def run_process(url, output_path):
    wget.download(url, out=output_path)

if __name__ == '__main__':
    cpus = multiprocessing.cpu_count()
    max_pool_size = 4
    pool = multiprocessing.Pool(cpus if cpus < max_pool_size else max_pool_size)

    df = pd.read_json("set_10000.json")

    train_images = df[['image_url','token_id']]
    print(f"Please wait, downloading {train_images.index.size} images.")
    for ind in train_images.index:
        image_url = df['image_url'][ind]
        filename = df['token_id'][ind]

        pool.apply_async(run_process, args=(f"{image_url}=s128", f"out/{filename}.png", ))

    pool.close()
    pool.join()
    print("Finished")


from flask import Flask, jsonify, render_template
import pandas as pd

belly_data = pd.read_excel("belly_data.xlsx", index=None)
samples = pd.read_csv("belly_button_biodiversity_samples.csv")
meta = pd.read_csv("Belly_Button_Biodiversity_Metadata.csv")

app = Flask(__name__)

@app.route("/")
def home():
    return render_template("index.html")

@app.route("/names")
def sample_id():
    samples_ids = list(samples.columns)
    samples_ids = samples_ids[1:]
    return jsonify(samples_ids)

@app.route("/otu")
def description():

    descriptions = list(belly_data["Lowest Taxonomic Level of Bacteria/Archaea Found"])
    return jsonify(descriptions)

@app.route("/metadata/<sample_id>")
def metadata(sample_id):
    sample_id = int(sample_id.replace("BB_", ""))
    match = meta[meta['SAMPLEID'] == sample_id][['SAMPLEID', 'ETHNICITY', 'GENDER', 'AGE', 'LOCATION','BBTYPE']].to_dict(orient='records')[0]
    return jsonify(match)

@app.route("/sample/<sample_id>")
def choosen_sample(sample_id):
    df = samples[['otu_id', sample_id]].sort_values(sample_id, ascending=False).dropna().rename(
        columns={sample_id: "sample_values"}).to_dict(orient='list')
    return jsonify(df)

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


from Resources.TestData import TestData
from Resources.Utilities import Utilities
from RobotControllers.BaseController import BaseController
from RobotControllers.TicktickController.Pages.TicktickHabitsPage import TicktickHabitsPage
from RobotControllers.TicktickController.Pages.TicktickLoginPage import TicktickLoginPage
from RobotControllers.TicktickController.Pages.TicktickStatisticsPage import TicktickStatisticsPage

import re

class TicktickController(BaseController):
    def go_to_main_page(self):
        self.robot_driver.get_driver().get(TestData.ticktick_signin_url)

    def login(self):
        self.go_to_main_page()
        login_page = TicktickLoginPage(self.robot_driver)

        login_page.enter_email(TestData.ticktick_email)
        login_page.enter_password(TestData.ticktick_password)
        login_page.sign_in()

    def go_to_statistics(self):
        self.robot_driver.get_driver().get(TestData.ticktick_statistics_url)

    def go_to_habits(self):
        self.robot_driver.get_driver().get(TestData.ticktick_habits_url)

    def get_focused_time(self):
        self.go_to_statistics()

        statistics_page = TicktickStatisticsPage(self.robot_driver)
        statistics_page.go_to_focus()
        raw_focused_hours = statistics_page.get_focused_time()

        extracted_hours = re.findall("\d+", raw_focused_hours)
        focused_hours = float(extracted_hours[0])
        focused_minutes = float(extracted_hours[1])
        focused_time = focused_hours + focused_minutes / 60
        focused_time = Utilities().round_number(focused_time, round_zero=False)

        return focused_time

    def get_amount_of_pomos(self):
        statistics_page = TicktickStatisticsPage(self.robot_driver)
        return int(statistics_page.get_amount_of_pomos())

    def get_task_completion_percentage(self):
        self.go_to_statistics()

        statistics_page = TicktickStatisticsPage(self.robot_driver)
        statistics_page.go_to_task()
        raw_completion_rate = statistics_page.get_completion_rate()

        completion_rate = int(re.match("\d+", raw_completion_rate).group(0))

        return completion_rate

    def get_habits(self) -> dict:
        habits = {}
        self.go_to_habits()

        habits_page = TicktickHabitsPage(self.robot_driver)

        for habit in TestData.ticktick_habit_list:
            habit_is_checked = self.robot_driver.is_element_present(
                habits_page.dynamic_habit_checked, habit
            )
            if habit_is_checked:
                habits[habit] = "|"
            else:
                habits[habit] = "-"

        return habits


import os
import json
import sys

import findspark
from IPython.core.display import display
import pyspark.sql.functions as psf
from pyspark.sql.functions import get_json_object
from pyspark.sql.types import ArrayType, StructType, StructField, StringType, IntegerType, DecimalType, DateType, \
    DoubleType, LongType

findspark.init('/Users/pradeepipol/Movies/BigData/spark-3.0.0-bin-hadoop2.7/')
import pyspark

from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession
from pyspark.streaming import StreamingContext, DStream

#from pyspark.streaming.dstream import d

f_count = 0;

def country_count_update(newValue, existingCount):
    if existingCount is None:
        existingCount = 0

    return sum(newValue) + existingCount
if __name__ == "__main__":
    os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages com.datastax.spark:spark-cassandra-connector_2.12:3.0.0-alpha2 pyspark-shell'

    data_spark_schema =StructType([
    StructField("venue", StructType([
        StructField("venue_name", StringType(), True),
        StructField("lon", DoubleType(), True),
        StructField("lat", DoubleType(), True),
        StructField("venue_id", DoubleType(), True),

    ]), True),
    StructField("visibility", StringType(), True),
    StructField("response", StringType(), True),
    StructField("guests", LongType(), True),
    StructField("member", StructType([
        StructField("member_id", LongType(), True),
        StructField("photo", StringType(), True),
        StructField("member_name", StringType(), True),
    ]), True),
    StructField("rsvp_id", LongType(), True),
    StructField("mtime", DateType(), True),
    StructField("event", StructType([
        StructField("event_name", StringType(), True),
        StructField("event_id", StringType(), True),
        StructField("time", DateType(), True),
        StructField("event_url", StringType(), True),
    ]), True),
    StructField("group", StructType([
        StructField("group_topics", ArrayType(StructType([
            StructField("urlkey", StringType(), True),
            StructField("topic_name", StringType(), True),
        ])), True),
        StructField("group_city", StringType(), True),
        StructField("group_country", StringType(), True),
        StructField("group_id", LongType(), True),
        StructField("group_name", StringType(), True),
        StructField("group_lon", DoubleType(), True),
        StructField("group_lat", DoubleType(), True),
        StructField("group_urlname", StringType(), True),
        StructField("group_state", StringType(), True),
    ]), True),
])

    spark = SparkSession \
       .builder \
       .config("spark.jars","spark-streaming-kafka-0-10_2.12-3.0.0.jar,spark-sql-kafka-0-10_2.12-3.0.0.jar,kafka-clients-2.5.0.jar,commons-pool2-2.8.0.jar,spark-token-provider-kafka-0-10_2.12-3.0.0.jar") \
        .config("spark.cassandra.connection.host", "127.0.0.1") \
        .config('spark.cassandra.output.consistency.level', 'ONE') \
        .appName("Q1") \
       .getOrCreate()

    streamingInputDF = spark \
        .readStream \
        .format("kafka") \
        .option("kafka.bootstrap.servers", "192.168.1.173:9092") \
        .option("subscribe", "meetup") \
        .load()

    stream_records = streamingInputDF.selectExpr("CAST(key AS STRING)", "CAST(value AS STRING) as meetup_data") \
        .select(psf.from_json("meetup_data", data_spark_schema).alias("meetup_data"))
    stream_records.printSchema()
    sites_flat = stream_records.select("meetup_data.*").alias("one").select("member.*","event.*","venue.*","group.*","one.*").drop("group_topics")
    sites_flat1=sites_flat.filter(sites_flat["group_state"]=="CA").select(psf.array_join('group.group_topics.topic_name',delimiter=',').alias("group_topics"),"*").drop("member","event","venue","group")

    sites_flat1.printSchema()

    query =sites_flat1.writeStream\
      .outputMode("append")\
      .format("org.apache.spark.sql.cassandra")\
      .option("checkpointLocation", "Local\Temp")\
      .option("keyspace", "meetup")\
      .option("table", "meet")\
      .start()

    query.awaitTermination()

    #streamingOutPut=streamingInputDF.writeStream.start()

   # print(streamingInputDF.)
   # print(streamingInputDF.status)
    #streamingSelectDF = streamingInputDF.select(get_json_object(($'value').cast("string"),"group_state").alias("state")).groupBy("state")

                                                #(($"value")).cast("string"),"$.group_state")).alias())
    #df.isStreaming()  # Returns True for DataFrames that have streaming sources

  #  print(streamingSelectDF.status)
    #df=pyspark.streaming("kafka").option("kafka.bootstrap.servers", "192.168.56.1:9092").option(
       # "subscribe", "meetup").load()

    #sc = SparkContext(appName="PythonStreamingDirectKafkaWordCount",conf=conf)
    #

   # ssc.checkpoint("checkpoint")

   # kvs = KafkaUtils.createDirectStream(ssc, ["meetup"], {"bootstrap.servers": '192.168.56.1:9092'})

    # , kafkaParams = {"metadata.broker.list":"localhost:9092"}
    #kvs = KafkaUtils.createDirectStream(ssc, topic, kafkaParams)
'''

    kvs = KafkaUtils.createStream(ssc, '192.168.56.1:9092', "1", {'topic': 1})
    rsvps = kvs.map(lambda x: x[1])
    rsvps_json = rsvps.map(lambda x: json.loads(x.encode('ascii', 'ignore')))
    rsvps_us = rsvps_json.filter(lambda x: x['group']['group_country'] == 'us')
    rsvps_city_pair = rsvps_us.map(lambda x: (x['group']['group_city'], 1))
    rsvps_city_statefulCount = rsvps_city_pair.updateStateByKey(country_count_update)

    rsvps_city_statefulCount.pprint()

    ssc.start()
ssc.awaitTermination()
'''


class Solution(object):
    def findLHS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        dic={}
        for n in nums:
            dic[n]=dic.get(n,0)+1
        m=0
        for key in dic:
            if dic.get(key) and dic.get(key-1):
                m=max(m,dic[key]+dic[key-1])
        return m


from datetime import datetime

from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect

from virtualbarcamp.accounts.forms import AcceptCodeOfConductForm
from virtualbarcamp.accounts.models import Account

def login(request):
    return render(request, "registration/login.html", {"include_bundle": "accounts"})

@login_required
def accept_code_of_conduct(request):
    if (
        hasattr(request.user, "account")
        and request.user.account.has_accepted_code_of_conduct is not None
    ):
        return redirect("home")

    if request.method == "POST":
        form = AcceptCodeOfConductForm(request.POST)
        if form.is_valid():
            Account.objects.get_or_create(
                user=request.user, has_accepted_code_of_conduct=datetime.now()
            )
            return redirect("home")
    else:
        form = AcceptCodeOfConductForm()

    return render(
        request,
        "registration/accept_code_of_conduct.html",
        {"form": form, "include_bundle": "accounts"},
    )


# 문제 : 정수 N이 주어졌을 때, 소인수분해하는 프로그램을 작성하시오.
# 조건 : 첫째 줄에 정수 N (1 ≤ N ≤ 10,000,000)이 주어진다.
#       N의 소인수분해 결과를 한 줄에 하나씩 오름차순으로 출력한다. N이 1인 경우 아무것도 출력하지 않는다.

N = int(input()) # 정수 입력받기
m = 2 # 2부터 시작하는 수 m으로 N이 나눠질 때까지 나눔
while N != 1:
    if N % m == 0:
        N /= m
        print(m) # 나눠질 때마다 출력
    else:
        m += 1 # 2로 더이상 나눠지지 않으면 1을 더해서 다시 반복


# Third-party modules
import PyQt5.QtWidgets as QtWid
import PyQt5.QtCore as QtCore

import numpy as np

# filters-tool project modules
from app.designer.aux_widgets.cells_settings import Ui_CellsSettings
from app.designer.aux_widgets.comp_par_block_imp import CompParBlock
from app.cells.sallen_key import SallenKey, CellGroup
from app.cells.fleischer_tow import FleischerTow
from app.cells.active_first_order import ActiveFirstOrder

class CellsSettings(QtWid.QWidget, Ui_CellsSettings):

    def __init__(self, cell_data, display_action=None, report_action=None, *args, **kwargs):
        super(CellsSettings, self).__init__(*args, **kwargs)
        self.setupUi(self)

        self.cell_data = cell_data
        self.cell_designers = [ActiveFirstOrder(), SallenKey(), FleischerTow(), None, None, None, None, None]

        # Callback for displaying circuit
        if display_action is None:
            self.display_circuit_action = self.ignore_data_action
        else:
            self.display_circuit_action = display_action
        if display_action is None:
            self.report_action = self.ignore_data_action
        else:
            self.report_action = report_action

        self.check_available_cells()
        self.design_cell()

        # Signal and slot connections
        self.cell_selector.currentIndexChanged.connect(self.design_cell)
        self.report_button.released.connect(self.generate_report)

    def ignore_data_action(self, *args, **kwargs):
        pass

    def check_available_cells(self):
        cell_type = self.cell_data['type']
        gain = 10**(self.cell_data['gain_data']/20)

        # ActiveFirstOrder are inverters, therefore their module gain is negative
        if self.cell_designers[0].is_valid_gain_mode(cell_type, -gain) and self.cell_data['pole']['n'] == 1:
            # Enable Compensated Derivator and Integrator
            variant_enable = QtCore.QVariant(1 | 32)
            self.cell_selector.setItemData(0, variant_enable, QtCore.Qt.UserRole - 1)
            self.cell_selector.setCurrentIndex(0)
        else:
            # Disable Compensated Derivator and Integrator
            variant_disable = QtCore.QVariant(0)
            self.cell_selector.setItemData(0, variant_disable, QtCore.Qt.UserRole - 1)

        if self.cell_designers[1].is_valid_gain_mode(cell_type, gain) and self.cell_data['pole']['n'] == 2:
            # Enable Sallen Key
            variant_enable = QtCore.QVariant(1 | 32)
            self.cell_selector.setItemData(1, variant_enable, QtCore.Qt.UserRole - 1)
            self.cell_selector.setCurrentIndex(1)
        else:
            # Disable Sallen Key
            variant_disable = QtCore.QVariant(0)
            self.cell_selector.setItemData(1, variant_disable, QtCore.Qt.UserRole - 1)

        if self.cell_designers[2].is_valid_gain_mode(cell_type, gain) and self.cell_data['pole']['n'] == 2:
            # Enable Fleischer Tow
            variant_enable = QtCore.QVariant(1 | 32)
            self.cell_selector.setItemData(2, variant_enable, QtCore.Qt.UserRole - 1)
            self.cell_selector.setCurrentIndex(2)
        else:
            # Disable Fleischer Tow
            variant_disable = QtCore.QVariant(0)
            self.cell_selector.setItemData(2, variant_disable, QtCore.Qt.UserRole - 1)

        # Disabeling the rest
        for i in range(self.cell_selector.count()):
            if i != 0 and i != 1 and i!= 2:
                # Disable
                variant_disable = QtCore.QVariant(0)
                self.cell_selector.setItemData(i, variant_disable, QtCore.Qt.UserRole - 1)

    def design_cell(self):
        # Designing cell
        cell_selected = self.cell_selector.currentIndex()
        cell_type = self.cell_data['type']
        gain = 10**(self.cell_data['gain_data']/20)
        if cell_selected == 0 or (cell_selected == 2 and cell_type != 'band-pass'):
            gain = -gain
        if self.cell_data['zero'] is not None:
            zeros = {
                'wz': self.cell_data['zero']['f0'] * 2*np.pi,
                'nz': self.cell_data['zero']['n']
            }
        else:
            zeros = None
        poles = {
            'wp': self.cell_data['pole']['fp'] * 2*np.pi,
            'qp': self.cell_data['pole']['q']
        }

        self.cell_designers[cell_selected].set_cell(cell_type, gain)
        self.cell_designers[cell_selected].design_components(zeros, poles, gain)

        # Adding components
        components = self.cell_designers[cell_selected].get_components()
        self.add_components(components)

        # Adding parameters and sensitivities
        zeros, poles, gain = self.cell_designers[cell_selected].get_parameters()
        sensitivities = self.cell_designers[cell_selected].get_sensitivities()
        self.add_parameters_and_sensitivies(zeros, poles, gain, sensitivities)

        # Displaying circuit
        path_to_circuit = self.cell_designers[cell_selected].get_circuit()
        self.display_circuit_action(path_to_circuit)

    def add_components(self, components):
        self.cell_components.clear()

        for component in components.keys():
            new_component_block = CompParBlock(self.update_components)
            new_component_block.comp.setText(component + ':')
            new_component_block.val.setValue(components[component] if components[component] is not None else 0)

            index = self.cell_components.count()

            new_item = QtWid.QListWidgetItem()
            new_item.setSizeHint(new_component_block.sizeHint())
            self.cell_components.insertItem(index, new_item)
            self.cell_components.setItemWidget(new_item, new_component_block)

    def add_parameters_and_sensitivies(self, zeros, poles, gain, sensitivities):
        self.cell_sensitivities.clear()

        if self.cell_data['zero'] is not None and zeros != {}:
            new_parameter_block = CompParBlock(self.update_components)
            new_parameter_block.comp.setText('f0:')
            new_parameter_block.val.setValue(zeros['wz'] / 2*np.pi)
            new_parameter_block.val.setReadOnly(True)
            new_item = QtWid.QListWidgetItem()
            new_item.setSizeHint(new_parameter_block.sizeHint())
            self.cell_sensitivities.insertItem(0, new_item)
            self.cell_sensitivities.setItemWidget(new_item, new_parameter_block)

        new_parameter_block = CompParBlock(self.update_components)
        new_parameter_block.comp.setText('fp:')
        new_parameter_block.val.setValue(poles['wp'] / 2*np.pi)
        new_parameter_block.val.setReadOnly(True)
        new_item = QtWid.QListWidgetItem()
        new_item.setSizeHint(new_parameter_block.sizeHint())
        self.cell_sensitivities.insertItem(1, new_item)
        self.cell_sensitivities.setItemWidget(new_item, new_parameter_block)

        if self.cell_data['pole']['n'] == 2:
            new_parameter_block = CompParBlock(self.update_components)
            new_parameter_block.comp.setText('Q:')
            new_parameter_block.val.setValue(poles['qp'])
            new_parameter_block.val.setReadOnly(True)
            new_item = QtWid.QListWidgetItem()
            new_item.setSizeHint(new_parameter_block.sizeHint())
            self.cell_sensitivities.insertItem(2, new_item)
            self.cell_sensitivities.setItemWidget(new_item, new_parameter_block)

        for sensitivity in sensitivities.keys():
            for parameter in sensitivities[sensitivity]:
                new_component_block = CompParBlock(self.update_components)
                new_component_block.comp.setText('S' + sensitivity + '->' + parameter + ':')
                new_component_block.val.setValue(sensitivities[sensitivity][parameter])
                new_component_block.val.setReadOnly(True)

                index = self.cell_sensitivities.count()

                new_item = QtWid.QListWidgetItem()
                new_item.setSizeHint(new_component_block.sizeHint())
                self.cell_sensitivities.insertItem(index, new_item)
                self.cell_sensitivities.setItemWidget(new_item, new_component_block)

    def update_components(self, component, value):
        cell_selected = self.cell_selector.currentIndex()

        components = self.cell_designers[cell_selected].get_components()
        components[component.split(':')[0]] = value

        # Adding parameters and sensitivities
        zeros, poles, gain = self.cell_designers[cell_selected].get_parameters()
        sensitivities = self.cell_designers[cell_selected].get_sensitivities()
        self.add_parameters_and_sensitivies(zeros, poles, gain, sensitivities)

        # Displaying circuit
        path_to_circuit = self.cell_designers[cell_selected].get_circuit()
        self.display_circuit_action(path_to_circuit)

    def generate_report(self):
        self.report_action()


from nltk.tokenize import *
import nltk.data
from nltk.corpus import inaugural
from nltk import FreqDist
from nltk.corpus import swadesh

class Preprocessor(object):
    def __init__(self, text, text_id):
        """reads the file text as a string"""
        self.text = text
        self.text_id = text_id

    @classmethod
    def from_nltk_book(cls):
        """Reads the inaugural text from the nltk book as a string. Note that this is a @classmethod
        which will be used instead of the default constructor when creating the object. Remember to
         return cls(something)"""
        text = inaugural.raw()
        return cls(text, "inaugural")

    @classmethod
    def from_text_file(cls, path, text_id):
        """Reads the text from given file as a string. Note that this is a @classmethod
        which will be used instead of the default constructor when creating the object.
         Remember to return cls(something)"""
        with open(path, "r") as fh:
            text = fh.read()
        return cls(text, text_id)

    def get_no_of_sents(self):
        """Split the input text into sentences and return the length of the text in sentences."""
        # sent_detector = nltk.data.load('tokenizers/punkt/english.pickle')
        # sents = sent_detector.tokenize(self.text.strip())
        sents = sent_tokenize(self.text)
        return len(sents)

    def tokenize_text(self):
        """Split the text into tokens. Use an nltk method for that, equivalent to s.split()"""
        return word_tokenize(self.text)

    def lemmatize_token(self, token):
        """Lemmatize the given token, after converting it to lowercase."""
        wnl = nltk.WordNetLemmatizer()
        return wnl.lemmatize(token.lower())

    def get_20_most_frequent_words(self):
        """Return the 20 most frequent words of the text after removing the stopwords and all non-alphanumeric characters
         (in other words, remove all punctuation). Note that the stopwords are stored with their lemmata so you
         will have to make sure you check whether the lemma of each word is contained in the stopwords list.
         Make sure you use the method tokenizeText() that you implemented above"""
        tokens = self.tokenize_text()
        word_freq = FreqDist(tokens)
        stopwords = set(nltk.corpus.stopwords.words("english"))

        # Solution using unicode
        # def is_alphanum_unicode(w):
        #     return all([ord('a') <= ord(c) <= ord('z') or ord('0') <= ord(c) <= ord('9') for c in set(w.lower())])
        # filtered_word_freq = dict((word, freq) for word, freq in word_freq.items() if is_alphanum_unicode(word) and self.lemmatize_token(word) not in stopwords)

        # Solution using regular expressions
        # def is_alphanum_regex(w):
        #     return bool(re.match('^[a-zA-Z0-9]+$', w))
        # filtered_word_freq = dict((word, freq) for word, freq in word_freq.items() if is_alphanum_regex(word) and self.lemmatize_token(word) not in stopwords)

        # Simplest and fastest solution (recommended)
        filtered_word_freq = dict((word, freq) for word, freq in word_freq.items() if word.isalnum() and self.lemmatize_token(word) not in stopwords)
        most_freq_dict = dict(sorted(filtered_word_freq.items(), key=lambda item: item[1], reverse=True))
        return list(most_freq_dict.keys())[:20]

    def get_originality_score(self, most_freq_words):
        """Return the originality score of a text. This score can be measured by counting how many words contained
        in the swadesh list of nltk are also contained in the list with the 20 most frequent words of the text.
        For example, if 10 words can be found in both lists, the originality score is 10.
        The list with the 20 most frequent words should be given to the method as a parameter. """
        english_words = swadesh.words("en")
        common_words = [x for x in most_freq_words if x in english_words]
        return len(common_words)

if __name__ == '__main__':
    """Create two instances of the Preprocessor class. One instance should be created through the text file
    ada_lovelace.txt and the other one through the inaugural text included in the nltk book. """
    text1 = Preprocessor.from_text_file("ada_lovelace.txt", "ada_lovelace")
    text2 = Preprocessor.from_nltk_book()

    """For each instance of the Preprocessor, do the following:
      a) print out the numbers of sentences of the text
      b) print out the 20 most frequent words of the text
      c) print out the originality score of the text."""
    most_freq_words1 = text1.get_20_most_frequent_words()
    text1.get_originality_score(most_freq_words1)

    most_freq_words2 = text2.get_20_most_frequent_words()
    text2.get_originality_score(most_freq_words2)


# https://practice.geeksforgeeks.org/problems/merge-sort/1

#User function Template for python3

class Solution:
    def merge(self,arr, l, m, r):
        n1 = m-l+1
        n2 = r-m
        left = list()
        right = list()
        res = list()
        for i in range(n1):
            left.append(arr[l+i])
        for j in range(n2):
            right.append(arr[m+1+j])

        i=0
        j=0
        k=l
        while i<n1 and j<n2:
            if left[i]<=right[j]:
                arr[k] = left[i]
                i+=1
                k+=1
            else:
                arr[k] = right[j]
                j+=1
                k+=1
        while i<n1:
            arr[k] = left[i]
            i+=1
            k+=1
        while j<n2:
            arr[k] = right[j]
            j+=1
            k+=1

    def mergeSort(self,arr, l, r):
        if r>l:
            m = l+(r-l)//2
            self.mergeSort(arr, l, m)
            self.mergeSort(arr, m+1, r)
            self.merge(arr, l, m, r)

#{
 # Driver Code Starts
#Initial Template for Python 3

import sys
input = sys.stdin.readline
if __name__ == "__main__":
    t=int(input())
    for i in range(t):
        n=int(input())
        arr=list(map(int,input().split()))
        Solution().mergeSort(arr, 0, n-1)
        for i in range(n):
            print(arr[i],end=" ")
        print()
# } Driver Code Ends


from manimlib import *
bpm = 95
note_time = 10/bpm

class Color_Change(Animation):
    CONFIG = {
        "suspend_mobject_updating": False,
        "int_func": np.round,
    }

    def __init__(self, group, color1, color2, **kwargs):
        self.all_submobjects = list(group.submobjects)
        self.color1 = color1
        self.color2 = color2
        super().__init__(group, **kwargs)

    def interpolate_mobject(self, alpha):
        n_submobs = len(self.all_submobjects)
        index = int(self.int_func(alpha * n_submobs))
        self.update_submobject_list(index)

    def update_submobject_list(self, index):
        self.mobject.set_submobjects(self.all_submobjects[:index])
        self.mobject.set_color(self.color1)
        for i in np.arange(np.maximum(-5,-len(self.mobject.submobjects)),0):
            self.mobject.submobjects[i].set_color(interpolate_color(self.color1, self.color2, (i+6)/5))

class Stretch(Transform):
    CONFIG = {
        "lag_ratio": DEFAULT_FADE_LAG_RATIO,
    }

    def __init__(self, mobject, **kwargs):
        super().__init__(mobject, **kwargs)

    def create_target(self):
        return self.mobject

    def create_starting_mobject(self):
        start = super().create_starting_mobject()
        start.stretch(0,0)
        return start

def lagrange_interpolation(points):
    n = len(points)
    def lagrange_basis(i, x):
        result = 1
        for j in range(n):
            if j == i:
                continue
            result *= (x - points[j][0]) / (points[i][0] - points[j][0])
        return result
    def lagrange_polynomial(x):
        result = 0
        for i in range(n):
            result += points[i][1] * lagrange_basis(i, x)
        return result
    return lagrange_polynomial

class Countable_infinity(Scene):
    def construct(self):
        self.add_sound("enchanted_love")

        def shaking_path(x): return np.array(
            [np.cos(10*x), np.sin(9*x), 0])
        frame = self.camera.frame
        frame.scale(2)
        #frame.add_updater(lambda obj:obj.move_to(shaking_path(self.time)))
        # self.add(frame)
        numlist = VGroup(*[Tex(str(i)).move_to(RIGHT*(i+1)*1.5)
                         for i in np.arange(30)])
        numlist2 = VGroup(*[Tex(str(i)).move_to(DOWN*(i+1)*1.5)
                          for i in np.arange(30)])
        numlist3 = VGroup(*[Tex(str(i)).set_opacity((i+1) %
                          2).move_to(np.array([i+1, -1, 0])*1.5) for i in np.arange(30)])
        numlist4_pre = VGroup(*[Tex(str(i)).set_opacity((i+1) %
                              2).move_to(np.array([i+1, -1, 0])*1.5) for i in np.arange(60)])
        numlist4 = VGroup(
            *[Tex(str(i*2)).move_to(np.array([i+1, -1, 0])*1.5) for i in np.arange(30)])
        for i in [*numlist, *numlist2]:
            i.save_state()
        numlist.save_state()
        numlist2.save_state()

        self.add(frame)
        frame.add_updater(lambda obj: obj.move_to(VGroup(*self.mobjects[1:])))
        self.wait(note_time)
        for i in range(4):
            self.add(numlist[i*5])
            self.wait(note_time)
            self.play(ShowIncreasingSubsets(
                numlist[i*5+1:(i+1)*5]), run_time=note_time*4)
            self.wait(note_time*6.05)
            if i == 2:
                frame.clear_updaters()
        self.add(numlist[20:])
        for j in range(4):
            self.play(frame.animate.shift(DOWN*1.25), run_time=note_time*5)
            if j == 3:
                self.play(frame.animate.shift(DOWN*1.25), run_time=note_time*5)
                self.wait(note_time*3)
            else:
                self.wait(note_time*7)

        self.play(TransformFromCopy(numlist, numlist3), run_time=note_time*5)
        self.wait(note_time*6)
        self.remove(numlist3)
        self.add(numlist4_pre)
        self.play(TransformMatchingShapes(numlist4_pre[::2], numlist4))
        frame.save_state()
        self.wait(note_time*5.45)
        relationship1 = VGroup(
            *[Arrow(i.get_center(), j.get_center()) for i, j in zip(numlist, numlist4)]).set_color(YELLOW_B)

        # self.wait(note_time*2)
        for i in range(4):
            self.add(relationship1[i*5])
            self.wait(note_time)
            self.play(ShowIncreasingSubsets(
                relationship1[i*5+1:(i+1)*5]), run_time=note_time*4)
            self.wait(note_time*6.1)

        self.wait(note_time*22)
        big_notation = Tex("\mathrm{card}~", "\mathds{N}", "=",
                           "\mathrm{card}~", "2\mathds{N}").move_to(frame).scale(4)

        # self.wait(note_time*5)

        self.play(ShowIncreasingSubsets(big_notation), run_time=5*note_time)
        self.remove(big_notation, relationship1, numlist4)
        back = Rectangle(width=200, height=200, color=WHITE, fill_opacity=1)
        self.add(back, numlist)
        numlist.set_color(BLACK)
        numlist2.set_color(BLACK)
        self.play(ReplacementTransform(numlist.copy(), numlist2,
                  path_arc=-PI/2), run_time=5*note_time)
        self.add(numlist2)
        self.wait(note_time*5)

        grid_of_fractions = VGroup(*[VGroup(*[Tex("{", str(j), "\\over ", str(i-j), "}").move_to(np.array(
            [numlist[j].get_x(), numlist2[i-j].get_y(), 0])).set_color(BLACK) for j in range(i+1)]) for i in range(30)])

        def form_grid(i):
            start = VGroup(*[VGroup(numlist[m], numlist2[i-m])
                           for m in range(i+1)])
            end = grid_of_fractions[i]
            if i != 29:
                return AnimationGroup(*[TransformMatchingShapes(k.copy(), j, path_arc=PI/2) for k, j in zip(start, end)], run_time=note_time*5)
            else:
                return AnimationGroup(*[TransformMatchingShapes(k, j, path_arc=PI/2) for k, j in zip(start, end)], run_time=note_time*5)

        for i in range(6):
            self.play(form_grid(i), rate_func=exponential_decay)
            self.wait(note_time*6.5)
        self.wait(note_time*13)
        self.play(LaggedStart(*[form_grid(i) for i in range(6,30)],lag_ratio=0.1),run_time=note_time*85)
        #self.wait(note_time*85)
        #self.add(grid_of_fractions[6:])
        self.remove(numlist, numlist2)
        frame.shift(-grid_of_fractions[0].get_center())
        frame_center = np.array([12.06236942, -6.25, 0.])-grid_of_fractions[0].get_center()
        grid_of_fractions.shift(-grid_of_fractions[0].get_center())

        def update(obj, alpha):
            obj.move_to(frame_center+0.2*np.array(
                [random.uniform(-1, 1), random.uniform(-1, 1), random.uniform(-1, 1)]))
        self.play(*[i.animate.shift(random.uniform(0, 5)*OUT) for k in grid_of_fractions for i in k],
                  rate_func=bezier([0, 0, 0, 1, 1, 1, 1, 1, 0]), run_time=11*note_time)
        self.play(UpdateFromAlphaFunc(frame, update), run_time=note_time)
        frame.move_to(frame_center)
        centers = []
        for i,f in enumerate(grid_of_fractions):
            if i%2 == 0:
                centers+=[m.get_center() for m in f]
            else:
                centers+=reversed([m.get_center() for m in f])

        UR_arrows = VGroup(*[VGroup(*[Arrow(p.get_center(), q.get_center()).set_color(YELLOW)
                           for p, q in zip(i[:-1], i[1:])]) for i in grid_of_fractions[1::2]])
        DL_arrows = VGroup(*[VGroup(*[Arrow(p.get_center(), q.get_center()).set_color(YELLOW)
                           for q, p in zip(i[:-1], i[1:])]) for i in grid_of_fractions[2::2]])
        D_arrows = VGroup(*[Arrow(p[0].get_center(), q[0].get_center()).set_color(YELLOW)
                          for p, q in zip(grid_of_fractions[::2], grid_of_fractions[1::2])])
        R_arrows = VGroup(*[Arrow(p[-1].get_center(), q[-1].get_center()).set_color(YELLOW)
                          for p, q in zip(grid_of_fractions[1::2], grid_of_fractions[2::2])])
        around_circ1 = Circle().flip().next_to(frame_center, buff=0)
        around_circ2 = Circle().next_to(frame_center, LEFT, buff=0)
        self.play(*[GrowArrow(i) for k in UR_arrows for i in k],
                  frame.animate.shift(UR*2), run_time=5*note_time)
        self.play(frame.animate.move_to(frame_center),
                  UR_arrows.animate.set_color("#03C497"), run_time=5*note_time)
        self.play(*[GrowArrow(i) for k in DL_arrows for i in k],
                  frame.animate.shift(DL*2), run_time=5*note_time)
        self.play(frame.animate.move_to(frame_center),
                  DL_arrows.animate.set_color("#03C497"), run_time=5*note_time)
        self.wait(6*note_time)
        self.play(MoveAlongPath(frame, around_circ1), run_time=6*note_time)
        self.wait(6*note_time)
        self.play(*[GrowArrow(i) for i in D_arrows],
                  frame.animate.shift(DOWN*2), run_time=3*note_time)
        self.play(frame.animate.move_to(frame_center),
                  D_arrows.animate.set_color("#03C497"), run_time=3*note_time)
        self.wait(6*note_time)
        self.play(MoveAlongPath(frame, around_circ2), run_time=6*note_time)
        self.wait(6*note_time)
        self.play(*[GrowArrow(i) for i in R_arrows],
                  frame.animate.shift(RIGHT*2), run_time=3*note_time)
        self.play(frame.animate.move_to(frame_center),
                  R_arrows.animate.set_color("#03C497"), run_time=3*note_time)

        swing_path = Arc(-150*DEGREES,120*DEGREES).next_to(frame_center,UP,buff=0)
        def swing(obj,alpha):
            obj.move_to(swing_path.pfp(np.sin(3*PI*alpha)*0.5+0.5)-OUT*np.sin(3*PI*alpha)**2)

        self.play(UpdateFromAlphaFunc(frame,swing),run_time=30*note_time)

        def get_frac(i, j):
            return (j, i-j)

        def modified_Cross(mobject):
            a = Circle().set_fill(TEAL_A,1).set_stroke("#03C497")
            return a.move_to(mobject)

        Crosses = VGroup()
        slope_list = []
        index_list = []
        for i in np.arange(0, 30):
            for j in np.arange(i+1):
                x, y = get_frac(i, j)
                f = np.gcd(x, y)
                if (x, y) == (0, 0):
                    Crosses.add(modified_Cross(grid_of_fractions[i][j]).scale(.6))
                    slope_list.append((1, 1))
                    index_list.append((i, j))
                elif y == 0:
                    Crosses.add(modified_Cross(grid_of_fractions[i][j]).scale(.6))
                    slope_list.append((x/f, y/f))
                    index_list.append((i, j))
                elif x == 0 and y > 1:
                    Crosses.add(modified_Cross(grid_of_fractions[i][j]).scale(.6))
                    slope_list.append((x/f, y/f))
                    index_list.append((i, j))
                elif np.gcd(x, y) > 1:
                    Crosses.add(modified_Cross(grid_of_fractions[i][j]).scale(.6))
                    slope_list.append((x/f, y/f))
                    index_list.append((i, j))

        lines = VGroup(*[Line(5*np.array([-i,j,0])/(i*i+j*j)**.5,60*np.array([-i,j,0])/(i*i+j*j)**.5) for i, j in slope_list]).set_color("#00A795")
        lines_tag = VGroup(*[Line(-30*np.array([-i,j,0])/(i*i+j*j)**.5,ORIGIN) for i, j in slope_list]).set_color("#00A795")

        self.play(frame.animate.move_to(-frame_center),run_time=12*note_time)
        self.play(
            ApplyMethod(frame.move_to,frame_center+shaking_path(self.time),run_time=12*note_time,rate_func=lambda t:1-exponential_decay(1-t))
        )
        shaking_path_factor = ValueTracker(0.5)
        frame.add_updater(lambda m: m.move_to(frame_center+shaking_path(self.time)*shaking_path_factor.get_value()))
        self.play(
            LaggedStart(*[Transform(i,j) for i,j in zip(lines,lines_tag)],lag_ratio=.01,run_time=54*note_time)
        )
        self.play(shaking_path_factor.animate.set_value(0.2),run_time=18*note_time)
        self.play(
            LaggedStart(*[ReplacementTransform(i,j) for i,j in zip(lines,Crosses)],lag_ratio=.01,run_time=30*note_time))
        labeled_num = VGroup()
        back_recs = VGroup()
        fracs = VGroup()
        k=0

        def back_rec(mob):
            return Rectangle(mob.get_width()+0.1,mob.get_height()+0.1).move_to(mob)

        for i in np.arange(0, 30):
            if i%2==1:
                for j in np.arange(i+1):
                    if not( (i,j) in index_list):
                        labeled_num.add(Integer(k).set_color(YELLOW_B).next_to(grid_of_fractions[i][j],UR,buff=0))
                        back_recs.add(back_rec((VGroup(grid_of_fractions[i][j],labeled_num[k]))).set_fill(RED,0.5).set_stroke(RED,5))
                        fracs.add(grid_of_fractions[i][j])
                        k+=1
            elif i%2==0:
                for j in np.arange(i,-1,-1):
                    if not( (i,j) in index_list):
                        labeled_num.add(Integer(k).set_color(YELLOW_B).next_to(grid_of_fractions[i][j],UR,buff=0))
                        back_recs.add(back_rec((VGroup(grid_of_fractions[i][j],labeled_num[k]))).set_fill(RED,0.5).set_stroke(RED,5))
                        fracs.add(grid_of_fractions[i][j])
                        k+=1
        #self.play(frame.animate.move_to(ORIGIN).scale(0.5),run_time=3*note_time)
        self.play(ShowIncreasingSubsets(back_recs),Color_Change(labeled_num,YELLOW_B,BLACK),run_time=54*note_time,rate_func=linear)
        formula2 = Tex("\mathrm{card}~\mathds{N}", "=","\mathrm{card}~\mathds{Q}").move_to(frame).scale(4).set_color(BLACK)
        self.wait(2*note_time)
        formula2.add_updater(lambda m: m.move_to(frame)).set_opacity(0)
        self.add(formula2)
        for i in range(3):
            formula2[i].set_opacity(1)
            self.wait(2*note_time)
        self.wait(4*note_time)
        self.remove(*self.get_mobjects())
        self.add(frame)
        realindex = VGroup(*[Tex(str(i)).move_to(DOWN*i)
                          for i in np.arange(30)])
        def rand_str():
            rand="0."
            for i in range(100):
                rand+=str(random.randint(0,9))
            return rand
        rand_str_list = [rand_str() for i in range(100)]
        final_per_str = "0."
        for i in range(100):
            final_per_str += rand_str_list[i][i+2]
        final_str = "0."
        for k in final_per_str[2:]:
            if int(k)<9:
                final_str += str(int(k)+1)
            else:
                final_str += "0"

        reallist = VGroup(*[Tex(*list(rand_str_list[i])).next_to(DOWN*i,RIGHT,buff=1) for i in range(100)])
        self.add(realindex[0])
        self.wait(note_time*6)
        self.play(ShowIncreasingSubsets(realindex[1:10]),run_time=9*note_time)
        self.play(Write(realindex[10:],run_time=30*note_time),Write(reallist[:14],lag_ratio=1,run_time=24*note_time))
        self.add(reallist[14:])
        digit_circle = VGroup(*[Circle(arc_center=reallist[i][2+i].get_center(),radius=0.3).set_fill(YELLOW_B,0.5).set_stroke(YELLOW_B,6) for i in range(100)])

        frame_path = bezier([
            frame_center,
            digit_circle[0].get_center(),
            digit_circle[0].get_center(),
            digit_circle[1].get_center(),
            digit_circle[-6].get_center(),
            digit_circle[-5].get_center(),
            digit_circle[-5].get_center(),
            frame_center])
        scale_fractor = bezier([1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,1])
        frame.save_state()
        def round_trip(obj,alpha):
            obj.restore()
            obj.scale(scale_fractor(alpha)).move_to(frame_path(alpha))
        self.play(ShowCreation(digit_circle[:14]),shaking_path_factor.animate.set_value(0),run_time=28*note_time,rate_func=linear)
        self.add(digit_circle[14:])
        frame.clear_updaters()
        final_per_tex = Tex(*list(final_per_str)).next_to(UP,RIGHT,buff=1)
        final_tex = Tex(*list(final_str)).next_to(UP*2,RIGHT,buff=1)
        relationship2 = VGroup(*[Arrow(reallist[i][i+2].get_center(),final_per_tex[i+2].get_center(),buff=0.3) for i in range(100)]).set_color(YELLOW_B)
        self.play(UpdateFromAlphaFunc(frame,round_trip),LaggedStart(*[ReplacementTransform(reallist[i][i+2].copy(),final_per_tex[i+2]) for i in range(100)]),
            LaggedStart(*[GrowArrow(relationship2[i]) for i in range(100)]),
            Write(final_per_tex[:2]),run_time=80*note_time)
        #self.play(FadeIn(final_tex[2:],shift=DOWN,lag_ratio=.05),FadeOut(final_per_tex[2:],shift=DOWN,lag_ratio=.05),run_time=10*note_time)
        relationship3 = VGroup(*[Arrow(final_per_tex[i+2].get_center(),final_tex[i+2].get_center()) for i in range(100)]).set_color(YELLOW_B)

        Crosses2 = VGroup(*[VGroup(Line(UR,DL),Line(UL,DR)).set_stroke(width=5).scale(0.1).move_to(i) for i in relationship3]).set_color(RED)
        frame.add_updater(lambda m: m.move_to(frame_center+shaking_path(self.time)*shaking_path_factor.get_value()))
        self.play(shaking_path_factor.animate.set_value(0.1),run_time=6*note_time)
        self.play(
            LaggedStart(*[ReplacementTransform(i.copy(),j) for i,j in zip(final_per_tex,final_tex)],lag_ratio=.1),
            LaggedStart(*[GrowArrow(relationship3[i]) for i in range(100)],lag_ratio=.1),
            LaggedStart(*[ShowCreation(c) for c in Crosses2],lag_ratio=.1),
            FadeOut(relationship2,lag_ratio=0.1),
            run_time=40*note_time
        )
        relationship4 = VGroup(*[Arrow(final_tex[i+2].get_center(),reallist[i][i+2].get_center(),buff=0.3) for i in range(100)]).set_color(YELLOW_B)
        self.wait(6*note_time)
        Crosses3 = VGroup(*[VGroup(Line(UR,DL),Line(UL,DR)).set_stroke(width=5).scale(0.1).move_to(i) for i in relationship4]).set_color(RED)

        self.play(
            LaggedStart(*[ReplacementTransform(i,j,path_arc=-PI) for i,j in zip(relationship3,relationship4)]),
            LaggedStart(*[ReplacementTransform(i,j,path_arc=-PI) for i,j in zip(Crosses2,Crosses3)]),
            run_time=40*note_time
        )
        self.wait(6*note_time)
        self.play(FadeOut(final_per_tex),run_time=6*note_time)
        full_rec = back_rec(reallist).set_stroke(RED,5).set_fill(RED,0.5)
        full_arrow = Arrow(final_tex.get_bottom(),full_rec.get_top(),buff=0.1).set_color(YELLOW_B)
        full_cross = VGroup(Line(UR,DL),Line(UL,DR)).set_stroke(RED,width=5).scale(0.1).move_to(full_arrow)
        self.bring_to_back(full_rec)
        self.play(
            FadeIn(full_rec),
            FadeOut(digit_circle),
            *[ReplacementTransform(i,full_arrow) for i in relationship4],
            *[ReplacementTransform(i,full_cross) for i in Crosses3],
            run_time=40*note_time
        )
        self.wait(6*note_time)
        formula3 = Tex("\mathrm{card}~","\mathds{N}","<","\mathrm{card}","~\mathds{R}").scale(2).fix_in_frame()
        self.play(Write(formula3),run_time=12*note_time)

        back.set_color(BLACK)
        self.add(back,formula3)
        self.play(FadeIn(back),formula3.animate.set_opacity(1),run_time=6*note_time)
        frame.clear_updaters().move_to(ORIGIN).scale(0.5)

        n = 50

        stair_corners = [np.array([20,-8,0]),np.array([20,-3,0])]
        jumping_corners = [np.array([4,-3,0])+i*np.array([-2,1,0]) for i in np.arange(int(n/2))]

        for i in range(n):
            if i == 0:
                stair_corners.append(np.array([5,-3,0]))
            elif i % 2 == 1:
                stair_corners.append(stair_corners[i+1]+LEFT*2)
            else:
                stair_corners.append(stair_corners[i+1]+UP)
        stair_corners.append(stair_corners[-1]+LEFT*50)
        jumping_corners += [jumping_corners[-1]+LEFT*i for i in np.arange(2,9,2)]

        def jumping_path(alpha):
            if alpha == 1:
                return jumping_corners[-1][1]
            else:
                path_index = int(np.floor(alpha*(len(jumping_corners)-1)))
                path_x = jumping_corners[0][0]*(1-alpha)+jumping_corners[-1][0]*alpha
                path_polynomial = lagrange_interpolation([jumping_corners[path_index],jumping_corners[path_index+1],jumping_corners[path_index+1]+UR])

                return np.array([path_x,path_polynomial(path_x)+0.3,0])

        def window():
            return VGroup(*[Square(side_length=1.9).set_fill(YELLOW_B,1).set_stroke(width=0) for _ in range(4)]).arrange_in_grid(2,2,buff=0.2)
        windows = VGroup()
        for i in np.arange(int(n/2)):
            if i% 20 == 9:
                windows.add(window().next_to(jumping_corners[i],UP,buff=3))

        def light():
            return Polygon(LEFT*2,RIGHT*2,RIGHT*4+DOWN*20,LEFT*4+DOWN*20).set_stroke(width=0).set_fill(YELLOW_B,.5)

        windows_light = VGroup(*[light().next_to(i.get_top(),DOWN,buff=0) for i in windows])
        self.add(windows_light,windows)

        stair = Polygon(*stair_corners,np.array([stair_corners[-1][0],stair_corners[0][1],0])).set_stroke(width=5).set_fill(BLACK,.9)

        final_square1 = Square(1.5).set_fill(BLACK,1).set_stroke(WHITE).move_to(jumping_corners[-1]+np.array([-2,0.75,0]))
        final_square2 = Square(1.5).set_fill(BLACK,1).set_stroke(WHITE).move_to(jumping_corners[-1]+np.array([-2,2.25,0]))
        final_square3 = Square(1.5).set_fill(BLACK,1).set_stroke(WHITE).move_to(jumping_corners[-1]+np.array([-2,2.25,0]))
        final_light = VGroup(
            Rectangle(width=3,height=30).set_stroke(width=0).set_fill("#00A795",1),
            Rectangle(width=3,height=30).set_stroke(width=0).set_fill("#05668D",1),
            Rectangle(width=2,height=30).set_stroke(width=0).set_fill("#00A795",1)
        ).next_to(final_square1.get_bottom(),UP,buff=0)

        R = Tex("\mathds{R}").move_to(jumping_corners[0]+0.3*UP)
        N = Tex("\mathds{N}").move_to(final_square1)

        def interpolate_between(p1,p2,num):
            return [p1*(1-alpha)+p2*alpha for alpha in np.linspace(0,1,num)]

        frame_path = Elbow().set_points_as_corners([*interpolate_between(ORIGIN,jumping_corners[len(jumping_corners)-6]+UP*3,6),final_square3.get_center()+UP*.75])
        self.add(final_square1,final_square2,N)
        self.play(
            FadeOut(formula3[0:4]),
            ReplacementTransform(formula3[4],R[0]),
            FadeIn(stair),
            run_time=6*note_time)
        self.play(
            UpdateFromAlphaFunc(R,lambda m,alpha: m.move_to(jumping_path(alpha))),
            MoveAlongPath(self.camera.frame,frame_path),
            run_time=20,rate_func=linear)
        R.move_to(jumping_corners[-1]+0.3*UP)
        final_jump = lagrange_interpolation([jumping_corners[-1]+UP*0.3,jumping_corners[-1]+np.array([-1,2.25,0]),jumping_corners[-1]+np.array([-2,2.25,0])])
        final_path = FunctionGraph(final_jump,x_range=[jumping_corners[-1][0]-2,jumping_corners[-1][0],0.001]).reverse_points()
        self.add(final_light,*final_light,stair,final_square1,final_square2,final_square3,N,R)
        self.play(
            Stretch(final_light,lag_ratio=0.1),
            MoveAlongPath(R,final_path,rate_func=linear),
            run_time=6*note_time)

        R.move_to(final_square3)
        self.wait(6*note_time)
        ques_mark = Tex("?").move_to(final_square2)
        self.add(final_square2,ques_mark,final_square3,R)
        self.play(final_square3.animate.shift(UP*1.5),R.animate.shift(UP*1.5),Write(ques_mark),run_time=6*note_time)

class Thumbnail_enchanted(Scene):
    def construct(self):

        ground = Line(np.array([-3,-3,0]),np.array([3,-3,0]))
        final_light = VGroup(
            Rectangle(width=4,height=30).set_stroke(width=0).set_fill("#05668D",1),
            Rectangle(width=3,height=30).set_stroke(width=0).set_fill("#00A795",1)
        ).next_to(ground,UP,buff=0)
        box = Square(side_length=1.4).set_fill(BLACK,1).set_stroke(WHITE).move_to(np.array([0,0.75,0]))
        boxes = VGroup(*[box.copy() for i in range(2)])
        boxes[0].rotate(20*DEGREES)
        boxes[1].rotate(-20*DEGREES)
        boxes.arrange(UP,buff=0).next_to(ground,UP,buff=0)
        N = Tex("\mathds{N}").scale(2).move_to(boxes[0]).rotate(20*DEGREES)
        R = Tex("\mathds{R}").scale(2).move_to(boxes[1]).rotate(-20*DEGREES)
        flash1 = VGroup(*[Line(ORIGIN,DOWN*.5,buff=0.05).rotate(PI/2*i,about_point=ORIGIN).set_stroke(width=8) for i in range(4)])
        flash1.move_to(np.array([-1.25,1.5,0]))
        flash2 = VGroup(*[Line(ORIGIN,DOWN*.5,buff=.08).rotate(PI/2*i,about_point=ORIGIN).set_stroke(width=8) for i in range(4)])
        flash2.move_to(np.array([1.35,2.5,0]))

        self.add(final_light,ground,boxes,N,R,flash1,flash2)


import netCDF4 as nc
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.mpl.ticker as mticker
import cartopy.feature
from cartopy.util import add_cyclic_point
from matplotlib import colors

emiss1 = np.zeros([12,192,288])
nc1 = nc.Dataset('F:/SOAGx1.5_anthro_surface_mol.nc')
lon1 = nc1.variables['lon'][:]
lat1 = nc1.variables['lat'][:]
for i in range(len(list(nc1.variables.keys()))):
    if (nc1.variables[list(nc1.variables.keys())[i]]).ndim == 3:
        emiss1 += nc1.variables[list(nc1.variables.keys())[i]][1968:1980]
emiss1_ = np.mean(emiss1[:,:,:] ,0)
emiss1_, lon1 = add_cyclic_point(emiss1_, coord=lon1)

emiss2 = np.zeros([12,192,288])
nc2 = nc.Dataset('F:/r_mod_SOAGx1.5_anthro_surface_mol.nc')
lon2 = nc2.variables['lon'][:]
lat2 = nc2.variables['lat'][:]
for i in range(len(list(nc2.variables.keys()))):
    if (nc2.variables[list(nc2.variables.keys())[i]]).ndim == 3:
        emiss2 += nc2.variables[list(nc2.variables.keys())[i]][1968:1980]
emiss2_ = np.mean(emiss2[:,:,:] ,0)
emiss2_, lon2 = add_cyclic_point(emiss2_, coord=lon2)

emiss3 = np.zeros([12,192,288])
nc3 = nc.Dataset('F:/SOAG_EA_L.nc')
lon3 = nc3.variables['lon'][:]
lat3 = nc3.variables['lat'][:]
for i in range(len(list(nc3.variables.keys()))):
    if (nc3.variables[list(nc3.variables.keys())[i]]).ndim == 3:
        emiss3 += nc3.variables[list(nc3.variables.keys())[i]][0:12]
emiss3_ = np.mean(emiss3[:,:,:] ,0)
emiss3_, lon3 = add_cyclic_point(emiss3_, coord=lon3)

emiss_gao = (emiss2_-emiss1_)/10**11
emiss_liu = (emiss3_-emiss1_)/10**11

vmin = -max(max(np.reshape(abs(emiss_gao),(192*289))),
           max(np.reshape(abs(emiss_liu),(192*289))))
vmax = max(max(np.reshape(abs(emiss_gao),(192*289))),
           max(np.reshape(abs(emiss_liu),(192*289))))

norm = colors.Normalize(vmin=vmin, vmax=vmax)

proj = ccrs.PlateCarree(central_longitude=0)
fig = plt.figure(figsize = (10,12))
ax1 = fig.add_subplot(2, 1, 1, projection=proj)
ax1.add_feature(cartopy.feature.COASTLINE)
ax1.add_feature(cartopy.feature.BORDERS)
extent=[70,150,15,55]
ax1.set_extent(extent)
ax1.set_xticks([70,90,110,130,150])
ax1.set_yticks([25,35,45,55])
lon_formatter = mticker.LongitudeFormatter()
lat_formatter = mticker.LatitudeFormatter()
ax1.xaxis.set_major_formatter(lon_formatter)
ax1.yaxis.set_major_formatter(lat_formatter)
ax1.set(title='gao')
h1 = plt.contourf(lon1, lat1, emiss_gao,
                  [-1.2,-1.0,-0.8,-0.6,-0.4,-0.2,-0.1,-0.01,0.01,0.1,0.2],
                  cmap = plt.cm.bwr,
                  norm = norm
                  )
ax2 = fig.add_subplot(2, 1, 2, projection=proj)
ax2.add_feature(cartopy.feature.COASTLINE)
ax2.add_feature(cartopy.feature.BORDERS)
extent=[70,150,15,55]
ax2.set_extent(extent)
ax2.set_xticks([70,90,110,130,150])
ax2.set_yticks([25,35,45,55])
lon_formatter = mticker.LongitudeFormatter()
lat_formatter = mticker.LatitudeFormatter()
ax2.xaxis.set_major_formatter(lon_formatter)
ax2.yaxis.set_major_formatter(lat_formatter)
ax2.set(title='liu')
h2 = plt.contourf(lon2, lat2, emiss_liu,
                  [-1.2,-1.0,-0.8,-0.6,-0.4,-0.2,-0.1,-0.01,0.01,0.1,0.2],
                  cmap = plt.cm.bwr,
                  norm = norm
                  )

#fig.subplots_adjust(right=0.9)

font = {'family' : 'serif',
#       'color'  : 'darkred',
    'color'  : 'black',
    'weight' : 'normal',
    'size'   : 16,
    }

cbar1 = fig.add_axes([0.15,0.075,0.7,0.015])
cb1 = plt.colorbar(h1, cax=cbar1,
  ticks=[-1.2,-1.0,-0.8,-0.6,-0.4,-0.2,-0.1,-0.01,0.01,0.1,0.2],
  orientation='horizontal')
cb1.ax.tick_params(labelsize=16)
cb1.set_label('10¹¹ molecules/cm²/s',fontdict=font)

'''
cbar2 = fig.add_axes([0.15,0.2,0.7,0.015])
cb2 = plt.colorbar(h2, cax=cbar2,orientation='horizontal')
cb2.ax.tick_params(labelsize=16)
cb2.set_label('molecules/cm²/s',fontdict=font)
'''

plt.savefig('F:/test_SOAG.png',  dpi=300)
plt.show()


from datetime import datetime

end_time = datetime(2021, 2, 12, 20)

sites_to_block = ['www.facebook.com', 'facebook.com']

hosts_path = "/etc/hosts"

redirect = "127.0.0.1"

def block_sites():
    if datetime.now() < end_time:
        print("block sites")
        # write all web-sites from our list to hostsfile
        with open(hosts_path, 'r+') as hostsfile:
            hosts_content = hostsfile.read()
            for site in sites_to_block:
                if site not in hosts_content:
                    hostsfile.write(redirect + " " + site + "\n")

    else:
        print("unblock sites")
        with open(hosts_path, 'r+') as hostsfile:
            lines = hostsfile.readline()
            hostsfile.seek(0)
            for line in lines:
                if not any(site in line for site in sites_to_block):
                    hostsfile.write(line)
                hostsfile.truncate()

if __name__ == "__main__":
    # 1. run manually
    block_sites()


# Conversor de monedas

def conversion(moneda,cantidad):
    if moneda == "dolares":
        factor = 19.95
    elif moneda == "pesos":
        factor = 1/(19.95)
    convertido = cantidad/factor
    convertido = round(convertido,2)
    print(f'Tienes {convertido} {moneda}')

def main():
    print("Selecciona una de las siguientes opciones.")
    print(''' [1] Convertir peso Mx a dolar Us
 [2] Convertir dolar Us a peso Mx\n''')
    opcion = int(input("Opcion: "))

    if opcion == 1:
        print("Convertir peso Mx a dolar Us\n")
        pesos = float(input("Cantidad de pesos: "))
        moneda = "dolares"
        conversion(moneda,pesos)
    elif opcion == 2:
        print("Convertir dolar Us a peso Mx\n")
        dolar = float(input("Cantidad de dolares: "))
        moneda = "pesos"
        conversion(moneda,dolar)
    else:
        print("\nIntentelo de nuevo ðŸ˜‚\n")
        main()

if __name__ == '__main__':
    main()


# the ioid of this script for JSON payload 'from'
from os.path import basename
ioid = basename(__file__)  # 'hello.py'

# Write the module functions with the proper reply
##########################################

def foo(incoming):
    match = incoming.find('Hello') > -1
    return 'Hello from Python.' if match else 'Who are you?'

# module method. Feel free to add more
def say_hi(msg):
    # the reply JSON payload.
    reply = {
        'output': foo(msg.get('input')),
        'to': msg.get('from'),
        'from': ioid,
        'hash': msg.get('hash')
    }
    # the py client will send this to target <to>
    return reply