#!/usr/bin/env python

__libname__ = 'ldtsmash'
__description__ = 'LEGO Desktop Toy Smash Archive Tool'
__version__ = '1.0.1'
__copyright__ = 'Copyright (c) 2019 JrMasterModelBuilder'
__license__ = 'Licensed under the Mozilla Public License, v. 2.0'

import os
import sys
import errno
import struct
import json
import argparse

def mkdirp(path):
	try:
		os.makedirs(path)
	except OSError as ex:
		if ex.errno == errno.EEXIST and os.path.isdir(path):
			pass
		else:
			raise ex

def openp(path, mode):
	base = os.path.dirname(path)
	if base:
		mkdirp(base)
	return open(path, mode)

def read_write_buffered(reader, writter, total, chunk):
	if chunk is None:
		writter.write(reader.read())
		return
	read = 0
	while read < total:
		size = total - read
		if size > chunk:
			size = chunk
		writter.write(reader.read(size))
		read += size

def class_str(instance):
	return class_repr(instance)

def class_repr(instance):
	return '<%s: %s>' % (instance.__class__, instance.__dict__)

class Error(Exception):
	pass

class TypeError(Error):
	pass

class FileReadError(Error):
	pass

class FileWriteError(Error):
	pass

class File():
	def __str__(self):
		return class_str(self)

	def __repr__(self):
		return class_repr(self)

	def __init__(self, fio, offset=None, size=None):
		# If offset no set, use current input offset.
		if offset is None:
			offset = fio.tell()

		# If a size is not set, base it on file seek end.
		if size is None:
			before = fio.tell()
			fio.seek(0, os.SEEK_END)
			size = fio.tell() - offset
			fio.seek(before, os.SEEK_SET)

		self.fio = fio
		self.offset = offset
		self.size = size
		self.__pos = 0

	def tell(self):
		return self.__pos

	def seek(self, offset, from_what=os.SEEK_SET):
		pos = None
		if from_what == os.SEEK_CUR:
			pos = self.__pos + offset
		elif from_what == os.SEEK_END:
			pos = self.__pos - offset
		elif from_what == os.SEEK_SET:
			pos = offset
		else:
			raise TypeError('Invalid seek from type: %s' % (from_what))

		if pos < 0 or pos > self.size:
			raise FileReadError('Cannot seek to: %s' % (pos))

		self.__pos = pos

	def can_read(self, size):
		return self.__pos + size <= self.size

	def read(self, size=None):
		pos = self.__pos
		fio = self.fio
		before = fio.tell()

		if size is None:
			size = self.size - pos

		if pos + size > self.size:
			raise FileReadError('Cannot read past end of file')

		fio.seek(self.offset + pos, os.SEEK_SET)
		try:
			ret = fio.read(size)
		finally:
			fio.seek(before, os.SEEK_SET)
		read_size = len(ret)

		if read_size != size:
			raise FileReadError('Read an unexpected size %s' % (read_size))

		self.__pos = pos + read_size
		return ret

	def write(self, data):
		pos = self.__pos
		fio = self.fio
		before = fio.tell()
		seekto = self.offset + pos

		if seekto > self.size:
			raise BLKFileWriteError('Cannot seek past end of file')

		fio.seek(seekto, os.SEEK_SET)
		try:
			fio.write(data)
		finally:
			fio.seek(before, os.SEEK_SET)

		self.__pos = pos + len(data)
		if self.__pos > self.size:
			self.size = self.__pos

	def can_read_struct(self, structure):
		return self.can_read(structure.size)

	def read_struct(self, structure):
		return structure.unpack_from(self.read(structure.size))

	def write_struct(self, structure, *args):
		self.write(structure.pack(*args))

	def sub(self, offset=None, size=None):
		if offset is None:
			offset = self.tell()
		if size is None:
			size = self.size - offset
		return self.__class__(self.fio, self.offset + offset, size)

class Entry():
	def __str__(self):
		return class_str(self)

	def __repr__(self):
		return class_repr(self)

	structure = struct.Struct(''.join([
		'<',   # little endian
		'16s', # name
		'I',   # offset
		'I'    # size
	]))
	size = structure.size
	size_name = 16
	size_offset = 4
	size_size = 4

	def __init__(self, name=None, offset=None, size=None):
		self.name = name
		self.offset = offset
		self.size = size

	def read_from(self, io):
		(name_enc, offset, size) = io.read_struct(self.structure)
		name = name_enc.split(b'\x00')[0].decode('ascii')
		self.name = name
		self.offset = offset
		self.size = size

	def write_to(self, io, name_buffer=None):
		name = self.name
		offset = self.offset
		size = self.size

		name_enc = name.encode('ascii')
		name_enc_len = len(name_enc)
		size_name = self.size_name
		if not (name_enc_len < size_name):
			raise FileWriteError(
				'File name longer than %s characters: %s' % (size_name - 1, name)
			)

		# Copy name bytes into name buffer, if provided.
		name_write = None
		if name_buffer:
			for i in range(name_enc_len):
				name_buffer[i] = name_enc[i]
			name_buffer[name_enc_len] = 0
			name_write = bytes(name_buffer)
		else:
			name_write = name_enc

		io.write_struct(self.structure, name_write, offset, size)

	def format_string(self):
		return '0x%08X 0x%08X %s' % (self.offset, self.size, self.name)

class Reader():
	Entry = Entry

	def __str__(self):
		return class_str(self)

	def __repr__(self):
		return class_repr(self)

	def __init__(self, file_idx, file_wad):
		self.file_idx = file_idx
		self.file_wad = file_wad

	def count(self):
		return self.file_idx.size // self.Entry.size

	def read(self):
		file_idx = self.file_idx
		file_wad = self.file_wad
		if file_idx.can_read(self.Entry.size):
			entry = self.Entry()
			entry.read_from(file_idx)
			io = None
			if file_wad:
				io = file_wad.sub(entry.offset, entry.size)
			return [entry, io]
		return None

	def reader(self):
		while True:
			read = self.read()
			if not read:
				return
			yield read

class Writter():
	Entry = Entry

	def __str__(self):
		return class_str(self)

	def __repr__(self):
		return class_repr(self)

	def __init__(self, file_idx, file_wad):
		self.file_idx = file_idx
		self.file_wad = file_wad

		# Name buffer, reusable to mirror the original encoder.
		self.name_buffer = bytearray(self.Entry.size_name)

	def write(self, entry, io, buffer_size=None, use_buffer=True):
		file_idx = self.file_idx
		file_wad = self.file_wad
		entry.offset = file_wad.tell()
		entry.size = io.size
		buf = None
		if use_buffer:
			buf = self.name_buffer
		entry.write_to(file_idx, buf)
		read_write_buffered(io, file_wad, io.size, buffer_size)

class FilelistReader():
	def __init__(self, fio):
		self.fio = fio

	def read(self):
		fio = self.fio
		while True:
			line = fio.readline()
			if not line:
				break
			s = line.strip()
			if s.startswith('"') and s.endswith('"'):
				return json.loads(s)
		return None

	def reader(self):
		while True:
			d = self.read()
			if d is None:
				break
			yield d

class FilelistWritter():
	def __init__(self, fio):
		self.fio = fio

	def write(self, filename):
		fio = self.fio
		fio.write(json.dumps(filename))
		fio.write('\n')

	def comment(self, lines):
		fio = self.fio
		for line in lines.split('\n'):
			fio.write('# ')
			fio.write(line)
			fio.write('\n')

class Process():
	filelist_name = '_ldtsmashlist.txt'
	filelist_comment = 'ldtsmash ordered list of file (JSON encoded strings)'
	buffer_size = 0x4000

	File = File
	Entry = Entry
	Reader = Reader
	Writter = Writter
	FilelistReader = FilelistReader
	FilelistWritter = FilelistWritter

	def __init__(self, options):
		self.options = options

	def realp(self, path):
		return path.replace('\\', '/')

	def filelist_open_r(self, directory):
		return open(os.path.join(directory, self.filelist_name), 'r')

	def filelist_open_w(self, directory):
		return openp(os.path.join(directory, self.filelist_name), 'w')

	def filelist_reader_next(self, fio):
		while True:
			line = fio.readline()
			if not line:
				break
			s = line.strip()
			if s.startswith('"') and s.endswith('"'):
				return json.loads(s)
		return None

	def filelist_reader_itter(self, fio):
		while True:
			d = self.filelist_reader_next(fio)
			if d is None:
				break
			yield d

	def entry_to_file(self, directory, entry, io):
		filepath = os.path.join(
			directory,
			self.realp(entry.name)
		)
		with openp(filepath, 'wb') as fio:
			read_write_buffered(io, fio, io.size, self.buffer_size)
			fio.close()

	def entry_from_file(self, directory, filename, writter):
		entry = self.Entry(filename)
		filepath = os.path.join(
			directory,
			self.realp(entry.name)
		)
		with open(filepath, 'rb') as fio:
			io = self.File(fio)
			writter.write(entry, io, self.buffer_size)
			fio.close()
		return entry

	def run_l(self):
		ndx = self.options.ndx
		with open(ndx, 'rb') as fio_nxd:
			reader = self.Reader(self.File(fio_nxd), None)

			for [entry, _] in reader.reader():
				print(entry.format_string())

			fio_nxd.close()
		return 0

	def run_e(self):
		ndx = self.options.ndx
		wad = self.options.wad
		directory = self.options.dir
		mkdirp(directory)

		with self.filelist_open_w(directory) as fl:
			fl_writter = self.FilelistWritter(fl)
			fl_writter.comment(self.filelist_comment)

			with open(ndx, 'rb') as fio_nxd:
				with open(wad, 'rb') as fio_wad:
					reader = self.Reader(self.File(fio_nxd), self.File(fio_wad))

					for [entry, io] in reader.reader():
						print(entry.format_string())
						fl_writter.write(entry.name)
						self.entry_to_file(directory, entry, io)
					fio_wad.close()
				fio_nxd.close()
			fl.close()
		return 0

	def run_c(self):
		ndx = self.options.ndx
		wad = self.options.wad
		directory = self.options.dir

		with self.filelist_open_r(directory) as fl:
			fl_reader = self.FilelistReader(fl)

			with openp(ndx, 'wb') as fio_nxd:
				with openp(wad, 'wb') as fio_wad:
					writter = self.Writter(self.File(fio_nxd), self.File(fio_wad))

					for fn in fl_reader.reader():
						entry = self.entry_from_file(directory, fn, writter)
						print(entry.format_string())
					fio_wad.close()
				fio_nxd.close()
			fl.close()
		return 0

	def run(self):
		c = self.options.command
		return getattr(self, 'run_%s' % (c))()

def main():
	parser = argparse.ArgumentParser(
		description=os.linesep.join([
			'%s - %s' % (__libname__, __description__),
			'Version: %s' % (__version__)
		]),
		epilog=os.linesep.join([
			__copyright__,
			__license__
		]),
		formatter_class=argparse.RawTextHelpFormatter
	)
	parser.add_argument(
		'-v', '--version',
		action='version',
		version=__version__
	)
	subparsers = parser.add_subparsers(help='command', dest='command')

	parser_l = subparsers.add_parser('l', help='list')
	parser_l.add_argument('ndx', help='in nxd file')

	parser_e = subparsers.add_parser('e', help='extract')
	parser_e.add_argument('ndx', help='in nxd file')
	parser_e.add_argument('wad', help='in wad file')
	parser_e.add_argument('dir', help='out directory')

	parser_c = subparsers.add_parser('c', help='compile')
	parser_c.add_argument('dir', help='in directory')
	parser_c.add_argument('ndx', help='out nxd file')
	parser_c.add_argument('wad', help='out wad file')

	return Process(parser.parse_args()).run()

if __name__ == '__main__':
	sys.exit(main())


from .element import Element, register_tag

@register_tag("NOTE")
class Note(Element):
    """Represents a note (NOTE)."""

    @property
    def full_text(self):
        """
        Return the full text of this note.

        Internally, notes are stores across many child nodes, with child
        CONT/CONS child nodes that store the other lines. This method assembles
        these elements into one continuusous string.
        """
        result = "" + self.value or ''

        for cons in self.child_elements:
            if cons.tag == 'CONT':
                result += "\n"
                result += cons.value or ''
            elif cons.tag == 'CONC':
                result += cons.value or ''
            else:
                raise ValueError("Full text can only consist of CONS and CONT")

        return result


def get_triangular_number():
    n = 1
    while True:
        yield n * (n + 1) / 2
        n += 1

def get_pentagonal_number():
    n = 1
    while True:
        yield n * (3 * n - 1) / 2
        n += 1

