from datetime import datetime
import docker
import mock
import unittest

from infra.services.android_docker import containers

class FakeDevice(object):
  """Mocks a usb_device.Device"""
  def __init__(self, serial, physical_port):
    self.serial = serial
    self.physical_port = physical_port
    self.major = 0
    self.minor = 0
    self.bus = 0
    self.dev_file_path = ''

class FakeClient(object):
  """Mocks the client object returned from docker's client API.

  containers.DockerClient wraps it. Mocked here to verify wrapper class
  bheaves correctly.
  """
  def __init__(self):
    self.containers = None

class FakeContainer(object):
  """Used to mock containers.Container"""
  def __init__(self, name, uptime=None):
    self._container = FakeContainerBackend(name)
    self.name = name
    self.uptime = uptime
    self.swarming_bot_killed = False

  def get_container_uptime(self, now):  # pylint: disable=unused-argument
    return self.uptime

  def kill_swarming_bot(self):
    self.swarming_bot_killed = True

class FakeContainerBackend(object):
  """Mocks the container objects returned from docker's client API.

  containers.Container wraps each one. Mocked here to verify the wrapper class
  behaves correctly.
  """
  def __init__(self, name):
    self.name = name
    self.was_deleted = False
    self.was_started = False
    self.is_paused = False
    self.exec_outputs = []
    self.exec_inputs = []
    self.attrs = {}

  def remove(self):
    self.was_deleted = True

  def start(self):
    self.was_started = True

  def pause(self):
    assert not self.is_paused
    self.is_paused = True

  def unpause(self):
    assert self.is_paused
    self.is_paused = False

  def exec_run(self, cmd):
    self.exec_inputs.append(cmd)
    return self.exec_outputs.pop(0)

class FakeContainerList(object):
  """Mocks the container list objects returned from docker's client API."""
  def __init__(self, containers_list):
    self._list = containers_list

  def create(self, **kwargs):
    return FakeContainerBackend(kwargs['name'])

  def list(self, filters=None):  # pylint: disable=unused-argument
    return self._list

  def get(self, name):
    for c in self._list:
      if c.name == name:
        return c
    raise docker.errors.NotFound('omg container missing')

class TestGetNames(unittest.TestCase):
  def setUp(self):
    self.device = FakeDevice('serial123', 1)

  def test_container_name(self):
    container_name = containers.get_container_name(self.device)
    self.assertEqual(container_name, 'android_serial123')

  @mock.patch('socket.gethostname')
  def test_container_hostname(self, mock_gethostname):
    mock_gethostname.return_value = 'build123-a4'
    container_hostname = containers.get_container_hostname(self.device)
    self.assertEqual(container_hostname, 'build123-a4--device1')

class TestDockerClient(unittest.TestCase):
  def setUp(self):
    self.fake_client = FakeClient()
    self.container_names = ['android_serial1', 'android_serial2']
    self.fake_client.containers = FakeContainerList(
        [FakeContainerBackend(name) for name in self.container_names])

  @mock.patch('docker.from_env')
  def test_get_running_containers(self, mock_from_env):
    mock_from_env.return_value = self.fake_client

    running_containers = containers.DockerClient().get_running_containers()
    self.assertEqual(
        set(c.name for c in running_containers), set(self.container_names))

  @mock.patch('docker.from_env')
  def test_get_container(self, mock_from_env):
    mock_from_env.return_value = self.fake_client
    fake_device = FakeDevice('serial2', 2)

    container = containers.DockerClient().get_container(fake_device)
    self.assertEqual(container.name, 'android_serial2')

  @mock.patch('docker.from_env')
  def test_get_missing_container(self, mock_from_env):
    mock_from_env.return_value = self.fake_client
    fake_device = FakeDevice('missing_device', 1)

    container = containers.DockerClient().get_container(fake_device)
    self.assertEqual(container, None)

  @mock.patch('docker.from_env')
  def test_stop_old_containers(self, mock_from_env):
    young_container = FakeContainer('young_container', uptime=10)
    old_container = FakeContainer('old_container', uptime=999)
    mock_from_env.return_value = self.fake_client

    containers.DockerClient().stop_old_containers(
        [young_container, old_container], 100)
    self.assertFalse(young_container.swarming_bot_killed)
    self.assertTrue(old_container.swarming_bot_killed)

  @mock.patch('docker.from_env')
  def test_delete_stopped_containers(self, mock_from_env):
    mock_from_env.return_value = self.fake_client

    containers.DockerClient().delete_stopped_containers()
    self.assertTrue(
        all(c.was_deleted for c in self.fake_client.containers.list()))

  @mock.patch('docker.from_env')
  def test_create_missing_containers(self, mock_from_env):
    running_containers = [
        FakeContainer('android_serial1'),
        FakeContainer('android_serial2'),
    ]
    devices = [
        FakeDevice('serial1', 1),
        FakeDevice('serial2', 2),
        FakeDevice('serial3', 3),
    ]
    self.fake_client.containers = FakeContainerList(running_containers)
    mock_from_env.return_value = self.fake_client

    needs_reboot = containers.DockerClient().create_missing_containers(
        running_containers, devices, 'image')
    # Ensure serial3 needs to be rebooted. This indicates that a new container
    # was created for it.
    self.assertEquals([d.serial for d in needs_reboot], ['serial3'])

class TestContainer(unittest.TestCase):
  def setUp(self):
    self.container_backend = FakeContainerBackend('container1')
    self.container = containers.Container(self.container_backend)

  def test_get_container_uptime(self):
    now = datetime.strptime(
        '2000-01-01T01:30:00.000000', '%Y-%m-%dT%H:%M:%S.%f')
    self.container_backend.attrs = {
        'State': {'StartedAt': '2000-01-01T00:00:00.0000000000'}
    }
    uptime = self.container.get_container_uptime(now)
    self.assertEquals(uptime, 90)

  def test_get_swarming_bot_pid(self):
    self.container_backend.exec_outputs = ['123']
    pid = self.container.get_swarming_bot_pid()
    self.assertEquals(pid, 123)

  def test_get_swarming_bot_pid_backend_error(self):
    self.container_backend.exec_outputs = ['rpc error: omg failure']
    pid = self.container.get_swarming_bot_pid()
    self.assertEquals(pid, None)

  def test_get_swarming_bot_pid_lsof_error(self):
    self.container_backend.exec_outputs = ['omg lsof failure']
    pid = self.container.get_swarming_bot_pid()
    self.assertEquals(pid, None)

  def test_kill_swarming_bot(self):
    self.container_backend.exec_outputs = ['123', '']
    self.container.kill_swarming_bot()
    self.assertEquals(self.container_backend.exec_inputs[-1], 'kill -15 123')

  def test_kill_swarming_bot_error(self):
    self.container_backend.exec_outputs = ['omg failure']
    self.container.kill_swarming_bot()
    # Ensure nothing was killed when the bot's pid couldn't be found.
    self.assertFalse(
        any('kill -15' in cmd for cmd in self.container_backend.exec_inputs))

  @mock.patch('time.sleep')
  @mock.patch('os.open')
  @mock.patch('os.write')
  @mock.patch('os.close')
  @mock.patch('os.path.exists')
  def test_add_device(self, mock_path_exists, mock_close, mock_write, mock_open,
                      mock_sleep):
    mock_sleep.return_value = None
    mock_path_exists.return_value = True
    self.container_backend.attrs = {'Id': 'abc123'}
    self.container_backend.exec_outputs = ['', '']
    device = FakeDevice('serial1', 1)
    device.major = 111
    device.minor = 9
    device.bus = 1
    device.dev_file_path = '/dev/bus/usb/001/123'
    self.container.add_device(device)

    self.assertTrue('abc123' in mock_open.call_args[0][0])
    # Ensure the device's major and minor numbers were written to the
    # cgroup file.
    self.assertEqual(mock_write.call_args[0][1], 'c 111:9 rwm')
    self.assertTrue(mock_close.called)
    self.assertFalse(self.container_backend.is_paused)

  @mock.patch('time.sleep')
  @mock.patch('os.open')
  @mock.patch('os.path.exists')
  def test_add_device_missing_cgroup(self, mock_path_exists, mock_open,
                                     mock_sleep):
    mock_sleep.return_value = None
    mock_path_exists.return_value = False
    self.container_backend.attrs = {'Id': 'abc123'}
    self.container_backend.exec_outputs = ['']
    device = FakeDevice('serial1', 1)

    self.container.add_device(device)

    self.assertFalse(mock_open.called)
    self.assertEquals(len(self.container_backend.exec_inputs), 1)
    self.assertFalse(self.container_backend.is_paused)

  @mock.patch('time.sleep')
  @mock.patch('os.open')
  @mock.patch('os.write')
  @mock.patch('os.close')
  @mock.patch('os.path.exists')
  def test_add_device_os_open_error(self, mock_path_exists, mock_close,
                                    mock_write, mock_open, mock_sleep):
    mock_sleep.return_value = None
    mock_path_exists.return_value = True
    mock_open.side_effect = OSError('omg open error')
    self.container_backend.attrs = {'Id': 'abc123'}
    self.container_backend.exec_outputs = ['']
    device = FakeDevice('serial1', 1)
    device.major = 111
    device.minor = 9
    self.container.add_device(device)

    self.assertTrue('abc123' in mock_open.call_args[0][0])
    self.assertFalse(mock_write.called)
    self.assertFalse(mock_close.called)
    self.assertEquals(len(self.container_backend.exec_inputs), 1)
    self.assertFalse(self.container_backend.is_paused)

  @mock.patch('time.sleep')
  @mock.patch('os.open')
  @mock.patch('os.write')
  @mock.patch('os.close')
  @mock.patch('os.path.exists')
  def test_add_device_os_write_error(self, mock_path_exists, mock_close,
                                     mock_write, mock_open, mock_sleep):
    mock_sleep.return_value = None
    mock_path_exists.return_value = True
    mock_write.side_effect = OSError('omg write error')
    self.container_backend.attrs = {'Id': 'abc123'}
    self.container_backend.exec_outputs = ['']
    device = FakeDevice('serial1', 1)
    device.major = 111
    device.minor = 9
    self.container.add_device(device)

    self.assertTrue('abc123' in mock_open.call_args[0][0])
    self.assertEquals(mock_write.call_args[0][1], 'c 111:9 rwm')
    self.assertTrue(mock_close.called)
    self.assertEquals(len(self.container_backend.exec_inputs), 1)
    self.assertFalse(self.container_backend.is_paused)


