import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.dates import date2num, num2date, DateFormatter
from obspy.core import UTCDateTime, read, Stream
from obspy.io.xseed import Parser
from obspy.imaging.cm import pqlx
from obspy.geodetics.base import calc_vincenty_inverse
from obspy.signal.rotate import rotate_ne_rt
import sys, os, glob, datetime, MySQLdb, imp, time, socket, subprocess, logging
GEMA_PATH = "%s/GEMA/PyGEMA" % (os.getenv("HOME"))
sys.path.append( GEMA_PATH )

from pygema.read.seiscomp3 import get_streams_seiscomp3
from pygema.core.mysqlDB import select_events_manual_loc
from pygema.read.parameters import load_station_metadata

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

network = "GM"
station = "COP2"

time_before = 20
time_after = 100

max_gap = 360
max_depth = 250

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

events_list = select_events_manual_loc( UTCDateTime(1970, 1,1), UTCDateTime(), table="LOC", max_gap=max_gap, max_depth=max_depth)
events_list = np.array(events_list)
events_list = events_list[np.argsort(events_list[:, 0])]

# print events found on the screen
count = 1; count_list = []
print("\n\n")
for event in events_list:
  count_list.append(str(count))
  pattern = "[%i] %s    %.4f %.4f   %.2f km Ml=%.1f  dx=%.1f km  dy=%.1f km  dz=%.1f km " % (count, event[0].strftime("%Y-%m-%d %H:%M:%S.%f"), event[1], event[2], event[3], event[8], event[9], event[10], event[11] )
  print(pattern)
  count += 1

print("(from PyGEMA database: Table = LOC; max_gap = %.1f deg; max_depth = %.1f km)" % (max_gap, max_depth) )

#print( "[%i] TODOS!!" % (count) )
flag = input("\n+ Type the seismic event that you want to plot: ")
while not flag in count_list:
  flag = input("+ Type the seismic event that you want to plot: ")
  if flag in count_list:
    break

this_event = events_list[int(flag)-1]

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

starttime = this_event[0] - time_before
endtime = this_event[0] + time_after

st, gaps = get_streams_seiscomp3([network], [station], starttime, endtime, only_vertical_channel=False, merge_method=None, remove_traces_with_gaps=False)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

fig = plt.figure(dpi=300)
title = "evtime = %s UTC; evmag = %.1f\nevlat = %.2f deg; evlon = %.2f deg; evdepth = %.1f km" % (this_event[0].strftime("%Y/%m/%d %H:%M:%S"), this_event[8], this_event[2], this_event[1], this_event[3] )
fig.suptitle(title, y=0.96, fontsize=8)
ax1 = plt.subplot(3,4,(1,2) )
ax2 = plt.subplot(3,4,(5,6) )
ax3 = plt.subplot(3,4,(9,10) )
ax11 = plt.subplot(3,4,3 )
ax22 = plt.subplot(3,4,7 )
ax33 = plt.subplot(3,4,11 )
ax111 = plt.subplot(3,4,4 )
ax222 = plt.subplot(3,4,8 )
ax333 = plt.subplot(3,4,12 )
plt.subplots_adjust(wspace=0.5, hspace=0.5)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ADD WAVEFORM

st1 = st.copy()
for tr in st1:
  tr.detrend('demean')
  tr.detrend('linear')
  tr.taper(max_percentage=0.005,type='hann')
  dataless = glob.glob( "%s/src/dataless/%s_%s.dataless" % (GEMA_PATH, tr.stats.network, tr.stats.station) )[0]
  parser = Parser(dataless)
  paz = parser.get_paz(tr.id)
  tr.simulate(paz_remove=paz, pre_filt=(0.01, 0.02, 50, 100), paz_simulate=None, remove_sensitivity=True)
  tr.filter("bandpass", freqmin=2, freqmax=10, corners=2)
  #tr.filter("highpass", freq=5)
  #tr.integrate(method='cumtrapz')

tr_z = st1.select(channel='*HZ').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]
tr_n = st1.select(channel='*HN').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]
tr_e = st1.select(channel='*HE').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]

networks, stations, stlons, stlats, stalts = load_station_metadata()
ind = np.where(tr_z.stats.station == stations)[0][0]
evdist, evaz, evbaz =   calc_vincenty_inverse(stlats[ind], stlons[ind], this_event[2], this_event[1])
RR,TT = rotate_ne_rt(tr_n.data, tr_e.data, evbaz)

ax1.plot(tr_z.times("utcdatetime")-this_event[0], tr_z.data, lw=0.5, color="C0", label=tr_z.id )
ax2.plot(tr_z.times("utcdatetime")-this_event[0], RR, lw=0.5, color="C1", label=tr_z.id[0:11]+"R")
ax3.plot(tr_z.times("utcdatetime")-this_event[0], TT, lw=0.5, color="C2", label=tr_z.id[0:11]+"T")