def get_hexagonal_number():
    n = 1
    while True:
        yield n * (2 * n - 1)
        n += 1

triangulars = get_triangular_number()
triangular_list = []
pentagonals = get_pentagonal_number()
pentagonal_list = []
hexagonals = get_hexagonal_number()
hexagonal_list = []

for i in range(1, 100000):
    triangular_list.append(triangulars.__next__())
    pentagonal_list.append(pentagonals.__next__())
    hexagonal_list.append(hexagonals.__next__())

for item in triangular_list:
    if item in pentagonal_list and item in hexagonal_list:
        print(item)


"""
The event module is intended to contain any handling of pygame events, and provide some interfaces
for working with events in general.

globals:
  KeyPressEvent         An event object which runs all registered objects when
                        a key is pressed.
  KeyReleaseEvent       An event object which runs all registered objects when
                        a key is released.
  KeyToggleEvent        An event object which runs all registered objects when
                        a key is pressed or released (toggled).

functions:
  update                Run through all events currently in the pygame event
                        queue and put them into the real event queue.

"""

from collections import deque
from heapq import merge

import pygame

from util import Event, RealEvent
from game import game

class _KeyEvent(Event):
    """
    A KeyEvent object can be directly registered to for any key (will be passed as first parameter),
    or a specific key can be registered to, which will not pass the key as a parameter.

    """

    def __getitem__(self, key):
        """Get Event for the specified key."""
        if key not in self.__events:
            # None exist, create new one
            self.__events[key] = Event()

        return self.__events[key]

    def __init__(self):
        self.__events = {}
        super().__init__()

# Information about these in the module docstring.
KeyPressEvent = _KeyEvent()
KeyReleaseEvent = _KeyEvent()
KeyToggleEvent = _KeyEvent()

class _KeyPress(RealEvent):
    """
    Event used to indicate a key was pressed.  Key Press/Release events are automatically
    generated when CurrentState does not match the next key state.

    """

    def __call__(self):
        """Run all relevant events."""
        KeyPressEvent[self.key]()
        KeyToggleEvent[self.key](True)

        KeyPressEvent(self.key)
        KeyToggleEvent(True)

    def __init__(self, key, time):
        self.key = key
        self.time = time
        self.invalid = False

class _KeyRelease(RealEvent):
    """
    Event used to indicate a key was released.  Key Press/Release events are automatically
    generated when CurrentState does not match the next key state.

    """

    def __call__(self):
        """Run all relevant events."""
        KeyReleaseEvent[self.key]()
        KeyToggleEvent[self.key](False)

        KeyReleaseEvent(self.key)
        KeyToggleEvent(False)

    def __init__(self, key, time):
        self.key = key
        self.time = time
        self.invalid = False

# Current Key State is not synced with the game's time.
# If you wish to know the current key state, you should
# register a function with KeyPressEvent and KeyReleaseEvent.
_CurrentState = []

def update(current_time):
    """
    Run through all events currently in the pygame event queue and put them
    into the real event queue.

    """

    pygame.event.pump()

    # Handle key press/release events
    global _CurrentState
    next_state = pygame.key.get_pressed()
    key_events = []
    for key, was_pressed in enumerate(_CurrentState):
        if next_state[key] and not was_pressed:
            key_events.append(_KeyPress(key, current_time))

        if was_pressed and not next_state[key]:
            key_events.append(_KeyRelease(key, current_time))
    game.real_events = deque(merge(game.real_events, key_events))
    _CurrentState = next_state


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

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from matplotlib.backends.backend_pdf import PdfPages

pp = PdfPages("curvy4.pdf")
print("Setup Complete")

def func(x, a, b, c):
    return a * np.exp(-b * x) + c

xdata = np.linspace(0, 4, 50)
y = func(xdata, 2.5, 1.3, 0.5)
rng = np.random.default_rng()
y_noise = 0.2 * rng.normal(size=xdata.size)
ydata = y + y_noise
plt.plot(xdata, ydata, "bo", label="data points")
plt.plot(xdata, ydata, "y", label="data")

popt, pcov = curve_fit(func, xdata, ydata)
print(popt)
plt.plot(xdata, func(xdata, *popt), "r-", label="fit: a=%5.3f, b=%5.3f, c=%5.3f" % tuple(popt))

popt, pcov = curve_fit(func, xdata, ydata, bounds=(0, [3.0, 1.0, 0.5]))
print(popt)
plt.plot(xdata, func(xdata, *popt), "g--", label="fit: a=%5.3f, b=%5.3f, c=%5.3f" % tuple(popt))
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
pp.savefig()

pp.close()


"""
EXECUTION: python script_apply_word_length_filter.py
           --directory <directory>
           [--threshold 20000]

PURPOSE: the script
         - takes all the dataset files in <directory>
         - for each dataset file, checks whether a document has a non-whitespace sequence of length > <threshold>
         - if so, it filters those documents and writes the rest to <directory>_FILTERED
"""
import os
from os.path import join, isdir, isfile
import json
import argparse

from os.path import abspath, dirname
import sys
BASE_DIR = abspath(dirname(dirname(dirname(abspath(__file__)))))
print(f">>> BASE_DIR: {BASE_DIR}")
sys.path.append(BASE_DIR)

def main(args):

    input_directory = join(BASE_DIR, args.directory)
    output_directory = join(BASE_DIR, f"{input_directory}_FILTERED")

    assert isdir(input_directory), f"ERROR! {input_directory} not found."

    input_files = [
        join(input_directory, elem)
        for elem in os.listdir(input_directory)
        if isfile(join(input_directory, elem)) and "_FILTERED.jsonl" not in elem
    ]

    print()
    print(f"> found {len(input_files)} files in {input_directory}")

    for i, input_file in enumerate(input_files):
        print(f"\n=== file #{i+1}: {input_file}")
        output_file = join(output_directory, input_file.split("/")[-1].replace(".jsonl", "_FILTERED.jsonl"))

        # read old data
        with open(input_file, "r", encoding="utf-8") as _file:
            data = [json.loads(line) for line in _file]
        print(f"> loaded {len(data)} documents from {input_file}")

        # new data: apply word length filter
        new_data = list()
        counter = {'kept': 0, 'removed': 0}
        for document in data:
            longest_word = max([len(elem) for elem in document["text"].split(" ")])
            if longest_word <= args.threshold:
                new_data.append(document)
                counter['kept'] += 1
            else:
                counter['removed'] += 1
        print(f"> applied filter with threshold = {args.threshold}")
        print(f"  kept    documents: {counter['kept']}")
        print(f"  removed documents: {counter['removed']}")

        # write new data if needed
        if counter['removed'] > 0:
            os.makedirs(output_directory, exist_ok=True)
            with open(output_file, "w", encoding="utf-8") as _file:
                for line in new_data:
                    _file.write(json.dumps(line, ensure_ascii=False) + "\n")
            print(f"> wrote {len(new_data)} documents to {output_file}")
        else:
            print(f"> no need to write a new file")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--directory", type=str, required=True)
    parser.add_argument("--threshold", type=int, default=20000)
    _args = parser.parse_args()

    main(_args)


from Model_Prediction_Modules.validation_pred_data import rawpreddatavalidation
from Model_Prediction_Modules.pred_preprocessing import pred_Preprocessor
from Model_Prediction_Modules.model_prediction import model_predictor
from Model_Training_Modules.validation_train_data import rawtraindatavalidation
from Model_Training_Modules.train_preprocessing import train_Preprocessor
from Model_Training_Modules.model_training import model_trainer
import pandas as pd
import streamlit as st
import joblib

def main():
    st.title("Wafer Status Prediction")
    html_temp = """

Wafer Status Prediction App

    """
    st.markdown(html_temp,unsafe_allow_html=True)
    if st.button("Training Data Validation"):
        trainvalidator = rawtraindatavalidation(
            tablename = 'sensordata', file_object = "Training_Logs/Training_Main_Log.txt", gooddir = "Good_Training_Data/", baddir = "Bad_Training_Data/")
        folders = ['Good_Training_Data/','Bad_Training_Data/','Archive_Training_Data/','Training_Data_FromDB/','Intermediate_Train_Results/','Caching/','Saved_Models/']
        trainvalidator.initial_data_preparation(
            schemapath = 'schema_training.json', folders = folders,batchfilepath = "Training_Batch_Files", goodfilepath = 'Good_Training_Data/', archivefilepath= 'Archive_Training_Data/',compileddatapath= 'Training_Data_FromDB/Training_Data.csv')
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")
    if st.button("Exploratory Data Analysis"):
        preprocessor = train_Preprocessor(
            file_object= "Training_Logs/Training_Preprocessing_Log.txt",data_path = 'Training_Data_FromDB/Training_Data.csv',result_dir= 'Intermediate_Train_Results/')
        preprocessor.eda(target_col = 'Output')
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")
    if st.button("Training Data Preprocessing"):
        preprocessor = train_Preprocessor(
            file_object= "Training_Logs/Training_Preprocessing_Log.txt", result_dir= 'Intermediate_Train_Results/')
        preprocessor.data_preprocessing(
            col_drop_path= 'Columns_Drop_from_Original.csv', index_col= 'Wafer', target_col = 'Output')
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")
    if st.button("Model Selection"):
        trainer = model_trainer(
            file_object= "Training_Logs/Training_Model_Log.txt")
        X = pd.read_csv('Intermediate_Train_Results/X.csv')
        y = pd.read_csv('Intermediate_Train_Results/y.csv')
        trainer.model_selection(
            input = X, output = y, num_trials = 20, folderpath = 'Intermediate_Train_Results/')
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")
    if st.button("Final Model Training"):
        trainer = model_trainer(
            file_object= "Training_Logs/Training_Model_Log.txt")
        X = pd.read_csv('Intermediate_Train_Results/X.csv')
        y = pd.read_csv('Intermediate_Train_Results/y.csv')
        trainer.final_model_tuning(
            input_data = X, output_data = y, num_trials = 20, folderpath = 'Intermediate_Train_Results/')
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")
    if st.button("Prediction Data Validation"):
        predvalidator = rawpreddatavalidation(
            tablename = 'predsensordata', file_object= "Prediction_Logs/Prediction_Main_Log.txt", gooddir= "Good_Prediction_Data/", baddir= "Bad_Prediction_Data/")
        folders = ['Good_Prediction_Data/','Bad_Prediction_Data/','Archive_Prediction_Data/','Prediction_Data_FromDB/','Intermediate_Pred_Results/']
        predvalidator.initial_data_preparation(
            schemapath = 'schema_prediction.json', folders = folders,batchfilepath= "Prediction_Batch_Files/", goodfilepath= 'Good_Prediction_Data/', archivefilepath= 'Archive_Prediction_Data/',compileddatapath= 'Prediction_Data_FromDB/Prediction_Data.csv')
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")
    if st.button("Prediction Data Preprocessing"):
        preprocessor = pred_Preprocessor(
            file_object= "Prediction_Logs/Prediction_Preprocessing_Log.txt")
        preprocessor.data_preprocessing(
            data_path= 'Prediction_Data_FromDB/Prediction_Data.csv',train_path= 'Intermediate_Train_Results/', index_col= 'Wafer')
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")
    if st.button("Model Prediction"):
        predictor = model_predictor(
            file_object= "Prediction_Logs/Prediction_Model_Log.txt")
        predictor.model_prediction(
            datapath = 'Intermediate_Pred_Results/Prediction_Processed_Data.csv', model = joblib.load('Saved_Models/FinalModel.pkl'), pipeline = joblib.load('Saved_Models/Preprocessing_Pipeline.pkl'))
        st.success(
            "This step of the pipeline has been completed successfully. Check the local files for more details.")

if __name__=='__main__':
    main()


import math

def calc_fuel(planet_mass):
    return math.floor(planet_mass/3) - 2

def part_one():
    planets = [int(line.rstrip()) for line in open('day1_data.txt').readlines()]
    fuel_needed = 0
    for planet_mass in planets:
        fuel_needed += calc_fuel(planet_mass)
    return fuel_needed

def part_two():
    planets = [int(line.rstrip()) for line in open('day1_data.txt').readlines()]
    fuel_needed = 0
    for mass in planets:
        fuel_req = mass  # init fuel_req > 0
        while fuel_req > 0:
            fuel_req = calc_fuel(fuel_req)
            fuel_needed += fuel_req
    return fuel_needed

print(part_one())
print(part_two())


import numpy as np
import matplotlib.pyplot as plt
import scipy.misc
import os
import pyclipper
from skimage import io
from PIL import Image
"""
This scripts find the axes of an object
"""