# -*- coding: UTF-8 -*-
# 百度人脸识别：https://ai.baidu.com/ai-doc/FACE/ek37c1qiz#%E4%BA%BA%E8%84%B8%E6%A3%80%E6%B5%8B
from aip import AipFace

from config import BAIDU_ID, BAIDU_KEY, BAIDU_SECRET_KEY

'''
百度人脸识别
优点：可免费使用，个人账户的限制为2QPS,企业账户的限制为10QPS
'''

""" 你的 APPID AK SK """
APP_ID = BAIDU_ID
API_KEY = BAIDU_KEY
SECRET_KEY = BAIDU_SECRET_KEY

client = AipFace(APP_ID, API_KEY, SECRET_KEY)

"""
image = "取决于image_type参数，传入BASE64字符串或URL字符串或FACE_TOKEN字符串"

imageType = "BASE64"

# 调用人脸检测
client.detect(image, imageType)

# 如果有可选参数
options = dict()
options["face_field"] = "age"
options["max_face_num"] = 2
options["face_type"] = "LIVE"
options["liveness_control"] = "LOW"

# 带参数调用人脸检测
client.detect(image, imageType, options)
"""

if __name__ == "__main__":
    url = "https://smartracing.oss-cn-hangzhou.aliyuncs.com/shared/images/profiles/full/1571196895035.jpg"
    options = {
        "face_field": "age,beauty,expression,face_shape,emotion"
    }
    res = client.detect(url, "URL", options)
    face = res['result']['face_list'][0]

    expression = {"none": "不笑", "smile": "微笑", "laugh": "大笑"}
    face_shape = {"square":" 正方形", "triangle": "三角形", "oval": "椭圆", "heart": "心形", "round": "圆形"}
    emotion = {"angry": "愤怒", "disgust": "厌恶", "fear": "恐惧", "happy": "高兴", "sad": "伤心", "surprise": "惊讶", "neutral": "无情绪"}

    print(f"检测年龄：{face['age']},颜值：{face['beauty']},表情：{expression.get(face['expression']['type'])},脸型：{face_shape.get(face['face_shape']['type'])}, 情绪:{emotion.get(face['emotion']['type'])}")


# -*- coding: utf-8 -*-
'''This example demonstrates how to extract named entities from text using default model.'''

from __future__ import unicode_literals, print_function
from pprint import pprint

from estnltk import Tokenizer, PyVabamorfAnalyzer, NerTagger

text = '''Eesti Vabariik on riik Põhja-Euroopas.
Eesti piirneb põhjas üle Soome lahe Soome Vabariigiga.

Riigikogu on Eesti Vabariigi parlament. Riigikogule kuulub Eestis seadusandlik võim.

2005. aastal sai peaministriks Andrus Ansip, kes püsis sellel kohal 2014. aastani.
2006. aastal valiti presidendiks Toomas Hendrik Ilves.
'''

tokenizer = Tokenizer()
analyzer = PyVabamorfAnalyzer()
tagger = NerTagger()

# tag the documents
ner_tagged = tagger(analyzer(tokenizer(text)))

# print the words and their explicit labels in BIO notation
pprint(list(zip(ner_tagged.word_texts, ner_tagged.labels)))

# print words grouped as named entities
pprint(ner_tagged.named_entities)


# -*- coding: utf-8 -*-
"""
Created on Tue Feb  8 16:09:50 2022

@author: Owner
"""
from Hamiltonian import Hamiltonian
import numpy as np
import math
import matplotlib.pyplot as plt
import copy

from Hamiltonian import Hamiltonian
from Fock_vector import fock_vector
import Ryser_Algorithm as ryser
import config as configs
from numpy import linalg as la
from decimal import Decimal
from Fock_vector import fock_vector
from Disc_Hamiltonian import disc_Hamiltonian

params = {
   'axes.labelsize': 35,
   'font.size': 35,
   'legend.fontsize': 35,
   'lines.linewidth' : 2,
   'lines.markersize' : 35,
   'xtick.labelsize': 35,
   'ytick.labelsize': 35,
   'figure.figsize': [40, 20]
   }
plt.rcParams.update(params)

def Dirac_Delta(a, b):
    '''
    Simple delta function
    '''
    if (a == b):
        return 1
    else:
        return 0