#date_format = DateFormatter('%H:%M:%S')
for ax in [ax1,ax2,ax3]:
  ax.legend(fontsize=6, frameon=True, fancybox=True)
  ax.minorticks_on()
  ax.tick_params(axis='both', which='major', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in')
  ax.tick_params(axis='both', which='minor', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in')
  ax.tick_params(axis='x', which='major', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in', rotation=0)
  ax.tick_params(axis='x', which='minor', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in', rotation=0)
  ax.spines['right'].set_visible(True)
  ax.spines['top'].set_visible(False)
  ax.spines['left'].set_visible(True)
  ax.spines['bottom'].set_visible(False)
  ax.grid(axis='x', lw=0.5, ls=':', color='0.5')
  ax.ticklabel_format(axis='y', style='sci', scilimits=(-1, 1))
  ax.yaxis.offsetText.set_fontsize(6)
  #ax.xaxis.set_major_formatter(date_format)
  #ax.set_xlim([ date2num(starttime.datetime), date2num(endtime.datetime) ])
  ax.set_xlim([ -time_before, time_after ])
  ax.set_xlabel("Tiempo relativo al origen (s)", fontsize=7)
  ax.set_ylabel("Velocidad (m/s)", fontsize=7)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ADD FFT

st2 = st.copy()
for tr in st2:
  tr.detrend('demean')
  tr.detrend('linear')
  tr.taper(max_percentage=0.005,type='hann')
  dataless = glob.glob( "%s/src/dataless/%s_%s.dataless" % (GEMA_PATH, tr.stats.network, tr.stats.station) )[0]
  parser = Parser(dataless)
  paz = parser.get_paz(tr.id)
  tr.simulate(paz_remove=paz, pre_filt=(0.01, 0.02, 50, 100), paz_simulate=None, remove_sensitivity=True)
  tr.filter("bandpass", freqmin=0.02, freqmax=10, corners=2)
  #tr.filter("highpass", freq=5)
  #tr.integrate(method='cumtrapz')

tr_z = st2.select(channel='*HZ').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]
tr_n = st2.select(channel='*HN').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]
tr_e = st2.select(channel='*HE').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]

networks, stations, stlons, stlats, stalts = load_station_metadata()
ind = np.where(tr_z.stats.station == stations)[0][0]
evdist, evaz, evbaz =   calc_vincenty_inverse(stlats[ind], stlons[ind], this_event[2], this_event[1])
RR,TT = rotate_ne_rt(tr_n.data, tr_e.data, evbaz)

Fs = tr_z.stats.sampling_rate       # sampling rate
Ts = 1.0/Fs                       # sampling interval
n = tr_z.stats.npts                 # length of the signal
k = np.arange(n)
T = n/Fs
frq = k/T                         # two sides frequency range
frq = frq[range(int(n/2))]        # one side frequency range
Y = np.fft.fft(tr_z.data)           # fft computing
#Y = Y/n                           # normalization
fft_amp = abs(Y[range(int(n/2))])
power_spectrum_db = 10*np.log10(2*(fft_amp**2)/n)
ax11.plot(frq, fft_amp**2, lw=0.5, color="C0")

Fs = tr_z.stats.sampling_rate       # sampling rate
Ts = 1.0/Fs                       # sampling interval
n = tr_z.stats.npts                 # length of the signal
k = np.arange(n)
T = n/Fs
frq = k/T                         # two sides frequency range
frq = frq[range(int(n/2))]        # one side frequency range
Y = np.fft.fft(RR)           # fft computing
#Y = Y/n                           # normalization
fft_amp = abs(Y[range(int(n/2))])
power_spectrum_db = 10*np.log10(2*(fft_amp**2)/n)
ax22.plot(frq, fft_amp**2, lw=0.5, color="C1")

Fs = tr_z.stats.sampling_rate       # sampling rate
Ts = 1.0/Fs                       # sampling interval
n = tr_z.stats.npts                 # length of the signal
k = np.arange(n)
T = n/Fs
frq = k/T                         # two sides frequency range
frq = frq[range(int(n/2))]        # one side frequency range
Y = np.fft.fft(TT)           # fft computing
#Y = Y/n                           # normalization
fft_amp = abs(Y[range(int(n/2))])
power_spectrum_db = 10*np.log10(2*(fft_amp**2)/n)
ax33.plot(frq, fft_amp**2, lw=0.5, color="C2")

for ax in [ax11,ax22,ax33]:
  ax.set_ylabel(r"Amplitud$^{2}$", fontsize=7)
  ax.set_xlabel("Frecuencia (Hz)", fontsize=7)
  ax.minorticks_on()
  ax.tick_params(axis='both', which='major', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in')
  ax.tick_params(axis='both', which='minor', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in')
  ax.tick_params(axis='x', which='major', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in', rotation=0)
  ax.tick_params(axis='x', which='minor', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in', rotation=0)
  ax.spines['right'].set_visible(True)
  ax.spines['top'].set_visible(False)
  ax.spines['left'].set_visible(True)
  ax.spines['bottom'].set_visible(False)
  ax.grid(axis='x', which="both", lw=0.5, ls=':', color='0.5')
  ax.ticklabel_format(axis='y', style='sci', scilimits=(-1, 1))
  ax.yaxis.offsetText.set_fontsize(6)
  ax.set_xlim([ 0.1,10])
  ax.set_xscale('log')

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ADD PARTICLE MOTION

st3 = st.copy()
for tr in st3:
  tr.detrend('demean')
  tr.detrend('linear')
  tr.taper(max_percentage=0.005,type='hann')
  dataless = glob.glob( "%s/src/dataless/%s_%s.dataless" % (GEMA_PATH, tr.stats.network, tr.stats.station) )[0]
  parser = Parser(dataless)
  paz = parser.get_paz(tr.id)
  tr.simulate(paz_remove=paz, pre_filt=(0.01, 0.02, 50, 100), paz_simulate=None, remove_sensitivity=True)
  tr.filter("bandpass", freqmin=0.1, freqmax=0.9, corners=2)
  #tr.filter("highpass", freq=5)
  #tr.integrate(method='cumtrapz')

tr_z = st3.select(channel='*HZ').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]
tr_n = st3.select(channel='*HN').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]
tr_e = st3.select(channel='*HE').merge(method=1, interpolation_samples=-1, fill_value='interpolate')[0]

networks, stations, stlons, stlats, stalts = load_station_metadata()
ind = np.where(tr_z.stats.station == stations)[0][0]
evdist, evaz, evbaz =   calc_vincenty_inverse(stlats[ind], stlons[ind], this_event[2], this_event[1])
RR,TT = rotate_ne_rt(tr_n.data, tr_e.data, evbaz)

ax111.plot(RR, tr_z.data, lw=0.5, color="C0")
ax222.plot(TT, RR, lw=0.5, color="C1")
ax333.plot(TT, tr_z.data, lw=0.5, color="C2")

ax111.set_ylabel("Vertical", fontsize=7)
ax111.set_xlabel("Radial", fontsize=7)
ax222.set_ylabel("Radial", fontsize=7)
ax222.set_xlabel("Transversal", fontsize=7)
ax333.set_ylabel("Vertical", fontsize=7)
ax333.set_xlabel("Transversal", fontsize=7)
for ax in [ax111,ax222,ax333]:
  ax.minorticks_on()
  ax.tick_params(axis='both', which='major', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in')
  ax.tick_params(axis='both', which='minor', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in')
  ax.tick_params(axis='x', which='major', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in', rotation=0)
  ax.tick_params(axis='x', which='minor', labelsize=7, bottom='off', top='off', left='on', right='on', direction='in', rotation=0)
  ax.spines['right'].set_visible(True)
  ax.spines['top'].set_visible(False)
  ax.spines['left'].set_visible(True)
  ax.spines['bottom'].set_visible(False)
  ax.grid(axis='x', which="both", lw=0.5, ls=':', color='0.5')
  plt.setp( ax.get_xticklabels(), visible=False)
  plt.setp( ax.get_yticklabels(), visible=False)

figname = "figs/%s/%s_waveforms.jpg" % (station, station)
plt.savefig(figname, dpi=300, bbox_inches='tight', transparent=False)
#plt.show()
plt.close()


"""
Instructions
Write a program that interprets the Body Mass Index (BMI) based on a user's weight and height.

It should tell them the interpretation of their BMI based on the BMI value.

Under 18.5 they are underweight
Over 18.5 but below 25 they have a normal weight
Equal to or over 25 but below 30 they are slightly overweight
Equal to or over 30 but below 35 they are obese
Equal to or over 35 they are clinically obese.
BMI Chart

The BMI is calculated by dividing a person's weight (in kg) by the square of their height (in m):

BMI Formula

Important: you do not need to round the result to the nearest whole number. It's fine to print out a floating point number for this exercise. The interpretation message needs to include the words in bold from the interpretations above. e.g. underweight, normal weight, overweight, obese, clinically obese.

Example Input 1
1.50
63
Example Output 1
Your BMI is 28.0, you are slightly overweight.
since 63 ÷ (1.50 x 1.50) = 28

The testing code will check for print output that is formatted like one of the lines below:

"Your BMI is 18.28678, you are underweight."
"Your BMI is 22.0, you have a normal weight."
"Your BMI is 28.50752, you are slightly overweight."
"Your BMI is 32.56189, you are obese."
"Your BMI is 37.50000, you are clinically obese."
Example Input 2
1.60
96
Example Output 2
Your BMI is 37.49999999999999, you are clinically obese.
Example Input 3
1.71
73
Example Output 3
Your BMI is 24.96494647925858, you have a normal weight.

"""

height = input("Enter you height in meters. ")
weight = input("Enter your weight in kilograms. ")

heightnum = float(height)
weightnum = float(weight)
BMI = float((weightnum / (heightnum * heightnum)))
# int BMI to get whole number for test cases

if BMI < 18.5:
    print(f"Your BMI is {BMI}, you are underweight.")
elif BMI > 18.5 and BMI < 25:
    print(f"Your BMI is {BMI}, you have a normal weight.")
elif BMI >= 25 and BMI < 30:
    print(f"Your BMI is {BMI}, you are slightly overweight.")
elif BMI >= 30 and BMI < 35:
    print(f"Your BMI is {BMI}, you are obese.")
elif BMI >= 35:
    print(f"Your BMI is {BMI}, you are clinically obese.")


import os
import shutil

from bentoctl.exceptions import TemplateExists, TemplateTypeNotDefined

from bentoctl_lambda.parameters import DeploymentValues
from bentoctl_lambda.utils import get_metadata

def generate(name, spec, template_type, destination_dir, values_only=True):
    """
    generates the template corresponding to the template_type.

    Parameters
    ----------
    name : str
        deployment name to be used by the template. This name will be used
        to create the resource names.
    spec : dict
        The properties of the deployment (specifications) passed from the
        deployment_config's `spec` section.
    template_type: str
        The type of template that is to be generated by the operator. The
        available ones are [terraform, cloudformation]

    Returns
    -------
    generated_path : str
        The path for the generated template.
    """
    if template_type == "terraform":
        template_file_name = "terraform_default.tf"
        generated_template_file_name = "main.tf"
        generated_params_file_name = "bentoctl.tfvars"
    else:
        raise TemplateTypeNotDefined(template_type)

    generated_files = [generated_params_file_name]
    generated_template_file_path = os.path.join(
        destination_dir, generated_template_file_name
    )
    if not values_only:
        if os.path.exists(generated_template_file_path):
            raise TemplateExists(generated_template_file_path)
        shutil.copyfile(
            os.path.join(os.path.dirname(__file__), f"templates/{template_file_name}"),
            generated_template_file_path,
        )
        generated_files.append(generated_template_file_name)

    # generate params file
    params = DeploymentValues(name, spec, template_type)
    params.to_params_file(os.path.join(destination_dir, generated_params_file_name))

    return generated_files


from collections import namedtuple

from construct import Struct, Int8ub, Int16ub, Int24ub, BytesInteger, Bytes, Enum, Byte, Switch, Prefixed, \
    GreedyBytes, IfThenElse, GreedyRange, Default

from . import tls
from .helper import Extensions
from ..const import tls as const_tls, dtls as const_dtls

# from dtls.constructs.old_adapter import Pre

Cookie = Prefixed(Int8ub, Default(GreedyBytes, b''))

ProtocolVersion = Enum(Int16ub, const_dtls.ProtocolVersion)

ClientHello = Struct(
    client_version=ProtocolVersion,
    random=Bytes(32),  # Random,
    session_id=tls.SessionID,
    cookie=Cookie,
    cipher_suites=tls.CipherSuites,
    compression_methods=tls.CompressionMethods,
    extension=Extensions,
)

HelloVerifyRequest = Struct(
    server_version=ProtocolVersion,
    cookie=Cookie,
)

Handshake = Struct(
    handshake_type=Enum(Byte, const_tls.HandshakeType),
    length=Int24ub,
    message_sequence=Int16ub,
    fragment_offset=Default(Int24ub, 0),
    fragment_length=Default(Int24ub, lambda ctx: ctx.length),
    fragment=IfThenElse(
        lambda ctx: ctx.length == ctx.fragment_length,
        Switch(lambda ctx: int(ctx.handshake_type), {
            const_tls.HandshakeType.CLIENT_HELLO.value: ClientHello,
            const_tls.HandshakeType.HELLO_VERIFY_REQUEST.value: HelloVerifyRequest,
            const_tls.HandshakeType.SERVER_HELLO.value: tls.ServerHello,
            const_tls.HandshakeType.CERTIFICATE.value: tls.Certificate,
            const_tls.HandshakeType.SERVER_HELLO_DONE.value: tls.ServerHelloDone,
            const_tls.HandshakeType.FINISHED.value: tls.Finished
        }, default=Bytes(lambda ctx: ctx.fragment_length)),
        Bytes(lambda ctx: ctx.fragment_length)
    )
)

RawHandshake = Struct(
    handshake_type=Enum(Byte, const_tls.HandshakeType),
    length=Int24ub,
    message_seq=Int16ub,
    fragment_offset=Int24ub,
    fragment_length=Int24ub,
    fragment=Bytes(lambda ctx: ctx.fragment_length)
)

Plaintext = Struct(
    type=tls.ContentType,
    version=ProtocolVersion,
    epoch=Int16ub,
    sequence_number=BytesInteger(6),
    fragment=Prefixed(
        Int16ub,
        Switch(lambda ctx: ctx.type.intvalue, {
            const_tls.ContentType.CHANGE_CIPHER_SPEC.value: GreedyBytes,
            const_tls.ContentType.ALERT.value: tls.Alert,
            const_tls.ContentType.HANDSHAKE.value: Handshake,
            const_tls.ContentType.APPLICATION_DATA.value: GreedyBytes
        }, default=GreedyBytes))
)

RawPlaintext = Struct(
    type=tls.ContentType,
    version=ProtocolVersion,
    epoch=Int16ub,
    sequence_number=BytesInteger(6),
    fragment=Prefixed(
        Int16ub,
        GreedyBytes
    )
)

RawDatagram = GreedyRange(RawPlaintext)
Datagram = GreedyRange(Plaintext)

AnswerRecord = namedtuple('AnswerRecord', ('content_type', 'epoch', 'fragment'))

TLSCompressed = Struct(
    type=tls.ContentType,
    version=ProtocolVersion,
    epoch=Int16ub,
    sequence_number=BytesInteger(6),
    fragment=Prefixed(
        Int16ub,
        GreedyBytes
    )
)

TLSCiphertext = Struct(
    type=tls.ContentType,
    version=ProtocolVersion,
    epoch=Int16ub,
    sequence_number=BytesInteger(6),
    fragment=Prefixed(
        Int16ub,
        Switch(lambda ctx: ctx._params.security_parameters.cipher_type, {
            'block': tls.GenericBlockCipher,
            # const_tls.CipherType.aead: GenericAEADCipher
        }, default=GreedyBytes))
)


#!/usr/bin/env python3.6
# -*- coding:Utf-8 -*-

import shutil
import os

bck_loc = os.path.expanduser("~/Library/Application Support/Google/Chrome/Default/BACKUP.nibjplbnmmklkfnkpecgbffkifmdbjed")
plu_loc = os.path.expanduser("~/Library/Application Support/Google/Chrome/Default/Extensions/nibjplbnmmklkfnkpecgbffkifmdbjed")

def day():
    if os.path.exists(plu_loc):
        shutil.rmtree(bck_loc)
        shutil.move(plu_loc, bck_loc)
    return True

def night():
    if os.path.exists(bck_loc) and not os.path.exists(plu_loc):
        shutil.copytree(bck_loc, plu_loc)
    return True

def apply_theme(thn:int):
    if thn == 1:
        return day()
    elif thn == 2:
        return night()
    else:
        return False


# Reads a file that has the text.

def textparser(file):
        with open(file) as k:
            s = ""
            for i in k:
                s = s + i
        return s

# Used to find the a base raised to a power, then modulo applied in log time with respect to the power. This uses
# properties of modulo to develop cases on whether the input power is odd or even.

def modexponenthelper(power, base, modulo):
    if base == 0:
        return 0
    if power == 0:
        return 1
    if power % 2 == 0:
        return (modexponenthelper(power/2, base, modulo) * modexponenthelper(power/2, base, modulo)) % modulo
    else:
        return ((modexponenthelper(power-1, base, modulo) % modulo) * (base % modulo)) % modulo

# Uses Horner's Method to calculate the initial hashes without causing integer overflows

def initializehash(substring, m, a):
    patternhash = 0
    temp = len(substring)
    for i in substring:
        patternhash = ((patternhash * a) + ord(i)) % m # initializes the hash value of pattern
        temp -= 1
    return patternhash

# Calculates the hash code for the next subseqeunce that has the length of the pattern using the previous hash code
# value

def recalculatehash(oldhash, oldchar, newchar, m, a, a1):
    newhash = ((((oldhash - (ord(oldchar) % m * a1) % m) * a) % m) + ord(newchar)) % m # The +m is just to make sure we don't have a negative
    return newhash

# Takes a file with the text, a list of all the patterns, a modulo value, and a multiplier (base) value. Outputs
# The location of where the pattern is located in the text if it is found.

def rabin_karp(file, patternset, modulo , multiplier):
    text = textparser(file)
    hashestopatterns = {}
    for i in patternset:
        phash = initializehash(i, modulo, multiplier)
        hashestopatterns[phash] = i

    # Pre-Processed Multiplier
    ppm = modexponenthelper(len(patternset[0]) - 1, multiplier, modulo)

    n = len(text)
    m = len(patternset[0])
    subhash = initializehash(text[0:m], modulo, multiplier)
    for i in range(0, n-m + 1):
        if hashestopatterns.__contains__(subhash):
            curr = text[i:i + m]
            if hashestopatterns[subhash].__eq__(curr):
                print(hashestopatterns[subhash] + " found at index " + str(i))
        if i == n-m:
            break
        subhash = recalculatehash(subhash, text[i], text[i + m], modulo, multiplier, ppm)


from __future__ import annotations

import os
from datetime import datetime

from airflow import DAG
from airflow.models.baseoperator import chain
from airflow.providers.amazon.aws.operators.ec2 import EC2StartInstanceOperator, EC2StopInstanceOperator
from airflow.providers.amazon.aws.sensors.ec2 import EC2InstanceStateSensor

INSTANCE_ID = os.getenv("INSTANCE_ID", "instance-id")

with DAG(
    dag_id='example_ec2',
    start_date=datetime(2021, 1, 1),
    tags=['example'],
    catchup=False,
) as dag:
    # [START howto_operator_ec2_start_instance]
    start_instance = EC2StartInstanceOperator(
        task_id="ec2_start_instance",
        instance_id=INSTANCE_ID,
    )
    # [END howto_operator_ec2_start_instance]

    # [START howto_sensor_ec2_instance_state]
    instance_state = EC2InstanceStateSensor(
        task_id="ec2_instance_state",
        instance_id=INSTANCE_ID,
        target_state="running",
    )
    # [END howto_sensor_ec2_instance_state]

    # [START howto_operator_ec2_stop_instance]
    stop_instance = EC2StopInstanceOperator(
        task_id="ec2_stop_instance",
        instance_id=INSTANCE_ID,
    )
    # [END howto_operator_ec2_stop_instance]

    chain(start_instance, instance_state, stop_instance)


import datetime
def printTimeStamp(name):
    print('prodaivoda yan prodaivoda dan: ' + name)
    print('Час компіляції: ' + str(datetime.datetime.now()))

x = int(input("Год: "))
y = int(input("Месяц: "))
z = int(input("День: "))
today = datetime.date(x, y, z)
tomorrow = today + datetime.timedelta(days=1)

print("Следуйщий день " + str(tomorrow))


import copy  # 보드를 카피하여 이길 수 있는 곳인지 체크하기 위해
import random  # 컴퓨터와 사용자 중 누가 먼저 시작할지 결정하기 위해

def print_state(Game):  # 보드의 상태를 출력하는 함수
    print("\n-----------")
    print(" %s | %s | %s" % (Game[1], Game[2], Game[3]))
    print(" %s | %s | %s" % (Game[4], Game[5], Game[6]))
    print(" %s | %s | %s" % (Game[7], Game[8], Game[9]))
    print("-----------\n")

def right_place(place, Game):  # 1~9까지의 숫자가 든 문자열과 보드를 입력받아 가능한 곳인지 판정하는 함수
    place = int(place)  # 문자열을 숫자로 변경
    if place > 0 and place < 10 and Game[place] == ' ':  # 범위에 맞고 보드가 비었다면 가능한 곳
        return True
    return False

def only_integer(num):  # 입력된 값이 '1'~'9'까지인지를 판별하는 함수
    for i in range(1, 10):
        if str(i) == num:  # '1'부터 '9'까지 중 같은 것이 있다면 True
            return True
    return False

def user_places(user, Game):  # 사용자가 입력한 위치에 따라 보드에 입력하는 함수
    print_state(Game)  # 게임판 출력
    print("What is your next move? (1-9):", end=' ')
    user_p = input()  # 입력받음
    while not only_integer(user_p) or not right_place(user_p, Game):
        user_p = input("(1-9) 중 둘 수 있는 곳의 위치를 입력하세요.")  # 범위에 없거나 둘 수 없으면 다시 입력받음
    Game[int(user_p)] = user

def iswin(player, Game):  # player와 보드판을 받아 player가 승리했는지 판정하는 함수
    win = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]]  # 이것들이 다 같으면 승리한 것임
    for i in range(8):  # win배열의 구성요소들에 대해
        cnt = 0
        for j in range(3):
            if Game[win[i][j]] == player:
                cnt += 1
        if cnt == 3:  # 세 개의 구성요소가 모두 player 였다면 player의 승리
            return True
        cnt = 0
    return False

def win_place(player, Game):  # player가 이길 수 있는 곳을 찾는 함수
    for i in range(1, 10):
        if right_place(i, Game):  # 가능한 모든 곳에 대해
            tmp = copy.deepcopy(Game)
            tmp[i] = player  # 보드판을 복사해서 채워넣기
            if iswin(player, tmp):  # 이겼다면 승리의 수가 존재한 것이브로 그곳을 반환
                return i
    return -1

def next_places(user, com, Game):  # 컴퓨터가 다음 둘 곳을 결정하는 함수
    now = win_place(com, Game)
    if now != -1:
        Game[now] = com  # 컴퓨터가 이길 수 있는 수가 있다면 그곳을 둠
        return
    now = win_place(user, Game)
    if now != -1:
        Game[now] = com  # 사용자가 이길 수 있는 수가 있다면 그곳을 막음
        return
    for i in range(1, 10):
        if right_place(i, Game):
            Game[i] = com  # 아니라면 그냥 가능한 곳에 둔다
            return

def play_again():  # 사용자에게 다시 플레이할 것인지 물어보는 함수
    print("Do you want to play again? (yes or no): ", end='')
    again = input()
    while again != "yes" and again != "no":
        again = input("yes나 no를 입력하세요.")  # yes나 no가 아니면 다시 입력받음
    if again == "yes":
        return True
    else:
        return False

def Odds(win, lose, tie):  # 승률을 출력하는 함수
    print("당신의 승률은 %.2f %% 입니다." % (win / (win + lose + tie) * 100))
    return

print("Welcome to Tic Tac Toe!")
Win = 0
Lose = 0
Tie = 0  # 승률 계산을 위한 변수

while True:
    board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']  # 보드 생성
    print("Do you want to be X or O? :", end=' ')
    user_pos = input()
    while user_pos not in "XO" or user_pos == '':  # 유저의 포지션을 입력받음, X나 O가 아니면 다시 입력
        user_pos = input("X나 O를 입력하세요.")
    if user_pos == 'O':
        com_pos = 'X'
    else:
        com_pos = 'O'

    first = random.randrange(0, 2)  # 첫번째에 누가 시작할지 랜덤으로 결정
    if first == 1:
        print("The player will go first.")  # 사용자가 먼저라면 사용자가 두게 함
        user_places(user_pos, board)
    else:
        print("The computer will go first.")
    cnt = 0
    while True:
        next_places(user_pos, com_pos, board)  # 컴퓨터의 차례
        if iswin(com_pos, board):  # 컴퓨터가 이겼다면 게임판을 출력하고 졌음을 알려줌
            print_state(board)
            print("You lose...")
            Lose += 1
            break
        cnt += 1  # 컴퓨터가 둔 후 시행횟수 +1
        if cnt >= 9:  # 컴퓨터가 둔 후 판이 다 찼다면 무승부를 출력
            print_state(board)
            print("The game is a tie!")
            Tie += 1
            break
        user_places(user_pos, board)  # 사용자의 차례
        if iswin(user_pos, board):  # 사용자가 이겼다면 게임판을 출력하고 이겼음을 알려줌
            print_state(board)
            print("Hooray! You have won the game!")
            Win += 1
            break
        cnt += 1  # 사용자가 둔 후 시행횟수 +1
        if cnt >= 9:  # 사용자가 둔 후 판이 다 찼다면 무승부를 출력
            print_state(board)
            print("The game is Tie!")
            break
    Odds(Win, Lose, Tie)  # 게임이 끝난 후 승률을 출력
    if not play_again():  # 다시 플레이할지 물어봄
        break


from bson.codec_options import CodecOptions
from motor import motor_asyncio
from pymongo.errors import ServerSelectionTimeoutError, OperationFailure

from Bubot.Helpers.ActionDecorator import async_action
from Bubot.Helpers.ExtException import ExtException, ExtTimeoutError, KeyNotFound
from Bubot.Helpers.Helper import get_tzinfo

class Mongo:
    tzinfo = get_tzinfo()

    def __init__(self, **kwargs):
        self.client = kwargs.get('client')

    pass

    @classmethod
    async def connect(cls, device=None, *, url='mongodb://localhost:27017', **kwargs):
        if device:
            url = device.get_param('/oic/con', 'storage_url', 'mongodb://localhost:27017')
        try:
            client = motor_asyncio.AsyncIOMotorClient(url, serverSelectionTimeoutMS=5000, tz_aware=False)
            res = await client.server_info()
        except ServerSelectionTimeoutError as err:
            raise ExtTimeoutError(message='Mongo connection timeout', parent=err)
        except Exception as err:
            raise ExtException(parent=err, message='Storage not connected')
        return cls(client=client)

    async def close(self):
        self.client.close()

    async def exist_database(self, db):
        db_names = await self.client.list_database_names()
        return db in db_names

    async def exist_table(self, db, name):
        if not await self.exist_database(db):
            return False
        try:
            await self.client[db].validate_collection(name)
            return True
        except OperationFailure:
            return False

    def create_table(self, db, name):
        table = self.client[db][name]

    async def create_index(self, db, name_, keys, **kwargs):
        await self.client[db][name_].create_index(keys, **kwargs)

    async def find_data_base(self, name):
        data_bases = await self.client.list_database_names()
        if name in data_bases:
            return self.client[name]
        return None

    @async_action
    async def update(self, db, table, data, create=True, *, where=None, _action=None, **kwargs):
        if data.get('_id') or where:
            if where:
                res = await self.client[db][table].update_many(
                    where,
                    {'$set': data}, upsert=create, **kwargs)
            else:
                res = await self.client[db][table].update_one(
                    dict(_id=data['_id']),
                    {'$set': data}, upsert=create, **kwargs)
            if res.upserted_id:
                data['_id'] = res.upserted_id
        else:
            if create:
                res = await self.client[db][table].insert_one(data)
                data['_id'] = res.inserted_id
            else:
                raise KeyError
        return res

    async def push(self, db, table, uid, field, item, **kwargs):
        res = await self.client[db][table].update_one({'_id': uid}, {'$push': {field: item}}, upsert=False)
        return res

    async def pull(self, db, table, uid, field, item, **kwargs):
        res = await self.client[db][table].update_one({'_id': uid}, {'$pull': {field: item}}, upsert=False)
        return res

    def set_timezone(self, db, table):
        self.client[db][table].with_options(
            codec_options=CodecOptions(
                tz_aware=False,
                # tzinfo=self.tzinfo
            ))

    async def find_one(self, db, table, where, **kwargs):
        self.set_timezone(db, table)
        return await self.client[db][table].find_one(where, **kwargs)

    async def delete_one(self, db, table, where):
        return await self.client[db][table].delete_one(where)

    async def delete_many(self, db, table, where):
        return await self.client[db][table].delete_many(where)

    async def count(self, db, table, **kwargs):
        return await self.client[db][table].count_documents(
            kwargs.get('where', {})
        )

    @staticmethod
    def check_db_and_table(db, table, action):
        if not db:
            raise ExtException(message='db not defined', action=action)
        if not table:
            raise ExtException(message='table not defined', action=action)

    async def list(self, db, table, *, where=None, projection=None, skip=0, limit=1000, order=None, _action=None,
                   **kwargs):
        self.check_db_and_table(db, table, _action)
        self.set_timezone(db, table)
        if where is not None:
            full_text_search = where.pop('_search', None)
            if full_text_search:
                where['$text'] = {'$search': full_text_search}

        cursor = self.client[db][table].find(
            filter=where,
            projection=projection,
            skip=skip,
            limit=limit
        )
        if order:
            cursor.sort(order)
        result = await cursor.to_list(length=1000)
        await cursor.close()
        return result

    @async_action
    async def get_previous(self, db, table, *, where=None, index=None, projection=None, skip=0, limit=1000, order=None,
                           _action=None, **kwargs):
        self.check_db_and_table(db, table, _action)
        self.set_timezone(db, table)

        cursor = self.client[db][table].find(
            filter=where,

        ).sort([(index, -1)]).limit(10)
        result = await cursor.to_list(length=1000)
        await cursor.close()
        return result

    async def pipeline(self, db, table, pipeline, *, projection=None, where=None, skip=0, sort=None, limit=1000,
                       **kwargs):
        self.set_timezone(db, table)
        self.check_db(db)
        _pipeline = []
        if where:
            _pipeline.append({'$match': where})

        _pipeline += pipeline

        if projection:
            _pipeline.append({'$project': projection})
        if sort:
            _pipeline.append({'$sort': sort})
        if skip:
            _pipeline.append({'$skip': skip})
        if limit:
            _pipeline.append({'$limit': limit})

        cursor = self.client[db][table].aggregate(_pipeline)
        result = await cursor.to_list(length=limit)
        return result

    async def find_one_and_update(self, db, table, where, data, **kwargs):
        return await self.client[db][table].find_one_and_update(where, {'$set': data}, **kwargs)

    @classmethod
    def check_db(cls, db):
        if not db:
            raise KeyNotFound(message='Data base not defined')

# #https://www.programmersought.com/article/87956455420/
# def asynchronize(framework, sync_method, doc=None):
#     """Decorate `sync_method` so it accepts a callback or returns a Future.
#
#     The method runs on a thread and calls the callback or resolves
#     the Future when the thread completes.
#
#     :Parameters:
#      - `motor_class`:       Motor class being created, e.g. MotorClient.
#      - `framework`:         An asynchronous framework
#      - `sync_method`:       Unbound method of pymongo Collection, Database,
#                             MongoClient, etc.
#      - `doc`:               Optionally override sync_method's docstring
#     """
#     @functools.wraps(sync_method)
#     def method(self, *args, **kwargs):
#         loop = self.get_io_loop()
#         callback = kwargs.pop('callback', None)
#         future = framework.run_on_executor(loop,
#                                            sync_method,
#                                            self.delegate,
#                                            *args,
#                                            **kwargs)
#
#         return framework.future_or_callback(future, callback, loop)
#
#     # This is for the benefit of motor_extensions.py, which needs this info to
#     # generate documentation with Sphinx.
#     method.is_async_method = True
#     name = sync_method.__name__
#     method.pymongo_method_name = name
#     if doc is not None:
#         method.__doc__ = doc
#
#     return method


from grove_rgb_lcd import *
import time
import grovepi
import math

sensor = 0
button = 4
grovepi.pinMode(button, "INPUT")

while True:
    try:
        button_status= grovepi.digitalRead(button)
        if button_status:
            setRGB(0,255,0)
            temp = grovepi.temp(sensor,'1.1')
            text = "temp = " +  str(temp) + " C"
            print(text)
            setText(text)
            time.sleep(.5)
        else:
            setRGB(255,0,0)
            print("Presiona el boton")
            setText("Presiona el\n boton")
            time.sleep(.5)
    except IOError:
        print ("Error")


import argparse
from textwrap import dedent

from handlers.spotify import Spotify
from handlers.youtube import Youtube

def spotify_to_yt(url: str, name: str = None):
    raise NotImplementedError

def yt_to_spotify(url: str, name: str = None):
    yt = Youtube()
    spotify = Spotify('b4eab4a6ee4e47c8acb628285fa1d716', '37a562b3a9af4af09fd425b64d7236ad')

    tracks = yt.get_playlist_tracks(url)
    spotify_uris = [spotify.search(track['title'], track['artist']) for track in tracks]

    name = name or input('Playlist name: ')

    spotify_playlist_url = spotify.create_playlist(name, spotify_uris)
    print(f'Playlist created: {spotify_playlist_url}')

def main():
    parser = argparse.ArgumentParser(description='Transfer playlists between Spotify and YouTube Music')
    parser.add_argument(
        '-u',
        '--url',
        type=str,
        metavar='URL',
        help='URL of the playlist to transfer'
    )
    parser.add_argument(
        '-d',
        '--direction',
        type=str,
        choices=['yt-to-spotify', 'spotify-to-yt'],
        metavar='DIRECTION',
        help='Direction of the transfer: [yt-to-spotify, spotify-to-yt]'
    )
    parser.add_argument(
        '-n',
        '--name',
        type=str,
        metavar='NAME',
        help='Name of the playlist to create'
    )
    args = parser.parse_args()

    direction = args.direction or 'yt-to-spotify' if int(input(dedent('''
    Transfer direction:
    1. YouTube Music to Spotify
    2. Spotify to YouTube Music
    Enter your choice: ''')).strip()) == 1 else 'spotify-to-yt'
    url = args.url or input('Playlist URL: ')

    if direction not in ['yt-to-spotify', 'spotify-to-yt']:
        raise ValueError('Invalid direction')

    if direction == 'yt-to-spotify':
        yt_to_spotify(url, args.name)
        return

    spotify_to_yt(url, args.name)

if __name__ == '__main__':
    main()


from config import *
import CGALPY.Ker as KER

Point_2 = KER.Point_2
FT = KER.FT
Gmpq = KER.Gmpq

def read_polygon(filename):
  with open(filename, "r") as f:
    input_data = f.readline().split(" ")
  output = []
  for i in range(0, int(input_data[0])):
    output.append((int(input_data[2*i + 1]), int(input_data[2*i + 2])))
  return output

def read_disc(filename):
  with open(filename, "r") as f:
    input_data = f.readline().split(" ")
    out = [int(i) for i in input_data]
  return out

def read_point(filename):
  with open(filename, "r") as f:
    input_data = f.readline().split(" ")
    out = [int(i) for i in input_data]
  return out

def read_polygon_scene(filename):
  out = []
  with open(filename, "r") as f:
    # num robots
    line = f.readline()
    input_data = line.split(" ")
    out.append(int(input_data[0]))
    # radius
    line = f.readline()
    input_data = line.split(" ")
    out.append(float(input_data[0]))
    # start
    out.append([])
    for _ in range(out[0]):
      line = f.readline()
      input_data = line.split(" ")
      out[len(out)-1].append(Point_2(FT(Gmpq(input_data[0])), FT(Gmpq(input_data[1]))))
    # goal
    out.append([])
    for _ in range(out[0]):
      line = f.readline()
      input_data = line.split(" ")
      out[len(out)-1].append(Point_2(FT(Gmpq(input_data[0])), FT(Gmpq(input_data[1]))))

    line = f.readline()
    while line:
      input_data = line.split(" ")
      polygon = []
      for i in range(0, int(input_data[0])):
        polygon.append(Point_2(FT(Gmpq(input_data[2 * i + 1])), FT((Gmpq(input_data[2 * i + 2])))))
      out.append(polygon)
      line = f.readline()
  return out

def save_path(path, filename):
  file = open(filename, 'w')
  for i in range(len(path)):
    p = path[i]
    x = p.x().exact()
    y = p.y().exact()
    line = str(x.numerator()) + '/' + str(x.denominator()) + ' ' + str(y.numerator()) + '/' + str(y.denominator())
    if i < len(path) - 1:  line = line + '\n'
    file.write(line)
  file.close()

def load_path(path, filename):
  with open(filename, 'r') as file:
    for line in file:
      coords = line.split(" ")
      x0 = FT(Gmpq(coords[0]))
      y0 = FT(Gmpq((coords[1])))
      x1 = FT(Gmpq(coords[2]))
      y1 = FT(Gmpq(coords[3]))
      p0 = Point_2(x0, y0)
      p1 = Point_2(x1, y1)
      path.append((p0, p1))


#
# Author: Marcel Willig
# Date: 10.06.2019
#
# Description: This program simulates an oven, whose heating
# current is set by a PID controller and plots its temperature.
# The settings of the PID controller can be changed by the user.
#

import sys

from PyQt5.QtCore import Qt, QBasicTimer
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QHBoxLayout, QGridLayout, QSizePolicy, QSlider, QWidget, QPushButton

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

from Oven import Controller

#
# Define the GUI which the user will see.
#

class PIDdrawer(QWidget):

    def __init__(self):
        super().__init__()
        self.left = 10
        self.top = 10
        self.title = 'PID-Controller Animation'
        self.width = 640
        self.height = 400
        self.c = Controller()
        self.initUI()

    def initUI(self):

        grid = QGridLayout()

        self.lbl_p = QLabel("P = {0}".format(self.c.P))
        self.lbl_p.setFixedWidth(100)
        sld_p = QSlider(Qt.Horizontal)
        sld_p.valueChanged.connect(self.changeP)
        grid.addWidget( self.lbl_p, 0, 0 )
        grid.addWidget( sld_p, 0, 1 )

        self.lbl_i = QLabel("I = {0}".format(self.c.I))
        sld_i = QSlider(Qt.Horizontal)
        sld_i.valueChanged.connect(self.changeI)
        grid.addWidget( self.lbl_i, 1, 0 )
        grid.addWidget( sld_i, 1 ,1 )

        self.lbl_d = QLabel("D = {0}".format(self.c.D))
        sld_d = QSlider(Qt.Horizontal)
        sld_d.valueChanged.connect(self.changeD)
        grid.addWidget( self.lbl_d, 2, 0 )
        grid.addWidget( sld_d, 2, 1 )

        self.canvas = PlotCanvas(width=5, height=4)
        self.canvas.plot( [self.c.oven.temperature for i in range(2)])

        vButtonBox = QVBoxLayout()
        self.button_start = QPushButton('Start')
        self.button_start.setToolTip('Start/Stop Drawing')
        self.button_start.clicked.connect( self.startStop )
        self.button_start.resize(140,100)
        button_restart = QPushButton('Reset')
        button_restart.setToolTip('Stop and Reset Drawing')
        button_restart.clicked.connect( self.restart )
        button_restart.resize(140,100)
        vButtonBox.addWidget(self.button_start)
        vButtonBox.addWidget(button_restart)

        hbox_canvas = QHBoxLayout()
        hbox_canvas.addWidget( self.canvas )
        hbox_canvas.addLayout( vButtonBox )

        vbox = QVBoxLayout()
        vbox.addLayout( grid )
        vbox.addLayout( hbox_canvas )

        self.setLayout(vbox)
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.timer = QBasicTimer()

        self.show()

    def changeP(self, p):
        p /= 50
        self.lbl_p.setText("P = {0}".format(p))
        self.c.setP(p)

    def changeI(self, i):
        i /= 1000
        self.lbl_i.setText("I = {0}".format(i))
        self.c.setI(i)

    def changeD(self, d):
        d /= 1000
        self.lbl_d.setText("D = {0}".format(d))
        self.c.setD(d)

    def startStop(self):
        if self.timer.isActive():
            self.timer.stop()
            self.button_start.setText('Continue')
        else:
            self.timer.start(100, self)
            self.button_start.setText('Stop')

    def restart(self):
        self.timer.stop()
        self.button_start.setText('Start')
        p = self.c.P
        i = self.c.I
        d = self.c.D
        self.c = Controller()
        self.c.setP(p)
        self.c.setI(i)
        self.c.setD(d)
        self.canvas.plot( [self.c.oven.temperature for i in range(2)])

    def timerEvent(self, e):
        self.c.timeStep()
        self.canvas.plot( self.c.data )

#
# A canvas widget which will be redrawn after each time step to animate the temperature change.
#

class PlotCanvas(FigureCanvas):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self,
                QSizePolicy.Expanding,
                QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

    def plot(self, data):
        self.axes.clear()
        self.axes.set_title("Temperature over Time")
        self.axes.set_xlabel("Time (A.U.)")
        self.axes.set_ylabel("Temperature (°C)")
        self.axes.plot( data )
        self.axes.plot([0,len(data)-1],[25,25])
        self.draw()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = PIDdrawer()
    sys.exit(app.exec_())


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

import argparse
import os
import pandas as pd
import re
import sys

# * text preprocessing steps in order:
# 1. strip
# 2. CHAR_FILTER sub
# 3. lowercasing
# 4. space collapsing

CHAR_FILTER = {
    # part 1: invisible/unprintable characters(mostly)
    '\x7f': '',     # (DEL -> '')
    '\x87': '',     # ('‡' -> '')
    '\xa0': ' ',    # (NBSP -> space)
    '\xad': '',     # (soft hyphen -> '')
    '\u115f': '',   # (hangul choseong filler -> '')
    '\u200b': '',   # (zero width space -> '')
    '\u200e': '',   # (left-to-right mark -> '')
    '\u202a': '',   # (left-to-right embedding -> '')
    '\u202c': '',   # (pop directional formatting -> '')
    '\u202d': '',   # (left-to-right override -> '')
    '\u2116': '',   # (№(numero) -> '')
    '\u3000': ' ',  # (ideographic space -> ' ')
    '\u302e': '',   # (HANGUL SINGLE DOT TONE MARK -> '')
    '\u3164': '',   # (hangul filler -> '')
    '\ufe0f': '',   # ('࿾' -> '')
    '\ufeff': '',   # (ZERO WIDTH NO-BREAK SPACE/BYTE ORDER MARK -> '')
    # part 2: non-ascii/non-alphanumeric characters(visible mostly)
    '˙': ' ',
    '˜': '~',
    '˝': '"',
    '̊': '˚',
    '·': '·',
    '‐': '-',
    '‑': '-',
    '–': '-',
    '—': '-',
    '―': '-',
    '‘': '\'',
    '’': '\'',
    '“': '"',
    '”': '"',
    '•': '·',
    '․': '·',
    '…': '..',
    '‧': '·',
    '‰': '%',
    '′': '\'',
    '″': '"',
    '‵': '\'',
    '⁄': '/',
    '₁': '1',
    '₂': '2',
    '₃': '3',
    '→': '->',
    '∕': '/',
    '∙': '·',
    '∪': 'U',
    '∼': '~',
    '≪': '<',
    '≫': '>',
    'ⓛ': '(1)',
    '┃': '|',
    '□': 'O',
    '○': 'o',
    '★': '*',
    '☆': '*',
    '♥': '♡',
    '➡': '->',
    '⟪': '<',
    '⟫': '>',
    '〃': '"',
    '〈': '<',
    '〉': '>',
    '《': '<',
    '》': '>',
    '「': '<',
    '」': '>',
    '『': '<',
    '』': '>',
    '【': '<',
    '】': '>',
    '〔': '[',
    '〕': ']',
    '〜': '~',
    '゜': '°',
    '・': '·',
    '㈔': '(사)',
    '㈜': '(주)',
    '㍱': 'hPa',
    '㎃': 'mA',
    '㎈': 'cal',
    '㎉': 'kcal',
    '㎎': 'mg',
    '㎏': 'kg',
    '㎐': 'Hz',
    '㎑': 'kHz',
    '㎒': 'MHZ',
    '㎓': 'GHz',
    '㎔': 'THz',
    '㎖': 'ml',
    '㎗': 'dl',
    '㎘': 'kl',
    '㎚': 'nm',
    '㎜': 'mm',
    '㎝': 'cm',
    '㎞': 'km',
    '㎟': 'sq mm',
    '㎠': 'sq cm',
    '㎡': 'sq m',
    '㎢': 'sq km',
    '㎥': 'cube m',
    '㎧': 'm/s',
    '㎨': 'm/sq s',
    '㎩': 'Pa',
    '㎫': 'MPa',
    '㎳': 'ms',
    '㎷': 'mV',
    '㎸': 'kV',
    '㎽': 'mW',
    '㎾': 'kW',
    '㎿': 'MW',
    '㏃': 'Bq',
    '㏄': 'cc',
    '㏈': 'dB',
    '㏊': 'hs',
    '㏏': 'kt',
    '％': '%',
    '＆': '&',
    '＋': '+',
    '，': ',',
    '－': '-',
    '．': '.',
    '３': '3',
    '：': ':',
    '＜': '<',
    '＞': '>',
    '？': '?',
    '～': '~',
    '｢': '<',
    '｣': '>',
    '･': '·',
    '￡': '£',
    '￦': '₩',
    # part 3: highly unlikely/useless by the corpus
    'ˈ': '',
    '¨': '',
    '«': '<',
    '»': '>',
    '¬': '-',
    'ː': ':',
    '¹': '1',
    '²': '2',
    '³': '3',
    '´': '\'',
    '¼': '1/4',
    '¾': '3/4',
    '÷': '/',
    'ʻ': '',
    'ㆍ': '·'
}

def main(excel_dir, corpus_dir, ko_corpus_name, en_corpus_name):
    # TODO refactoring
    rep = dict((re.escape(k), v) for k, v in CHAR_FILTER.items())
    pattern = re.compile('|'.join(rep.keys()))
    pattern2 = re.compile('[ ]{2,}')  # pattern for consecutive spaces
    exl2df = {}
    for file_name in sorted(os.listdir(excel_dir)):
        if not file_name.endswith('.xlsx'):
            continue
        exl2df[file_name] = pd.read_excel(excel_dir + '/' + file_name,
                                          usecols=['원문', '번역문'])
        print('{:<50s}{}'.format(file_name, exl2df[file_name].shape))
    ko_lines = []
    en_lines = []
    for file_name in sorted(exl2df.keys()):
        tmpdf = exl2df[file_name]
        ko_lines.extend(
            [pattern.sub(lambda m: rep[re.escape(m.group(0))], line.strip())
             for line in list(tmpdf[tmpdf.columns[0]])])
        en_lines.extend(
            [pattern.sub(lambda m: rep[re.escape(m.group(0))], line.strip())
             for line in list(tmpdf[tmpdf.columns[1]])])
    if len(ko_lines) != len(en_lines):
        print('[ERROR] (main) counts of lines in ko/en corpus are different!')
        sys.exit(1)
    ko_outf = open(corpus_dir + '/' + ko_corpus_name, 'wt')
    en_outf = open(corpus_dir + '/' + en_corpus_name, 'wt')
    ko_outf.write(pattern2.sub(' ', ('\n'.join(ko_lines)).lower()))
    en_outf.write(pattern2.sub(' ', ('\n'.join(en_lines)).lower()))
    ko_outf.close()
    en_outf.close()
    del exl2df, ko_lines, en_lines

if __name__ == '__main__':
    print('[' + __file__ + '] main invoked')

    AP = argparse.ArgumentParser(description='args parser')
    AP.add_argument('-excel_dir', action='store', required=True,
                    help='path to AI Hub Ko/En bilingual excel files')
    AP.add_argument('-corpus_dir', action='store', required=True,
                    help='path to parsed Ko/En monolingual corpus files')
    AP.add_argument('-ko_corpus_name', action='store', default='ko.txt',
                    help='Korean corpus file name')
    AP.add_argument('-en_corpus_name', action='store', default='en.txt',
                    help='English corpus file name')
    ARGS = AP.parse_args()

    main(ARGS.excel_dir, ARGS.corpus_dir, ARGS.ko_corpus_name,
         ARGS.en_corpus_name)


import gc
import sys
from threading import Thread
import traceback
from types import ModuleType
from copy import copy

import nbformat

from plotolo.script.script_context import set_run_context, RunContext, get_run_context, SessionContext
from plotolo.script.script_storage import ScriptStorage
from plotolo.util.constant import PLOTOLO_SCRIPT_THREAD_PREFIX
from plotolo.util.logging import SessionLogger
from plotolo.script.script_info import ScriptInfo
from plotolo.script.script_status import ScriptStatus, ScriptState
from plotolo.session.widget_state import CellInfo
from plotolo.util.util import to_json
from plotolo.widget.common import StopExecutionException

class ScriptRunner:
    """
    Executes the Notebook's cells on low-level and in a separate thread and in a persistent namespace.
    Sends events to the SessionHandler.
    """
    def __init__(self, script_id: str, session_context: SessionContext, on_script_error, on_script_started,
                 on_script_finished, on_script_stopped, on_cell_started, on_cell_finished):
        self.session_context: SessionContext = session_context
        self.script_info: ScriptInfo = ScriptStorage.get_current().get(script_id)
        self.script_state: ScriptState = ScriptState()

        self.script_module: ModuleType | None = None
        self.script_thread: Thread | None = None

        self.on_script_error = on_script_error
        self.on_script_started = on_script_started
        self.on_script_stopped = on_script_stopped
        self.on_script_finished = on_script_finished
        self.on_cell_started = on_cell_started
        self.on_cell_finished = on_cell_finished

        self.script_run_index = -1

        self.logger = SessionLogger.getLogger(session_context.session_id)

    def get_run_context(self):
        return get_run_context(self.script_thread)

    def _setup_script_module(self):
        """
        Creates a new module for the script and sets it as the main module.
        Used for a persistent namespace between reruns.
        Should be called from the script thread.
        """
        self.logger.debug('Setting up script module:', self.script_info.id)

        module = ModuleType("__main__")
        module.__file__ = self.script_info.filename
        module.__loader__ = self
        sys.modules["__main__"] = module
        self.script_module = module

    def _should_rerun(self, cell_indexes_to_rerun=None):
        """
        Checks if the script should be rerun or it can be skipped.
        If the current script execution covers to new request, it can be skipped,
        otherwise it should be rerun.
        """
        if cell_indexes_to_rerun is None:
            return True

        if not self.script_thread or not self.script_thread.is_alive():
            return True

        if self.script_state.status == ScriptStatus.STOPPED:
            return True

        if self.get_run_context().cell_info.cell_index >= min(cell_indexes_to_rerun):
            self.get_run_context().rerun = True
            return True

        return False

    def run(self, cell_indexes_to_rerun: [int] = None):
        """
        Runs the script in a separate thread and with its context.
        """
        if not self._should_rerun(cell_indexes_to_rerun):
            self.logger.debug('Rerun skipped')
            return

        self.logger.debug('Starting thread...')
        self.script_run_index += 1
        thread_run_context = self.init_run_context()

        self.script_thread = Thread(
            target=self._execute_script_thread,
            name=f"{PLOTOLO_SCRIPT_THREAD_PREFIX}:{self.script_info.name}:{self.session_context.session_id}:{self.script_run_index}",
            args=[thread_run_context, cell_indexes_to_rerun]
        )
        self.script_thread.start()
        setattr(self.script_thread, RunContext.RUN_CONTEXT_ATTR, thread_run_context)

        # self.script_thread.join()  # only for debug purposes!
        # print_module(self.script_module)  # only for debug purposes!

    def init_run_context(self):
        return RunContext(self.session_context, CellInfo(script_run_index=self.script_run_index))

    def before_cell_exec(self, cell):
        """
        Sets the cell info in the run context.
        """
        context = self.get_run_context()
        context.cell_info.cell_index = cell.index
        context.cell_info.cell_id = cell.id
        context.cell_info.widget_index = 0
        context.cell_info.script_run_index = self.script_run_index

        if self.on_cell_started:
            self.on_cell_started(context.cell_info)

    def after_cell_exec(self):
        gc.collect()
        if self.on_cell_finished:
            self.on_cell_finished(copy(self.get_run_context().cell_info))

    def script_started(self, cell_indexes_to_rerun: [int]):
        self.script_state.status = ScriptStatus.RUNNING
        if self.on_script_started:
            self.on_script_started(cell_indexes_to_rerun)

    def script_finished(self):
        if not self.get_run_context().rerun:
            self.script_state.status = ScriptStatus.STOPPED
            if self.on_script_finished:
                self.on_script_finished()

    def script_error(self, error_msg):
        self.script_state.errors.append(error_msg)
        self.logger.error('Error:', error_msg, '- Cell info:', to_json(self.get_run_context().cell_info))
        if self.on_script_error:
            self.on_script_error()

    def _execute_script_thread(self, thread_run_context: RunContext, cell_indexes_to_rerun: [int] = None):
        """
        Executes the Notebook's cells in a loop and sends events.
        """
        if not self.script_module:
            self._setup_script_module()

        if not cell_indexes_to_rerun:
            # if not set, run all cells
            cell_indexes_to_rerun = list(range(self.script_info.n_cells))

        set_run_context(thread_run_context)

        self.script_started(cell_indexes_to_rerun)

        self.logger.debug('Running cells :', ', '.join(str(idx) for idx in cell_indexes_to_rerun))
        try:
            for cell_index in cell_indexes_to_rerun:
                cell = self.script_info.compiled_cells[cell_index]

                self.logger.debug(f'Executing cell: {cell.index}')
                self.before_cell_exec(cell)

                exec(cell.code, self.script_module.__dict__)

                if thread_run_context.rerun:
                    self.logger.debug('Script stopped for rerun')
                    return

                self.after_cell_exec()

        except StopExecutionException as e:
            self.logger.debug('Script ran and stopped successfully')
            self.on_script_stopped(e.clear_all_outputs_bellow)
        except Exception as e:
            self.logger.error('Script error occurred:', traceback.format_exc())
            self.script_error(repr(e)),
        else:
            self.logger.debug('Script ran successfully')
        finally:
            self.script_finished()

# Investigate:
#   nbclient: https://nbclient.readthedocs.io/en/latest/reference/nbclient.html
#   IPython InteractiveShell: https://ipython.readthedocs.io/en/stable/api/generated/IPython.core.interactiveshell.html


from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Border Relief Types')
root.resizable(0, 0)
root.config(bg='#25D366')
def center_window(w, h):
    ws = root.winfo_screenwidth()
    hs = root.winfo_screenheight()
    x = (ws/2) - (w/2)
    y = (hs/2) - (h/2)
    root.geometry('%dx%d+%d+%d' % (w, h, x, y))
center_window(200, 260)
label01 = Label(root, text='Relief = Flat', bg='#E50914')
label01.config(borderwidth=5, relief='flat')
label02 = Label(root, text='Relief = Groove', bg='#E50914')
label02.config(borderwidth=10, relief='groove')
label03 = Label(root, text='Relief = Raised', bg='#E50914')
label03.config(borderwidth=10, relief='raised')
label04 = Label(root, text='Relief = Ridge', bg='#E50914')
label04.config(borderwidth=10, relief='ridge')
label05 = Label(root, text='Relief = Solid', bg='#E50914')
label05.config(borderwidth=5, relief='solid')
label06 = Label(root, text='Relief = Sunken', bg='#E50914')
label06.config(borderwidth=10, relief='sunken')
label01.grid(row=0, column=0, sticky=W, pady=2)
label02.grid(row=1, column=0, sticky=W, pady=2)
label03.grid(row=2, column=0, sticky=W, pady=2)
label04.grid(row=3, column=0, sticky=W, pady=2)
label05.grid(row=4, column=0, sticky=W, pady=2)
label06.grid(row=5, column=0, sticky=W, pady=2)
root.mainloop()


#!/usr/bin/env python

import sys
import os.path
import matplotlib.pyplot as plt
import matplotlib.image as matImg
import argparse
import cv2
import serial
from pylab import *
from PIL import Image
from natsort import natsorted, ns
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt, Slot, Signal, QThread
from PySide2.QtWidgets import QApplication, QMainWindow, QPushButton
from PySide2.QtGui import QPen, QPixmap
import pylisten
import sliceViewer
from mainGUI import Ui_MainWindow
from threading import Event
from arduinoControl import ControlArduino

# global variable
encoder_reading = 0.0
start = 0.0
flag = 0
previous_time = 1e-10

# custom event for handling change in freeze state
class FreezeEvent(QtCore.QEvent):
    def __init__(self, frozen):
        super().__init__(QtCore.QEvent.User)
        self.frozen = frozen

# custom event for handling button presses
class ButtonEvent(QtCore.QEvent):
    def __init__(self, btn, clicks):
        super().__init__(QtCore.QEvent.Type(QtCore.QEvent.User + 1))
        self.btn = btn
        self.clicks = clicks

# custom event for handling new images
class ImageEvent(QtCore.QEvent):
    def __init__(self):
        super().__init__(QtCore.QEvent.Type(QtCore.QEvent.User + 2))

# manages custom events posted from callbacks, then relays as signals to the main widget
class Signaller(QtCore.QObject):
    freeze = QtCore.Signal(bool)
    button = QtCore.Signal(int, int)
    image = QtCore.Signal(QtGui.QImage)

    def __init__(self):
        QtCore.QObject.__init__(self)
        self.usimage = QtGui.QImage()

    def event(self, evt):
        if evt.type() == QtCore.QEvent.User:
            self.freeze.emit(evt.frozen)
        elif evt.type() == QtCore.QEvent.Type(QtCore.QEvent.User + 1):
            self.button.emit(evt.btn, evt.clicks)
        elif evt.type() == QtCore.QEvent.Type(QtCore.QEvent.User + 2):
            self.image.emit(self.usimage)
        return True

# global required for the listen api callbacks
signaller = Signaller()

# draws the ultrasound image
class ImageView(QtWidgets.QGraphicsView):
    def __init__(self, listen):
        QtWidgets.QGraphicsView.__init__(self)
        self.listen = listen
        self.setScene(QtWidgets.QGraphicsScene())

    # set the new image and redraw
    def updateImage(self, img):
        self.image = img
        self.scene().invalidate()

    # resize the scan converter, image, and scene
    def resizeEvent(self, evt):
        w = evt.size().width()
        h = evt.size().height()
        self.listen.setOutputSize(w, h)
        self.image = QtGui.QImage(w, h, QtGui.QImage.Format_ARGB32)
        self.image.fill(QtCore.Qt.black);
        self.setSceneRect(0, 0, w, h)

    # black background
    def drawBackground(self, painter, rect):
        painter.fillRect(rect, QtCore.Qt.black)

    # draws the image
    def drawForeground(self, painter, rect):
        if not self.image.isNull():
            painter.drawImage(rect, self.image)

#draws sliceViewer plots
class MplGraphics(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        QtWidgets.QGraphicsView.__init__(self, parent)

        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)

        vertical_layout = QtWidgets.QVBoxLayout()
        vertical_layout.addWidget(self.canvas)

        self.canvas.axes = self.figure.subplots()
        self.canvas.axes.index = 15 #should be 0
        self.canvas.axes.set_title('Ultrasound Slice Viewer')
        self.canvas.axes.set_xlabel('Image Number: 0')
        self.setLayout(vertical_layout)

    def setVol(self, volume):
        # sliceViewer.remove_keymap_conflicts({'j', 'k'})
        self.canvas.axes.volume = volume
        self.canvas.axes.imshow(volume[self.canvas.axes.index])
        self.canvas.draw()
        self.canvas.mpl_connect('key_press_event', self.process_key)

    def process_key(self, event):
        print('nuggets')
        ax = self.canvas.axes.volume[15]
        if event.key == 'j':
            sliceViewer.previous_slice(ax)
        elif event.key == 'k':
            sliceViewer.next_slice(ax)
        self.canvas.draw()

# Plots 3d surface plot
class MplCanvas(FigureCanvas):
    def __init__(self, parent=None, width=6, height=5):
        fig = Figure(figsize=(width,height))
        self.axes = fig.add_subplot(111, projection='3d')
        super(MplCanvas, self).__init__(fig)

    # def displaySet(self, list):

class Mpl3DPlot(FigureCanvas):
    def __init__(self, init_image):
        # plt.ion()
        self.fig = Figure(figsize=(10,9))
        self.ax = self.fig.add_subplot(111, projection='3d')
        self.ax.set_xlim3d(0, 480) #650
        self.ax.set_ylim3d(-200, 200)
        self.ax.set_zlim3d(0, 410) #490
        self.ax.view_init(190, 45)
        self.rows = init_image.shape[0]
        self.cols = init_image.shape[1]
        self.mat = cv2.getRotationMatrix2D((100, 100), 0, 1)
        self.new_img = cv2.warpAffine(init_image, self.mat, (self.cols, self.rows))
        self.y_new, self.x_new = ogrid[0:self.new_img.shape[0], 0:self.new_img.shape[1]]
        self.y_diff = np.multiply(self.y_new, 0)
        self.surf_plot = self.ax.plot_surface(self.x_new, self.y_diff, self.y_new, rstride=10, cstride=10,
                                              facecolors=init_image)
        super(Mpl3DPlot, self).__init__(self.fig)
        # plt.draw()

    def update_plot(self, updated_image, deg_rot):
        self.surf_plot.remove()
        # plt.pause(5)
        # self.ax.cla()
        # self.ax.set_xlim3d(0, 480) #650
        # self.ax.set_ylim3d(-200, 200)
        # self.ax.set_zlim3d(0, 410) #490
        self.rows = updated_image.shape[0]
        self.cols = updated_image.shape[1]
        self.mat = cv2.getRotationMatrix2D((100, 100), deg_rot, 1)
        self.new_img = cv2.warpAffine(updated_image, self.mat, (self.cols, self.rows))
        self.y_new, self.x_new = ogrid[0:self.new_img.shape[0], 0:self.new_img.shape[1]]
        self.y_diff = np.multiply(self.y_new, deg_rot)
        self.surf_plot = self.ax.plot_surface(self.x_new, self.y_diff, self.y_new, rstride=35, cstride=35, facecolors=updated_image)
        # self.surf_plot = self.ax.plot_surface(self.x_new, self.y_diff, self.y_new, rstride=10, cstride=10)
        # facecolors=updated_image)
        # plt.draw()
        self.fig.canvas.draw()
        # self.fig.canvas.flush_events()
        plt.pause(0.01)

class MainWindow(QMainWindow):
    def __init__(self, listen):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.listen = listen

        #Encoder Graphic and esp setup
        # pen = QPen(Qt.red)
        # pen.setWidth(3)
        # pen.setCapStyle(Qt.RoundCap)
        # scene = QtWidgets.QGraphicsScene()
        # pen.setCosmetic(True)
        # scene.addPixmap(QPixmap('back.png'))
        # self.item = scene.addLine(60, 170, 97, 97, pen)
        # pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.gray))
        # brush = QtGui.QBrush(pen.color().darker(100))
        # scene.addEllipse(87, 87, 20, 20, pen, brush)
        # self.item.setTransformOriginPoint(97, 97)
        # self.ui.graphicsView.setScene(scene)

        self.stop_flag_time = Event()
        self.stop_flag_RS232 = Event()

        self.getArduino = ControlArduino(self.stop_flag_RS232)
        self.getArduino.newValue.connect(self.updateEncoder)
        self.getArduino.testRS232.connect(self.updateInfoESP32)
        self.getArduino.start()
        #Encoder graphic and esp setup

        # self.ui.pushButton.clicked.connect(self.sliceMethod)
        self.addToolBar(NavigationToolbar(self.ui.MplGraphics.canvas, self))

        # setting placeholder text and mask for IP and Port in Live Viewer
        self.ui.ip.setPlaceholderText("192.168.1.1")
        self.ui.ip.setInputMask("000.000.000.000")
        self.ui.port.setPlaceholderText("58285")
        self.ui.port.setInputMask("00000")

        # setting placeholder text and mask for IP and Port in Slice Viewer
        self.ui.ip2.setPlaceholderText("192.168.1.1")
        self.ui.ip2.setInputMask("000.000.000.000")
        self.ui.port2.setPlaceholderText("58285")
        self.ui.port2.setInputMask("00000")

        # try to connect/disconnect to/from the probe
        def tryConnect():
            if not listen.isConnected():
                if listen.connect(self.ui.ip.text(), int(self.ui.port.text())):
                    self.statusBar().showMessage("Connected")
                    self.ui.connect.setText("Disconnect")
                else:
                    self.statusBar().showMessage("Failed to connect to {0}".format(self.ui.ip.text()))
                    self.ui.connect.setText("Retry")
            else:
                if listen.disconnect():
                    self.statusBar().showMessage("Disconnected")
                    self.ui.connect.setText("Connect")
                else:
                    self.statusBar().showMessage("Failed to disconnect")

        self.ui.connect.clicked.connect(tryConnect)
        self.ui.Quit.clicked.connect(self.shutdown)

        # add widgets to layout
        self.img = ImageView(listen)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.img)
        self.ui.liveStr.setLayout(layout)

        # images slices in 3d view with angle info
        self.path = "/home/amalik/Documents/listener/src/python/sample_img/"
        self.list_files = os.listdir(self.path)  # looking for files in current directory
        self.list_files = natsorted(self.list_files)  # sort list of images in order of timestamp
        self.img_list = []

        for file in self.list_files:
            try:
                # read in image as numpy array
                pltImage = matImg.imread(self.path + file)
                # Crop out 64 rows off the top of the image (remove top 13.33% of image)
                croppedImage = pltImage[64:, :]
                self.img_list.append(croppedImage)
            except (IOError, SyntaxError) as e:
                print('Bad file:', file)

        #add Mpl3DPlot to view3d QWidget
        plt.ion()
        self.sc = Mpl3DPlot(self.img_list[0])
        surfaceLayout = QtWidgets.QVBoxLayout()
        surfaceLayout.addWidget(self.sc)
        self.ui.view3d.setLayout(surfaceLayout)

        # connect signals
        signaller.freeze.connect(self.freeze)
        signaller.button.connect(self.button)
        signaller.image.connect(self.image)

        # get home path
        path = os.path.expanduser("~/")
        if  listen.init(path, 640, 480):
            self.statusBar().showMessage("Initialized")
        else:
            self.statusBar().showMessage("Failed to initialize")

    # Slots to update encoder readings and esp32 info
    @Slot()
    def on_btnExit_clicked(self):
        self.stop_flag_time.set()
        self.stop_flag_RS232.set()
        sys.exit(0);

    def updateEncoder(self, poti, potiRotation):
        # self.item.setRotation(potiRotation)
        int_reading = int(poti)
        # int_reading = int_reading*2
        global encoder_reading
        if int_reading >= 0:
            encoder_reading = (int_reading/50)*-1
        else:
            # int_reading = int_reading-360
            encoder_reading = (int_reading/50)*-1
        # else:
        #     encoder_reading = 0     (150)
        self.ui.lcdNumber.display(str(int_reading))

    def updateInfoESP32(self, rs232):
        print(rs232)
        if rs232:
            print("Board is connected")
        else:
            print("Board is not connected")
            self.ui.lcdNumber.display(0)
            self.stop_flag_RS232.set()

    # handles freeze messages
    @Slot(bool)
    def freeze(self, frozen):
        if frozen:
            self.statusBar().showMessage("Image Stopped")
        else:
            self.statusBar().showMessage("Image Running")

    # handles button messages
    @Slot(int, int)
    def button(self, btn, clicks):
        self.statusBar().showMessage("Button {0} pressed w/ {1} clicks".format(btn, clicks))

    # handles new images
    @Slot(QtGui.QImage)
    def image(self, img):
        self.img.updateImage(img)
        img_arr = QImageToNumpyArray(img)
        img_arr = img_arr / 255
        # shape: (401, 471, 4)
        croppedImage = img_arr[70:, :]
        self.sc.update_plot(croppedImage, encoder_reading)
        # image type: QtGui.QImage

    # handles shutdown
    @Slot()
    def shutdown(self):
        self.listen.destroy()
        QtWidgets.QApplication.quit()

    # def sliceMethod(self):

    #     path = "/home/amalik/Documents/listener/src/python/slice_data/"

    #     list_files = os.listdir(path)  # looking for files in current directory
    #     list_files = natsorted(list_files) #sort list of images in order of timestamp

    #     img_list = []

    #     for filename in list_files:
    #         if filename.endswith('.png'):
    #             try:
    #                 # img.verify()  # verify that it is, in fact an image
    #                 img = matImg.imread(path + filename)
    #                 img_list.append(img)
    #             except (IOError, SyntaxError) as e:
    #                 print('Bad file:', filename)
    #                 os.remove(path+filename)

    #     self.ui.MplGraphics.setVol(img_list) #run images with sliceviewer
    #     plt.show()

        # self.ui.MplWidget.canvas.axes.clear()
        # self.ui.MplWidget.canvas.axes.set_title('Fried Chicken')
        # self.ui.MplWidget.canvas.draw()

def QImageToNumpyArray(incoming_img):
    # print(incoming_img.format())
    incoming_img = incoming_img.convertToFormat(QtGui.QImage.Format.Format_ARGB32)
    width = incoming_img.width()
    height = incoming_img.height()
    ptr = incoming_img.constBits()
    arr = np.array(ptr).reshape(height, width, 4)  #  Copies the data
    return arr

## called when a new processed image is streamed
# @param image the scan-converted image data
# @param width width of the image in pixels
# @param height height of the image in pixels
# @param bpp bits per pixel
# @param micronsPerPixel microns per pixel
# @param timestamp the image timestamp in nanoseconds
def newProcessedImage(image, width, height, bpp, micronsPerPixel, timestamp, imu):
    img = QtGui.QImage(image, width, height, QtGui.QImage.Format_ARGB32)
    # a deep copy is important here, as the memory from 'image' won't be valid after the event posting
    signaller.usimage = img.copy()
    evt = ImageEvent()
    QtCore.QCoreApplication.postEvent(signaller, evt)

    # uncomment to collect data v
    global start
    global positional_data
    global previous_time
    # global encoder_reading

    if(start == 0.0):
        start = np.round_((timestamp/1e+9), decimals = 3)

    # img = Image.frombytes('L', (width, height), image)
    if bpp == 32:
        img = Image.frombytes('RGBA', (width, height), image)
    else:
        img = Image.frombytes('L', (width, height), image)

    time_frame = abs(np.round_((timestamp/1e+9 - start), decimals = 3))
    path_img = "/home/amalik/Documents/listener/src/python/slice_data/" + f"{time_frame}{encoder_reading}.png"
    img.save(path_img)
    # uncomment to collect data ^
    return

## called when a new raw image is streamed
# @param image the raw pre scan-converted image data, uncompressed 8-bit or jpeg compressed
# @param lines number of lines in the data
# @param samples number of samples in the data
# @param bps bits per sample
# @param axial microns per sample
# @param lateral microns per line
# @param timestamp the image timestamp in nanoseconds
# @param jpg jpeg compression size if the data is in jpeg format
def newRawImage(image, lines, samples, bps, axial, lateral, timestamp, jpg):
    return

# Called when new processed image is streamed. Saves individual images with time frame
# def newProcessedSlice(image, width, height, bpp, micronsPerPixel, timestamp, imu):
#     print("new image (sc): {0}, {1}x{2} @ {3} bpp, {4:.2f} um/px, imu: {5} pts".format(timestamp, width, height, bpp, micronsPerPixel, len(imu)))
#     global start
#     global positional_data
#     global previous_time

#     if(start == 0.0):
#         start = np.round_((timestamp/1e+9), decimals = 3)

#     # img = Image.frombytes('L', (width, height), image)
#     if bpp == 32:
#         img = Image.frombytes('RGBA', (width, height), image)
#     else:
#         img = Image.frombytes('L', (width, height), image)

#     time_frame = abs(np.round_((timestamp/1e+9 - start), decimals = 3))

#     # /********************************************
#     # for raw imu data:
#     imu_data = imu_data_processing(imu, len(imu))
#     write_to_csv(imu_data,time_frame,previous_time)

#     # ********************************************/
#     previous_time = time_frame
#     # /********************************************
#     # for positional data:
#     # position_data = positional_data_processing(imu_data)
#     # write_to_csv(position_data,time_frame)
#     # ********************************************/

#     path_img = "/home/amalik/Documents/listener/src/python/slice_data/" + f"{time_frame}.png"
#     img.save(path_img)
#     return

# ## called when a new raw image is streamed
# # @param image the raw pre scan-converted image data, uncompressed 8-bit or jpeg compressed
# # @param lines number of lines in the data
# # @param samples number of samples in the data
# # @param bps bits per sample
# # @param axial microns per sample
# # @param lateral microns per line
# # @param timestamp the image timestamp in nanoseconds
# # @param jpg jpeg compression size if the data is in jpeg format
# def newRawSlice(image, lines, samples, bps, axial, lateral, timestamp, jpg):
#     print("new image (ps): {0}, {1}x{2} @ {3} bps, {4:.2f} um/s, {5:.2f} um/l".format(timestamp, lines, samples, bps, axial, lateral))
#     if jpg == 0:
#         img = Image.frombytes('L', (samples, lines), image, "raw")
#     else:
#         # note! this probably won't work unless a proper decoder is written
#         img = Image.frombytes('L', (samples, lines), image, "jpg")
#     img.save("raw_image.jpg")
#     return

## called when freeze state changes
# @param frozen the freeze state
def freezeFn(frozen):
    evt = FreezeEvent(frozen)
    QtCore.QCoreApplication.postEvent(signaller, evt)
    return

## called when a button is pressed
# @param button the button that was pressed
# @param clicks number of clicks performed
def buttonsFn(button, clicks):
    evt = ButtonEvent(button, clicks)
    QtCore.QCoreApplication.postEvent(signaller, evt)
    return

def main():
    path = os.path.expanduser("~/")
    listen = pylisten.Listener(newProcessedImage, newRawImage, freezeFn, buttonsFn)
    # listenSlice = pylisten.Listener(newProcessedSlice, newRawSlice, freezeFn, buttonsFn)
    app = QApplication(sys.argv)
    window = MainWindow(listen)
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

# to convert ui to py file
    # pyside2-uic -x /home/amalik/Documents/listener/src/python/mainGUI.ui -o mainGUI.py

# Edit needed when update mainGUI.py
    # from clariusGUI import MplGraphics

# Clarius network password:
    # xdOmUnr0

# self.ui.pushButton.clicked.connect(self.clickedMethod)

# def sliceMethod(self):
#         print('Clicked Push Button')
#         os.system('python sliceViewer.py')


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import os
import sys
import tarfile

from six.moves import urllib
import tensorflow as tf
import skimage.io

from lxml import etree
from utils.check_sum import file_md5_check

DATA_URL = 'http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar'
MD5_SUM = '6cd6e144f989b92b3379bac3b3de84fd'

parser = argparse.ArgumentParser()

parser.add_argument(
    '--data_dir', type=str,
    default=os.environ.get('TF_DATA_DIR', '/tmp/pascal_voc_data'),
    help='Directory to download data and extract the tarball')

def file_info(tar_file_obj, predicate):
    for info in tar_file_obj:
        if predicate(info.name):
            return info

def examples_in_tar_file(tar_file_obj, records):
    for index, record in enumerate(records):
        annotation_info = file_info(tar_file_obj,
                                    lambda name: ('%s.xml' % record) in name)
        with tar_file_obj.extractfile(annotation_info) as fo:
            xml_content = fo.read()

        annotation_xml = etree.fromstring(xml_content)
        image_filename = annotation_xml.xpath('/annotation/filename/text()')

        image_width = annotation_xml.xpath('/annotation/size/width/text()')
        image_height = annotation_xml.xpath('/annotation/size/height/text()')
        image_depth = annotation_xml.xpath('/annotation/size/depth/text()')

        objects_name = annotation_xml.xpath('/annotation/object/name')

        bbox_xmin = annotation_xml.xpath('/annotation/object/bndbox/xmin/text()')
        bbox_ymin = annotation_xml.xpath('/annotation/object/bndbox/ymin/text()')
        bbox_xmax = annotation_xml.xpath('/annotation/object/bndbox/xmax/text()')
        bbox_ymax = annotation_xml.xpath('/annotation/object/bndbox/ymax/text()')

        image_info = file_info(tar_file_obj,
                               lambda name: ('JPEGImages/%s' % image_filename[0]) in name)

        with tar_file_obj.extractfile(image_info) as fo:
            image = skimage.io.imread(fo)

        image_feature = tf.train.Feature(bytes_list=tf.train.BytesList(value=[
            image.tobytes()
        ]))
        image_shape_feature = tf.train.Feature(int64_list=tf.train.Int64List(value=[
            int(image_height[0]),
            int(image_width[0]),
            int(image_depth[0]),
        ]))
        objects_feature = tf.train.Feature(bytes_list=tf.train.BytesList(value=[
            x.text.encode('utf-8') for x in objects_name
        ]))

        bbox_xmin_feature = tf.train.Feature(int64_list=tf.train.Int64List(value=[
            int(x) for x in bbox_xmin
        ]))
        bbox_xmax_feature = tf.train.Feature(int64_list=tf.train.Int64List(value=[
            int(x) for x in bbox_xmax
        ]))
        bbox_ymin_feature = tf.train.Feature(int64_list=tf.train.Int64List(value=[
            int(x) for x in bbox_ymin
        ]))
        bbox_ymax_feature = tf.train.Feature(int64_list=tf.train.Int64List(value=[
            int(x) for x in bbox_ymax
        ]))

        example = tf.train.Example(features=tf.train.Features(
            feature={
                'image': image_feature,
                'image/shape': image_shape_feature,
                'objects': objects_feature,
                'bbox/xmin': bbox_xmin_feature,
                'bbox/xmax': bbox_xmax_feature,
                'bbox/ymin': bbox_ymin_feature,
                'bbox/ymax': bbox_ymax_feature,
            }
        ))

        yield example
        print('>> Convert %d/%d' % (index, len(records)), end='\r')

def create_writer(subset):
    options = tf.python_io.TFRecordOptions(tf.python_io.TFRecordCompressionType.ZLIB)
    return tf.python_io.TFRecordWriter(
        os.path.join(FLAGS.data_dir, 'pascal_voc_{}.tfrecords'.format(subset)),
        options=options
    )

def main(_):
    """Download and convert the Pascal VOC dataset into TFRecord."""
    if not os.path.exists(FLAGS.data_dir):
        os.makedirs(FLAGS.data_dir)

    filename = DATA_URL.split('/')[-1]
    file_path = os.path.join(FLAGS.data_dir, filename)

    if not os.path.exists(file_path) or \
            not file_md5_check(file_path, MD5_SUM):

        def _progress(count, block_size, total_size):
            sys.stdout.write('\r>> Downloading %s %.1f%%' % (
                filename, 100.0 * count * block_size / total_size))
            sys.stdout.flush()

        file_path, _ = urllib.request.urlretrieve(DATA_URL, file_path, _progress)
        print()
        stat_info = os.stat(file_path)
        print('Successfully downloaded', filename, stat_info.st_size, 'bytes.')

    with tarfile.open(file_path, 'r') as tar_file_obj:
        for info in tar_file_obj:
            if 'ImageSets/Main/train.txt' in info.name:
                with tar_file_obj.extractfile(info) as fo:
                    train_files = [line.decode('utf-8').strip() for line in fo.readlines()]

                with create_writer('train') as writer:
                    example_count = 0
                    for example in examples_in_tar_file(tar_file_obj, train_files):
                        writer.write(example.SerializeToString())
                        example_count += 1

                    print('\nWrite %d examples to %s.tfrecords' % (
                        example_count, 'train'
                    ))

            if 'ImageSets/Main/val.txt' in info.name:
                with tar_file_obj.extractfile(info) as fo:
                    val_files = [line.decode('utf-8').strip() for line in fo.readlines()]

                with create_writer('validation') as writer:
                    example_count = 0
                    for example in examples_in_tar_file(tar_file_obj, val_files):
                        writer.write(example.SerializeToString())
                        example_count += 1

                    print('\nWrite %d examples to %s.tfrecords' % (
                        example_count, 'validation'
                    ))

if __name__ == '__main__':
    FLAGS, not_parsed = parser.parse_known_args()
    tf.app.run(argv=[sys.argv[0]] + not_parsed)


# receives 2 integers and returns the sum as an integer
def myAdd(a: int, b: int) -> int:
    sum_nums = a+b
    return sum_nums

# receives 2 integers and returns the quotient as an integer
def myDivide(a: int, b: int) -> int:
    quotient = int(a/b)
    return quotient

# receives 2 integers and returns the difference as an integer
def mySubtract(a: int, b: int) -> int:
    difference = a-b
    return difference

# receives 2 integers and returns the product as an integer
def myMultiply(a: int, b: int) -> int:
    product = a*b
    return product

# receives a list of operators and a list of numbers parsed from the user input and returns the final answer
def performCalculation(operators_list: list, numbers_list: list) -> int:
    operator_combo = "".join(operators_list)

    a, b, c = numbers_list[0], numbers_list[1], numbers_list[2]

    # created dictionary for the combinations of operators instead of 16 "if/elif/else" statements
    operations_dict = {
        "+-": mySubtract((myAdd(a, b)), c),
        "-+": myAdd((mySubtract(a, b)), c),
        "+/": myAdd(a, (myDivide(b, c))),
        "/+": myAdd((myDivide(a, b)), c),
        "+*": myAdd(a, (myMultiply(b, c))),
        "*+": myAdd((myMultiply(a, b)), c),
        "-/": mySubtract(a, (myDivide(b, c))),
        "/-": mySubtract((myDivide(a, b)), c),
        "*-": mySubtract((myMultiply(a, b)), c),
        "-*": mySubtract(a, (myMultiply(b, c))),
        "/*": myMultiply((myDivide(a, b)), c),
        "*/": myDivide((myMultiply(a, b)), c),
        "++": myAdd((myAdd(a, b)), c),
        "--": mySubtract((mySubtract(a, b)), c),
        "**": myMultiply((myMultiply(a, b)), c),
        "//": myDivide((myDivide(a, b)), c),
    }
    return operations_dict[operator_combo]

# Takes 2 lists, loops though them and concatenates the expression together and returns the output in string format
def displayUserExpression(list_of_numbers: list, list_of_operators: list, final_answer: list) -> str:
    final_output = ""

    for i in range(len(list_of_numbers)):
        final_output += f"{list_of_numbers[i]} {list_of_operators[i]} "

    final_output += f"\n{final_answer}"

    return final_output


from collections import namedtuple
from unittest.mock import MagicMock

import pytest

from momapper import MappedClass, Field
from momapper.types import StringType, IntType

class Example(MappedClass):
    name = Field("name", StringType)
    count = Field("count", IntType)

@pytest.fixture
def mocked_example(monkeypatch):
    MockedExample = namedtuple("MockedExample", "impl, made_doc, validated")
    with monkeypatch.context() as m:
        made_doc = object()
        m.setattr(Example, "make_document", MagicMock(return_value=made_doc))

        validated = object()
        m.setattr(Example, "validate", MagicMock(return_value=validated))
        yield MockedExample(impl=Example, made_doc=made_doc, validated=validated)

class Cop(MappedClass):
    name = Field("the_name", StringType)
    surname = Field("the_surname", StringType)
    skill_level = Field("skill_level", IntType, required=True, if_missing=0)


#строковые методы
pi = 3.15
print (str(pi))

"""Методы, которые используют точечную нотацию работают только со строками.
С другой стороны, Len () и Str () может работать и на других типах данных.
"""
ministry = "The Ministry of Silly Walks"
print(len(ministry))
print(ministry.upper())

#конкатенация строк
print("Spam " + "and " + "eggs")
#объединение строки с чем-то что не является строкой
print("The value of pi is around " + str(3.14))
#форматирование строк. Если вы хотите напечатать переменную со строкой, есть лучший способ, чем конкатенация строк вместе.
name = "Mike"
print("Hello %s" % (name))
string_1 = "Camelot"
string_2 = "place"
print("Let's not go to %s. 'Tis a silly %s." % (string_1, string_2))
#форматирование строк
"""name = input("What is your name?")
quest = input("What is your quest?")
color = input("What is your favorite color?")
print("Ah, so your name is %s, your quest is %s, " \
"and your favorite color is %s." % (name, quest, color))"""

###################### Date and time library
import datetime
from datetime import datetime
now = datetime.now()
print(now)
print(now.year)
print(now.month)
print(now.day)

print("Formatted date:", "%s-%s-%s" % (now.year, now.month, now.day))
print("Formatted time:", "%s:%s:%s" % (now.hour, now.minute, now.second))
print("Formatted datetime string:", "%s/%s/%s %s:%s:%s" % (now.month, now.day, now.year, now.hour, now.minute, now.second))

#### User inpit IF ELIF ELSE lesson
"""def clinic():
    print("You've just entered the clinic!")
    print("Do you take the door on the left or the right?")
    answer = input("Type left or right and hit 'Enter'.").lower()
    if answer == "left" or answer == "l":
        print("This is the Verbal Abuse Room, you heap of parrot droppings!")
    elif answer == "right" or answer == "r":
        print("Of course this is the Argument Room, I've told you that already!")
    else:
        print("You didn't pick left or right! Try again.")
        clinic()
clinic()"""
# Assign True or False as appropriate on the lines below!
# Set this to True if 17 < 328 or to False if it is not.
bool_one = True   # We did this one for you!
# Set this to True if 100 == (2 * 50) or to False otherwise.
bool_two = True
# Set this to True if 19 <= 19 or to False if it is not.
bool_three = True
# Set this to True if -22 >= -18 or to False if it is not.
bool_four = False
# Set this to True if 99 != (98 + 1) or to False otherwise.
bool_five = False
"""
    Boolean Operators
------------------------      True and True is True
True and False is False
False and True is False
False and False is False

True or True is True
True or False is True
False or True is True
False or False is False

Not True is False
Not False is True
"""
def using_control_once():
    if True:
        return "Success #1"

def using_control_again():
    if True:
        return "Success #2"

print(using_control_once())
print(using_control_again())
# Else problems
answer = "'Tis but a scratch!"

def black_knight():
    if answer == "'Tis but a scratch!":
        return True
    else:
        return False        # Make sure this returns False

def french_soldier():
    if answer == "Go away, or I shall taunt you a second time!":
        return True
    else:
        return False        # Make sure this returns False

# immutable типы bytearray, tuple (кортеж)
# создать пустой корреж(tuple)
mytuple = tuple()
#mutable - list
immutable_1 = (1,2,3,4)
mutable_1 = [1,1,3,4]
mutable_1[0] = False
print(mutable_1)
# положить внутрь списка еще один список
mutable_1[0] = [True, True, True]
print(mutable_1)
# доступ к элементам вложенного списка
mutable_1[0][1] = False
print(mutable_1)
#операции над списками: append[добавить в конец] clear copy count extend index insert[вставка по индексу] pop[удаление из конца] remove reverse sort
mutable_1.append(1111)
print(mutable_1)
# добавление в произвольное место списка
mutable_1.insert(4, 2222)
print(mutable_1)
# bytearray - изменяемая последовательность байтов
b = bytearray(b'abc')


import json
import requests
import base64

#replace xxxx with fqdn or the ip of the Client Accelerator Controller ex. https://my-controlller.local
controller="xxxxx"

#replace xxxx with access_code generated on the Client Accelerator Controller page
#https://my-controlller.local/mgmt/gui?p=setupRESTInterface
access_code='xxxxx'

def get_token(access_code):

    api_url='/api/common/1.0.0/oauth/token'

    #https://supportkb.riverbed.com/support/index?page=content&id=S24393&actp=search&viewlocale=en_US&searchid=1609955176980
    a=base64.b64encode(b'{"alg":"none"}\n')
    b=access_code
    c=''

    total_access_code=a.decode("ascii")+"."+b+"."+c

    payload = {'grant_type': 'access_code','assertion': total_access_code, 'state': 'state_string'}
    r = requests.post(controller+api_url, verify=False, data=payload)

    content_dict = json.loads(r.text)

    return content_dict['access_token']

def get_services(token):
    api_url = '/api/appliance/1.0.0/services'
    headers = {"Authorization": "Bearer "+token}
    r = requests.get(controller+api_url, verify=False, headers=headers)
    return json.loads(r.text)

def get_license(token):
    api_url = '/api/appliance/1.0.0/status/license'
    headers = {"Authorization": "Bearer " + token}
    r = requests.get(controller + api_url, verify=False, headers=headers)
    return json.loads(r.text)

def main():
    my_token = get_token(access_code)
    print(get_services(my_token))
    print(get_license(my_token))

if __name__ == '__main__':
    main()


import cv2 as cv

img = cv.imread('photos/nature.jpg')
cv.imshow('Original', img)

# blur is using average bluring method by average surrounding pixel.
avg = cv.blur(img, (7,7))
cv.imshow('Avg', avg)

# Gaussian blur is bluring using kernel weight, 0 is sigmaX is standard deviation in x direction value.
gauss = cv.GaussianBlur(img, (7,7), 0)
cv.imshow('Gaussian', gauss)

# Median blur is using median value in kernel size.
median = cv.medianBlur(img, 3)
cv.imshow('Median', median)

# Bilateral blur is bluring using d-> kernel size, sigmaColor-> number of pixel that consider when blur and sigmaSpace-> space that will random choose pixel to consider.
bilateral = cv.bilateralFilter(img, 9, 50, 40)
cv.imshow('Bilateral', bilateral)

cv.waitKey(0)


class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        result=100000
        for i in range(len(nums)):
            if(i!=0 and nums[i]==nums[i-1]):continue
            j=i+1
            k=len(nums)-1
            while(j<k):
                # print(i,j,k)
                s=nums[i]+nums[j]+nums[k]
                if(abs(target-s)<abs(target-result)):
                    result=s
                else:
                    pass
                if(s==target):
                    return target
                elif(s>target):
                    k-=1
                else:
                    j+=1
        return result