"""
First Method: Covariance matrix and eigens
"""
# 1.Matrix of points:
#   We'll be dealing with 2D points so our matrix is 2xm. The 1st row are the x-coordinates,
#   2nd row are the y-coordinates and m indicates the number of points.
os.chdir("/home/mrobot/Documentos/TFG/code/Skin-Lesion-Analysis-Towards-Melanoma-Detection")
img = scipy.misc.imread('image/train_ground/ISIC_0000000_segmentation.png', flatten=True)
y, x = np.nonzero(img)

# 2.Subtract the mean for each point:
#   Calculate the mean of the row of x-coordinates. For each x-point, subtract the mean from it. Do the same for
#   the y-coordinate. Mean subtraction minimises the mean square error of approximating the data and centers the data.

x = x - np.mean(x)
y = y - np.mean(y)
coords = np.vstack([x,y])

# 3.Covariance matrix calculation:
#   Calculate the 2x2 covariance matrix.

cov = np.cov(coords)

# 4.Eigenvector, eigenvalues of covariance matrix:
#   Find the 2 eigen-pairs of our dataset.

evals, evecs = np.linalg.eig(cov)

# 5.Rearrange the eigen-pairs:
#   Sort by decreasing eigenvalues

sort_indices = np.argsort(evals)[::-1]
evec1, evec2 = evecs[:, sort_indices]
x_v1, y_v1 = evec1
x_v2, y_v2 = evec2

# Plot tumor
plt.plot(x, y, 'k.')

# Rotation of the tumor
theta = np.arctan((x_v1)/(y_v1))
rotation_mat = np.matrix([[np.cos(theta), -np.sin(theta)],
                          [np.sin(theta), np.cos(theta)]])
transformed_mat = rotation_mat * coords
x_transformed, y_transformed = transformed_mat.A

plt.plot(x_transformed, y_transformed, 'g.')

# Obtener el área que no se solapa con su reflexión
"""
t = [[1, 0]]
d = t * transformed_mat
index_over = np.where(d>=0)[1]
x_over = x_transformed[index_over]
y_over = y_transformed[index_over]

index_sub = np.where(d<0)[1]
x_sub = x_transformed[index_sub]
y_sub = y_transformed[index_sub]

plt.plot(x_over*-1, y_over, 'y.')
plt.plot(x_sub*-1, y_sub, 'b.')
"""

# Inversa del tumor en sentido del eje x
x_transformed_reflection = x_transformed*-1
y_transformed_reflection = y_transformed

plt.plot(x_transformed_reflection, y_transformed_reflection, 'y.')

# Encuentra el convex hull
from scipy.spatial import ConvexHull

points_t = np.array([x_transformed, y_transformed]).transpose()
points_tr = np.array([x_transformed_reflection, y_transformed_reflection]).transpose()
hull_t = ConvexHull(points_t)
hull_tr = ConvexHull(points_tr)

plt.plot(points_t[hull_t.vertices,0], points_t[hull_t.vertices,1], 'r--', lw=2)

#for simplex in hull.simplices:
#    plt.plot(points_t[simplex, 0], points_t[simplex, 1], 'k-')
#    plt.plot(points_tr[simplex, 0], points_tr[simplex, 1], 'r-')

#d = (y_v1)*x0 + (-x_v1)*y0 # determines if a certain point (x0,y0) is over(d>0) or sub(d<0) to the straight line
#print(d)
#plt.plot([x0], [y0], 'wo')

# 6.Plot the principal components
scale = 60

plt.plot([x_v1*-scale*2, x_v1*scale*2],
         [y_v1*-scale*2, y_v1*scale*2], color='red')

plt.plot([x_v2*-scale, x_v2*scale],
         [y_v2*-scale, y_v2*scale], color='blue')

plt.plot([0], [0], 'ro')

plt.axis('equal')
plt.gca().invert_yaxis()
plt.show()


from rplt import *

datafiles = [
    'DataTreeTrilepton-DoubleElectron-Run2011A-05Aug2011-v1.root',
    'DataTreeTrilepton-DoubleElectron-Run2011A-May10ReReco-v1.root',
    'DataTreeTrilepton-DoubleElectron-Run2011A-PromptReco-v4.root',
    'DataTreeTrilepton-DoubleElectron-Run2011A-PromptReco-v6.root',
    'DataTreeTrilepton-DoubleElectron-Run2011B-PromptReco-v1.root',
    'DataTreeTrilepton-DoubleMu-Run2011A-05Aug2011-v1.root',
    'DataTreeTrilepton-DoubleMu-Run2011A-May10ReReco-v1.root',
    'DataTreeTrilepton-DoubleMu-Run2011A-PromptReco-v4.root',
    'DataTreeTrilepton-DoubleMu-Run2011A-PromptReco-v6.root',
    ]
datadirs = [File(x) for x in datafiles]
data = SumView(datadirs)

lumi = 4700.

zzdirs = [
    ScaleView(File('ZZTo2e2mu_7TeV-powheg-pythia6.root'), lumi * 0.0308 / 499917.0),
    ScaleView(File('ZZTo2e2tau_7TeV-powheg-pythia6.root'), lumi * 0.0308 / 484063.0),
    ScaleView(File('ZZTo2mu2tau_7TeV-powheg-pythia6.root'), lumi * 0.0308 / 486266.0),
    ScaleView(File('ZZTo4e_7TeV-powheg-pythia6.root'), lumi * 0.0154 / 499929.0),
    ScaleView(File('ZZTo4mu_7TeV-powheg-pythia6.root'), lumi * 0.0154 / 499918.0),
    ScaleView(File('ZZTo4tau_7TeV-powheg-pythia6.root'), lumi * 0.0154 /473838.0),
    ]
zz = SumView(zzdirs)

zjets = ScaleView(File('DYJetsToLL_TuneZ2_M-50_7TeV-madgraph-tauola.root'), lumi * 3050 / 36209629.0)
gv = ScaleView(File('GVJets_7TeV-madgraph.root'), lumi * 173 / 1067879.0)
#tt = ScaleView(File('TTJets_TuneZ2_7TeV-madgraph-tauola.root'), lumi * 158. / 50098875.0)
#wjets = ScaleView(File('WJetsToLNu_TuneZ2_7TeV-madgraph-tauola.root'), lumi * 31300 / 68447497.0)
ww = ScaleView(File('WWJetsTo2L2Nu_TuneZ2_7TeV-madgraph-tauola.root'), lumi * 4.89 / 1197558.0)
wz = ScaleView(File('WZJetsTo3LNu_TuneZ2_7TeV-madgraph-tauola.root'), lumi * .879 / 1221134.0)
vv = SumView(zz, ww)

wzscale = args.wz

titles = [
    r'Data',
    r'$WZ \times\,%i$' % wzscale,
    r'$Z$ + jets',
    r'$ZZ + WW$',
    r'$t\bar{t}$ + jets',
    ]
linestyles = ['solid', 'dashed', 'dashdot', 'dotted'] * 3
linestyles = ['solid'] * 20

colors_tranquility = [
    (182,193,177),
    (152,186,174),
    (32,199,191),
    (50,134,135),
    (100,81,104),
    ]
# mcdirs = [tt, vv, zjets, wz]
mcdirs = [wz]
for i, d in enumerate(mcdirs):
    # mcdirs[i] = StyleView(d, markercolor=colors_tranquility[i], fillcolor=None)
    mcdirs[i] = StyleView(d, fillcolor=colors_tranquility[i])
    mcdirs[i] = ScaleView(mcdirs[i], wzscale)
# data = NormalizeView(data)
dirs = [data] + mcdirs

histnames = [
    'hb_pt',
    'hb_sieie',
    'hb_detain',
    'hb_dphiin',
    'hb_nmiss',
    'hb_dist',
    'hb_dcot',
    'hb_iso',
    'he_pt',
    'he_sieie',
    'he_detain',
    'he_dphiin',
    'he_nmiss',
    'he_dist',
    'he_dcot',
    'he_iso',
    'hm_pt',
    'hm_npix',
    'hm_ntrk',
    'hm_nmuo',
    'hm_nseg',
    'hm_chi2',
    'hm_d0',
    'hm_iso',
]

xlabels = [
    r'Muon pt/GeV',
    r'Muon Chi2',
    ] * 20

replacements = [
    ('dist', r'Conversion Distance $d$/cm'),
    ('dcot', r'$\Delta\cot{(\theta)}$'),
    ('dphiin', r'$\Delta\phi_\mathrm{in}$'),
    ('detain', r'$\Delta\eta_\mathrm{in}$'),
    ('iso', r'$R_\mathrm{iso}$'),
    ('pT', r'$p_\mathrm{T}$/GeV'),
    ('sieie', r'$\sigma_{i\eta i\eta}$'),
    ('chi2', r'Normalized $\chi^2$'),
    ('d0', r'$d_0$'),
    ('nmiss', r'Number of Missing Hits'),
    ('nmuo', r'$N$ Muon System Hits'),
    ('npix', r'$N$ Pixel Tracker Hits'),
    ('ntrk', r'$N$ Tracker System Hits'),
    ('nseg', r'$N$ Matched Muon Segments'),
    ]

def myrep(string):
    for args in replacements:
        string = string.replace(args[0], args[1])
    return string

def exclude(histname, minmax, *args):
    if len(args) == 4:
        if 'hb' in histname:
            args = args[0::2]
        else:
            args = args[1::2]
    for bound in args:
        if bound is None:
            continue
        if minmax == 'min':
            plt.axvspan(0., bound, linewidth=0., facecolor='k', alpha=0.15)
            plt.axvspan(-bound, 0, linewidth=0., facecolor='k', alpha=0.15)
        else:
            plt.axvspan(bound, 3000., linewidth=0., facecolor='k', alpha=0.15)
            plt.axvspan(-3000, -bound, linewidth=0., facecolor='k', alpha=0.15)

def intticks(numticks):
    plt.xticks([x + 0.5 for x in range(numticks)], range(numticks))

for histname, xlabel in zip(histnames, xlabels):
    hists = [d.Get(histname) for d in dirs]
    for i, h in enumerate(hists):
        h.SetTitle(titles[i])
        h.SetLineStyle(linestyles[i])
    for i, h in enumerate(hists[1:]):
        # h.SetFillColor(['#900','#090','#009',][i%3])
        # h.SetFillColor(str((i+1.)/len(hists)))
        h.SetFillColor(colors_tranquility[i])
    if True:
        # hists[-1].SetFillStyle('hollow')
        hists[1].SetMarkerColor((100,81,104))
        hists[1].SetMarkerStyle('square')
        # rplt.bar(hists[1], linewidth=0, log=True)
        # rplt.errorbar(hists[1], xerr=False, capsize=1)
        rplt.hist(hists[1:], reverse=True)
        rplt.errorbar(hists[0], xerr=False, capsize=1)
        ax.yaxis.set_label_coords(-0.11, 0.5)
        plt.ylim(ymin=0.01)
        plt.legend()
        xlabel = myrep(hists[0].GetXaxis().GetTitle())
        if histname.startswith('he'):
            xlabel = 'Endcap ' + xlabel
        if histname.startswith('hb'):
            xlabel = 'Barrel ' + xlabel
        plt.xlabel(xlabel)
        plt.ylabel('Events')
        if 'sieie' in histname:
            exclude(histname, 'max', 0.012, 0.031, 0.010, 0.031)
        if '_pt' in histname:
            exclude(histname, 'min', 10., 20.)
        if 'dphiin' in histname:
            exclude(histname, 'max', 0.800, 0.700, 0.027, 0.021)
        if 'detain' in histname:
            exclude(histname, 'max', 0.007, 0.011, 0.005, 0.006)
            plt.xlim(-0.01,0.01)
        if 'nmiss' in histname:
            exclude(histname, 'max', 1, 1)
            plt.xlim(0,6)
            intticks(6)
        if 'dist' in histname:
            exclude(histname, 'min', None, None, 0.02, 0.02)
        if 'dcot' in histname:
            exclude(histname, 'min', None, None, 0.02, 0.02)
        if 'iso' in histname:
            if histname.startswith('hm'):
                exclude(histname, 'max', 0.15, 0.1)
            else:
                exclude(histname, 'max', 0.15, 0.10, 0.07, 0.06)
        if 'd0' in histname:
            exclude(histname, 'max', 0.2)
        if 'chi2' in histname:
            exclude(histname, 'max', 10.)
        if histname == 'hm_npix':
            exclude(histname, 'min', 1)
            intticks(8)
        if histname == 'hm_ntrk':
            exclude(histname, 'min', 11)
        if histname == 'hm_nmuo':
            exclude(histname, 'min', 1)
        if histname == 'hm_nseg':
            exclude(histname, 'min', 2)
            intticks(5)
            # plt.axvspan(0.010, 1., linewidth=0., facecolor='k', alpha=0.15)
            # plt.axvspan(0.012, 1., linewidth=0., facecolor='k', alpha=0.15)
        # for label in plt.gca().get_xaxis().get_ticklabels():
        #     label.set_verticalalignment('baseline')
        # for label in plt.gca().get_yaxis().get_ticklabels():
        #     label.set_verticalalignment('baseline')
        # # # rplt.col(hists[0])
        # plt.ylim(ymin=0.01)
        plt.savefig(histname)
        plt.cla()
        plt.ylim((0,1))