class non_rotatingHamiltonian(Hamiltonian):

    '''
    Core class for impelementing Full-Configuration Interaction
    Hamiltonians in bosonic Fock space basis for non-rotating pancakes
    '''
    def __init__(self,N, M, S, length_ratio=10, L=0):
        super().__init__(N,M)
        self.tolerance = 1e-10
        self. L = L # Restrict total angular momentum for each Fock vector
        self.S = S
        assert M == 2*S + 1
        self.M = M
        # Set interaction energy scale to 1
        self.V0 = 1
        self.lengthratio = length_ratio # = (a_z/a_s: trap length/scattering length)
        # Scale kinetic energy scale accordingly
        self.T0 = (np.pi**2)*self.lengthratio

        self.condensate_fraction = None # No. excitations in lowest SP state
        self.GP_amplitude = None # Weight of Gross-Pitaevskii (fully condensed) permanent
        self.GP_index = None
        self.MF_perm = None # Amplitude of dominant permanent in FCI expansion
        self.MF_energy = None # Energy content of dominant permanent in FCI expansion
        self.MF_amplitude = None # Amplitude of Gross-Pitaevskii permanent

    def generate_basis(self):
        '''
        Generate many-body basis states from repeated combinations
        and index them
        '''
        print('Basis generation...')
        configs.sphere_config_fast(int(self.N), int(self.M), int(self.L), int(self.S))
        index = 0
        file='Sphere_Configurations_N%dM%dL%dS%d.txt'%(self.N, self.M, self.L, self.S)
        print('Reading in configurations...')
        with open(file, 'r') as f:
            for line in f:
                split_line = line.split()
                if (split_line[0]=='N,'):
                    continue
                N = split_line[0]
                M = split_line[1]
                L = split_line[2]
                S = split_line[3]
                basis = []
                config = split_line[4:]
                #print(config)
                for item in config:
                    #print(item)
                    basis.append(int(item))
                #print(N, M, L, len(config), len(basis))
                #print(config, basis)
                #print(self.N, N, self.M, M)
                assert int(N) == self.N and int(M) == self.M and int(M) == 2*(self.S) +1
                vector = fock_vector(int(N), int(M), np.array(basis), int(S))
                assert vector.ang_mom() == self.L
                vector = fock_vector(int(N), int(M), np.array(basis), S= int(S), index=index)
                self.basis.append(vector)
                if (self.S in vector.occup_basis):
                    if (vector.occups[self.S] == self.N):
                        self.GP_index = index
                index += 1
                if (index % 100 == 0):
                    print('No. basis read-in ', index)

        print('Basis generation complete')
        print('Fock space size: ', self.fock_size)

        self.basis = np.array(self.basis)
        self.fock_size = index
        self.many_body_H = np.zeros((self.fock_size, self.fock_size))

    def matrix_overlap(self, i, j, k, l):
        '''
        Construct many-body overlap matrix for disc Hamiltonian
        '''

        self.additionalfactor = 1

        if (i+j != k+l):
            return 0
        else:
            return self.V0*self.additionalfactor

    def kineticterm(self, i):

        return self.T0*((i-self.S)**2)

    def diag_entry(self, basis):
        '''
        Returns diagonal entry for contact repulsion Hamiltonian
        '''
        assert len(self.basis) == self.fock_size # Check if basis generation has not been invoked
        diag_element = 0

        occup_basis = np.sort(basis.occup_basis)
        #print(basis.print_info())
        #print(occup_basis)
        for index in range(len(occup_basis)):
            i = occup_basis[index]
            diag_element += self.kineticterm(i)*basis.occups[i]
            if basis.occups[i] > 1:
                #print(i)
                # Half factor comes from Hamiltonian definition
                diag_element += 0.5*self.matrix_overlap(i, i, i, i)\
                                *basis.occups[i]*(basis.occups[i]-1)

            # we only have to consider non-equal i, j pairs as symmetry
            # gives equal elements for ijij jiij, ijji, jiji basis indices

            for jndex in range(index+1, len(occup_basis)):
                j = occup_basis[jndex]
                #print(i, j)

                diag_element += 2*self.matrix_overlap(i, j, i, j)\
                                *basis.occups[i]*(basis.occups[j])
        return diag_element

    def construct_off_diag_entries(self, basis):

        off_diag_element = 0
        occup_basis = np.sort(basis.occup_basis)
        new_occups = np.zeros(self.M)
        for index in range(len(occup_basis)):
            i = occup_basis[index]

            for jndex in range(index, len(occup_basis)):
                j = occup_basis[jndex]
                for k in range(self.M):
                    new_occups = np.zeros(self.M)
                    new_basis_index = None
                    l = i + j - k
                    if (l >= self.M or l < 0):
                        continue
                    if (k == i or k == j or l == k or l == i or l == j):
                        continue
                    if (i != j):
                        # Copy basis occupation
                        for q in basis.occup_basis:
                            new_occups[q] = basis.occups[q]
                        # Construct basis with non-zero entry
                        new_occups[i] = basis.occups[i] - 1
                        new_occups[j] = basis.occups[j] - 1
                        if (k in basis.occups):
                            new_occups[k] = basis.occups[k] + 1
                        else:
                            new_occups[k] =  1

                        if (l in basis.occups):
                            new_occups[l] = basis.occups[l] + 1
                        else:
                            new_occups[l] = 1

                        new_fock = fock_vector(self.N, self.M, new_occups)
                        new_basis_index = None
                        # Search newly constructed basis index
                        for basis2 in self.basis:
                            if basis2.occups == new_fock.occups:
                                if (basis2.index != basis.index):
                                    new_basis_index = basis2.index
                                    break
                        if (new_basis_index is None):
                            print('New basis not in Hamiltonian space')
                            print(new_fock.print_info)
                            self.show_basis()
                            assert 0

                        # Assign matrix element
                        self.many_body_H[basis.index, new_basis_index] = \
                        2*np.sqrt(basis.occups[i]*basis.occups[j]*new_occups[k]*new_occups[l])*self.matrix_overlap(i, j, k, l)
                        self.many_body_H[new_basis_index, basis.index] = self.many_body_H[basis.index, new_basis_index]

                    else:
                        if (basis.occups[i] < 2):

                            continue
                        # Construct basis with non-zero entry for i = j
                        for q in basis.occup_basis:
                            new_occups[q] = basis.occups[q]
                        # See Wilkin paper for angular momentum transfer rules
                        new_occups[i] = basis.occups[i] - 2
                        if (k in basis.occups):
                            new_occups[k] = basis.occups[k] + 1
                        else:
                            new_occups[k] =  1

                        if (l in basis.occups):
                            new_occups[l] = basis.occups[l] + 1
                        else:
                            new_occups[l] = 1

                        new_fock = fock_vector(self.N, self.M, new_occups)
                        new_basis_index = None
                        # Search newly constructed basis index
                        for basis2 in self.basis:
                            if basis2.occups == new_fock.occups:
                                if (basis2.index != basis.index):
                                    new_basis_index = basis2.index
                                    break
                        if (new_basis_index is None):
                            print('New basis not in Hamiltonian space')
                            print(new_fock.print_info)
                            self.show_basis()
                            assert 0

                        # Assign matrix element
                        self.many_body_H[basis.index, new_basis_index] = \
                        np.sqrt(basis.occups[i]*(basis.occups[i]-1)*new_occups[k]*new_occups[l])*self.matrix_overlap(i, j, k, l)
                        self.many_body_H[new_basis_index, basis.index] = self.many_body_H[basis.index, new_basis_index]

    def construct_Hamiltonian_fast(self):
        # Wilkin exact eigenstates paper prescription
        assert len(self.basis) == self.fock_size # Check if basis generation has not been invoked

        # Diagonal entries
        #print(self.basis)
        print('Hamiltonian construction...')
        print('Fock size: ', self.fock_size)
        counter = 1
        for basis in self.basis:
            self.many_body_H[basis.index, basis.index] = self.diag_entry(basis)
            self.construct_off_diag_entries(basis)
            if (counter % 100 == 0):
                print('Fast Hamiltonian construction progress [%] ', (counter/self.fock_size)*100)
            counter += 1

    def ground_state_analysis(self):
        # Index of MF permanent
        #print(np.max(self.e_vector_ground.T))
        #print(self.e_vector_ground[0])
        max_index = np.where(max(self.e_vector_ground[0], key=abs) == self.e_vector_ground[0])[0][0]
        print('max index', max_index)

        self.MF_perm = self.basis[max_index]
        self.MF_amplitude = self.e_vector_ground[0][max_index]
        print('Mean-field permanent info')
        print(self.MF_perm.print_info())
        print('Amplitude: ', self.MF_amplitude)

        self.GP_amplitude = self.e_vector_ground[0][self.GP_index]
        #print('All permanents:', self.e_vector_ground[0])
        print('Gross-Pitaevskii permanent amplitude: ', self.GP_amplitude)

        #print('Permanent energy: ', self.many_body_H[max_index, max_index])
        #print('MF energy / E0: ',  self.many_body_H[max_index, max_index]/self.e_ground)

        # Calculating condensate fraction

        self.condensate_fraction = 0

        for index, amplitude in enumerate(self.e_vector_ground.squeeze()):

            if (self.S not in self.basis[index].occup_basis):
                continue
            else:
                self.condensate_fraction += \
                    abs(amplitude)**2 * self.basis[index].occups[self.S]/self.N

        print('Expected condensate fraction: ', self.condensate_fraction)
        print('Condensate depletion: ', 1-self.condensate_fraction)

        return self.MF_amplitude, self.GP_amplitude, self.condensate_fraction

    def check_degeneracy(self):
        '''
        Find degeneracies within spectrum
        '''
        self.degen_evalues = []
        self.degen_evectors = []

        for i in range(len(self.evalues)):
            self.degen_evalues.append([i])
            self.degen_evectors.append([self.evectors.T[i]])
            for j in range(i+1, len(self.evalues)):
                if abs(self.evalues[i] - self.evalues[j]) <= self.tolerance:
                    self.degen_evalues[-1].append(j)
                    self.degen_evectors[-1].append(self.evectors.T[j])

        degeneracy = np.zeros(len(self.evalues))

        for i in range(len(self.evalues)):
            degeneracy[i] = len(self.degen_evalues[i])

        plt.title('Degeneracy of spectrum\n'+\
                 'Disc geometry\nN = %d   M = %d   L = %d'%(self.N, self.M, self.L))
        plt.bar(x=np.arange(1, self.fock_size+1), height=degeneracy)
        plt.xlabel('Sorted eigenstate index')
        plt.ylabel('Degeneracy')
        plt.grid()
        plt.legend()
        plt.savefig('BEC_Degeneracy_N%d_M%d_S%d_L%d.jpeg'%(self.N, self.M, self.S, self.L))
        plt.close()

        plt.title('Eigenvalue spectrum\n'+\
                 'Disc geometry\nN = %d   M = %d   L = %d'%(self.N, self.M, self.L))
        nT, binsT, patchesT = plt.hist(x=self.evalues, bins=15, color='red',
                            alpha=0.7, rwidth=0.85, label='FCI Spectrum')
        plt.xlabel('Eigenvalues [$V_0$]')
        plt.ylabel('Degeneracy')
        plt.legend()
        plt.grid()
        plt.savefig('BEC_Spectrum_N%d_M%d_S%d_L%d.jpeg'%(self.N, self.M, self.S, self.L))
        plt.close()

        assert (self.evalues.min() == self.evalues[0])
        assert (self.fock_size == len(self.evalues))

        for ground_index in range(len(self.degen_evalues[0])):
            print(len(self.degen_evectors[0]), len(self.degen_evalues[0]))
            assert len(self.degen_evectors[0]) == len(self.degen_evalues[0])
            #print(self.degen_evectors[0][ground_index])
            print(len(self.degen_evectors[0][ground_index]))
            print(ground_index)
            plt.figure(ground_index)
            plt.title('Degenerate ground state configuration index %d \n'%(ground_index)+\
                     'Disc geometry\nN = %d   M = %d   L = %d'%(self.N, self.M, self.L))
            plt.bar(x=np.arange(1, self.fock_size+1), height=self.degen_evectors[0][ground_index][0])
            #nT, binsT, patchesT =\
            #plt.hist(x=self.degen_evectors[0][ground_index],bins=self.fock_size, color='red',alpha=0.7, rwidth=0.85, label='Full Configuration')
            plt.xlabel('Many-body basis index')
            plt.ylabel('Amplitude')
            plt.grid()
            plt.legend()
            plt.savefig('BEC_Ground_Config_i%d_N%d_M%d_S%d_L%d.jpeg'%(ground_index, self.N, self.M,self.S, self.L))
            plt.close()

        #print('Degenerate evector indices')
        #print(self.degen_evalues)
        #print(self.degen_evectors)

'''
H = non_rotatingHamiltonian(N=3,S=1,M=3)
H.generate_basis()
H.construct_Hamiltonian_fast()
#H.print_matrix(H.many_body_H)

evalues, evecs = H.diagonalise()
print('Hamiltonian eigenvalues [V0]')
print(evalues)
print('Ground state energy [V0] ', H.e_ground)
print('Ground state configuration', H.e_vector_ground)
#H.show_basis()
MF_amp, GP_amp = H.ground_state_analysis()
print(MF_amp, GP_amp)
#H.check_sign_problem()
H.check_degeneracy()
'''


words_dict = {'proper' : '적절한',
'possible' : '가능한',
'moral' : '도덕적인',
'patient' : '참을성 있는',
'balance' : '균형',
'perfect' : '완벽한',
'logical' : '논리적인',
'legal' : '합법적인',
'relevant' : '관련 있는',
'responsible' : '책임감 있는',
'regular' : '규칙적인'}

# correct : 정확한 -> in 을 붙여서 반댓말을 만든다(incorrect)

# 아래의 경우에는 in이 아니라 변화형이 앞에 붙게 된다.
# 1. 단어가 b 또는 m 또는 p로 시작하는 경우 -> im
# 2. 단어가 l 로 시작하는 경우 -> il
# 3. 단어가 r 로 시작하는 경우 -> ir

def get_opposite(words_dict): # words_dict는 반댓말로 바꾸고 싶은 단어들이 있다.(딕셔너리로 들어온다)
    # 반댓말로 만들고 나서 dictinary 형식으로 리턴 할 것이기 때문에
    opposite_dict = {}
    # key : 원래 단어 / value : 반대 단어

    for word in words_dict.keys():
        # 반댓말로 만들때 원래 단어가 어떤 철자로 시작하는지를 알아야 규칙을 적용할 수 있다.
        start = word[0]
        # 리턴할 반대의미를 가진 단어
        opposite = ""
        # 조건문을 통해서 start가 어떤 철자인지 알아본 후에 규칙을 적용

        if start == "b" or start == "m" or start == "p":
            opposite = "im" + word
        elif start == "l":
            opposite = "il" + word
        elif start == "r":
            opposite = "ir" + word
        else:
            opposite = "in" + word

        # 반댓말을 만들고 나서 딕셔너리에 추가를해준다.
        opposite_dict[word] = opposite # word 키에 opposite value(값)을 짝지어 준다.

    sorted_result = sorted(opposite_dict.items(), key=lambda item: item[1])
    # 원래말 : 반댓말 이렇게 이루어진 딕셔너리에서
    # items() -> (key, value)
    # item = (key, value)
    # item[0] key
    # item[1] value <- 이걸 기준으로 정렬하겠다.
    # 반댓말(value)를 기준으로 정렬할 때
    return sorted_result

print(get_opposite(words_dict))


'''
    Write a python server program that
        0. initialized a socket connection on localhost and port 10000
        1. accepts a connection from a  client
        2. receives a "Hi <name>" message from the client
        3. generates a random numbers and keeps it a secret
        4. sends a message "READY" to the client
        5. waits for the client to send a guess
        6. checks if the number is
            6.1 equal to the secret then it should send a message "Correct! <name> took X attempts to guess the secret"
            6.2 send a message "HIGH" if the guess is greater than the secret
            6.3 send a message "LOW" if the guess is lower than the secrent
        7. closes the client connection and waits for the next one
'''
import socket
from random import randint

server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
server_socket.bind(('localhost',10000))
server_socket.listen(1)
# while True:
# 	connection, clietn_address = server_socket.accept()
# 	print("Connetion established!")
# 	while True:
# 		client_data = connection.recv(1024)
# 		if (client_data != "q" and len(client_data) > 0):
# 			print(client_data.decode("utf-8"))
# 			connection.send(client_data)
# 		else:
# 			print(client_data.decode("utf-8"))
# 			connection.send(client_data)
# 			break
# 	if (client_data != 'q'):
# 		connection.close()

while True:
	connection, client_address = server_socket.accept()
	count = 0;
	name = connection.recv(1024).decode("utf-8")
	print(name[3:])
	value = randint(0,100)
	print("vaue = ",value)
	connection.send("READY".encode("utf-8"))
	while True:
		client_data = int(connection.recv(1024).decode("utf-8"))
		count += 1
		if client_data == value:
			connection.send(str(f"Correct! {name} took {count} attempts to guess the secret").encode("utf-8"))
			break
		elif value > client_data:
			connection.send("LOW".encode("utf-8"))
		else:
			connection.send("HIGH".encode("utf-8"))
	connection.close()


"""Provides functional layers for the model"""
import numpy as np
import torch
import torch.nn.functional as F
from common_types import Tensor, Union, _float, _int
from torch.types import Device, _size

_opt_arg = Union[_int, _size]
_opt_tensor = Union[Tensor, None]

def conv2d(x: Tensor,
           weight: Tensor,
           bias: _opt_tensor = None,
           device: Device = 'cpu',
           stride: _opt_arg = 1,
           padding: _opt_arg = 0,
           dilation: _opt_arg = 1,
           groups: _int = 1) -> Tensor:

  return F.conv2d(x, weight.to(device), bias.to(device), stride, padding,
                  dilation, groups)

def batchnorm(x: Tensor,
              weight: Tensor = None,
              bias: _opt_tensor = None,
              device: Device = 'cpu',
              running_mean: _opt_tensor = None,
              running_var: _opt_tensor = None,
              training: bool = True,
              eps: _float = 1e-5,
              momentum: _float = 0.1) -> Tensor:
  ''' momentum = 1 restricts stats to the current mini-batch '''
  # This hack only works when momentum is 1 and avoids needing to track
  # running stats by substuting dummy variables
  running_mean = torch.zeros(np.prod(np.array(x.data.size()[1]))).to(device)
  running_var = torch.ones(np.prod(np.array(x.data.size()[1]))).to(device)
  return F.batch_norm(x, running_mean, running_var, weight, bias, training,
                      momentum, eps)

def leaky_relu(x: Tensor, negative_slope: _float = 0.01) -> Tensor:
  return F.leaky_relu(x, negative_slope, True)

def pixel_shuffle(x: Tensor, scale: _int):
  return F.pixel_shuffle(x, scale)


import pygame
from pygame.draw import *
from random import randint
pygame.init()