import time
import random  # Import the random module. Using this for simulations to mimic API calls
from create_objects import create_boreholes, create_sensors, initialize_statuses

def update_real_time_statuses(status_data):
    for sensor_id, status_info in status_data.items():
        # Simulate changes in sensor status. I modified this function to mimic API call that was receiving sensor statuses
        new_status = random.choice(['Off', 'Normal', 'Stretched', 'Critical'])
        status_info.status = new_status
        status_info.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

def sensor_monitoring(boreholes, sensors, status_data):
    borehole_hash = {borehole.borehole_id: borehole for borehole in boreholes}
    sensor_hash = {sensor.sensor_id: sensor for sensor in sensors}

    while True:
        # Simulate real-time status updates. I modified this function to mimic API calls that were updating the status
        update_real_time_statuses(status_data)

        # Update sensor_hash with the latest statuses
        for sensor_id, status_info in status_data.items():
            sensor_hash[sensor_id].current_status = status_info.status

        # Predictive algorithm. I modified this function to mimic API calls that were predicting sensor statuses
        for sensor_id, status_info in status_data.items():
            if status_info.status == 'Stretched':
                print(f"Predicting potential critical status for Sensor {sensor_id} in Borehole {sensor_hash[sensor_id].borehole_id}!")

        # Simulate a time delay between updates. I modified this function to mimic API calls that were calculating delay between updates
        time.sleep(60)

if __name__ == "__main__":
    excel_file_path = "sensor_statuses.csv"

    boreholes = create_boreholes(excel_file_path)
    sensors = create_sensors(excel_file_path)
    statuses = initialize_statuses(excel_file_path)

    status_data = {status.sensor_id: status for status in statuses}

    sensor_monitoring(boreholes, sensors, status_data)


import sys
import os
import utils.config
import argparse
import traceback
import importlib
from datetime import datetime
from datetime import timedelta
from random import shuffle
import syslog
from syslog import LOG_ERR
from cerebralcortex.cerebralcortex import CerebralCortex
from cerebralcortex.core.util.spark_helper import get_or_create_sc

cc_config_path = None
gps_key = None

def process_features(feature_list, all_users, all_days, num_cores=1):
    '''
    This method runs the processing pipeline for each of
    the features in the list.
    '''
    for module in feature_list:
        if num_cores > 1:
            #num_cores *= 4

            print('Driver: Spark job',module)
            spark_context = get_or_create_sc(type="sparkContext")
            if 'core.feature.gps.gps' == str(module) \
                or 'sleep_duration_analysis' in str(module) \
                or 'office_time' in str(module) \
                or 'phone_screen_touch_features' in str(module) \
                or 'socialjetlag' in str(module) \
                or 'gps_location_daywise' in str(module):
                '''
                # FIXME # TODO Currently only GPS feature computes features on a
                range of days. Need to find a better way if there are other
                modules that also works on range of days.
                '''
                print('-'*120)
                print('MODULE parallelized on only users',module)
                rdd = spark_context.parallelize(all_users,num_cores)
                results = rdd.map(
                    lambda user: process_feature_on_user(user, module, all_days,
                                                         cc_config_path))
                results.count()
            else:
                print('MODULE',module)
                parallelize_per_day = []
                for usr in all_users:
                    for day in all_days:
                        parallelize_per_day.append((usr,[day]))

                shuffle(parallelize_per_day)
                rdd = spark_context.parallelize(parallelize_per_day,
                                                len(parallelize_per_day))
                results = rdd.map(
                    lambda user_day: process_feature_on_user(user_day[0],
                                                             module, user_day[1],
                                                             cc_config_path))
                results.count()

            spark_context.stop()
        else:
            print('Driver: single threaded')
            for user in all_users:
                process_feature_on_user(user, module, all_days, cc_config_path)

def process_feature_on_user(user, module_name, all_days, cc_config_path):
    try:
        cc = CerebralCortex(cc_config_path)
        module = importlib.import_module(module_name)
        feature_class_name = getattr(module,'feature_class_name')
        feature_class = getattr(module,feature_class_name)
        feature_class_instance = feature_class(cc)

        if gps_key is not None:
            feature_class_instance.gps_api_key = gps_key

        f = feature_class_instance.process
        f(user,all_days)
    except Exception as e:
        err=str(e) + "\n" + str(traceback.format_exc())
        print(err)
        syslog.openlog(ident="CerebralCortex-Driver")
        syslog.syslog(LOG_ERR,err)
        syslog.closelog()

def discover_features(feature_list):
    '''
    This method discovers all the features that are present.
    '''
    feature_dir = os.path.join(utils.config.FEATURES_DIR_NAME)
    found_features = []
    if feature_list:
        feature_subdirs = feature_list
    else:
        feature_subdirs = os.listdir(feature_dir)

    for subdir in feature_subdirs:
        feature = os.path.join(feature_dir,subdir)
        if not os.path.exists(feature):
            syslog.openlog(ident="CerebralCortex-Driver")
            syslog.syslog(LOG_ERR,'Feature not found %s.' % subdir)
            syslog.closelog()
            continue
        if os.path.isdir(feature):
            mod_file_path = os.path.join(feature,subdir) + '.py'

            if not os.path.exists(mod_file_path):
                continue
            sys.path.append(feature)
            try:
                module_name = mod_file_path[:-3] # strip '.py'
                module_name_dotted = module_name.replace('/','.')
                found_features.append(module_name_dotted)
                syslog.openlog(ident="CerebralCortex-Driver")
                syslog.syslog('Added feature %s for importing' % feature)
                syslog.closelog()
            except Exception as exp:
                err = str(exp) + '\n' + str(traceback.format_exc())
                print(err)
                syslog.openlog(ident="CerebralCortex-Driver")
                syslog.syslog(LOG_ERR, str(exp) + err)
                syslog.closelog()

    return found_features

def generate_feature_processing_order(feature_list):
    '''
    This method returns the execution order of processing the features
    after resolving the inter dependencies.
    '''
    return feature_list

def main():
    global cc_config_path
    global metadata_dir
    global gps_key
    # Get the list of the features to process
    parser = argparse.ArgumentParser(description='CerebralCortex '
                                     'Feature Processing Driver')
    parser.add_argument("-f", "--feature-list", help="List of feature names "
                        "seperated by commas", nargs='?', default=None,
                        required=False)
    parser.add_argument("-c", "--cc-config", help="Path to file containing the "
                        "CerebralCortex configuration", required=True)
    parser.add_argument("-s", "--study-name", help="Study name.", required=True)
    parser.add_argument("-u", "--users", help="Comma separated user uuids",
                         nargs='?', default=None, required=False)
    parser.add_argument("-sd", "--start-date", help="Start date in "
                         "YYYYMMDD Format", required=True)
    parser.add_argument("-ed", "--end-date", help="End date in "
                         "YYYYMMDD Format", required=True)
    parser.add_argument("-p", "--num-cores", type=int, help="Set a number "
                        "greater than 1 to enable spark "
                        "parallel execution ", required=False)
    parser.add_argument("-k", "--gps-key", help="GPS API "
                         "key", required=False)

    args = vars(parser.parse_args())
    feature_list = None
    study_name = None
    users = None
    start_date = None
    end_date = None
    date_format = '%Y%m%d'
    num_cores = 1 # default single threaded

    if args['feature_list']:
        feature_list = args['feature_list'].split(',')
    if args['cc_config']:
        cc_config_path = args['cc_config']
    if args['study_name']:
        study_name = args['study_name']
    if args['users']:
        users = args['users'].split(',')
    if args['start_date']:
        start_date = datetime.strptime(args['start_date'], date_format)
    if args['end_date']:
        end_date = datetime.strptime(args['end_date'], date_format)
    if args['num_cores']:
        num_cores = args['num_cores']
    if args['gps_key']:
        gps_key = args['gps_key']

    all_days = []
    while True:
        all_days.append(start_date.strftime(date_format))
        start_date += timedelta(days = 1)
        if start_date > end_date : break

    CC = None
    all_users = None
    try:
        CC = CerebralCortex(cc_config_path)
        if not users:
            users = CC.get_all_users(study_name)
            if not users:
                print('No users found')
                return
            if not len(users):
                print('No users found')
                return # no point continuing
            all_users = [usr['identifier'] for usr in users]
        else:
            all_users = users
    except Exception as e:
        print(str(e))
        print( str(traceback.format_exc()))
    if not all_users:
        print('No users found for the study',study_name)
        return

    found_features = discover_features(feature_list)
    feature_to_process = generate_feature_processing_order(found_features)
    process_features(feature_to_process, all_users, all_days, num_cores)

if __name__ == '__main__':
    main()


from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.views.generic.list import ListView
from django.utils import timezone
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from .form import PacienteForm
from .models import Paciente

def poslogin(request):

    if request.user.id:
     return render(request, 'Bem_vindo.html', {})
    else:
        return HttpResponseRedirect("/")

def cadastroPaciente(request):

 if not request.user.id:
    return HttpResponseRedirect("/")

 else:

    if request.method == 'POST':

        form = PacienteForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            form.save()
            # redirect to a new URL:
            return HttpResponseRedirect('/inicio/')

    # if a GET (or any other method) we'll create a blank form
    else:
        form = PacienteForm()

    return render(request, 'CadastroPaciente.html', {'form': form})

class PacienteListVeiw(ListView):

    model = Paciente
    def lista(self, **kwargs):

        list = super (PacienteListVeiw, self)
        return list

class PacienteUpdate(UpdateView):
    model = Paciente
    success_url = '/inicio/lista/'
    fields = fields = ['nome','cpf','data_Nascimento','sexo','estadoCivil','data_Atendimento','queixaPrincipal',]

class PacienteDelete(DeleteView):
    model = Paciente
    success_url = '/inicio/lista/'


import numpy as np
import pandas as pd
import openpyxl as pp
n = 3                                    # can use n=(max_index-1)/7
df = pd.read_excel("timetable.xlsx")     # where max_index is highest index in excel sheet
lec = pd.DataFrame(columns = ['name','age','roll','room'])
d = input("Enter day:")
x = int(input("Starting period:"))
y = int(input("Ending period:"))
for i in range(0,n):
  table = df.iloc[7*i+0:7*i+6]
  table.index = ['MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','SATURDAY']
  table.columns = [1,2,3,4,5,6,7]
  particulars = df.iloc[7*i+6:7*i+7,0:3]
  particulars.index = ['PARTICULARS']
  particulars.columns = ['name','age','roll']
  j = x
  c = 0
  while(j<=y):
    if ((table[j][d.upper()]) == 1):
      print(particulars.iloc[0,0],"is not free")
      break
    else:
      j += 1
      c += 1
  if(c == (y-x+1)):
    print(particulars.iloc[0,0],"is free")
    lec = lec.append({'name':particulars.iloc[0,0]
                      ,'age':particulars.iloc[0,1]
                      ,'roll':particulars.iloc[0,2]}
                      ,ignore_index=True)
new_lec = lec.sort_values('age')
new_lec.to_excel("arranged.xlsx",index=False)


# Step 1. 필요한 모듈을 import합니다.
# -*- coding: utf-8 -*-
import common.common as cm
import pprint as pp
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
import os
import numpy as np
import collections as clt
import pandas as pd
import random as rd

# Step 2. 경마정보조회를 위한 요청변수 및 요청주소 등을 구성합니다.
# Step 2-1. Looging을 위하여 공통 모듈에서 로거를 정의합니다.
f = cm.pre_logging() # 등록마 조회 결과 파일을 로딩

# Step 2-2. '4-1'에서 저장한 파일을 이용하여 해당 데이터를 로딩합니다.
c = []
fn = os.getcwd() + '/data/' + 'RegisteredHorse.da' # url = 'http://data.kra.co.kr/publicdata/service/hrReg/getHrReg' # 등록마 조회 (meet)
c.append(cm.open_file(fn, True))
cm.logF(f, c)

# Step 3. item의 구조를 분석하고, 분석하고자 하는 값들을 추출하기 위한 데이터를 전처리합니다.
pp = pp.PrettyPrinter(indent=4)
data = []
for i in range(0, len(c)):
    try:
        # 응답값이 XML일 경우
        _djson = cm.x2j(c[i])
        item = _djson['response']['body']['items']['item']

        # pp.pprint(item)
        cm.logF(f, item)
        if (isinstance(item, dict)):
            data.append(item)
        else:
            data.extend(item)
    except Exception as e:
        continue

cm.logF(f, data)

# Step 3-1. data에서 일부 데이터(전체 갯수의 10%수준)를 추출합니다.
data = rd.sample(data, int(len(data) * 0.1))
cm.logF(f, data)
rd.shuffle(data)

# Step 3-2. 일부 데이터를 기준으로 각 요소의 빈도를 집계합니다.
# color : 경주마 털색, sex : 경주마 성별
df = pd.DataFrame(data)
cm.logF(f, df)

color_counts = clt.Counter(df['color'])
stat = pd.DataFrame(
    {'color' : list(color_counts.keys()), 'count' : list(color_counts.values()), 'point' : [10, 5, 3, 2]}
)
cm.logF(f, stat)

# Step 4. 확률을 계산합니다. 확률변수 - 기대값, 분산(표준편차)
# Step 4-1. 등록마(표본전체) 중 털색이 ['갈색', '밤색', '흑갈색', '회색']인 말을 선택할 확률을 구합니다.
# 1. 경주마 털색, 2. 뽑을 때 점수, 3. 확률 : ['갈색', '밤색', '흑갈색', '회색'], [10, 5, 3, 2], [ ]
number_of_total_event_occurs = len(data)
cm.logF(f, '***** 확률을 계산합니다. *****')
cm.logF(f, ('표본갯수 : %d' %  number_of_total_event_occurs))
color = list(color_counts.keys()) # ['갈색', '밤색', '흑갈색', '회색']
cm.logF(f, ('경주마 털색 종류 : %s' % color))

i = 0
cp = {}
for key, value in color_counts.items():
    i += 1
    tv = float(value / number_of_total_event_occurs) # probability of color
    cp.update({key : tv})

df_color = pd.DataFrame(
    {'color' : list(cp.keys()), 'probability' : list(cp.values())}
)
cm.logF(f, df_color)

stat = pd.merge(stat, df_color, left_on='color', right_on='color')
cm.logF(f, stat)

# 기대값 : 각 요소별 '확률*포인트(사건이 발생할 때의 결과=이득)'의 합
expectation = (stat['point'] * stat['probability']).sum()
cm.logF(f, '경주마 털색 추출에 대한 기대값은? %f' % expectation)

# 분산 : 기대값과 확률변수들간의 거리(떨어진 정도)
variance = np.var(stat['point'] - expectation)
# 표준편차 : 기대값으로부터의 일반적 차이
stdev = np.std(stat['point'] - expectation)
cm.logF(f, '분산 : %f, 표준편차 : %f' % (variance, stdev))

# Step 5. 데이터 분석을 위한 표본에 대하여 시각화를 진행합니다.
x1 = stat['color']
y1 = stat['count']
x2 = ['기대값', '분산', '표준편차']
y2 = [expectation, variance, stdev]

fig, (ax1, ax2) = plt.subplots(2)
ax1.plot(x1, y1, 'ko-')
ax1.set(title='등록마 조회 서비스', ylabel='경주마 털색')
ax2.plot(x2, y2, 'r.-')
ax2.set(xlabel='%', ylabel='기대값,분산,표준편차')

plt.show()


try:
  import tkinter as tk
  from tkinter import ttk
  from math import *
  import re
except: ImportError

class main:
  def __init__(self,master):
    self.master = master
    self.master.title('Calculator')

  #vars

    self.var = tk.BooleanVar(value=False)

  #styles
    self.frm_style = ttk.Style()
    self.frm_style.configure('TFrame',master=self.master,width=200,height=50)

    self.btn_style = ttk.Style()
    self.btn_style.configure('TButton',relief=tk.RAISED,width=5,borderwidth=3,focuscolor='white')

#creation

    self.frm_1 = tk.Frame()
    self.frm_2 = tk.Frame()
    self.frm_3 = tk.Frame()
    self.frm_4 = tk.Frame()
    self.frm_5 = tk.Frame()
    self.frm_6 = tk.Frame()
    self.frm_7 = tk.Frame()
    self.frm_8 = tk.Frame()

    self.lbl_1 = tk.Label(self.frm_1,relief=tk.SUNKEN,width=20,bd=3,bg='light green',anchor='e')

    self.btn_0 = ttk.Button(self.frm_8,text='0')
    self.btn_1 = ttk.Button(self.frm_7,text='1')
    self.btn_2 = ttk.Button(self.frm_7,text='2')
    self.btn_3 = ttk.Button(self.frm_7,text='3')
    self.btn_4 = ttk.Button(self.frm_6,text='4')
    self.btn_5 = ttk.Button(self.frm_6,text='5')
    self.btn_6 = ttk.Button(self.frm_6,text='6')
    self.btn_7 = ttk.Button(self.frm_5,text='7')
    self.btn_8 = ttk.Button(self.frm_5,text='8')
    self.btn_9 = ttk.Button(self.frm_5,text='9')
    self.btn_dot = ttk.Button(self.frm_8,text='.')
    self.btn_equall = ttk.Button(self.frm_8,text='=')
    self.btn_add = ttk.Button(self.frm_8,text='+')
    self.btn_minus = ttk.Button(self.frm_7,text='-')
    self.btn_times = ttk.Button(self.frm_6,text='\N{multiplication sign}')
    self.btn_divide = ttk.Button(self.frm_5,text='/')
    self.btn_clear = ttk.Button(self.frm_2,text='AC')
    self.btn_percent = ttk.Button(self.frm_2,text='%')
    self.btn_sqrt = ttk.Button(self.frm_2,text='√')
    self.btn_off = ttk.Button(self.frm_2,text='Off')
    self.btn_back = ttk.Button(self.frm_1,text='⌫',width=3)
    #self.btn_ans = ttk.Button(self.frm_4,text='Ans')
    self.btn_lparent = ttk.Button(self.frm_3,text='(')
    self.btn_rparent = ttk.Button(self.frm_3,text=')')
    #self.btn_2nd = ttk.Button(self.frm_3,text='2nd')
    #self.btn_deg = ttk.Button(self.frm_3,text='Deg')
    self.btn_sin = ttk.Button(self.frm_4,text='sin')
    self.btn_cos = ttk.Button(self.frm_4,text='cos')
    self.btn_tan = ttk.Button(self.frm_4,text='tan')

#binding

    self.btn_0.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'0')])
    self.btn_1.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'1')])
    self.btn_2.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'2')])
    self.btn_3.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'3')])
    self.btn_4.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'4')])
    self.btn_5.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'5')])
    self.btn_6.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'6')])
    self.btn_7.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'7')])
    self.btn_8.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'8')])
    self.btn_9.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'9')])
    self.btn_dot.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'.')])
    self.btn_equall.bind('<Button-1>',lambda z:[ self.__evalError__(),self.var.set(True)])

    self.btn_add.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'+')])
    self.btn_minus.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'-')])
    self.btn_times.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'*')])
    self.btn_divide.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'/')])
    self.btn_clear.bind('<Button-1>',lambda z: self.lbl_1.configure(text=''))
    self.btn_percent.bind('<Button-1>',lambda z:[self.__dropError__(), self.__percentError__()])
    self.btn_sqrt.bind('<Button-1>',lambda z: [self.__dropError__(),self.__sqrtError__()])
    self.btn_off.bind('<Button-1>', lambda z:self.__onoff__(self.btn_off.cget('text')))
    self.btn_back.bind('<Button-1>', lambda z: [self.__clearEntry__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))[0:-1])])
    self.btn_lparent.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'(')])
    self.btn_rparent.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+')')])
    self.btn_sin.bind('<Button-1>',lambda z: [self.__dropError__(),self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'sin(')])
    self.btn_cos.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'cos(')])
    self.btn_tan.bind('<Button-1>',lambda z:[self.__dropError__(), self.lbl_1.configure(text=str(self.lbl_1.cget('text'))+'tan(')])

    #self.btn_sqrt.bind('<FocusOut>',lambda z: self.__dropError__(),add='+')

    self.btn_back.bind('<FocusOut>', lambda z: self.var.set(False),add='+')

#Gridding

    self.frm_1.grid(row=0,column=0,sticky='news')
    self.frm_2.grid(row=1,column=0,sticky='news')
    self.frm_3.grid(row=2,column=0,sticky='news')
    self.frm_4.grid(row=3,column=0,sticky='news')
    self.frm_5.grid(row=4,column=0,sticky='news')
    self.frm_6.grid(row=5,column=0,sticky='news')
    self.frm_7.grid(row=6,column=0,sticky='news')
    self.frm_8.grid(row=7,column=0,sticky='news')

    self.lbl_1.grid(row=0,column=0,padx=(15,7),pady=10)

    self.btn_0.grid(row=0,column=0,padx=(5,0),pady=(0,2))
    self.btn_1.grid(row=0,column=0,padx=(5,0),pady=(0,2))
    self.btn_2.grid(row=0,column=1,pady=(0,2))
    self.btn_3.grid(row=0,column=2,pady=(0,2))
    self.btn_4.grid(row=0,column=0,padx=(5,0),pady=(0,2))
    self.btn_5.grid(row=0,column=1,pady=(0,2))
    self.btn_6.grid(row=0,column=2,pady=(0,2))
    self.btn_7.grid(row=0,column=0,padx=(5,0),pady=(0,2))
    self.btn_8.grid(row=0,column=1,pady=(0,2))
    self.btn_9.grid(row=0,column=2,pady=(0,2))
    self.btn_dot.grid(row=0,column=1,pady=(0,2))
    self.btn_equall.grid(row=0,column=2,pady=(0,2))
    self.btn_add.grid(row=0,column=3,padx=(10,5),pady=(0,2))
    self.btn_minus.grid(row=0,column=3,padx=(10,5),pady=(0,2))
    self.btn_times.grid(row=0,column=3,padx=(10,5),pady=(0,2))
    self.btn_divide.grid(row=0,column=3,padx=(10,5),pady=(0,2))
    self.btn_off.grid(row=0,column=0,padx=(5,0),pady=(0,2))
    self.btn_sqrt.grid(row=0,column=1,pady=(0,2))
    self.btn_percent.grid(row=0,column=2,pady=(0,2))
    self.btn_clear.grid(row=0,column=3,padx=(10,5),pady=(0,2))
    self.btn_back.grid(row=0,column=1,padx=(3,5),pady=10)
    #self.btn_ans.grid(row=0,column=3,padx=(10,5),pady=(0,2))
    #self.btn_2nd.grid(row=0,column=0,padx=(5,0),pady=(0,2))
    self.btn_lparent.grid(row=0,column=1,pady=(0,2))
    self.btn_rparent.grid(row=0,column=2,pady=(0,2))
    #self.btn_deg.grid(row=0,column=3,padx=(10,5),pady=(0,2))
    self.btn_sin.grid(row=0,column=0,padx=(5,0),pady=(0,2))
    self.btn_cos.grid(row=0,column=1,pady=(0,2))
    self.btn_tan.grid(row=0,column=2,pady=(0,2))

# on/off

  def __onoff__(self,x):
    if x == 'Off':
      self.btn_0.configure(state='disabled')
      self.btn_1.configure(state='disabled')
      self.btn_2.configure(state='disabled')
      self.btn_3.configure(state='disabled')
      self.btn_4.configure(state='disabled')
      self.btn_5.configure(state='disabled')
      self.btn_6.configure(state='disabled')
      self.btn_7.configure(state='disabled')
      self.btn_8.configure(state='disabled')
      self.btn_9.configure(state='disabled')
      self.btn_dot.configure(state='disabled')
      self.btn_equall.configure(state='disabled')
      self.btn_add.configure(state='disabled')
      self.btn_minus.configure(state='disabled')
      self.btn_times.configure(state='disabled')
      self.btn_divide.configure(state='disabled')
      self.btn_clear.configure(state='disabled')
      self.btn_percent.configure(state='disabled')
      self.btn_sqrt.configure(state='disabled')

      self.lbl_1.configure(text='',bg='grey')
      self.btn_off.configure(text='On')

    elif x =='On':
      self.btn_0.configure(state='normal')
      self.btn_1.configure(state='normal')
      self.btn_2.configure(state='normal')
      self.btn_3.configure(state='normal')
      self.btn_4.configure(state='normal')
      self.btn_5.configure(state='normal')
      self.btn_6.configure(state='normal')
      self.btn_7.configure(state='normal')
      self.btn_8.configure(state='normal')
      self.btn_9.configure(state='normal')
      self.btn_dot.configure(state='normal')
      self.btn_equall.configure(state='normal')
      self.btn_add.configure(state='normal')
      self.btn_minus.configure(state='normal')
      self.btn_times.configure(state='normal')
      self.btn_divide.configure(state='normal')
      self.btn_clear.configure(state='normal')
      self.btn_percent.configure(state='normal')
      self.btn_sqrt.configure(state='normal')

      self.lbl_1.configure(bg='light green')
      self.btn_off.configure(text='Off')