FPS = 60 #число новых кругов в секунду
number_of_balls=4 #число обычных шаров
points=0 #счетчик очков
base_points_multiplier=100 #базовый множитель начисления очков
x_res,y_res=1920/1.25, 1080/1.25 #разрешение
res=[x_res,y_res]
sp_mult=0.01 #множитель скорости
screen = pygame.display.set_mode((x_res,y_res))
'''создаем массив цветов шарика в формате pygame.color'''
RED = (255, 0, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
MAGENTA = (255, 0, 255)
CYAN = (0, 255, 255)
BLACK = (0, 0, 0)
COLORS = [RED, BLUE, YELLOW, GREEN, MAGENTA, CYAN]

class ball:
    '''хранит координаты шаров, пересчитывает их при переходе на следующий кадр, pos=[x,y] и spd=[Vx,Vy], где V - изменение координаты за кадр'''
    def __init__(self):
        self.r=randint(y_res//100,y_res//8) #радиус
        self.pos=[randint(self.r, int(x_res-self.r)),randint(self.r, int(y_res-self.r))] #координата
        self.spd=[randint(-int(x_res*sp_mult), int(x_res*sp_mult)),randint(-int(y_res*sp_mult), int(y_res*sp_mult))] # скррости
        self.color=COLORS[randint(0,len(COLORS)-1)] # цвет
    def new_frame(self): #рисуем новый кадр
        pygame.draw.circle(screen, self.color,self.pos,self.r)
        for i in range(2):
            self.pos[i]+=self.spd[i]
            if(self.pos[i]<self.r or self.pos[i]>res[i]-self.r):
                self.spd[i]=-self.spd[i]
                self.pos[i]+=self.spd[i]

def click_check(event, balls,add):
    '''увеличивает счетчик попаданий и выводит его в случае попадания точки в круг, возвращает счетчик
    на вход принимает event щелчка, массив кругов, множитель начисления быллов, начисляемые баллы обартно пропорциональны радиусу окружности'''
    global points
    for i in range(len(balls)):
        x=balls[i].pos[0]
        y=balls[i].pos[1]
        if(((event.pos[0]-x)**2+(event.pos[1]-y)**2)<balls[i].r**2):
            points += add/balls[i].r

def create_balls(n):
    '''создает шары, n - количество'''
    balls=[]
    for i in range(n):
        balls.append(ball())
    return balls

def draw_balls(balls):
    '''рисует шары из массива'''
    for i in range(len(balls)):
        balls[i].new_frame()

def gravitation(balls,a):
    '''меняет скорость шаров из переданного массива, а - ускорение'''
    for i in range(len(balls)):
        balls[i].spd[1]+=a
'''создаем шары разных видов'''
balls=create_balls(number_of_balls)
gravity_balls=create_balls(int(number_of_balls/2))
pygame.display.update()
clock = pygame.time.Clock()
finished = False

while not finished:
    clock.tick(FPS)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            finished = True
        elif event.type == pygame.MOUSEBUTTONDOWN:
            click_check(event,balls,base_points_multiplier) #проверяем попадание по шару
            click_check(event,gravity_balls,2*base_points_multiplier)
            print(points)
    draw_balls(balls) #рисуем шары
    gravitation(gravity_balls,2) #применяем гравитацию
    draw_balls(gravity_balls)
    pygame.display.update()
    screen.fill(BLACK)

pygame.quit()


from django.conf.urls import url
from .views import Discount_view, Category_view, Product_view, Product_detail_view, Category_detail_view

#These two added for viewsets
# from django.conf.urls import include
from rest_framework.routers import DefaultRouter
from django.urls import path, include
from django.contrib import admin
from . import views

router = DefaultRouter()
urlpatterns = [
    path('api/discounts', Discount_view, name='discount'),
    path('api/categories', Category_view, name='category api'),
    path('api/categories/<int:category_id>', Category_detail_view, name='category detail'),
    path('api/products', Product_view, name='product'),
    path('api/products/<int:product_id>', Product_detail_view, name='product detail api'),
    path('', views.homepage, name='home'),
    path('categories', views.categories, name='category'),
    path('categories/<int:category_id>/products', views.products, name='products'),
    path('categories/<int:category_id>/products/<int:product_id>', views.product_detail, name='product detail'),
    path('products/register', views.product_regi, name="product register"),
    path('cart/', views.cart, name='cart'),
    path('about/', views.about, name='about'),
    path('support/', views.support, name='support'),
    path('signin/', views.signin, name='signin'),
    path('register/', views.register, name='register'),
    path('signout/', views.signout, name='signout'),
    path('account/', views.account, name='account'),
    path('payment/', views.payment, name='payment'),
    path('shipping/', views.shipping, name='shipping'),
    path('application/', views.application, name='application'),
    path('order/', views.order, name='order')
]


#python program to print number pattern using while loop
n = int(input("Enter number of rows: "))
k = 1
i = 1
while i<=n:
    j = 1
    while j<+i:
        print(k,end= "")
        j+=1
        k+=1
    print()
    i+=1


############################################################################
## Django ORM Standalone Python Template
############################################################################

# Turn off bytecode generation
from datetime import time
import sys

sys.dont_write_bytecode = True

# Django specific settings
import os
project_path = "../"
project_root = "../../"
os.environ.get("DJANGO_SETTINGS_MODULE", "ctimanager.settings")
sys.path.append(project_path)
os.chdir(project_path)
import django
django.setup()
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Import your models for use in your script
from content.models import *

############################################################################
## START OF APPLICATION
############################################################################
import requests
import json
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.utils import ChromeType
from urllib.parse import urlparse, parse_qs
from PIL import Image, ImageChops, ImageDraw2, ImageFont
from io import BytesIO
import boto3

SPACES_APIKEY = os.environ.get('SPACES_APIKEY')
SPACES_APISECRET = os.environ.get('SPACES_APISECRET')

"""
class NewsSources(models.Model):
    name = models.CharField(max_length=100, blank=True)
    title = models.TextField(blank=False)
    domain = models.CharField(max_length=100, blank=False)
    rss_url = models.URLField()
    article_selector = models.CharField(max_length=255)
    region = models.CharField(max_length=5, blank=True)

    def __str__(self):
        return self.name

class News(models.Model):
    cryptopanic_id = models.IntegerField(blank=True)
    cryptopanic_url = models.URLField(blank=True)
    type = models.CharField(max_length=20, blank=False)
    domain = models.CharField(max_length=100, blank=True, null=True)
    projects = models.ManyToManyField(Project)
    # Note! The JSON1 module needs to be enables in SQL, if you get an error this might be the problem.
    votes = models.JSONField(blank=True, null=True)
    article_url = models.URLField(blank=False)
    source = models.ForeignKey(NewsSources, on_delete=models.SET_NULL, null=True)
    publish_data = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

"""

def resize_and_store(news_id, image_url):

        try:
            if image_url:

                file_path = f"{BASE_PATH}/static/content/media/news_image_{news_id}.png"

                proxies = {'http': "socks5://84.107.32.223:1080", 'https': "socks5://84.107.32.223:1080"}

                headers = {
                        "Connection": "keep-alive",
                        "DNT": "1",
                        "Upgrade-Insecure-Requests": "1",
                        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36",
                        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
                        "Sec-Fetch-Site": "none",
                        "Sec-Fetch-Mode": "navigate",
                        "Sec-Fetch-Dest": "document",
                        "Referer": "https://www.google.com/",
                        "Accept-Encoding": "gzip, deflate, br",
                        "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8" }

                response = requests.get(image_url, proxies=proxies, headers=headers)

                if response.status_code == 200:
                    img = Image.open(BytesIO(response.content))

                    if img.height < 629:
                        myheight = 629
                        hpercent = (myheight/float(img.size[1]))
                        wsize = int((float(img.size[0])*float(hpercent)))
                        img = img.resize((wsize,myheight), resample=Image.ANTIALIAS)

                    mywidth = 1200

                    wpercent = (mywidth/float(img.size[0]))
                    hsize = int((float(img.size[1])*float(wpercent)))
                    img = img.resize((mywidth,hsize), resample=Image.ANTIALIAS)

                    new_width = 1200
                    new_height = 629

                    width, height = img.size   # Get dimensions

                    left = (width - new_width)/2
                    top = (height - new_height)/2
                    right = (width + new_width)/2
                    bottom = (height + new_height)/2

                    # Crop the center of the image
                    im = img.crop((left, top, right, bottom))

                    im.save(file_path, format="png")

                    print(f"saving: {file_path}")
                    if upload_image_to_s3(file_path,f"news_image_{news_id}.png"):
                        print("image uploaded to s3")
                    else:
                        print("image not uploaded to s3")

                else:
                    print(f"Response code {response.status_code} message: {response.text}")

        except Exception as e:
            print(f"Error reading image with error: {e}")

def check_news_source(source):

    try:
        if NewsSources.objects.filter(title=source['title']).exists():
            return True
        else:
            try:
                title = source['title']
            except Exception as e:
                print("No title found for source {source}")

            try:
                domain = source['domain']
            except Exception as e:
                print("No domain found for source {source}")

            try:
                region = source['region']
            except Exception as e:
                print("No region found for source {source}")

            try:
                path = source['path']
            except Exception as e:
                print("No path found for source {source}")

            NewsSources.objects.create(domain=domain, region=region, title=title, path=path)
            return True

    except Exception as e:
        print(f"Trouble checking and adding the news source with error {e}")
        return False

def extract_video_id(url):

    query = urlparse(url)
    if query.hostname == 'youtu.be': return query.path[1:]
    if query.hostname in {'www.youtube.com', 'youtube.com'}:
        if query.path == '/watch': return parse_qs(query.query)['v'][0]
        if query.path[:7] == '/watch/': return query.path.split('/')[1]
        if query.path[:7] == '/embed/': return query.path.split('/')[2]
        if query.path[:3] == '/v/': return query.path.split('/')[2]
        # below is optional for playlists
        if query.path[:9] == '/playlist': return parse_qs(query.query)['list'][0]
   # returns None for invalid YouTube url
    return None

def get_real_url(cryptopanic_url,source_domain):
    print(f"getting real url for cryptopanic_url: {cryptopanic_url}")

    ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36'

    os.environ['WDM_LOG_LEVEL'] = '0'
    os.environ['WDM_PRINT_FIRST_LINE'] = 'False'

    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument('ignore-certificate-errors')
    chrome_options.add_argument('--proxy-server=socks5://84.107.32.223:1080')
    chrome_options.add_argument(f"--user-agent={ua}")

    try:
        if sys.platform == "darwin":
            browser = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options)
        else:
            browser = webdriver.Chrome(executable_path="chromedriver", options=chrome_options)

        browser.get(cryptopanic_url)
        time.sleep(3)
        url = browser.find_element(By.XPATH, '//*[@id="detail_pane"]/div[1]/h1/a[2]').get_attribute('href')
        print(f"article url: {url}")
        browser.quit()

        return url
    except Exception as e:
        print(f"error: {e}")

def get_article_image(article_url):

    if 'youtube.com' in article_url or 'youtu.be' in article_url:
        video_id = extract_video_id(article_url)
        url = f"https://metafetcher.gurustacks.com/video/youtube/{video_id}"

        response = requests.get(url)

        if response.status_code==200:
            if 'standard' in response.json()['images']:
                return response.json()['images']['standard']['url']
            else:
                return None

    elif 'twitter.com' in article_url:
        url = f"https://metafetcher.gurustacks.com/website/{article_url}"
        response = requests.get(url)

        if response.status_code==200:
            if 'icon_192x192' in response.json()['images']:
                return response.json()['images']['icon_192x192']
            else:
                return None

    else:
        url = f"https://metafetcher.gurustacks.com/website/{article_url}"
        response = requests.get(url)

        if response.status_code==200:
            if 'image' in response.json()['images']:
                return response.json()['images']['image']
            else:
                return None

def upload_image_to_s3(image_url, image_name):

    try:

        session = boto3.session.Session()
        client = session.client('s3', region_name='ams3',
                                endpoint_url='https://ams3.digitaloceanspaces.com',
                                aws_access_key_id=SPACES_APIKEY,
                                aws_secret_access_key=SPACES_APISECRET)

        client.upload_file(image_url, 'cryptapi-news-images', image_name, ExtraArgs={'ACL':'public-read'})
        return True

    except Exception as e:
        print(f"Error uploading file: {e}")
        return False

for num in range(1,5):

    url = f"https://cryptopanic.com/api/v1/posts/?auth_token={os.environ.get('CRYPTO_PANIC_API_KEY')}&page={num}"

    try:
        response = requests.get(url)

        if response.status_code==200:

            for item in response.json()['results']:

                if check_news_source(item['source']):
                    cryptopanic_id = item['id']

                    if item['source']['domain'] == 'twitter.com':
                        type = "twitter"
                    else:
                        type = item['kind']

                    title = item['title']
                    published_at = item['published_at']
                    cryptopanic_url = item['url']
                    votes = item['votes']
                    domain = item['domain']

                    try:
                        source_obj = NewsSources.objects.get(title=item['source']['title'])
                    except Exception as e:
                        print(f"News Source Not Found with error {e} for  {item}")

                    if News.objects.filter(cryptopanic_id=cryptopanic_id).exists():

                        try:
                            news = News.objects.get(cryptopanic_id=cryptopanic_id)

                            if news.article_url == "":
                                article_url = get_real_url(cryptopanic_url,item['source']['domain'])
                                if article_url:
                                    news.article_url = article_url
                                else:
                                    news.delete()
                                    continue

                            news.votes = item['votes']
                            news.title = item['title']
                            news.save()
                            print(f"Updating news item {item['title']}")
                        except Exception as e:
                            print(f"Failed updating news item with error {e}")

                    else:
                        try:
                            article_url = get_real_url(cryptopanic_url,item['source']['domain'])
                            if article_url is not None:
                                article_image = get_article_image(article_url)

                                if article_image is not None:
                                    news_item = News.objects.create(cryptopanic_id=cryptopanic_id, article_url=article_url, type=type, title=title, image=article_image, domain=domain, published_at=published_at, cryptopanic_url=cryptopanic_url, votes=votes, source=source_obj)
                                    print(f"Adding news item with title {title} and new news_id: {news_item.id}")

                                    # Resize and store imnage
                                    if article_image:
                                        try:
                                            resize_and_store(news_item.id, news_item.image)
                                        except Exception as e:
                                            print("Failed downloading image for news item")

                                    try:
                                        if 'currencies' in item.keys():
                                            for currency in item['currencies']:
                                                symbol = currency['code'].lower()
                                                if Project.objects.filter(symbol=symbol,status='ACTIVE').exists():
                                                    news_item.projects.add(Project.objects.filter(symbol=symbol,status='ACTIVE').first())
                                                    print(f"adding {symbol} to news item")
                                                else:
                                                    print(f"No project found for currency {symbol}")

                                    except Exception as e:
                                        print(f"Problems adding projects to news item with error {e}")
                                else:
                                    raise Exception(f"No image found for news item {item['url']}")

                            else:
                                raise Exception("Article URL not found")

                        except Exception as e:
                            print(f"Failed adding news item with error {e}")
                else:
                    print(f"Problems with the news source.. Skipping..")

        else:
            print(f"Not Hotdog! {response.status_code}")
            time.sleep(5)

    except Exception as e:
        print("Time out! Skipping")


import argparse
import subprocess
import os.path
import math

def dispatch(out_file, err_file, cmd, go, num_cores=1, num_nodes=1, max_hours=1, memory_in_gb=16):
    """
    Populates 'runscript.sh' file to run 'dqn_original.py' file
    on cluster's GPU partition for 'max_hours' hours with 1 node, 1 core, and 32GB memory
    """
    with open('runscript.sh', 'w+') as f:
        f.write(
            f"""#!/bin/bash
#SBATCH -n {num_cores}                 # Number of cores
#SBATCH -N {num_nodes}                 # Ensure that all cores are on one machine
#SBATCH -t {format_time(max_hours)}           # Runtime in D-HH:MM, minimum of 10 minutes
#SBATCH -p gpu               # Partition to submit to
#SBATCH --gres=gpu           # number of GPUs (here 1; see also --gres=gpu:n)
#SBATCH --mem={gb_to_mb(memory_in_gb)}          # Memory pool for all cores (see also --mem-per-cpu)
#SBATCH -o {out_file}  # File to which STDOUT will be written, %j inserts jobid
#SBATCH -e {err_file}  # File to which STDERR will be written, %j inserts jobid
module load Anaconda3/5.0.1-fasrc01  # Load modules
module load cudnn/7.6.5.32_cuda10.1-fasrc01
module load cuda/10.0.130-fasrc01
source activate gpt2  # Switch to correct conda environment
{cmd}  # Run code
"""
        )
    if go:
        subprocess.call(['sbatch', 'runscript.sh'])

def format_time(total_hours):
    '''Converts hours to D-HH:MM format.'''
    days = total_hours // 24
    frac_hour, hours = math.modf(total_hours % 24)
    minutes = math.ceil(frac_hour * 60.0)
    if minutes == 60:
        hours += 1
        minutes = 0
    if hours == 24:
        hours = 0
        days += 1
    return f'{int(days)}-{int(hours):02d}:{int(minutes):02d}'

def gb_to_mb(gb):
    '''Converts gb to mb'''
    mb = int(gb * 1000)
    return mb

def print_red(string):
    print('\033[1;31;40m' + string + '\033[0;37;40m')

def print_yellow(string):
    print('\033[1;33;40m' + string + '\033[0;37;40m')

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('run_name', type=str,
                        help="""
                        (str) Base name for output and error files to which SLURM writes results,
                        and ID for storing checkpoints and samples.
                        """)
    parser.add_argument('dataset', type=str,
                        help='(str) Path to dataset for training')
    parser.add_argument('restore_from', type=str,
                        help='(str) Either "latest", "fresh", or a path to a checkpoint file')
    parser.add_argument('--sample_every', default=100, type=int,
                        help='(int) How often to generate samples (every N steps)')
    parser.add_argument('--save_every', default=1000, type=int,
                        help='(int) How often to create model checkpoint (every N steps)')
    parser.add_argument('--go', action='store_true',
                        help='(flag) Submits jobs to cluster if present. Default disabled')
    parser.add_argument('--num_cores', default=1, type=int,
                        help='(int) Number of cores to run on')
    parser.add_argument('--num_nodes', default=1, type=int,
                        help='(int) Number of nodes to run on')
    parser.add_argument('--hours', default=1., type=float,
                        help='(float) Wall clock time to request on SLURM')
    parser.add_argument('--gb_memory', default=16., type=float,
                        help='(float) Memory (in GB) to request')
    args = parser.parse_args()

    basename = args.run_name
    out_file = basename + '.txt'
    err_file = basename + '.err.txt'
    cmd = f'python3 train.py --dataset {args.dataset} --restore_from {args.restore_from} --run_name {args.run_name}\
    --sample_every {args.sample_every} --save_every {args.save_every}'

    # If file for a configuration exists, skip over that configuration
    if os.path.exists(out_file) or os.path.exists(err_file):
        print_red(f'{basename} (already exists; skipping)')

    else:
        # Otherwise, generate and run script on cluster
        # Populates 'runscript.sh' file to run specified file
        # on cluster's GPU partition with specified number of nodes, cores, and memory
        # Dispatches 'runscript.sh' to SLURM if '--go' flag was specified in CLI
        print(basename)
        dispatch(out_file=out_file,
                 err_file=err_file,
                 cmd=cmd,
                 go=args.go,
                 num_cores=args.num_cores,
                 num_nodes=args.num_nodes,
                 max_hours=args.hours,
                 memory_in_gb=args.gb_memory)

    if not args.go:
        print_yellow('''
*** This was just a test! No jobs were actually dispatched.
*** If the output looks correct, re-run with the "--go" argument.''')
        print(flush=True)

if __name__ == '__main__':
    main()


from src.main.python.Solution import Solution

# Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target?
# Find all unique quadruplets in the array which gives the sum of target.
#
# Note:
#   Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
#   The solution set must not contain duplicate quadruplets.
#
# For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
#
#   A solution set is:
#       (-1,  0, 0, 1)
#       (-2, -1, 1, 2)
#       (-2,  0, 0, 2)

class Q018(Solution):
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        ans = []
        if nums:
            nums.sort()
            a = 0
            while a < len(nums)-3:
                b = a+1
                while b < len(nums)-2:
                    c, d = b+1, len(nums)-1
                    while c < d:
                        sum = nums[a]+nums[b]+nums[c]+nums[d]
                        if sum == target:
                            ans.append([nums[a], nums[b], nums[c], nums[d]])
                            c += 1
                            while c < d and nums[c] == nums[c-1]:
                                c += 1
                            d -= 1
                            while c < d and nums[d] == nums[d+1]:
                                d -= 1
                        elif sum < target:
                            c += 1
                        else:
                            d -= 1
                    b += 1
                    while b < len(nums)-2 and nums[b] == nums[b-1]:
                        b += 1
                a += 1
                while a < len(nums)-3 and nums[a] == nums[a-1]:
                    a += 1
        return ans


#Answer to Find the Runner-Up Score!

if __name__ == '__main__':
    n = int(input())
    arr = list(map(int, input().split()))
    j=-100
    k=max(arr)
    for i in arr:
        if(i>j):
            if(i!=k):
                j=i
    print(j)

Practice/Basic Data Types/Find the Runner-Up Score!.py


"""
Kaming Yip
CS677 A1 Data Science with Python
Apr 3, 2020
Assignment 9.3: Random Forest
"""

from pandas_datareader import data as web
import os
import pandas as pd
import numpy as np
from tabulate import tabulate
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import confusion_matrix
from sklearn.ensemble import RandomForestClassifier

def main():
    def get_stock(ticker, start_date, end_date):
        """
        download the historical data from yahoo web
        & manipulate the data to create desirable columns
        """
        try:
            df = web.get_data_yahoo(ticker, start=start_date, end=end_date)
            df['Return'] = df['Adj Close'].pct_change()
            df['Return'].fillna(0, inplace = True)
            df['Return'] = 100.0 * df['Return']
            df['Return'] = df['Return'].round(3)
            df['Date'] = df.index
            df['Date'] = pd.to_datetime(df['Date'])
            df['Month'] = df['Date'].dt.month
            df['Year'] = df['Date'].dt.year
            df['Day'] = df['Date'].dt.day
            for col in ['Open', 'High', 'Low', 'Close', 'Adj Close']:
                df[col] = df[col].round(2)
            df['Weekday'] = df['Date'].dt.weekday_name
            df['Week_Number'] = df['Date'].dt.strftime('%U')
            df['Year_Week'] = df['Date'].dt.strftime('%Y-%U')
            col_list = ['Date', 'Year', 'Month', 'Day', 'Weekday',
                        'Week_Number', 'Year_Week', 'Open',
                        'High', 'Low', 'Close', 'Volume', 'Adj Close',
                        'Return']
            num_lines = len(df)
            df = df[col_list]
            print('read', num_lines, 'lines of data for ticker:' , ticker)
            return df
        except Exception as error:
            print(error)
            return None

    # design the selected stock name and time frame
    try:
        ticker='YELP'
        input_dir = os.getcwd()
        output_file = os.path.join(input_dir, ticker + '.csv')
        df = get_stock(ticker, start_date='2016-01-01', end_date='2019-12-31')
        df.to_csv(output_file, index=False)
        print('wrote ' + str(len(df)) + ' lines to file: ' + ticker + '.csv', end = "\n\n" + "-" * 50 + "\n\n")
    except Exception as e:
        print(e)
        print('failed to get Yahoo stock data for ticker: ', ticker, end = "\n\n" + "-" * 50 + "\n\n")

    def weekly_return_volatility(data, start_date, end_date):
        """
        calculate the weekly mean return and volatility
        & create a new file to contain these infor
        """
        try:
            df_2 = data[data['Date'] >= start_date]
            df_2 = df_2[df_2['Date'] <= end_date]
            df_2 = df_2[['Year', 'Week_Number', 'Open', 'Adj Close', 'Return']]
            df_2.index = range(len(df_2))
            df_grouped = df_2.groupby(['Year', 'Week_Number'])['Return'].agg([np.mean, np.std])
            df_grouped.reset_index(['Year', 'Week_Number'], inplace=True)
            df_grouped.rename(columns={'mean': 'mean_return', 'std':'volatility'}, inplace=True)
            df_grouped.fillna(0, inplace=True)
            df_grouped["Open"] = df_2.groupby(["Year", "Week_Number"])["Open"].head(1).\
                                 reset_index(drop = True).copy()
            df_grouped["Adj Close"] = df_2.groupby(["Year", "Week_Number"])["Adj Close"].tail(1).\
                                      reset_index(drop = True).copy()
            return df_grouped
        except Exception as error:
            print(error)
            return None

    # create the weekly dataframe with mean return and volatility values
    try:
        df_weekly = weekly_return_volatility(df, start_date='2018-01-01', end_date='2019-12-31')
    except Exception as e:
        print("Error in weekly_return_volatility: ", end = " ")
        print(e)

    def weekly_label(data, year):
        """
        to create labels
        """
        try:
            df_label = data[data["Year"] == year].copy()
            mean_return_percent50 = np.percentile(df_label["mean_return"], 50)
            volatility_percent50 = np.percentile(df_label["volatility"], 50)
            df_label["True Label"] = np.where((df_label["mean_return"] >= mean_return_percent50) & \
                                              (df_label["volatility"] <= volatility_percent50), "Green", "Red")
            return df_label
        except Exception as error:
            print(error)
            return None

    try:
        df_labeling = pd.DataFrame()
        for year in [2018, 2019]:
            df_year_label = weekly_label(df_weekly, year)
            label_count = df_year_label.groupby("True Label")["True Label"].size().to_frame(name = "Freq")
            print("Label Count for Year {0}".format(year))
            print(tabulate(label_count, headers = "keys", numalign = "right"), end = "\n\n")
            df_labeling = df_labeling.append(df_year_label, ignore_index = True)
        df_labeling["Week_Number"] = df_labeling["Week_Number"].astype(int)
    except Exception as e:
        print("Error in weekly_label:", end = " ")
        print(e)

    def random_forest(train_data, test_data, predictor, N, d):
        # train the Random Forest model by stock data in year 1
        train_X = train_data[predictor].values
        le = LabelEncoder()
        train_Y = le.fit_transform(train_data["True Label"].values)
        model = RandomForestClassifier(n_estimators = N, max_depth = d,
                                       criterion = "entropy", random_state = 3)
        model.fit(train_X, train_Y)

        # predict the labels in year 2
        test_X = test_data[predictor].values
        test_Y = le.fit_transform(test_data["True Label"].values)
        pred_Y = model.predict(test_X)
        error_rate = np.mean(pred_Y != test_Y)
        pred_Y = le.inverse_transform(pred_Y)
        return pred_Y, error_rate

    def designed_confusion_matrix(actual, pred):
        cm = confusion_matrix(actual, pred)
        list_of_tuples = list(zip(cm[0], cm[1]))
        designed_cm = pd.DataFrame(list_of_tuples,
                                   columns = ["Actual Green", "Actual Red"],
                                   index = ["Predicted Green", "Predicted Red"])
        diagonal_sum = cm.trace()
        sum_of_all_elements = cm.sum()
        accuracy = diagonal_sum / sum_of_all_elements
        TPR = cm[0,0]/(cm[0,0] + cm[0,1])
        TNR = cm[1,1]/(cm[1,0] + cm[1,1])
        return designed_cm, accuracy, TPR, TNR

    def printout(actual, pred, year):
        cm, accuracy, TPR, TNR = designed_confusion_matrix(actual, pred)
        print(" * The Confusion Matrix for Year {0} * ".format(year),
              cm,
              "The accuracy of this model is {0:.3f}.\n".format(accuracy) +\
              "The true positive rate of this model is {0:.3f}.\n".format(TPR) +\
              "The true negative rate of this model is {0:.3f}.\n".format(TNR),
              sep = "\n\n", end = "\n\n")

    def trade_with_labels(data, col_name):
        money = 100.0
        shares = 0.0
        position = "No"
        balance = []
        df_trade_labels = data.copy()
        for i in range(len(df_trade_labels) - 1):
            if i == 0:
                label = df_trade_labels.iloc[i][col_name]
                if label == "Green":
                    shares = money / df_trade_labels.iloc[i]["Open"]
                    money = 0.0
                    position = "Long"
                    balance.append(shares * df_trade_labels.iloc[i]["Adj Close"])
                else:
                    balance.append(money)
            else:
                label = df_trade_labels.iloc[i+1][col_name]
                if label == "Red":
                    if position == "Long":
                        money = shares * df_trade_labels.iloc[i]["Adj Close"]
                        shares = 0.0
                        position = "No"
                    balance.append(money)
                else:
                    if position == "No":
                        shares = money / df_trade_labels.iloc[i+1]["Open"]
                        money = 0.0
                        position = "Long"
                    balance.append(shares * df_trade_labels.iloc[i]["Adj Close"])
        if position == "Long":
            balance.append(shares * df_trade_labels.iloc[-1]["Adj Close"])
        else:
            balance.append(money)
        return balance

    def script_text(data, year, col_name):
        label_text_max = "{0} Week {1}\nmax ${2}".\
                         format(year,
                                data.iloc[data[data["Year"] == year][col_name].idxmax()]["Week_Number"],
                                round(data[data["Year"] == year][col_name].max(), 2))
        label_x_max = data[data["Year"] == year][col_name].idxmax()
        label_y_max = round(data[data["Year"] == year][col_name].max(), 2)

        label_text_min = "{0} Week {1}\nmin ${2}".\
                         format(year,
                                data.iloc[data[data["Year"] == year][col_name].idxmin()]["Week_Number"],
                                round(data[data["Year"] == year][col_name].min(), 2))
        label_x_min = data[data["Year"] == year][col_name].idxmin()
        label_y_min = round(data[data["Year"] == year][col_name].min(), 2)

        label_text_final = "{0} Final:\n${1}".format(year, round(data[data["Year"] == year].iloc[-1][col_name], 2))
        label_x_final = data[data["Year"] == year].tail(1).index.values
        label_y_final = round(data[data["Year"] == year].iloc[-1][col_name], 2)

        return label_text_max, label_x_max, label_y_max,\
                   label_text_min, label_x_min, label_y_min,\
                       label_text_final, label_x_final, label_y_final

    def buy_n_hold(data):
        money = 100.0
        shares = 0.0
        balance = []
        df_buy_hold = data.copy()
        for i in range(len(df_buy_hold)):
            if i == 0:
                shares = money / df_buy_hold.iloc[i]["Open"]
            balance.append(shares * df_buy_hold.iloc[i]["Adj Close"])
        return balance

    ########## Q1 ##########
    print("\n" + "#" * 35 + " Q1 " + "#" * 35 + "\n")
    try:
        df_2018 = df_labeling.loc[df_labeling["Year"] == 2018].copy().reset_index(drop = True)
        df_2019 = df_labeling.loc[df_labeling["Year"] == 2019].copy().reset_index(drop = True)
        predictor = ["mean_return", "volatility"]
        Y_2019 = df_2019[["True Label"]].values
        N_list = list(range(1, 11))
        d_list = list(range(1, 6))
        x_list = []
        y_list = []
        size_list = []
        results = pd.DataFrame(columns = N_list, index = d_list)
        best_combo = [0, 0, float("inf")]
        for N in N_list:
            for d in d_list:
                x_list.append(N)
                y_list.append(d)
                pred_Y, error_rate = random_forest(df_2018, df_2019, predictor, N, d)
                results.loc[d, N] = error_rate
                size_list.append(error_rate)
                if error_rate < best_combo[2]:
                    best_combo = [N, d, error_rate]
                else:
                    pass
        results = results.astype(float)
        print(" " * 10 + " * The Error Rate Results of Different Random Forests * ",
              tabulate(results.round(3), headers = "keys", numalign = "left"),
              sep = "\n\n", end = "\n\n")

        min_size, max_size = min(size_list), max(size_list)
        for i, ele in enumerate(size_list):
            size_list[i] = (ele - min_size) / (max_size - min_size) * 800
        plt.figure(figsize = (8, 4))
        plt.scatter(x_list, y_list, marker = ".", s = size_list)
        plt.title("The Error Rates with Different Combinations of N and d")
        plt.xlabel("Number of Trees (N)")
        plt.xticks(N_list)
        plt.ylabel("Max Depth of Each Subtree (d)")
        plt.yticks(d_list)
        plt.show()

        print("\nAs displayed above, the best combination is N = {0:d}, d = {1:d},".\
              format(best_combo[0], best_combo[1]),
              "with the minimal error rate of {0:.3f}.".format(best_combo[2]),
              sep = "\n")
    except Exception as e:
        print("Error in Question 1:", end = " ")
        print(e)

    ########## Q2 & Q3 ##########
    print("\n" + "#" * 35 + " Q2 & Q3 " + "#" * 35 + "\n")
    try:
        optimal_N, optimal_d = best_combo[0], best_combo[1]
        pred_Y, error = random_forest(df_2018, df_2019, predictor, optimal_N, optimal_d)
        printout(Y_2019, pred_Y, 2019)
    except Exception as e:
        print("Error in Question 2:", end = " ")
        print(e)

    ########## Q4 ##########
    print("\n" + "#" * 35 + " Q4 " + "#" * 35 + "\n")
    try:
        df_trading = df_labeling[df_labeling["Year"] == 2019].copy().reset_index(drop = True)
        df_trading["True Label Balance"] = trade_with_labels(df_trading, "True Label")
        df_trading["Buy and Hold Balance"] = buy_n_hold(df_trading)
        df_trading["Random Forest Label"] = pred_Y
        df_trading["Random Forest Balance"] = trade_with_labels(df_trading, "Random Forest Label")

        fig, ax = plt.subplots(figsize = (9, 5))

        label_text_max_2019, label_x_max_2019, label_y_max_2019,\
            label_text_min_2019, label_x_min_2019, label_y_min_2019,\
                label_text_final_2019, label_x_final_2019, label_y_final_2019 =\
                    script_text(df_trading, 2019, "True Label Balance")

        forest_text_max_2019, forest_x_max_2019, forest_y_max_2019,\
            forest_text_min_2019, forest_x_min_2019, forest_y_min_2019,\
                forest_text_final_2019, forest_x_final_2019, forest_y_final_2019 =\
                    script_text(df_trading, 2019, "Random Forest Balance")

        buy_hold_text_max_2019, buy_hold_x_max_2019, buy_hold_y_max_2019,\
            buy_hold_text_min_2019, buy_hold_x_min_2019, buy_hold_y_min_2019,\
                buy_hold_text_final_2019, buy_hold_x_final_2019, buy_hold_y_final_2019 =\
                    script_text(df_trading, 2019, "Buy and Hold Balance")

        # Trading with True Label
        ax.plot(df_trading.index, "True Label Balance", data = df_trading, color = "blue")

        ax.annotate(label_text_max_2019, xy = (label_x_max_2019, label_y_max_2019), xycoords = "data",
                    xytext = (label_x_max_2019+5, label_y_max_2019+5), color = "blue",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "blue"),
                    ha = "left", va = "bottom")
        ax.annotate(label_text_min_2019, xy = (label_x_min_2019, label_y_min_2019), xycoords = "data",
                    xytext = (label_x_min_2019+5, label_y_min_2019+17), color = "blue",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "blue"),
                    ha = "left", va = "bottom")
        ax.annotate(label_text_final_2019, xy = (label_x_final_2019, label_y_final_2019), xycoords = "data",
                    xytext = (label_x_final_2019+5, label_y_final_2019-5), color = "blue",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "blue"),
                    ha = "left", va = "bottom")

        # Buy and Hold
        ax.plot(df_trading.index, "Buy and Hold Balance", data = df_trading, color = "red")

        ax.annotate(buy_hold_text_max_2019, xy = (buy_hold_x_max_2019, buy_hold_y_max_2019), xycoords = "data",
                    xytext = (buy_hold_x_max_2019+5, buy_hold_y_max_2019+11), color = "red",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "red"),
                    ha = "left", va = "bottom")
        ax.annotate(buy_hold_text_min_2019, xy = (buy_hold_x_min_2019, buy_hold_y_min_2019), xycoords = "data",
                    xytext = (buy_hold_x_min_2019+4, buy_hold_y_min_2019+2), color = "red",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "red"),
                    ha = "left", va = "bottom")
        ax.annotate(buy_hold_text_final_2019, xy = (buy_hold_x_final_2019, buy_hold_y_final_2019), xycoords = "data",
                    xytext = (buy_hold_x_final_2019+5, buy_hold_y_final_2019-2), color = "red",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "red"),
                    ha = "left", va = "bottom")

        # Trading with Decision Tree Label
        ax.plot(df_trading.index, "Random Forest Balance", data = df_trading, color = "green")

        ax.annotate(forest_text_max_2019, xy = (forest_x_max_2019, forest_y_max_2019), xycoords = "data",
                    xytext = (forest_x_max_2019+5, forest_y_max_2019+5), color = "green",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "green"),
                    ha = "left", va = "bottom")
        ax.annotate(forest_text_min_2019, xy = (forest_x_min_2019, forest_y_min_2019), xycoords = "data",
                    xytext = (forest_x_min_2019+5, forest_y_min_2019+27), color = "green",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "green"),
                    ha = "left", va = "bottom")
        ax.annotate(forest_text_final_2019, xy = (forest_x_final_2019, forest_y_final_2019), xycoords = "data",
                    xytext = (forest_x_final_2019+5, forest_y_final_2019-15), color = "green",
                    arrowprops = dict(arrowstyle = "->", connectionstyle = "angle,angleA=0,angleB=90", color = "green"),
                    ha = "left", va = "bottom")

        plt.title("* Year 2019 *\n" + "Performance against Different Investing Strategies", loc = "center")
        plt.xlabel("Week Number")
        plt.xticks(np.arange(0, 60, 5))
        plt.ylabel("Total Balance($)")
        plt.legend()
        plt.show()

        print("\nAs displayed in the plot above, the {0} strategy results in a".\
              format("buy-and-hold" if buy_hold_y_final_2019 > forest_y_final_2019 else "Random Forest Classifier"),
              "larger amount as ${0} at the end of the year 2019.".\
              format(buy_hold_y_final_2019 if buy_hold_y_final_2019 > forest_y_final_2019 else forest_y_final_2019),
              sep = "\n")
    except Exception as e:
        print("Error in Question 4:", end = " ")
        print(e)

main()


import pyodbc
from db_connect_oop import *

class NWEmployees(MSDBConnection):

    def all_employees(self):
        query = 'select * from employees'
        data = self._MSDBConnection__sql_query(query)
        while True:
            record = data.fetchone()
            if record is None:
                break
            print(record)

    def one_employee(self):
        employee_id = input('Input employee id: ')
        query = f"select * from employees where EmployeeID = '{employee_id}'"
        employee_id_info = self._MSDBConnection__sql_query(query).fetchone()
        return employee_id_info

    def employee_search(self):
        employee_name = input('Insert employee name: ')
        query = f"select * from employees where FirstName like '%{employee_name}%' or LastName like '%{employee_name}%'"
        employee_name_info = self._MSDBConnection__sql_query(query).fetchone()
        return employee_name_info