#Debugging

  def __evalError__(self):
    e = 'Error: Syntax'
    try:
      x = re.sub(r"((?<=^)|(?<=[^\.\d]))0+(\d+)", r"\1\2", str(self.lbl_1.cget('text')))
      if eval(x) < 10**-99 or eval(x) > 10**99:
        e = 'Error: Overflow'
        raise Exception
      else:
        e = 'Error: Syntax'
      self.lbl_1.configure(text=(eval(x)))

    except:

      self.lbl_1.configure(text=e)

  def __sqrtError__(self):
    try:
      self.lbl_1.configure(text=str(sqrt(float(str(self.lbl_1.cget('text'))))))
    except:
      self.lbl_1.configure(text='Error: Syntax')
      self.var.set(True)

  def __percentError__(self):
    try:
      self.lbl_1.configure(text=str(float(str(self.lbl_1.cget('text')))/100))
    except:
      self.lbl_1.configure(text='Error: Syntax')
      self.var.set(True)

  def __dropError__(self):
    print('r')
    if 'Error' in str(self.lbl_1.cget('text')):
      self.lbl_1.configure(text='')

  def __clearEntry__(self):
    if self.var.get():
      self.lbl_1.configure(text='')
      self.var.set(False)

def app():
  root = tk.Tk()
  main(root)
  root.mainloop()

app()


import requests
import urllib.parse
user_icon = "bear"
user_name = "駆け抜ける熊(偽物)"
room_id = "3762bf77fb8249d3d9b69f6bcda036d4"
session = requests.session()
session.cookies.set("profile", urllib.parse.quote(user_name) + ":" + user_icon + ":ja-JP:ziten")
req = session.get("https://drrrkari.com")
header = {'User-Agent':'w3m'}
info = {
    "login":"login",
    "id":room_id,
}
req = session.post("https://drrrkari.com/room/", data=info, headers=header)
req = session.post("https://drrrkari.com/ajax.php")


import sys
from algorithms.algo_base import AlgoBase
import numpy as np
from decorators import base, delay, reserve, sbac

from platforms.task import Task

@base('ippts')
class IPPTS(AlgoBase):

    def task_compare(self, task1: Task, task2: Task):
        return task2.priority - task1.priority

    def calculate_priority(self, task: Task):
        self.calculate_pcm(task)
        for t in self.tasks:
            self._calculate_priority(t)

    def _calculate_priority(self, task: Task):
        if task.priority:
            return task.priority
        rank_pcm = np.average(task.pcm)
        p_rank = rank_pcm * len(task.out_edges)
        task.priority = p_rank
        return task.priority

    def calculate_pcm(self, task: Task):

        if task.pcm[0]:
            return task.pcm

        for i in range(len(task.cost_table)):
            max = task.cost_table[i]
            for edge in task.out_edges:
                min = sys.maxsize
                for cid, cost in enumerate(edge.target.cost_table):
                    pcm = self.calculate_pcm(edge.target)
                    tmp = pcm[cid] + task.cost_table[cid] + \
                        cost + (edge.weight if i != cid else 0)
                    if tmp < min:
                        min = tmp
                if min > max:
                    max = min
            task.pcm[i] = max
        return task.pcm

    def find_processor(self, task: Task, schedule):
        min_eft_procId = np.argmin(task.cost_table)
        min_eft = task.cost_table[min_eft_procId] if task.is_entry(
        ) else sys.maxsize
        min_lhead_eft = sys.maxsize
        # Calculate start time
        selected_ast = est = 0 if task.is_entry() else max(
            [edge.source.aft if edge.source.aft else 0 for edge in task.in_edges])
        # Choose a processor
        for pid, cost in enumerate(task.cost_table):
            proc_est = schedule[pid][-1].aft if len(
                schedule[pid]) > 0 else est
            lhet = task.pcm[pid] - cost

            # Check if current task and its parents are on the same processor
            for in_edge in task.in_edges:
                if in_edge.source.procId-1 != pid:
                    proc_est = max(in_edge.source.aft +
                                in_edge.weight, proc_est)
            eft = proc_est + cost
            lhead_eft = eft + lhet
            if lhead_eft < min_lhead_eft:
                selected_ast = proc_est
                min_eft_procId = pid
                min_eft = eft
                min_lhead_eft = lhead_eft

        return selected_ast, min_eft, min_eft_procId

@delay('ippts')
class IPPTSDelay(IPPTS):
    pass

@reserve('ippts')
class IPPTSReserve(IPPTS):
    pass

@sbac('ippts')
class IPPTSSBAC(IPPTS):
    pass


import numpy as np
import random
import cv2

def draw_rect(im, cords, color=None):
    im = im.copy()
    cords = cords.reshape(-1, 4)
    if not color:
        color = [255, 255, 255]
    for cord in cords:
        pt1, pt2 = (cord[0], cord[1]), (cord[2], cord[3])
        pt1 = int(pt1[0]), int(pt1[1])
        pt2 = int(pt2[0]), int(pt2[1])
        im = cv2.rectangle(im.copy(), pt1, pt2, color, int(max(im.shape[:2]) / 200))
    return im

class RandomHorizontalFlip(object):
    def __init__(self, prob=1):
        self.prob = prob

    def __call__(self, img, bboxes=None):
        if random.uniform(0, 1) < self.prob:
            return img, bboxes
        img_center = np.array(img.shape[:2])[::-1] / 2
        img_center = np.hstack((img_center, img_center))
        img = img.astype('float64')
        if not bboxes:
            return img,bboxes
        bboxes = bboxes.astype('float64')
        img = img[:, ::-1, :]
        img = img.astype('uint8')
        if len(bboxes) == 0:
            return img, bboxes
        bboxes[:, [0, 2]] += 2 * (img_center[[0, 2]] - bboxes[:, [0, 2]])
        box_w = abs(bboxes[:, 0] - bboxes[:, 2])
        bboxes[:, 0] -= box_w
        bboxes[:, 2] += box_w

        return img, bboxes


'''
Enviar um email com os detalhes da compra online (maximo 3 tentativas) pra compras confirmadas
'''

compra_confirmada = True
dados_compra = 'compra no valor de R$ 12,30 e entrega confirmada'

for enviar in range(3):
    if compra_confirmada:
        print(dados_compra)
        print('Detalhes enviados no email')
        break
    else:
        print('Compra falhou')


import random
import pyperclip

def main(length: int):
    nums, upper, lower, chrs = "0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", \
                               "abcdefghijklmnopqrstuvwxyz", r" !@#$%^&*()\")[]{}"
    while True:
        string = ''.join(random.choices(nums + upper + lower + chrs, k=length))
        string_as_set = set(string)
        if all((len(set(nums) & string_as_set),
                len(set(upper) & string_as_set),
                len(set(lower) & string_as_set),
                len(set(chrs) & string_as_set))):
            return string

if __name__ == "__main__":
    pyperclip.copy(main(64))


# 퀴즈 대회에 참가해서 우승을 하게 되면 보너스 상금을 획득할 수 있는 기회를 부여받는다.
# 우승자는 주어진 숫자판들 중에 두 개를 선택에서 정해진 횟수만큼 서로의 자리를 위치를 교환할 수 있다.
# 예를 들어, 다음 그림과 3, 2, 8, 8, 8 의 5개의 숫자판들이 주어지고 교환 횟수는 2회라고 하자.
# 교환전>
# 처음에는 첫번째 숫자판의 3과 마지막에 있는 8을 교환해서 8, 2, 8, 3, 8이 되었다.
# 다음으로, 두 번째 숫자판 2와 네 번째 숫자판의 8을 교환해서 8, 8, 8, 3, 2이 되었다.
# 정해진 횟수만큼 교환이 끝나면 숫자판의 위치에 부여된 가중치에 의해 상금이 계산된다.
# 숫자판의 오른쪽 끝에서부터 1원이고 왼쪽으로 한자리씩 갈수록 10의 배수만큼 커진다.
# 위의 예에서와 같이 최종적으로 숫자판들이 8,8,8,3,2의 순서가 되면 88832원의 보너스 상금을 획득한다.
# 여기서 주의할 것은 반드시 횟수만큼 교환이 이루어져야 하고 동일한 위치의 교환이 중복되어도 된다.
# 다음과 같은 경우 1회의 교환 횟수가 주어졌을 때 반드시 1회 교환을 수행하므로 결과값은 49가 된다.
# 94의 경우 2회 교환하게 되면 원래의 94가 된다.
# 정해진 횟수만큼 숫자판을 교환했을 때 받을 수 있는 가장 큰 금액을 계산해보자.
# [입력]
# 가장 첫 줄은 전체 테스트 케이스의 수이다.
# 최대 10개의 테스트 케이스가 표준 입력을 통하여 주어진다.
# 각 테스트 케이스에는 숫자판의 정보와 교환 횟수가 주어진다.
# 숫자판의 정보는 정수형 숫자로 주어지고 최대 자릿수는 6자리이다.
# [출력]
# 각 테스트 케이스마다, 첫 줄에는 “#C”를 출력해야 하는데 C는 케이스 번호이다.
# 같은 줄에 빈 칸을 하나 사이에 두고 교환 후 받을 수 있는 가장 큰 금액을 출력한다.

import sys
sys.stdin = open('input.txt')

for tc in range(int(input())):
    data, cnt = map(int,input().split())
    datas = list(map(int,str(data)))
    # for c in range(cnt):
    change = 1
    wait = []

    if len(datas) == 2:
        if cnt%2:
            datas = datas[::-1]
    else:
        idx = 0
        while cnt != 0:
            if idx == len(datas)-1:
                #if 같은수가 2개이상이면 -> 같은수 끼리 바꾸기
                for d in range(len(datas)):
                    if datas.count(datas[d]) >= 2:
                        change = 0
                        break
                if change and cnt%2:
                    datas[idx-1],datas[idx] = datas[idx],datas[idx-1]
                break
            if datas[idx] == max(datas[idx:len(datas)]):
                idx += 1
            else:
                target = datas[::-1].index(max(datas[idx:len(datas)])) #len(datas)-1-target
                datas[idx],datas[len(datas)-1-target] = datas[len(datas)-1-target],datas[idx]
                # if len(wait) == 0:
                #     wait = [datas[len(datas)-1-target]]
                # elif idx>0 and datas[idx] == datas[idx-1]:
                #     wait.append(datas[len(datas)-1-target]) #datas[len(datas)-1-target+1] 그전의 데이터
                # elif len(wait) > 1:
                #     wait = sorted(wait)
                #     datas[len(datas)-1-target:len(datas)-1-target+len(wait)-1] = wait
                # else:
                #     wait = [datas[len(datas)-1-target]]
                if idx>0 and datas[idx] == datas[idx-1] and datas[len(datas)-1-target] < datas[len(datas)-1-target+1]:
                    datas[len(datas)-1-target], datas[len(datas)-1-target+1] = datas[len(datas)-1-target+1], datas[len(datas)-1-target]
                idx += 1
                cnt -= 1
    ans = list(map(str, datas))
    ans = ''.join(ans)
    print('#{} {}'.format(tc+1,ans))


# -*- coding: UTF-8 -*-
from sympy import *
from math import gcd
from functools import lru_cache

def miller_rabin(testee, witness):
    n, a = testee, witness
    if n % 2 == 0 or 1 < gcd(a, n) < n:
        return True
    q = n - 1
    k = 0
    while q % 2 == 0:
        q //= 2
        k += 1
    a = pow(a, q, n)
    if a == 1:
        return False
    for i in range(0, k):
        if a == n - 1:
            return False
        a = (a * a) % n
    return True

def is_prime(n):
    if n == 1:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False
    witnesses = [2, 3]
    return not any(miller_rabin(n, w) for w in witnesses)

def primes_upto(N):
    mx = (N-3) >> 1
    sq = 0
    v = 0
    i = -1
    primes = []
    prime = [True] * (mx + 1)
    if N >= 2:
        primes.append(2)
    while True:
        i += 1
        if i > mx:
            break
        if prime[i]:
            v = (i << 1) + 3
            primes.append(v)
            sq = i * ((i << 1) + 6) + 3
            if sq > mx:
                break
            for j in range(sq, mx+1, v):
                prime[j] = False
    while True:
        i += 1
        if i > mx:
            break
        if prime[i]:
            primes.append((i << 1) + 3)
    return primes

# Problems

def m2p1(n):
    '''Given a non-negative integer n calculate n-th Tribonacci number, using recursion.
    '''
    if n <= 1:
        return 0
    if n == 2:
        return 1
    return m2p1(n-1) + m2p1(n-2) + m2p1(n-3)

memo = {0:0, 1:0, 2:1}
def m2p2(n):
    '''Given a non-negative integer n calculate n-th Tribonacci number, using recursion and memoization.
    '''
    if n < 0:
        return 0
    if n in memo:
        return memo[n]
    else:
        new_value = memo[n] = m2p2(n-1) + m2p2(n-2) + m2p2(n-3)
        memo[n] = new_value
        return new_value

def m2p3(n):
    '''Given a non-negative integer n calculate n-th Tribonacci number using memoization with a list, and without using recursion
    '''
    T = [0,0,1] + [0]*(n-2)

    for i in range(3, n+1):
        T[i] = T[i-1] + T[i-2] + T[i-3]
    return T[n]

def m2p4(n):
    '''Given a non-negative integer n calculate n-th Tribonacci number, without using recursion and only storing three values.
    '''
    if n <= 1:
        return 0
    t3, t2, t1 = 1, 0, 0
    for _ in range(3, n+1):
        t3, t2 ,t1 = t1+t2+t3 ,t3 ,t2
    return t3

def m2p5(n,L):
    '''Project Euler Problem 31.
The input n is a positive integer and the input L is a list of coin values.
The returned value is the number of ways n can be split using the coin values in the list L.
    '''
    ways = [1] + [0]*n
    for i in L:
        for j in range(i, n+1):
            ways[j] += ways[j-i]

    return ways[n]

def m2p6(k):
    '''Project Euler Problem 76.
The input k should be a positive integer. The returned value is the number of
different ways k can be written as a sum of at least two positive integers.
    '''
    ways = [0] *(k+1)
    ways[0] = 1 #only 1 way to get sum 1
    #ways for sums involving numbers in [1, k]
    for i in range(1, k):
        for j in range(i, k+1):
            ways[j] += ways[j-i]
    return ways[k]

    # ways = [1] + [0]*k
    # for num in range(1,k):
    #     for i in range(num, k+1):
    #         ways[i] += ways[i-k]
    # return ways[k]
    # return (binomial_coefficients_list(k))

def m2p7(k):
    '''Project Euler Problem 77.
The input k should be a positive integer. The returned value is the smallest positive
integer n such that the number of ways to write n as a sum of primes exceeds k
    '''
    #nota coins gaurinn m2p5, n=k og primes = L
    primes = [i for i in primerange(1, k+1)]
    for p in primes:
        n = m2p5(k,primes)
        nm = npartitions(prim)
    return nm

    # if k < 0: return 0
    # if k == 0: return 2

    # primes = [i for i in primerange(0,k+1)]
    # for j in range(k):
    #     binomial(k,primes[j])
    #     return m2p5(k,primes)

def m2p8(k):
    '''Project Euler Problem 78.
The input k should be a positive integer. The returned value is the smallest positive
integer n such that number of ways n coins can be separated into piles is divisible by k.
    '''
    return -1

def m2p9(M):
    '''Project Euler Problem 81.
The input M should be an n x n matrix containing integers, given as a list of lists.
The output is the minimal path sum, as defined on Project Euler.
    '''
    for i in range(len(M)-2, -1, -1): #sny fylkinu við
        M[len(M)-1][i] += M[len(M)-1][i+1]
        M[i][len(M)-1] += M[i+1][len(M)-1]

    for i in range((len(M))-2, -1, -1): #byrja neðst til hægri og leita upp
        for j in range((len(M))-2, -1, -1):
            M[i][j] += min(M[i+1][j], M[i][j+1])

    return M[0][0] #skila vinstra efsta

if __name__ == "__main__":
    # print(m2p1(8))
    # print(m2p2(8))
    print(m2p3(1000000))
    # print(m2p4(10000))
    # print(m2p5(20,[1,2,5]))
    # print(m2p6(5))
    # print(m2p7(4))
    # print(m2p8(7))
    # print(m2p9([[1,1,9],[9,1,1],[9,9,1]]))


from abc import ABC, abstractmethod
from typing import Any

import numpy as np

from sportslabkit import Tracklet

class BaseMotionModel(ABC):
    """Abstract base class for motion models.

    This class defines a common interface for all motion models.
    Derived classes should implement the update, and predict methods. MotionModels are procedural and stateless. The state of tracklet is managed by the Tracklet class. The tracklet must have the required observations and states for the motion model to work. If the tracklet doesn't have the required observations or states, the motion model will raise an error and tell the user which observations or states are missing.
    """

    hparam_search_space: dict[str, type] = {}
    required_observation_types: list[str] = NotImplemented
    required_state_types: list[str] = NotImplemented

    def __init__(self, is_multi_target=False):
        """Initialize the MotionModel."""

        self.input_is_batched = False  # initialize the input_is_batched attribute
        self.name = self.__class__.__name__
        self.is_multi_target = is_multi_target

    def __call__(self, tracklet: Tracklet) -> Any:
        """Call the motion model to update its state and return the prediction.

        Args:
            tracklet (Tracklet): The single object tracker instance.

        Returns:
            Any: The predicted state after updating the motion model.
        """
        if self.is_multi_target:
            return self._multi_target_call(tracklet)

        self._check_required_observations(tracklet)
        self._check_required_states(tracklet)

        if isinstance(tracklet, Tracklet):
            _obs = tracklet.get_observations()
            observations = {t: _obs[t] for t in self.required_observation_types}
        else:
            observations = {t: tracklet[t] for t in self.required_observation_types}

        prediction, new_states = self.predict(observations, tracklet.states)
        tracklet.update_states(new_states)
        return prediction

    def _multi_target_call(self, tracklets: list[Tracklet]) -> list[Any]:
        """Call the motion model to update its state and return the prediction for multiple targets.

        Args:
            tracklets (List[Tracklet]): The list of tracklet instances.

        Returns:
            List[Any]: The list of predicted states after updating the motion model for each tracklet.
        """
        all_observations = []
        all_states = []
        for tracklet in tracklets:
            self._check_required_observations(tracklet)
            self._check_required_states(tracklet)

            if isinstance(tracklet, Tracklet):
                _obs = tracklet.get_observations()
                observations = {t: _obs[t] for t in self.required_observation_types}
            else:
                observations = {t: tracklet[t] for t in self.required_observation_types}
            all_observations.append(observations)
            all_states.append(tracklet.states)

        all_predictions, all_new_states = self.predict(all_observations, all_states)
        for i, tracklet in enumerate(tracklets):
            tracklet.update_states(all_new_states[i])
        return all_predictions

    @abstractmethod
    def predict(
        self,
        observations: float | np.ndarray,
        states: float | np.ndarray | None,
    ) -> tuple[float | np.ndarray | None, float | np.ndarray]:
        """Compute the next internal state and prediction based on the current observation and internal state.

        Args:
            observation (Union[float, np.ndarray]): The current observation.
            states (Union[float, np.ndarray, None]): The current internal state of the motion model.

        Returns:
            Tuple[Union[float, np.ndarray, None], Union[float, np.ndarray]]: The next internal state and the prediction.
        """
        pass

    @classmethod
    def from_config(cls: type["BaseMotionModel"], config: dict) -> "BaseMotionModel":
        """Initialize a motion model instance from a configuration dictionary.

        Args:
            config (Dict): The configuration dictionary containing the motion model's parameters.

        Returns:
            MotionModel: A new instance of the motion model initialized with the given configuration.
        """
        return cls(**config)

    def _check_required_observations(self, tracklet: Tracklet) -> None:
        """Check if the required observations are registered in the SingleObjectTracker instance.

        Args:
            sot (SingleObjectTracker): The single object tracker instance.

        Raises:
            KeyError: If a required observation is not registered in the SingleObjectTracker instance.
        """
        for obs_type in self.required_observation_types:
            if obs_type not in tracklet._observations:
                raise KeyError(f"{self.name} requires observation type `{obs_type}` but it is not registered.")
            if len(tracklet._observations[obs_type]) == 0:
                raise KeyError(f"{self.name} requires observation type `{obs_type}` but it is empty.")

    def _check_required_states(self, tracklet: Tracklet) -> None:
        """Check if the required states are registered in the SingleObjectTracker instance.

        Args:
            sot (SingleObjectTracker): The single object tracker instance.

        Raises:
            KeyError: If a required state is not registered in the SingleObjectTracker instance.
        """
        for state in self.required_state_types:
            if state not in tracklet._states:
                tracklet.register_state_type(state)


# https://leetcode.com/problems/flood-fill/
# ---------------------------------------------------
from collections import deque
from typing import List

# Runtime Complexity: O(N), where N is the amount of same-colored neighbors
# Space Complexity: O(N) in worst case, if same-colored neighbors are in positioned as continuous line.
class Solution:
    # __init_ is created, so that there is no warning that self.* vars are defined outside of __init__ initially
    def __init__(self):
        self.rows = self.cols = 0
        self.color = None
        self.image = None

    def floodFill(self, image: List[List[int]], sr: int, sc: int, new_color: int) -> List[List[int]]:
        self.rows, self.cols = len(image), len(image[0])
        self.color = image[sr][sc]
        self.image = image

        if self.color == new_color:
            return image

        stack = deque()
        stack.append((sr, sc))

        while stack:
            (r, c) = stack.pop()

            image[r][c] = new_color
            stack.extend(self.getSameColorNeighbors(r, c))

        return image

    def getSameColorNeighbors(self, r, c):
        neighbors = []
        for dr, dc in ((-1, 0), (0, 1), (1, 0), (0, -1)):
            if self.isValidCell(r + dr, c + dc) and self.image[r + dr][c + dc] == self.color:
                neighbors.append((r + dr, c + dc))

        return neighbors

    def isValidCell(self, r, c):
        return 0 <= r < self.rows and 0 <= c < self.cols

# ---------------------------------------------------
#                    Test Cases
# ---------------------------------------------------
solution = Solution()
#   [2,2,2],
#   [2,2,0],
#   [2,0,1]
print(solution.floodFill([
    [1,1,1],
    [1,1,0],
    [1,0,1]], 1, 1, 2))


#!/usr/bin/env python3

import sys
import shutil
import numpy as np
np.set_printoptions(threshold=sys.maxsize)
import random as rnd
import time
import abc
from abc import ABC, abstractmethod

def get_random_result(density: float) :
    return rnd.random() < density

class field :
    @abstractmethod
    def __init__(self) :
        self._field = np.empty(shape=(self.nrow, self.ncol), dtype=object)
        self._field.fill(" ")
        self._pos = np.array([0,0])

    def x(self) :
        return self._pos[0]

    def y(self) :
        return self._pos[1]

    def get_field(self) :
        return self._field

class snowflake(field) :
    ncol = 1
    nrow = 1

    def __init__(self, x, y) :
        super().__init__()
        self.melted = False
        self._pos = np.array([x, y])

    def x(self) :
        return self._pos[0]

    def y(self) :
        return self._pos[1]

    def fall(self, ymax) :
        self._pos += np.array([0, 1])
        if self._pos[1] + 1 > ymax :
            self.melted = True

class house(field) :
    ncol = 12
    nrow = 5

    _row1 = "   /        "
    _row2 = "  ((        "
    _row3 = " .-#------. "
    _row4 = "/__________\\"
    _row5 = "_| []  []_|_"

    def __init__(self, x, y) :
        super().__init__()
        self._pos = np.array([x, y])

        self._field[0,:] = np.array(list(self._row1))
        self._field[1,:] = np.array(list(self._row2))
        self._field[2,:] = np.array(list(self._row3))
        self._field[3,:] = np.array(list(self._row4))
        self._field[4,:] = np.array(list(self._row5))

class tree(field) :
    ncol = 5
    nrow = 4

    _row1 = " \ / "
    _row2 = "- * -"
    _row3 = " /|\ "
    _row4 = "//|\\\\"

    def __init__(self, x, y) :
        super().__init__()
        self._pos = np.array([x, y])

        self._field[0,:] = np.array(list(self._row1))
        self._field[1,:] = np.array(list(self._row2))
        self._field[2,:] = np.array(list(self._row3))
        self._field[3,:] = np.array(list(self._row4))

class snowman(field):
    ncol = 7
    nrow = 5

    _row1 = "   _   "
    _row2 = " _|-|_ "
    _row3 = "  (\")  "
    _row4 = "--(_)--"
    _row5 = " (___) "

    def __init__(self, x, y) :
        super().__init__()
        self._pos = np.array([x, y])

        self._field[0,:] = np.array(list(self._row1))
        self._field[1,:] = np.array(list(self._row2))
        self._field[2,:] = np.array(list(self._row3))
        self._field[3,:] = np.array(list(self._row4))
        self._field[4,:] = np.array(list(self._row5))

class santa(field) :
    ncol = 42
    nrow = 4

    _row1 = "                                   _ ,.W, "
    _row2 = " \)      \)      \)      \)       {\\'* , ;"
    _row3 = "c(/'--,  (/'--,  (/'--,  (/'--,  c_)(___,'"
    _row4_0 = "  <| |\   /| <|   <\ /|   <| |\ (_\____/__"
    _row4_1 = "  /| <|   <\ /|   /| <|   /| <\ (_\____/__"

    def __init__(self, x, y) :
        super().__init__()
        self._pos = np.array([x,y])
        self._stance = 0
        self.vanished = False

        self._field[0,:] = np.array(list(self._row1))
        self._field[1,:] = np.array(list(self._row2))
        self._field[2,:] = np.array(list(self._row3))
        self._field[3,:] = np.array(list(self._row4_0))

    def ride(self) :
        self._pos[0] -= 3
        self._stance = (self._stance+1) % 2
        if self._stance == 0 :
            self._field[3,:] = np.array(list(self._row4_0))
        if self._stance == 1:
            self._field[3,:] = np.array(list(self._row4_1))
        if self._pos[0] <= -self.ncol :
            self.vanished = True

class snowfield(field) :
    ncol, nrow = shutil.get_terminal_size((50,20))
    nrow -= 2
    snow_density = 0.01
    santa_prob = 0.02
    house_density = 0.05
    tree_density = 0.03
    snowman_density = 0.02

    def __init__(self) :
        self._snowflakes = []
        self._santa = []
        self._houses = []
        self._trees = []
        self._snowmen = []
        super().__init__()
        for row in range(self.nrow - 1) :
            for col in range(self.ncol) :
                if get_random_result(self.snow_density) :
                    self._field[row][col] = '❄'
                    self._snowflakes.append(snowflake(col, row))
        for col in range(self.ncol) :
            self._field[self.nrow - 1][col] = '_'
        for col in range(self.ncol - house.ncol) :
            if get_random_result(self.house_density) :
                if not self.cell_is_occupied(self.nrow-2, col) :
                    self._houses.append(house(col, self.nrow-house.nrow))
        for hou in self._houses :
            housefield = hou.get_field()
            rows, cols = np.shape(housefield)
            for col in range(cols) :
                for row in range(rows) :
                    col_ = hou.x() + col
                    row_ = hou.y() + row
                    if col_ < len(self._field[0,:]) and col_ >= 0 and row_ < len(self._field[:,0]) and row_ >= 0 :
                        self._field[row_][col_] = housefield[row][col]
        for col in range(self.ncol - tree.ncol) :
            if get_random_result(self.tree_density) :
                if not self.cell_is_occupied(self.nrow-2, col) and not self.cell_is_occupied(self.nrow-2, col+tree.ncol) :
                    self._trees.append(tree(col, self.nrow-tree.nrow))
        for tre in self._trees :
            treefield = tre.get_field()
            rows, cols = np.shape(treefield)
            for col in range(cols) :
                for row in range(rows) :
                    col_ = tre.x() + col
                    row_ = tre.y() + row
                    if col_ < len(self._field[0,:]) and col_ >= 0 and row_ < len(self._field[:,0]) and row_ >= 0 :
                        self._field[row_][col_] = treefield[row][col]
        for col in range(self.ncol - snowman.ncol) :
            if get_random_result(self.snowman_density) :
                if not self.cell_is_occupied(self.nrow-2, col) and not self.cell_is_occupied(self.nrow-2, col+snowman.ncol) :
                    self._snowmen.append(snowman(col, self.nrow-snowman.nrow))
        for sno in self._snowmen :
            snowmanfield = sno.get_field()
            rows, cols = np.shape(snowmanfield)
            for col in range(cols) :
                for row in range(rows) :
                    col_ = sno.x() + col
                    row_ = sno.y() + row
                    if col_ < len(self._field[0,:]) and col_ >= 0 and row_ < len(self._field[:,0]) and row_ >= 0 :
                        self._field[row_][col_] = snowmanfield[row][col]

    def let_it_snow(self) :
        nrow_sky = self.nrow - 1

        # santa rides along
        for san in self._santa :
            san.ride()
            if san.vanished :
                self._santa.remove(san)
            else :
                santafield = san.get_field()
                rows, cols = np.shape(santafield)
                for col in range(cols) :
                    for row in range(rows) :
                        col_ = san.x() + col
                        row_ = san.y() + row
                        if col_ < len(self._field[0,:]) and col_ >= 0 and row_ < len(self._field[:,0]) and row_ >= 0 :
                            self._field[row_][col_] = santafield[row][col]

        # erase trails of moving objects
        for row in range(nrow_sky) :
            for col in range(self.ncol) :
                if not self.cell_is_occupied(row, col) :
                    self._field[row][col] = ' '

        # snow falls and old snow melds
        for flake in self._snowflakes :
            flake.fall(nrow_sky)
            if flake.melted :
                self._snowflakes.remove(flake)
            else :
                if not self.cell_is_occupied(flake.y(), flake.x()) :
                    self._field[flake.y(), flake.x()] = '❄'

        # make some fresh snow
        for col in range(self.ncol) :
            if get_random_result(self.snow_density) :
                self._field[0][col] = '❄'
                self._snowflakes.append(snowflake(col, 0))

        # ask if santa wants to come
        if len(self._santa) == 0 and get_random_result(self.santa_prob) :
            if self.nrow < 11 or self.ncol < 50 :
                pass
            y_start = rnd.randint(1,self.nrow-10)
            self._santa.append(santa(self.ncol, y_start))

    def cell_is_occupied(self, y, x) :
        if y == self.nrow-1 :
            return True
        for san in self._santa :
            if x >= san.x() and x < san.x() + san.ncol and y >= san.y() and y < san.y() + san.nrow :
                return True
        for hou in self._houses :
            if x >= hou.x() and x < hou.x() + hou.ncol and y >= hou.y() and y < hou.y() + hou.nrow :
                return hou.get_field()[y-hou.y()][x-hou.x()] != ' '
        for tre in self._trees :
            if x >= tre.x() and x < tre.x() + tre.ncol and y >= tre.y() and y < tre.y() + tre.nrow :
                return True
        for sno in self._snowmen :
            if x >= sno.x() and x < sno.x() + sno.ncol and y >= sno.y() and y < sno.y() + sno.nrow :
                return True
        return False

    def __str__(self) :
        print("\033[" + str(self.nrow + 3) + "A")
        for row in range(self.nrow) :
            for col in range(self.ncol) :
                print(self._field[row][col], end='')
            print('')

        return ' '

def main() :
    sf = snowfield()
    print(sf)

    while True :
        time.sleep(1)
        sf.let_it_snow()
        print(sf)

if __name__ == "__main__" :
    main()


import os
import time
import json
import sqlite3

from threading import Thread, Lock
from plugin import *

class stalker(plugin):
    def __init__(self, bot):
        super().__init__(bot)
        self.db_name = self.bot.get_server_name()
        os.makedirs(os.path.dirname(os.path.realpath(self.config['db_location'])), exist_ok=True)

        self.db_connection = sqlite3.connect(self.config['db_location'], check_same_thread=False)
        self.db_cursor = self.db_connection.cursor()
        self.db_cursor.execute(f"CREATE TABLE IF NOT EXISTS '{self.db_name}' (host TEXT primary key not null, nicks TEXT)")  # host -> {nicknames}
        self.db_mutex = Lock()
        self.updating_thread = None

    def on_welcome(self, **kwargs):
        self.bot.names()

    def on_pubmsg(self, source, **kwargs):
        self.update_database(source.nick, source.host)

    def on_ctcp(self, source, **kwargs):
        self.update_database(source.nick, source.host)

    def on_whoisuser(self, nick, host, **kwargs):
        self.update_database(nick, host)

    def on_join(self, source, **kwargs):
        self.update_database(source.nick, source.host)

    def on_nick(self, source, new_nickname, **kwargs):
        self.update_database(new_nickname, source.host)

    def on_namreply(self, nicknames, **kwargs):
        if self.updating_thread is None or not self.updating_thread.is_alive():
            self.updating_thread = Thread(target=self.update_all, args=(nicknames,))
            self.updating_thread.start()

    def update_all(self, nicknames):
        self.logger.debug("updating whole stalker's database started...")
        for nick in nicknames:
            self.bot.whois(nick)
            time.sleep(1)  # to not get kicked because of Excess Flood

        self.logger.debug("updating whole stalker's database finished")

    def update_database(self, nick, host):
        result = self.get_nicknames_from_database(host)
        nick = irc_nickname(nick)

        if result:
            if nick not in result:
                result.extend([nick])
                with self.db_mutex:
                    self.db_cursor.execute(f"UPDATE '{self.db_name}' SET nicks = ? WHERE host = ?", (json.dumps(result), host))
                    self.db_connection.commit()

                self.logger.info(f'new database entry: {host} -> {nick}')
        else:
            with self.db_mutex:
                self.db_cursor.execute(f"INSERT INTO '{self.db_name}' VALUES (?, ?)", (host, json.dumps([nick])))
                self.db_connection.commit()

            self.logger.info(f'new database entry: {host} -> {nick}')

    def get_nicknames_from_database(self, host):
        with self.db_mutex:
            self.db_cursor.execute(f"SELECT nicks FROM '{self.db_name}' WHERE host = ?", (host,))
            result = self.db_cursor.fetchone()

        if result:
            result = json.loads(result[0])
            result = [irc_nickname(x) for x in result]

        return result

    def get_all_nicknames_from_database(self):
        with self.db_mutex:
            self.db_cursor.execute(f"SELECT nicks FROM '{self.db_name}'")
            result = self.db_cursor.fetchall()

        if result:
            result = [json.loads(x[0]) for x in result if x[0]]
            result = [[irc_nickname(y) for y in x] for x in result]

        return result

    def get_all_hosts_from_database(self):
        with self.db_mutex:
            self.db_cursor.execute(f"SELECT host FROM '{self.db_name}'")
            result = self.db_cursor.fetchall()

        if result:
            result = [x[0] for x in result]

        return result

    @command
    @doc('stalk_nick <nickname>: get all known hosts of <nickname> user')
    def stalk_nick(self, sender_nick, args, **kwargs):
        if not args: return
        nick = irc_nickname(args[0])
        all_hosts = self.get_all_hosts_from_database()
        result = set([host for host in all_hosts if nick in self.get_nicknames_from_database(host)])

        if result:
            response = f'known hosts of {nick}: {", ".join(result)}'
            if self.bot.is_msg_too_long(response):
                self.bot.say(f'{sender_nick}: too much data, check your privmsg')
                self.bot.say(response, sender_nick)
            else:
                self.bot.say(response)
        else:
            self.bot.say_err(nick)

        self.logger.info(f'{sender_nick} asks about hosts of {nick}: {result}')

    @command
    @doc("stalk <nickname>: get other <nickname> user's nicknames")
    def stalk(self, sender_nick, args, **kwargs):
        if not args: return
        nick = irc_nickname(args[0])
        result = set()
        all_nicknames = self.get_all_nicknames_from_database()
        for x in all_nicknames:
            if nick in x: result.update(x)

        self.logger.info(f'{sender_nick} stalks {nick}: {result}')

        if result == {nick}:
            self.bot.say(f"I don't know other {nick} nicks")
        else:
            if nick in result: result.remove(nick)

            if result:
                self.bot.say(f'other nicks of {nick}: {", ".join(result)}')
            else:
                self.bot.say_err(nick)

    @command
    @doc('stalk_host <host>: get all nicknames from <host>')
    def stalk_host(self, sender_nick, args, **kwargs):
        if not args: return
        host = args[0]
        nicks = self.get_nicknames_from_database(host)
        if nicks:
            response = f'known nicks from {host}: {", ".join(nicks)}'
            if self.bot.is_msg_too_long(response):
                self.bot.say(f'{sender_nick}: too much data, check your privmsg')
                self.bot.say(response, sender_nick)
            else:
                self.bot.say(response)
        else:
            self.bot.say_err(host)

        self.logger.info(f'{sender_nick} asks about nicks from {host}: {nicks}')