import re

PATTERN = '\[(\d+)-(\d+)-(\d+) (\d+):(\d+)\] (?:Guard #(\d+) )?(begins shift|wakes up|falls asleep)'

records = []

with open('input.txt', 'r') as f:
    for line in f:
        match = re.findall(PATTERN, line.rstrip())[0]

        date = (int(match[0]), int(match[1]), int(match[2]), int(match[3]), int(match[4]))
        action = match[5]
        gid = match[6]

        records.append((date, action, gid))

records = sorted(records, key=lambda r: r[0])

naps = {}
cur_guard = 0
start = 0
for record in records:
    if record[1]:
        cur_guard = record[1]
    elif record[2] == 'falls asleep':
        start = record[0][4]
    elif record[2] == 'wakes up':
        for i in range(start, record[0][4]):
            guard_naps = naps.setdefault(cur_guard, [0] * 60)
            guard_naps[i] += 1

# Part 1
sleepy_guard, time = 0, 0
for guard, guard_naps in naps.items():
    if sum(guard_naps) > time:
        sleepy_guard, time = guard, sum(guard_naps)

hour = naps[sleepy_guard].index(max(naps[sleepy_guard]))
print(int(sleepy_guard) * hour)

# Part 2
sleepy_guard, maxtime = 0, 0

for guard, guard_naps in naps.items():
    if max(guard_naps) > maxtime:
        sleepy_guard, maxtime = guard, max(guard_naps)

print(int(sleepy_guard) * naps[sleepy_guard].index(maxtime))


from enum import Enum
import os.path
import cv2
import numpy as np

# ----------------------------------------------------------------------------
# Define Test Images
def test_images():
    """Generator to return test images.

    :return:        Test Image Filename
    :rtype:         str
    """
    test_directory = './NICTA/TestSet/PositiveSamples'
    test_set = [
        'item_00000000.pnm'
    ]
    for image, _ in enumerate(test_set):
        yield os.path.join(test_directory, test_set[image])

def gamma_correction(image, gamma=1.0):
    """Power-Law (Gamma) Transformation of grayscale image.

    :param image:   Original Image
    :type:          numpy.ndarray
    :param gamma:   Gamma value to apply
    :type:          float
    :return:        gamma transformed image file
    :rtype:         numpy.ndarray
    """
    bits_per_pixel = np.iinfo(image.dtype).max

    norm_image = image / np.max(image)
    new_image = bits_per_pixel * np.power(norm_image, gamma)
    new_image = new_image.astype(np.uint8)

    return new_image

def compute_gradients(image, is_signed=False):
    """
    - Cellsize[8 8]
    - Blocksize[16 16]
    - Gradient operators: Gx = [-1 0 1] and Gy = [-1 0 1]T
    - Number of orientation bins = 9

    :param is_signed:
    :param image:
    :return:
    """
    kernel_prewitt = np.array([[1, 1, 1],
                               [0, 0, 0],
                               [-1, -1, -1]])
    gradient_x = cv2.filter2D(image, -1, kernel_prewitt)
    gradient_y = cv2.filter2D(image, -1, np.transpose(kernel_prewitt))

    orientation_size = 360 if is_signed else 180

    magnitude = np.sqrt(np.square(gradient_x) + np.square(gradient_y))
    angle = np.arctan2(gradient_y, gradient_x) * (orientation_size / np.pi)
    return gradient_x, gradient_y, magnitude, angle

def calculate_histogram(magnitudes, angles, bin_count=9, is_signed=False):
    """Calculate the localized histogram of each cell.

    :param magnitudes:          The maginitude of each cell
    :type:                      np.ndarray
    :param angles:              The angle of each cell
    :type:                      np.ndarray
    :param bin_count:           The bins of each cell
    :type:                      int
    :param is_signed:           Should angular data be signed?
    :type:                      bool
    :return:                    Histogram of cell
    :rtype:                     np.array
    """
    cell_size_x, cell_size_y = magnitudes.shape
    orientation_size = 360 if is_signed else 180
    bin_width = orientation_size // bin_count
    cell_histogram = np.zeros(bin_count)
    for row in range(cell_size_x):
        for col in range(cell_size_y):
            orientation = angles[row][col]
            histogram_bin = int(orientation // bin_width)
            cell_histogram[histogram_bin] += magnitudes[row][col]
    return cell_histogram / np.product(magnitudes.shape)

def compute_weighted_vote(gradient, cell_size=(8, 8), bin_count=9, is_signed=False):
    """Compute the weighted vote of each cell.

    :param gradient:            Gradient value of each cell
    :type:                      np.ndarray
    :param cell_size:           2D cell size
    :type:                      tuple
    :param bin_count:           number of bins
    :type:                      int
    :param is_signed:           is the orientatinos signed or not
    :type:                      bool
    :return:                    weighted histgram
    :rtype:                     np.ndarray
    """

    gradient_x = gradient[0]
    gradient_y = gradient[1]
    gradient_magnitudes = gradient[2]
    gradient_angles = gradient[3]

    grad_size_x, grad_size_y = gradient_magnitudes.shape
    cell_size_x, cell_size_y = cell_size
    cell_count_x = int(grad_size_x / cell_size_x)  # Number of cells in x axis
    cell_count_y = int(grad_size_y / cell_size_y)  # Number of cells in y axis

    #print("[INFO] Cell counts:  x={} y={}".format(cell_count_x, cell_count_y))
    hog_cells = np.zeros((cell_count_x, cell_count_y, bin_count))

    prev_x = 0
    # Compute HOG of each cell
    for row in range(cell_count_x):
        prev_y = 0
        for col in range(cell_count_y):
            magnitudes_cell = gradient_magnitudes[prev_x:prev_x + cell_size_x, prev_y:prev_y + cell_size_y]
            angles_cell = gradient_angles[prev_x:prev_x + cell_size_x, prev_y:prev_y + cell_size_y]
            hog_cells[row][col] = calculate_histogram(magnitudes_cell, angles_cell, bin_count, is_signed)

            prev_y += cell_size_y
        prev_x += cell_size_x

    #print("[DEBUG] Cells array shape:    {}".format(hog_cells.shape))

    return hog_cells, (cell_count_x, cell_count_y)

def contrast_normalize(vector, epsilon=1e-5):
    """Performt the L2-norm on block.

    :param vector:          The input
    :type:                  np.ndarray
    :param epsilon:         That CYA value
    :type:                  float
    :return:                Normalized block
    :rtype"                 np.ndarray
    """
    #print("[DEBUG]  What am I normalizing?:  {}".format(vector.shape))
    return vector / np.sqrt(np.linalg.norm(np.square(vector), 2) + np.square(epsilon))

def normalize_blocks(cells, cell_size=(8, 8), block_size=(16, 16), bin_count=9):
    """Normalize all the things!

    :param cells:           Input cell
    :type:                  np.ndarray
    :param cell_size:       2D tuple
    :type:                  tuple
    :param block_size:      2D tuple
    :type:                  tuple
    :param bin_count:       Number of bins
    :type:                  bin
    :return:                Array of normalized blocks
    :rtype:                 np.ndarray
    """
    cell_size_x, cell_size_y = cells.shape[:2]
    block_size_x, block_size_y = block_size
    block_count_x = cell_size_x - 1
    block_count_y = cell_size_y - 1
    cells_per_block_x = int(block_size_x // cell_size[0])
    cells_per_block_y = int(block_size_y // cell_size[1])
    #print("[INFO] Block counts:  x={} y={}".format(block_count_x, block_count_y))

    normalized_blocks = np.zeros((block_count_x, block_count_y, cells_per_block_x*cells_per_block_y*bin_count))

    # Normalize HOG by block
    for row in range(block_count_x):
        for col in range(block_count_y):
            xrange = row+cells_per_block_x
            yrange = col+cells_per_block_y
            #print("[DEBUG] Row={} Col={}\n\t Getting cells {} and {}".format(row, col, xrange, yrange))
            hog_block = cells[row:row + cells_per_block_x, col:col + cells_per_block_y].ravel()
            normalized_blocks[row, col] = contrast_normalize(hog_block)

    return normalized_blocks, (block_count_x, block_count_y)

if __name__ == '__main__':
    for my_image in test_images():
        # Step 1 - Input Image
        # Load in the test image, resize to 64x128, and convert to grayscale
        print("[INFO] Loading test image {}".format(my_image))
        test_image = cv2.imread(my_image)
        test_image = cv2.resize(test_image, (64, 128))
        test_image = cv2.cvtColor(test_image, cv2.COLOR_RGB2GRAY)

        # Step 2 - Normalize gamma and color
        gamma_value = 1.0
        test_image = gamma_correction(test_image, gamma_value)

        # Step 3 - Compute gradients
        test_gradient = compute_gradients(test_image)
        TEST_GRADIENT = True
        if TEST_GRADIENT:
            gx, gy = test_gradient[0], test_gradient[1]
            gheight = gx.shape[1] * 4
            gwidth = gx.shape[0] * 4
            gx = cv2.resize(gx, (gheight, gwidth))
            gy = cv2.resize(gy, (gheight, gwidth))
            output_stack = np.hstack((gx, gy))
            cv2.imshow('Filter results', output_stack)
            cv2.waitKey(0)

        # Step 4 - Weighted vote into spatial and orientation cells
        cell_histograms, _ = compute_weighted_vote(test_gradient)

        # Step 5 - Contrast normalize over overlapping spatial blocks
        hog_blocks, _ = normalize_blocks(cell_histograms)
        # Step 6 - Collect HOG's over detection window

        print(hog_blocks.ravel().shape)
        # Step 7 - Linear SVM

    cv2.destroyAllWindows()


lst = [1, 2, 3, 4, 5]
for items in lst:
    print(items)

# add date to the last using append method

lzt = []
for i in range(1, 10, 2):
    lzt.append(i)
print(lzt)


'''
-Medium-

Given a string s and an integer k, return true if you can use all the characters in s to construct k palindrome strings or false otherwise.

Example 1:

Input: s = "annabelle", k = 2
Output: true
Explanation: You can construct two palindromes using all characters in s.
Some possible constructions "anna" + "elble", "anbna" + "elle", "anellena" + "b"
Example 2:

Input: s = "leetcode", k = 3
Output: false
Explanation: It is impossible to construct 3 palindromes using all the characters of s.
Example 3:

Input: s = "true", k = 4
Output: true
Explanation: The only possible solution is to put each character in a separate string.

Constraints:

1 <= s.length <= 105
s consists of lowercase English letters.
1 <= k <= 105

'''

from collections import Counter

class Solution:
    def canConstruct(self, s: str, k: int) -> bool:
        n = len(s)
        if n < k: return False
        elif n == k: return True
        cnt = Counter(s)
        odd = sum(1 for x in cnt.values() if x % 2)
        return True if odd <= k else False

if __name__ == "__main__":
    # print(Solution().canConstruct(s = "annabelle", k = 2))
    print(Solution().canConstruct(s ="yzyzyzyzyzyzyzy", k = 2))


from hypertunity.domain import Domain
from hypertunity.optimisation import random

from . import _common as test_utils

def test_random_simple_continuous():
    domain = Domain({"x": [-1., 6.]})
    rs = random.RandomSearch(domain=domain, seed=7)
    test_utils.evaluate_continuous_1d(rs, batch_size=50, n_steps=2)

def test_random_simple_mixed():
    domain = Domain({"x": [-5., 6.], "y": {"sin", "sqr"}, "z": set(range(4))})
    rs = random.RandomSearch(domain=domain, seed=1)
    test_utils.evaluate_heterogeneous_3d(rs, batch_size=50, n_steps=25)

def test_update():
    domain = Domain({"x": [-5., 6.]})
    rs = random.RandomSearch(domain)
    rs.update([domain.sample() for _ in range(4)], list(range(4)))
    rs.update(domain.sample(), {"score": 23.0})
    rs.update(domain.sample(), 2.0)
    assert len(rs.history) == 6
    rs.reset()
    assert len(rs.history) == 0


"""
Custom FTS tokeniser and suffixer.

For our suffix table tokeniser, we have two modes: When search_mode is False,
all terms are expanded to their suffixes.  When search_mode is True, it acts
like the normal tokeniser.  (We don't want to get search results for *all*
the possible suffixes within the search terms.)
"""
import functools
import re

import oce.logger

logger = oce.logger.getLogger(__name__)

from oce.providers.sqlite.bindings import Tokenizer

class OCETokeniser(Tokenizer):
    """
    Custom tokeniser:
    1) Folds text to lower case
    2) Treats all non-alphanumeric ASCII chars as delimiters
    3) Each character outside the ASCII range is treated as one single
       token
    """

    def tokenize(self, text):
        """
        Expected to return an iterator over the tokens in `text`.
        """
        text = text.lower()
        list_tokens = self.tokenise_as_list(text)
        return iter(list_tokens)

    @functools.lru_cache(maxsize=128)
    def tokenise_as_list(self, text):
        """
        Memoised version of the tokeniser; returns a list instead of an
        iterator.  This cache should not need to be cleared; any
        modifications to the tokeniser will only take effect on restart
        """
        logger.debug('Running OCETokeniser: {}'.format(text))

        tokenised_list = []

        token_open = False
        token_start = 0
        token_end = 0
        for char in text:
            if re.match(r'[^a-zA-Z0-9]', char):
                # The character is non-alphanumeric.  If it is within the
                # ASCII range, close the current token and yield it.  If
                # not, yield it as a new token.
                if ord(char) <= 127:
                    if token_open:
                        # Was in token.  Yield token and advance cursors
                        # to next character.
                        token_open = False
                        tokenised_list.append(self.yield_token(text,
                                                               token_start,
                                                               token_end))
                        token_end += 1
                        token_start = token_end
                    else:
                        # Was not in token.  Advance cursors in tandem.
                        token_end += 1
                        token_start += 1
                else:
                    if token_open:
                        # Was in token.  Yield and advance start cursor.
                        token_open = False
                        tokenised_list.append(self.yield_token(text,
                                                               token_start,
                                                               token_end))
                        token_start = token_end

                    # Yield one more character (the non-ASCII one)
                    token_end += 1
                    tokenised_list.append(self.yield_token(text,
                                                           token_start,
                                                           token_end))
                    token_start = token_end
            else:
                # In a token.  Move the end cursor.
                token_open = True
                token_end += 1

        # Yield the last token
        if token_open:
            tokenised_list.append(self.yield_token(text,
                                                   token_start,
                                                   token_end))

        return tokenised_list

class OCESuffixes(Tokenizer):
    """
    Custom tokeniser:
    1) Runs against OCETokeniser to get tokenised input string.
    2) For each token in the input, returns the suffix array for that token
       if the token has length > 1

    UNLESS:
    1) If search_mode is True, returns only the output of OCETokeniser (
       so that we don't unnecessarily process search queries)
    """

    def __init__(self, main_tokeniser):
        self.main_tokeniser = main_tokeniser
        self.search_mode = False

    def tokenize(self, text):
        """
        Expected to return an iterator over the tokens in `text`.
        """
        text = text.lower()
        list_suffixes = self.suffixes_as_list(text, self.search_mode)
        return iter(list_suffixes)

    @functools.lru_cache(maxsize=128)
    def suffixes_as_list(self, text, search_mode):
        """
        Memoised version of the suffixer; returns a list instead of an
        iterator.  This cache should not need to be cleared; any
        modifications to the tokeniser will only take effect on restart
        """
        logger.debug(
            "Running OCESuffixer: {}, search_mode: {}".format(text,
                                                              search_mode)
        )

        # Perform any pre-processing that might be appropriate
        text = self._preprocess_text(text)

        # The start and end values given by OCETokeniser are in bytes,
        # but we prefer to work with characters; we'll convert them in the
        # loop.
        b_text = text.encode('utf-8')

        main_tokenised = self.main_tokeniser.tokenise_as_list(text)
        if search_mode:
            return main_tokenised

        tokenised_list = []
        for token, b_start, b_end in main_tokenised:
            if len(token) == 1:
                # One character token.  No need to extract suffixes.
                continue

            # Byte position -> Character position
            c_before = len(b_text[:b_start].decode('utf-8'))

            # Skip the first suffix (i.e., the whole token)
            c_start = c_before + 1
            c_end = c_before + len(token)
            for suffix_start in range(c_start, c_end):
                tokenised_list.append(self.yield_token(text,
                                                       suffix_start,
                                                       c_end))

        return tokenised_list

    def _preprocess_text(self, text):
        """
        Do stuff to the record before finding its suffixes.
        """
        # Try to remove the UUID part of URLs from Twitter's URL shortener.
        # (They gum up the suffix database with a whole bunch of
        # single-record entries)
        # http://t.co/<UUID>
        text = re.sub(r'http://t[.]co/[a-zA-Z0-9]+', 'http://t.co/', text)

        return text


import logging
import traceback

from queue import Queue, Full
from threading import Thread

from . import command

#NOTE Thread lock if TOTAL_WORKER_THREADS is 1:
#    In Queue.put(), the new worker thread blocks, if the last worker thread in the _queue is still running -->
#    the _queue is not full and therefore Queue.put() does not time-out and a Queue.Full exception is not raised.
TOTAL_WORKER_THREADS = 8

logger = logging.getLogger(__name__)

# Singleton wrapper class (class containing a singleton)
class CommandQueue:
    """ Push commands in one of the available queues and execute them when popped from the queue.
        Running commands from different queues run in parallel.
    """

    class _Worker(Thread):

        def __init__(self, queue):
            Thread.__init__(self)
            self._queue = queue

        def run(self):
            while True:
                cmd, keywords = self._queue.get()
                try:
                    command.run(cmd, **keywords)
                except:
                    traceback.print_exc()
                    #raise
                self._queue.task_done()

    def __init__(self):
        self._queue = _get_queue()

        # Start worker threads
        for unused_i in range(TOTAL_WORKER_THREADS):
            thread = CommandQueue._Worker(self._queue)
            thread.setDaemon(True)
            thread.start()

    def run(self, cmd, **keywords):
        try:
            # Timeout (in seconds)
            self._queue.put((cmd, keywords), True, 2)
            logger.debug("run(): _queue size=" + str(self._queue.qsize()) + ", empty=" + str(self._queue.empty()) + ", full=" + str(self._queue.full()))
        except Full:
            return False
        return True

# Convenience method
#def run(*arguments, **keywords):
def run(cmd, **keywords):
    """ Push the command on a queue and run the command when there is a thread free to run the command.
        Return true if command was successfully put on the queue.
    """
    #return CommandQueue().run(*arguments, **keywords)
    return CommandQueue().run(cmd, **keywords)

def size():
    """ Return queue size. """
    return _get_queue().qsize()

####

# Singleton queue
_queue = None

def _get_queue():
    global _queue
    #if _command_queue is None:
    if not _queue:
        _queue = Queue()
    return _queue


try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

with open('README.md', 'r') as f:
    long_description = f.read()

setup(
    name='codetimer',
    version='1.0.0',
    packages=['codetimer'],
    url='https://github.com/gulaki/code-timer',
    license='MIT',
    author='Anustuv',
    author_email='anustuv@gmail.com',
    description='A library of methods to time code paths and functions in a flexible way.'
)


#
# Definition for binary tree:
# class Tree(object):
#   def __init__(self, x):
#     self.value = x
#     self.left = None
#     self.right = None
def largestValuesInTreeRows(t):

    if not t:
        return []

    # value at key is the largest at depth key in tree
    largest = {}
    queue = []
    queue.insert(0, (t, 0))

    # BFS
    while queue:
        curr, depth = queue.pop()

        if largest.get(depth, 0):
            if curr.value > largest[depth]:
                largest[depth] = curr.value
        else:
            largest[depth] = curr.value

        if curr.left:
            queue.insert(0, (curr.left, depth+1))
        if curr.right:
            queue.insert(0, (curr.right, depth+1))

    result = []
    for i in sorted(largest.keys()):
        result.append(largest[i])

    return result

CodingTasks/Depth-First Search - Breadth-First Search/largestValuesInTreeRows/largestValuesInTreeRows.py


import sys
import numpy as np

if __name__ == '__main__':
    File = sys.argv[1]
    with open(File) as f:
        lines = f.read().splitlines()
    out = []
    for i in lines:
        i = list(map(int, list(i)))
        out.append(i)

    out = np.array(out)
    gamma = np.sum(out, 0) > np.shape(out)[0]/2
    epsilon = 1-gamma
    Mask = np.flip(2**np.arange(0, np.shape(out)[1], 1))
    print("{} --> {}".format(1*gamma, np.sum(gamma * Mask)))
    print("{} --> {}".format(1*epsilon, np.sum(epsilon * Mask)))

    print(np.sum(gamma * Mask) * np.sum(epsilon * Mask))


# Gerenciamento de Memória na GPU através da muliplicação de 2 matrizes

# Pacotes
import numpy as np
from pycuda import driver, compiler, gpuarray, tools

# Inicializando o device
import pycuda.autoinit

# Kernel
kernel_code_template = """
__global__ void MatrixMulKernel(float *a, float *b, float *c)
{
    int tx = threadIdx.x;
    int ty = threadIdx.y;
    float Pvalue = 0;
    for (int k = 0; k < %(MATRIX_SIZE)s; ++k) {
        float Aelement = a[ty * %(MATRIX_SIZE)s + k];
        float Belement = b[k * %(MATRIX_SIZE)s + tx];
        Pvalue += Aelement * Belement;
    }

    c[ty * %(MATRIX_SIZE)s + tx] = Pvalue;
}
"""

# Define o tamanho da Matriz
MATRIX_SIZE = 5

# Variáveis para armazenar as matrizes na memória do host
a_cpu = np.random.randn(MATRIX_SIZE, MATRIX_SIZE).astype(np.float32)
b_cpu = np.random.randn(MATRIX_SIZE, MATRIX_SIZE).astype(np.float32)
c_cpu = np.dot(a_cpu, b_cpu)

# Variáveis para armazenar as matrizes na memória do device
a_gpu = gpuarray.to_gpu(a_cpu)
b_gpu = gpuarray.to_gpu(b_cpu)
c_gpu = gpuarray.empty((MATRIX_SIZE, MATRIX_SIZE), np.float32)

# Define o kernel
kernel_code = kernel_code_template % {
    'MATRIX_SIZE': MATRIX_SIZE
    }

# Compila o kernel
mod = compiler.SourceModule(kernel_code)

# Obtém o kernel
matrixmul = mod.get_function("MatrixMulKernel")

# Executa o kernel
matrixmul(
    a_gpu, b_gpu,
    c_gpu,
    block = (MATRIX_SIZE, MATRIX_SIZE, 1),
    )

# Imprime is resultados
print ("-" * 80)
print ("Matriz A (GPU):")
print (a_gpu.get())

print ("-" * 80)
print ("Matriz B (GPU):")
print (b_gpu.get())

print ("-" * 80)
print ("Matriz C (GPU):")
print (c_gpu.get())

print ("-" * 80)
print ("Diferença CPU-GPU:")
print (c_cpu - c_gpu.get())

np.allclose(c_cpu, c_gpu.get())

3_ProgramacaoParalelaEmGPU/8 - Programação Paralela em Python - Parte 1/03-PyCudaMatrixManipulation/03-PyCudaMatrixManipulation.py


"""Exercise 5.5: Apply a function to a vector
Given a vector v = (2, 3, -1) and a function f(x) = x^3 + xe^x + 1, apply f to
each element in v. Then calculate by hand f(v) as the NumPy expression v**3 +
v*exp(v) + 1 using vector computing rules. Demonstrate that the two results are
equal."""
import numpy as np

v = np.array([2,3,-1])
f = lambda x: x**3 + x*np.exp(x) + 1
print(f(v))

v1 = (2**3 + 2*np.exp(2) + 1)
v2 = (3**3 + 3*np.exp(3) + 1)
v3 = (-1**3 + -1*np.exp(-1) + 1)

v_secondary = np.array([v1,v2,v3])
print(v_secondary)

equal_or_not = np.array_equal(f(v), v_secondary)
print(equal_or_not)


"""A Tracer implementation that records to LangChain endpoint."""
from __future__ import annotations

import logging
import os
from typing import Any, Dict, Optional, Union

import requests

from langchain.callbacks.tracers.base import BaseTracer
from langchain.callbacks.tracers.schemas import (
    ChainRun,
    LLMRun,
    ToolRun,
    TracerSession,
    TracerSessionCreate,
)

class LangChainTracer(BaseTracer):
    """An implementation of the SharedTracer that POSTS to the langchain endpoint."""

    def __init__(self, session_name: str = "default", **kwargs: Any) -> None:
        """Initialize the LangChain tracer."""
        super().__init__(**kwargs)
        self._endpoint: str = os.getenv("LANGCHAIN_ENDPOINT", "http://localhost:8000")
        self._headers: Dict[str, Any] = {"Content-Type": "application/json"}
        if os.getenv("LANGCHAIN_API_KEY"):
            self._headers["x-api-key"] = os.getenv("LANGCHAIN_API_KEY")
        self.session = self.load_session(session_name)

    def _persist_run(self, run: Union[LLMRun, ChainRun, ToolRun]) -> None:
        """Persist a run."""
        if isinstance(run, LLMRun):
            endpoint = f"{self._endpoint}/llm-runs"
        elif isinstance(run, ChainRun):
            endpoint = f"{self._endpoint}/chain-runs"
        else:
            endpoint = f"{self._endpoint}/tool-runs"

        try:
            requests.post(
                endpoint,
                data=run.json(),
                headers=self._headers,
            )
        except Exception as e:
            logging.warning(f"Failed to persist run: {e}")

    def _persist_session(self, session_create: TracerSessionCreate) -> TracerSession:
        """Persist a session."""
        try:
            r = requests.post(
                f"{self._endpoint}/sessions",
                data=session_create.json(),
                headers=self._headers,
            )
            session = TracerSession(id=r.json()["id"], **session_create.dict())
        except Exception as e:
            logging.warning(f"Failed to create session, using default session: {e}")
            session = TracerSession(id=1, **session_create.dict())
        return session

    def _load_session(self, session_name: Optional[str] = None) -> TracerSession:
        """Load a session from the tracer."""
        try:
            url = f"{self._endpoint}/sessions"
            if session_name:
                url += f"?name={session_name}"
            r = requests.get(url, headers=self._headers)

            tracer_session = TracerSession(**r.json()[0])
        except Exception as e:
            session_type = "default" if not session_name else session_name
            logging.warning(
                f"Failed to load {session_type} session, using empty session: {e}"
            )
            tracer_session = TracerSession(id=1)

        self.session = tracer_session
        return tracer_session

    def load_session(self, session_name: str) -> TracerSession:
        """Load a session with the given name from the tracer."""
        return self._load_session(session_name)

    def load_default_session(self) -> TracerSession:
        """Load the default tracing session and set it as the Tracer's session."""
        return self._load_session("default")


# Exercise 9: Compound Interest
# (19 Lines)
# Pretend that you have just opened a new savings account that earns 4 percent interest
# per year. The interest that you earn is paid at the end of the year, and is added
# to the balance of the savings account. Write a program that begins by reading the
# amount of money deposited into the account from the user. Then your program should
# compute and display the amount in the savings account after 1, 2, and 3 years. Display
# each amount so that it is rounded to 2 decimal places.

amount_in_account = float(input("How much money do you have?\n"))
i = 0
while i < 3:
    i+=1
    interest = amount_in_account * 0.04
    amount_in_account += interest
    print(f"You have {round(amount_in_account,2)} $ in your account after having accrued {round(interest,2)} $ in interest in year {i}")


"""
Implementation of Girvan-Newman Algorithm. (details of the algoritm: chapter 10 in mmds)

> gn = GirvanNewman(nodes=_rdd_nodes, edges=_rdd_edges)
> gn.run(print_result=True, plot_modularity_curve=True)
> best_q = gn.get_best_q()
> best_community = gn.get_best_community()
"""
from pyspark import SparkContext
from collections import namedtuple, deque
import heapq
import numpy as np
import matplotlib.pyplot as plt

class GirvanNewman(object):
    ScoreLevel = namedtuple("ScoreLevel", ("score", "level"))
    CommunityInfo = namedtuple("CommunityInfo", ("iteration", "q", "num_community"))

    def __init__(self, nodes=None, edges=None, removing_step=5, early_stopping=20):
        self._num_of_removed_edges_in_pass = removing_step
        self._early_stopping = early_stopping
        self._nodes = nodes
        self._edges = edges
        self._num_of_edges, self._num_of_nodes = 0, 0
        self._best_q, self._best_community = 0, list()
        self._modularity_curve = list()

    def add_nodes(self, nodes):
        """
        Add nodes to the community
        :param nodes: RDD<node>
        """
        if self._nodes is None:
            self._nodes = nodes
        else:
            self._nodes = self._nodes.union(nodes)

    def add_edges(self, edges):
        """
        Add edges to the community
        :param edges: RDD<(node, node)>
        """
        edges = edges.filter(lambda pair: pair[0] != pair[1])
        if self._edges is None:
            self._edges = edges
        else:
            self._edges = self._edges.union(edges)

    def graph_info(self):
        """
        Print Graph Information (nodes/edges number)
        """
        self._num_of_nodes = self._nodes.count()
        self._num_of_edges = self._edges.count()
        print(
            "Number of nodes =", self._num_of_nodes, "\n",
            "Number of edges =", self._num_of_edges
        )

    def get_best_q(self):
        return self._best_q

    def get_best_community(self):
        return self._best_community

    def get_modularity_curve(self):
        return self._modularity_curve

    def print_result(self):
        """
        Print the results after running the algorithm.
        """
        print("Best modularity(Q)=", self._best_q)
        idx = 1
        singulars = set()
        for _community in self._best_community:
            if len(_community) > 1:
                print("Community %s:" % idx, _community)
                idx += 1
            elif len(_community) == 1:
                singulars |= _community
        print("Singulars :", singulars)

    def plot_modularity_curve(self):
        """
        Plot the curve:
        ->upper: modularity vs iteration
        ->lower: number of communities vs iteration
        """
        plt.figure("212", figsize=(10, 8))
        plt.subplot("211")
        plt.plot(
            [c.iteration for c in self._modularity_curve],
            [c.q for c in self._modularity_curve]
        )
        plt.ylabel("Modularity(Q)")
        plt.subplot("212")
        plt.plot(
            [c.iteration for c in self._modularity_curve],
            [c.num_community for c in self._modularity_curve]
        )
        plt.ylabel("Number of Communities")
        plt.xlabel("Iteration")
        plt.show()

    def run(self, print_result=False, plot_modularity_curve=False):
        """
        The main function to compute communities of community.
        """
        if self._check_nodes_edges():
            self.graph_info()
        else:
            return False

        edges = self._edges.flatMap(
            lambda pair: [(pair[0], pair[1]), (pair[1], pair[0])]
        ).aggregateByKey(
            set(), lambda u, v: u | {v}, lambda u1, u2: u1 | u2
        )
        self._best_q, self._best_community = self._iterate_removing_edges(
            rdd_nodes=self._nodes,
            list_edges=edges.collect(),
            num_of_edges=self._num_of_edges
        )

        if print_result:
            self.print_result()
        if plot_modularity_curve:
            self.plot_modularity_curve()

    def _check_nodes_edges(self):
        """
        Check if the nodes and edges have been inputted.
        :return: bool(True/False)
        """
        if self._nodes is None:
            print("No node input. Please add nodes with add_nodes method")
            return False
        if self._edges is None:
            print("No edge input. Please add edges with add_edges method")
            return False
        return True

    def _iterate_removing_edges(self, rdd_nodes, list_edges, num_of_edges):
        """
        Iterated process of removing edges:
        -> Step 0: Broadcast edges to partitions
        -> Step 1: Compute the betweeness of edges
        -> Step 2: Remove k edges with highest betweenness
        -> Step 3: Compute modularity of the community to see if it reaches the maximum peak.
        -> Iterate step 1~3
        -----------------------------------------
        :param rdd_nodes: RDD<node>
        :param list_edges: List<(node, set<node>)>
        :param num_of_edges: Int
        :return: best_q, best_community
        """
        sc = SparkContext.getOrCreate()

        """
        Broadcast edges
        """
        broadcast_edges = sc.broadcast(list_edges)

        """
        edges: dict<node, list<node>>. Used for search the connected nodes.
        node_degrees: dict<node, int>. The degrees (degree = number of edges connected to the node ) of nodes.
        excluded_edges: list<(node, node)>. The edges to be removed from origin edges.
        list_nodes: list<node>. Node list.
        """
        edges = dict(list_edges)
        node_degrees = {node: len(neighbors) for node, neighbors in list_edges}
        excluded_edges = list()
        list_nodes = rdd_nodes.collect()

        best_q = -10  # a number smaller than -1 is ok
        iteration = 0
        while True:
            iteration += 1
            """
            Calculate the betweenness scores of edges.
            For each loop, the removed edges will be updated. These will be treated as changes to the origin edges /
            for the purpose of reducing communication cost.
            """
            broadcast_excluded_edges = sc.broadcast(excluded_edges)
            betweenness = self._compute_betweenness(
                rdd_nodes, broadcast_edges, broadcast_excluded_edges
            )
            """
            Find the edge with highest score, and remove that edge.
            (Broadcast the removed edges)
            """
            top_k_edges = self._top_k(betweenness, self._num_of_removed_edges_in_pass)
            for removed, _ in top_k_edges:
                excluded_edges.append(removed)
                self._remove_edge(edges, removed)

            """
            Calculate modularity (Q), and decide next step: breaking the loop or entering the next loop.
            """
            next_q, next_community = self._modularity(list_nodes, edges, num_of_edges, node_degrees)
            self._modularity_curve.append(
                self.CommunityInfo(iteration=iteration, q=next_q, num_community=len(next_community))
            )
            if next_q > best_q:
                best_community = next_community
                best_q = next_q
                best_iteration = iteration
            elif next_q == best_q:
                best_iteration = iteration
            elif iteration >= best_iteration + self._early_stopping or len(top_k_edges) == 0:
                break

        return best_q, best_community

    @classmethod
    def _compute_betweenness(cls, nodes, broadcast_edges, broadcast_excluded_edges):
        """
        calculate credits with each root, and sum up all credits to get betweenness.
        :param nodes: RDD<node>
        :param broadcast_edges: (broadcast)list<(node, set<node>)>
        :param broadcast_excluded_edges: (broadcast)list<(node, node)>
        :return: RDD<((node, node), float)>
        """
        betweenness = nodes.mapPartitions(
            lambda roots: cls._calculate_credits(roots, broadcast_edges, broadcast_excluded_edges)
        ).reduceByKey(lambda x, y: x+y)
        return betweenness

    @classmethod
    def _calculate_credits(cls, iterator_roots, bc_edges, bc_excluded_edges):
        """
        Regard one node as root, then calculate credits of edges
        :param iterator_roots: Iterator<node>
        :param bc_edges: (broadcast)list<(node, set<node>)>
        :param bc_excluded_edges: (broadcast)list<(node, node)>
        :return:
        """
        edges = dict(bc_edges.value)
        excluded_edges = bc_excluded_edges.value

        # Remove edges.
        for excluded_edge in excluded_edges:
            cls._remove_edge(edges, excluded_edge)

        for root in iterator_roots:
            if root not in edges:
                continue

            # Label score to each node in each level
            # -> score = the number of shortest paths that reach the node from root
            scores = cls._credit_label_scores(root, edges)
            yield from cls._credit_assign_credits(root, edges, scores)

    @classmethod
    def _credit_label_scores(cls, root, edges):
        """
        Label scores to nodes: The numbers of shortest paths from the root to nodes.
        :param root: node
        :param edges: dict<node, set<node>>
        :return: dict<node, ScoreLevel(score, level)>
        """
        scores = {root: cls.ScoreLevel(score=1, level=0)}
        prev_layer = deque([root])
        while len(prev_layer) > 0:
            node = prev_layer.pop()
            parent_score, parent_level = scores[node]
            for e in edges[node]:
                if e not in scores:
                    scores[e] = cls.ScoreLevel(score=parent_score, level=parent_level+1)
                    prev_layer.appendleft(e)
                elif scores.get(e).level == parent_level+1:
                    child_score, child_level = scores.get(e)
                    scores[e] = cls.ScoreLevel(score=parent_score + child_score, level=child_level)
        return scores

    @staticmethod
    def _credit_assign_credits(root, edges, scores):
        """
        Assign credits to DAGs, from leaves to roots.
        :param root: node
        :param edges: dict<node, set<node>>
        :param scores: dict<node, ScoreLevel(score, level)>
        :return: list<(edge, credit(or betweenness))>
        """
        credit_map = {}
        dags = []

        # Travel the whole tree
        def _get_credits(node):
            if node in credit_map:
                return credit_map[node]
            score, level = scores.get(node)
            credit = 1
            for child in edges[node]:
                child_score, child_level = scores.get(child)
                if level - child_level == -1:
                    credit += _get_credits(child) * score / child_score
            for parent in edges[node]:
                parent_score, parent_level = scores.get(parent)
                if level - parent_level == 1:
                    dags.append((tuple(sorted([node, parent])), credit * parent_score / score / 2))
            credit_map[node] = credit
            return credit

        _get_credits(root)
        return dags

    @staticmethod
    def _top_k(betweenness, k):
        """
        Find edges with top-k highest betweenness
        :param betweenness: RDD<(edge, betweenness score)>
        :param k: int
        :return: list<(edge, betweenness)>
        """
        if k == 1:
            removed = betweenness.reduce(lambda x, y: x if x[1] > y[1] else y)
            return [removed]
        else:
            top_k_s = betweenness.mapPartitions(
                lambda iterator: heapq.nlargest(k, iterator, key=lambda key_value: key_value[1])
            ).collect()
            return heapq.nlargest(k, top_k_s, key=lambda key_value: key_value[1])

    @staticmethod
    def _remove_edge(edges, excluded_edge):
        """
        Remove an edge from edges.
        :param edges: dict<node, set<node>>
        :param excluded_edge: (node, node)
        :return:
        """
        start, to = excluded_edge
        if start in edges:
            try:
                edges[start].remove(to)
            except KeyError:
                # (start, to) is not in the edges.
                pass
            if len(edges[start]) == 0:
                del edges[start]
        if to in edges:
            try:
                edges[to].remove(start)
            except KeyError:
                # (start, to) is not in the edges.
                pass
            if len(edges[to]) == 0:
                del edges[to]

    @staticmethod
    def _modularity(nodes, edges, num_of_edges, node_degrees):
        """
        Calculate modularity of the community
        :param nodes: list<node>
        :param edges: dict<node, list<node>>
        :param num_of_edges: int
        :param node_degrees: dict<node, int>
        :return: modularity: int, communities: list<set<node>>
        """
        """
        Find communities from the community.
        """
        # Group nodes
        communities, grouped_nodes = list(), set()

        # Travel the entire community
        def _travel_nodes(node):
            if node in grouped_nodes:
                return []
            elif node not in edges:
                grouped_nodes.add(node)
                yield node
            else:
                grouped_nodes.add(node)
                yield node
                for _neighbor in edges[node]:
                    yield from _travel_nodes(_neighbor)

        for _node in nodes:
            if _node in grouped_nodes:
                continue
            else:
                communities.append(set(_travel_nodes(_node)))

        """
        Calculate modularity(Q) of the community.
        -> Q is between -1~1, Q>0.3~0.7 means significant community structure
        """
        # Calculate Modularity Q
        modularity = 0
        for _group in communities:
            if len(_group) == 1:
                continue
            for _node1 in _group:
                for _node2 in _group:
                    modularity -= node_degrees.get(_node1, 0) * node_degrees.get(_node2, 0) / (2 * num_of_edges)
                    if _node2 in edges[_node1]:
                        modularity += 1
        modularity = modularity / (2 * num_of_edges)
        return modularity, communities

if __name__ == '__main__':
    np.random.seed(0)
    num_nodes, num_edges, num_communities = 500, 5000, 5
    connecting_strength_among_communities = 0.01

    sc = SparkContext.getOrCreate()
    list_of_nodes = [i for i in range(num_nodes)]
    list_of_edges = list()
    for i in range(5000):
        edge = tuple(np.random.choice(list_of_nodes, 2))
        if edge[0]//(num_nodes//num_communities) != edge[1]//(num_nodes//num_communities) \
                and np.random.rand() < 1 - connecting_strength_among_communities:
            continue
        else:
            list_of_edges.append(edge)
    print(len(list_of_edges))
    _rdd_nodes = sc.parallelize(list_of_nodes)
    _rdd_edges = sc.parallelize(list_of_edges)
    GirvanNewman(nodes=_rdd_nodes, edges=_rdd_edges).run(print_result=True, plot_modularity_curve=True)


import json
import logging
import os
import traceback
from typing import Any, Dict, List, Optional, Tuple, TypedDict

import azure.storage.queue

from pctasks.core.cosmos.containers.process_item_errors import (
    ProcessItemErrorsContainer,
)
from pctasks.core.models.base import PCBaseModel
from pctasks.core.models.event import IngestErrorType, IngestItemErrorRecord
from pctasks.ingest.constants import DB_CONNECTION_STRING_ENV_VAR
from pctasks.ingest_task.pgstac import PgSTAC
from pctasks.ingest_task.task import ingest_item
from pctasks.task.context import TaskContext
from pctasks.task.streaming import (
    NoOutput,
    StreamingTaskInput,
    StreamingTaskMixin,
    StreamingTaskOptions,
)
from pctasks.task.task import Task

logger = logging.getLogger(__name__)

class StreamingIngestMessage(PCBaseModel):
    data: Dict[str, Any]

class StreamingIngestItemsInput(PCBaseModel):
    streaming_options: StreamingTaskOptions

class ExtraOptions(TypedDict):
    pgstac: PgSTAC
    process_item_errors_container: ProcessItemErrorsContainer[IngestItemErrorRecord]

class StreamingIngestItemsTask(
    StreamingTaskMixin, Task[StreamingIngestItemsInput, NoOutput]
):
    _input_model = StreamingIngestItemsInput
    _output_model = NoOutput

    def get_required_environment_variables(self) -> List[str]:
        return [DB_CONNECTION_STRING_ENV_VAR]

    def get_extra_options(
        self, input: StreamingTaskInput, context: TaskContext
    ) -> ExtraOptions:
        assert isinstance(input, StreamingIngestItemsInput)

        conn_str = os.environ[DB_CONNECTION_STRING_ENV_VAR]
        pgstac = PgSTAC(conn_str)
        process_item_errors_container = ProcessItemErrorsContainer(
            IngestItemErrorRecord
        )
        process_item_errors_container.__enter__()

        return {
            "pgstac": pgstac,
            "process_item_errors_container": process_item_errors_container,
        }

    def cleanup(self, extra_options: ExtraOptions) -> None:
        pgstac: Optional[PgSTAC] = extra_options["pgstac"]
        if pgstac:
            pgstac.db.close()
        extra_options["process_item_errors_container"].__exit__(None, None, None)

    def process_message(
        self,
        message: azure.storage.queue.QueueMessage,
        input: StreamingTaskInput,
        context: TaskContext,
        extra_options: ExtraOptions,
    ) -> Tuple[Optional[Dict[str, Any]], Any]:
        assert isinstance(input, StreamingIngestItemsInput)

        pgstac = extra_options["pgstac"]
        # What errors can occur here?
        # 1. This message might not be valid JSON.
        # 2. The pgstac ingest might fail.
        item = err = None
        error_id = f"{message.id}:{context.run_id}:{message.dequeue_count}"
        try:
            item = json.loads(message.content)
        except json.JSONDecodeError:
            logger.exception("Error decoding message for ingest")
            err = IngestItemErrorRecord(
                id=error_id,
                type=IngestErrorType.INVALID_DATA,
                input=message.content,
                run_id=context.run_id,
                attempt=message.dequeue_count,
                traceback=traceback.format_exc(),
            )
        else:
            logger.info(
                "Loading item collection=%s id=%s", item["collection"], item["id"]
            )

            try:
                ingest_item(pgstac, item)
            except Exception:
                logger.exception("Error during ingest")
                err = IngestItemErrorRecord(
                    id=error_id,
                    type=IngestErrorType.ITEM_INGEST,
                    input=message.content,
                    run_id=context.run_id,
                    attempt=message.dequeue_count,
                    traceback=traceback.format_exc(),
                )

        return (item, err)

    def finalize_message(
        self,
        message: azure.storage.queue.QueueMessage,
        context: TaskContext,
        result: Tuple[Dict[str, Any], Any],
        extra_options: ExtraOptions,
    ) -> None:
        _, err = result
        process_item_errors_container = extra_options["process_item_errors_container"]

        if err:
            logger.info(
                "Recording error %s to %s",
                err.get_id(),
                process_item_errors_container.name,
            )
            process_item_errors_container.put(err)


import os
import collections
import re

no_file: bool = False

ec = 0

root_dev = 'c:/Users/roman/YandexDisk/Navicon/~Merlion/DEV/'
root_wrk = 'c:/Users/roman/YandexDisk/Navicon/~Merlion/WRK/'
task_file= 'c:/Users/roman/YandexDisk/Navicon/~Merlion/task.csv'

# root_dev = 'c:/Users/hrs/YandexDisk/Navicon/~Merlion/DEV/'
# root_wrk = 'c:/Users/hrs/YandexDisk/Navicon/~Merlion/WRK/'
# task_file= 'c:/Users/hrs/YandexDisk/Navicon/~Merlion/task.csv'
log_file= 'c:/Users/roman/YandexDisk/Navicon/~Merlion/log.txt'

def get_filename(base_dir: str, csv_splitted_line: list) -> str:
    fn = f'{csv_splitted_line[1]}/{csv_splitted_line[2].lower()[0]}{csv_splitted_line[3]}.txt'
    return os.path.join(base_dir, fn)

def get_count_task_code_marks(filename: str, task_code: str) -> int:
    if not os.path.exists(filename):
        return 0

    file_body: str
    with open(filename, 'r', encoding='cp866') as fi:
         file_body = fi.read()

    if not file_body:
        return 0

    found = re.findall(rf'{task_code}', file_body, re.IGNORECASE)
    return len(found)

diff_log = collections.defaultdict(list)

with open(task_file, 'r') as fi:
    for cc, ln in enumerate(fi):
        ln = ln.strip()
        part = ln.split(';')
        task_code = part[0]
        object_id = f'{part[2]} {part[3]}'
        database = part[1]

        obj_file_dev = get_filename(root_dev, part)
        obj_file_wrk = get_filename(root_wrk, part)

        no_file = False
        if not os.path.exists(obj_file_dev):
            diff_log[task_code].append(f'{object_id} is not exist in DEV {database}')
            no_file = True

        if not os.path.exists(obj_file_wrk):
            diff_log[task_code].append(f'{object_id} is not exist in WRK {database}')
            no_file = True

        if no_file:
            ec += 1
        else:
            if get_count_task_code_marks(obj_file_dev, task_code) != get_count_task_code_marks(obj_file_wrk, task_code):
                diff_log[task_code].append(f'{object_id} is not equal in WRK and DEV {database}')
                ec += 1

# print(f'Errors in {ec} line of {cc}')
# for task_code, messages in diff_log.items():
#     print(task_code, '\n')
#     for msg in messages:
#         print('\t', msg)
#     print('\n')

with open(log_file, 'w') as fo:
    fo.write(f'Errors in {ec} line of {cc}\n\n')
    for task_code, messages in diff_log.items():
        fo.write(f'{task_code}\n')
        for msg in messages:
            fo.write(f'x\t{msg}\n')
        fo.write('\n')


import discord
from discord.ext import commands, tasks
import random
from discord.ext.commands.cooldowns import BucketType
import json

class Item:
    def __init__(self, name, cost):
        self.name = name
        self.cost = cost

class PlayerCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def start(self, ctx):
        players = json.load(open("WordSmithMoney.json"))
        if str(ctx.author.id) in players.keys():
            await ctx.send(
                embed=discord.Embed(description=f"An account already exists for {ctx.author.mention}."))
        else:
            players[str(ctx.author.id)] = {"money": 1,
                                           "prestigeTokens": 0,
                                           "items": {"Rocks": 0,
                                                     "Papers": 0,
                                                     "Scissors": 0},
                                           "idle":
                                               {"upgrades": 1,
                                                "prestige": 0,
                                                "couponBook": 0,
                                                "autoInvestor": 0,
                                                "petCare": 0,
                                                "petCareCooldown": 0}}
            embed = discord.Embed(
                description=f"Account created for {ctx.author.mention}.",
                color=discord.Color.green())
            await ctx.send(embed=embed)
            json.dump(players, open("WordSmithMoney.json", "w"), indent=4)

    @commands.command(aliases=["Donate", "DONATE", "give", "Give", "GIVE"])
    async def donate(self, ctx, user: discord.Member, money: int):
        if money > 0:
            players = json.load(open("WordSmithMoney.json"))
            if str(user.id) in players.keys():
                if players[str(ctx.author.id)]["money"] >= money:
                    players[str(user.id)]["money"] += money
                    players[str(ctx.author.id)]["money"] -= money
                    await ctx.send(embed=discord.Embed(description=f"${money} has been given to {user.mention}!",
                                                       color=discord.Color.green()))
                else:
                    await ctx.send(embed=discord.Embed(
                        description=f"You do not have enough money to donate {money}{ctx.author.mention}!",
                        color=discord.Color.red()))
            else:
                await ctx.send(
                    embed=discord.Embed(
                        description=f"{user.mention} does not yet have an account {ctx.author.mention}!",
                        color=discord.Color.red()))
            json.dump(players, open("WordSmithMoney.json", "w"), indent=4)
        else:
            await ctx.send("Error: Donation negative.")

    @commands.command()
    @commands.cooldown(1, 3600, BucketType.user)
    async def hourly(self, ctx):
        players = json.load(open("WordSmithMoney.json"))
        player = players[str(ctx.author.id)]
        player['money'] += 10
        await ctx.send(embed=discord.Embed(description=f"Hourly claimed {ctx.author.mention}. You gained $10!"))
        json.dump(players, open("WordSmithMoney.json", "w"), indent=4)

    @commands.command(aliases=["bal", "b", "Bal", "BAL", "B", "Balance", "BALANCE"])
    async def balance(self, ctx, member: discord.Member = None):
        players = json.load(open("WordSmithMoney.json"))
        if member is None:
            await ctx.send(embed=discord.Embed(
                description=f"Your balance, {ctx.author.mention}, is ${round((players[str(ctx.author.id)]['money']), 2)}."))
        else:
            if str(member.id) in players.keys():
                await ctx.send(embed=discord.Embed(
                    description=f"{member.display_name} has ${players[str(member.id)]['money']} in their account."))
            else:
                await ctx.send(embed=discord.Embed(
                    description=f"I could not find an account for {member.display_name}, {ctx.author.mention}."))

    @commands.command()
    async def rps(self, ctx, choice, bet):
        players = json.load(open("WordSmithMoney.json"))
        bet = int(bet)
        if players[str(ctx.author.id)]['money'] >= bet:
            choice = choice.lower()
            choices = ["rock", "paper", "scissors"]
            botChoice = random.choice(choices)
            if choice == "rock":
                players[str(ctx.author.id)].rock += 1
            elif choice == "scissors":
                players[str(ctx.author.id)].scissors += 1
            elif choice == "paper":
                players[str(ctx.author.id)].paper += 1
            if choice == botChoice:
                embed = discord.Embed(title=f"We tied! We both chose {choice}!")
            elif choice == "rock" and botChoice == "paper" or choice == "paper" and botChoice == "scissors" or choice == "scissors" and botChoice == "rock":
                embed = discord.Embed(title=f"I won! {botChoice} beats {choice}!", color=discord.Color.green())
                players[str(ctx.author.id)]['money'] -= bet
            elif choice == "rock" and botChoice == "scissors" or choice == "paper" and botChoice == "rock" or choice == "scissors" and botChoice == "paper":
                embed = discord.Embed(title=f"You won! {choice} beats {botChoice}!", color=discord.Color.green())
                players[str(ctx.author.id)]['money'] += bet
            else:
                embed = discord.Embed(
                    title=f"Error: {choice} is not a valid option.")
            await ctx.send(embed=embed)
            if players[str(ctx.author.id)].rock == 500:
                players[str(ctx.author.id)].items["rock"] += 1
                await ctx.send(embed=discord.Embed(
                    description=f"Congrats, {ctx.author.mention}! You have earned a rock collectible.",
                    color=discord.Color.green()))
            elif players[str(ctx.author.id)].paper == 500:
                players[str(ctx.author.id)].items["paper"] += 1
                await ctx.send(embed=discord.Embed(
                    description=f"Congrats, {ctx.author.mention}! You have earned a paper collectible.",
                    color=discord.Color.green()))
            elif players[str(ctx.author.id)].scissors == 500:
                players[str(ctx.author.id)].items["scissors"] = +1
                await ctx.send(embed=discord.Embed(
                    description=f"Congrats, {ctx.author.mention}! You have earned a scissors collectible    .",
                    color=discord.Color.green()))
            json.dump(players, open("WordSmithMoney.json", "w"), indent=4)

        else:
            await ctx.send(embed=discord.Embed(
                description=f"Not enough money {ctx.author.mention}! You only have ${players[str(ctx.author.id)]['money']}!"))

    @rps.error
    async def rpserror(self, ctx, error):
        await ctx.send(f"Please use the correct format for this command: `eco!rps rock 100`")

    @commands.command(aliases=["Items", "ITEMS"])
    async def items(self, ctx):
        players = json.load(open("WordSmithMoney.json"))
        player = players[str(ctx.author.id)]
        embed = discord.Embed(color=discord.Color.teal())
        embed.set_author(icon_url=ctx.author.avatar_url, name=f"{ctx.author.display_name}'s items:")
        for item, value in player.items.items():
            if value != "none" and value != 0 and value != "0":
                embed.add_field(name=f"{item.name}", value=f"{value} owned.")
        await ctx.send(embed=embed)

    @commands.command()
    async def buy(self, ctx, *, Items):
        Items = Items.lower()
        players = json.load(open("WordSmithMoney.json"))
        player = players[str(ctx.author.id)]
        for item in player.items.keys():
            if item.name.lower() == Items:
                if item.cost == "none":
                    await ctx.send(embed=discord.Embed(description=f"This item is not for sale, {ctx.author.mention}.",
                                                       color=discord.Color.red()))
                else:
                    if float(player['money']) >= float(item.cost):
                        player.items[item] += 1
                        item.cost = float(item.cost)
                        player['money'] -= item.cost
                        item.cost *= 1.1
                        await ctx.send(
                            embed=discord.Embed(description=f"You have purchased a {item.name} {ctx.author.mention}!",
                                                color=discord.Color.green()))
                    else:
                        await ctx.send(embed=discord.Embed(
                            description=f"You cannot afford to buy this item {ctx.author.mention}! You need ${item.cost}, and you only have ${player['money']}!",
                            color=discord.Color.red()))
        json.dump(players, open("WordSmithMoney.json", "w"), indent=4)

def setup(bot):
    bot.add_cog(PlayerCog(bot))


import json
import time
from socket import *
from ipaddress import ip_address
import re, argparse, threading
from ipaddress import ip_address
from netaddr import IPNetwork
import requests
# ***************************************
bufferSize  = 1024
serverPort = 67
server_ip = "127.0.0.1"
msgFromServer = "Hello UDP Client"
bytesToSend = str.encode(msgFromServer)
reservation_list = []
banned_list = []
gateway = "192.168.1.1"
dns = ["9.7.10.15",	"9.7.10.16","9.7.10.18"]
# ***************************************
IP_list = {}
# start_time = 0
running = True

def packet_analyser(packet):
    OP = packet[0]
    HTYPE = packet[1]
    HLEN = packet[2]
    HOPS = packet[3]
    XID = packet[4:8]
    SECS = packet[8:10]
    FLAGS = packet[10:12]
    CIADDR = packet[12:16]
    YIADDR = packet[16:20]
    SIADDR = packet[20:24]
    GIADDR = packet[24:28]
    CHADDR = packet[28:28 + 16 + 192]
    magic_cookie = packet[236:240]
    DHCPoptions = packet[240:]

    return OP, HTYPE, HLEN, HOPS, XID, SECS, FLAGS, CIADDR, YIADDR, SIADDR, GIADDR, CHADDR, magic_cookie, DHCPoptions

def DHCP_offer(xid, ciaddr, chaddr, magic_cookie, ip):
	OP = bytes([0x02])
	HTYPE = bytes([0x01])
	HLEN = bytes([0x06])
	HOPS = bytes([0x00])
	XID = xid
	SECS = bytes([0x00, 0x00])
	FLAGS = bytes([0x00, 0x00])
	CIADDR = ciaddr
	YIADDR = inet_aton(ip) 													#adresse a donner
	SIADDR = inet_aton(server_ip)
	GIADDR = bytes([0x00, 0x00, 0x00, 0x00])
	CHADDR = chaddr
	DHCPoptions1 = bytes([53, 1, 2])
	DHCPoptions2 = bytes([1 , 4]) + inet_aton(subnet_mask)				# read from json file
	DHCPoptions3 = bytes([3 , 4 ]) + inet_aton(gateway) 				# gateway/router
	DHCPOptions4 = bytes([51 , 4]) + ((lease_time).to_bytes(4, byteorder='big')) 	#IP address lease time
	DHCPOptions5 = bytes([54 , 4]) + inet_aton(server_ip) 				# DHCP server
	DHCPOptions6 = bytes([6, 4 * len(dns)]) 							#DNS servers
	# for i in dns:
		# DHCPOptions6 += i

	ENDMARK = bytes([0xff])

	package = OP + HTYPE + HLEN + HOPS + XID + SECS + FLAGS + CIADDR + YIADDR + SIADDR + GIADDR + CHADDR + magic_cookie + DHCPoptions1 + DHCPoptions2 + DHCPoptions3 + DHCPOptions4 + DHCPOptions5 + DHCPOptions6 + ENDMARK
	return package

def DHCP_ack(xid, ciaddr, chaddr, magicookie, ip):
	OP = bytes([0x02])
	HTYPE = bytes([0x01])
	HLEN = bytes([0x06])
	HOPS = bytes([0x00])
	XID = xid
	SECS = bytes([0x00, 0x00])
	FLAGS = bytes([0x00, 0x00])
	CIADDR = ciaddr
	YIADDR = inet_aton(ip) 													#adresse a donner
	SIADDR = inet_aton(server_ip)
	GIADDR = bytes([0x00, 0x00, 0x00, 0x00])
	CHADDR = chaddr
	Magiccookie = magicookie
	DHCPoptions1 = bytes([53 , 1 , 5]) 										#DHCP ACK(value = 5)
	DHCPoptions2 = bytes([1 , 4]) + inet_aton(subnet_mask)				# subnet_mask 255.255.255.0
	DHCPoptions3 = bytes([3 , 4 ]) + inet_aton(gateway) 				# gateway
	DHCPoptions4 = bytes([51 , 4]) + ((lease_time).to_bytes(4, byteorder='big'))
	DHCPoptions5 = bytes([54 , 4]) + inet_aton(server_ip) 				# DHCP server
	DHCPOptions6 = bytes([6, 4 * len(dns)]) 							# DNS servers
	ENDMARK = bytes([0xff])

	package = OP + HTYPE + HLEN + HOPS + XID + SECS + FLAGS + CIADDR + YIADDR + SIADDR + GIADDR + CHADDR + Magiccookie + DHCPoptions1 + DHCPoptions2 + DHCPoptions3 + DHCPoptions4 + DHCPoptions5 + DHCPOptions6 + ENDMARK
	return package

def init_IP(mode, Ip_block, Ip_mask):
	global IP_list
	if mode == "range":
		start = ip_address(Ip_block)
		end = ip_address(Ip_mask)
		while start <= end:
			# 1:IP address - 2nd: lease time
			p = str(start)
			IP_list[p] = ("null",0,"null")
			start+=1
	elif mode == "subnet":
		network = IPNetwork('/'.join([ip_block, Ip_mask]))
		generator = network.iter_hosts()
		for ip in list(generator):
			# 1:IP address - 2nd: lease time, 3nd: remaining time
			key = str(ip)
			IP_list[key] = ("null",0,"null")

def get_free_ip():
	global IP_list
	for key, value in IP_list.items() :
		if(value[0] == "null"):
			return key
	return False

def get_ip(mac_address, ip):
	global IP_list
	for key, value in IP_list.items() :
		if(value[0] == mac_address):
			return key

	# if clien't ip request is free, set it.
	if(ip == True):
		if(IP_list.get(ip)[0] == "null"):
			return ip

	return get_free_ip()

def get_banned_adresses():
	return banned_list

def ip_addr_format(address):
    return ('{}.{}.{}.{}'.format(*bytearray(address)))

def mac_addr_format(address):
    address = address.hex()[:16]
    return (':'.join(address[i:i+2] for i in range(0,12,2)))

def update_ip(ip, mac_address, lease, init_time = "null"):
	global IP_list
	IP_list.update({ip: (mac_address,lease, init_time)})
	return

def clientManage(server, address, packet):
	# global start_time
	# print("new Dosscover message")
	dhcp_client_packet = packet_analyser(packet)
	dhcpoptions = packet_analyser(packet)[13]
	dhcpMessageType = dhcpoptions[2]
	dhcpRequestedIp = False
	dest = ('255.255.255.255', address[1])

	# read requested IP address
	for i in range(len(dhcpoptions)):
	    if(dhcpoptions[i:i+2] == bytes([50, 4])):
	        dhcpRequestedIp = ip_addr_format(dhcpoptions[i+2:i+6])

	xid, ciaddr, chaddr, magic_cookie = dhcp_client_packet[4], dhcp_client_packet[7], dhcp_client_packet[11], dhcp_client_packet[12]
	dhcpClientMacAddress = mac_addr_format(chaddr)
	if(dhcpClientMacAddress not in get_banned_adresses()):
		if(dhcpMessageType == 1):
			ip = get_ip(str(dhcpClientMacAddress), dhcpRequestedIp)
			if(ip != False):
				# print("send offer")
				data = DHCP_offer( xid, ciaddr, chaddr, magic_cookie, ip)
				server.sendto(data, dest)
			else:
				print("all ips are occupied")

		if(dhcpMessageType == 3):
			# print("Receive DHCP request.(" + dhcpClientMacAddress + ')')
			ip = get_ip(str(dhcpClientMacAddress), dhcpRequestedIp)
			if(ip != False):
				data = DHCP_ack(xid, ciaddr, chaddr, magic_cookie, ip)
				update_ip(ip, str(dhcpClientMacAddress),lease_time,time.time())
				server.sendto(data, dest)
				# print("send ack message")
				while True:
					current_time = time.time()
					elapsed_time = current_time - IP_list[ip][2]
					if elapsed_time > (IP_list[ip][1]+1):
						update_ip(ip, "null", 0, current_time)
						# print(f"free { ip }")
						break
	else:
		print("this client is banned")
		server.sendto(b"banned", dest)

def get_mac_details(mac_address):
	url = "https://api.macvendors.com/"
	response = requests.get(url + mac_address).text
	return response
	# if response.status_code != 200:
	    # raise Exception("[!] Invalid MAC Address!")
	# return response.content.decode()

def stop():
	global running
	running = False

def get_ip_allocated():
	global IP_list
	package = "IP ADDRESSES  |  MAC ADDRESSES  |  Lease time |  Device Name \n----------------------------- \n"
	for key, value in IP_list.items():
		if(value[0] != "null"):
			package += ("(" + key + ") at " + value[0] + '\n')
			if value[2] != "null":
				package += "remaining time: " + str(time.time() - value[2])+'\n'
			else:
				package+= "reserved \n"
			# try:
			vendor_name = get_mac_details(value[0])
			package += "Device vendor is " + vendor_name +'\n'
			# except:
				# package +=	"Device Name: " + "[!] Invalid MAC Address! \n"
				# package +="****************************\n"
	return package

def get_ip_available():
	global IP_list
	package = "IP availables : "
	for key, value in IP_list.items() :
		if(value[0] == "null"):
			package += ("\t(" + key + ") \n")
	return package

def gui():
	global running
	print("[ stop ]	: stop the DHCP server ")
	print("[ usage ] : show ip assignment ")
	print("[ available ] : show ip still available ")
	print("*******************************************************")
	while running:
		request = input(">>Server: ").lower()
		if(request == "stop"):
			stop()

		elif(request == "usage"):
			print(get_ip_allocated())

		elif(request == "available"):
			print(get_ip_available())
	print("DHCP server gui has stoped")

def dhcp_server():
	global running
	server = socket(AF_INET, SOCK_DGRAM)
	server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
	server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
	server.bind((server_ip, serverPort))
	while running:
		bytesAddressPair = server.recvfrom(bufferSize)
		packet = bytesAddressPair[0]
		address = bytesAddressPair[1]
		newThread = threading.Thread(target=clientManage, args=(server, address, packet))
		newThread.start()
	print("Bye")

if __name__ == '__main__':
	f = open('config.json')
	data = json.load(f)
	pool_mode = data['pool_mode']

	ip_from = data['range']['from']
	ip_to = data['range']['to']

	ip_block = data['subnet']['ip_block']
	subnet_mask = data['subnet']['subnet_mask']

	lease_time = int(data['lease_time'])

	f.close()

	if pool_mode == "range":
		init_IP(pool_mode,ip_from,ip_to)
	else:
		init_IP(pool_mode,ip_block,subnet_mask)

	for pair in data["reservation_list"]:
		p = data["reservation_list"][pair]
		reservation_list.append(p)
		update_ip(p[1],p[0],0)

	for ban in range(len(data["black_list"])):
		mac = data["black_list"][ban]
		banned_list.append(mac)

	server_gui = threading.Thread(target=gui, name='gui')
	server_gui.start()
	dhcp_server()
	server_gui.join()


import json
import os
import asyncio

from aiohttp import web
from aiohttp.web_request import Request

from lennoxs30api.s30api_async import LENNOX_STATUS_GOOD, LENNOX_STATUS_NOT_AVAILABLE

class AppConnection(object):
    def __init__(self, app_id: str):
        self.app_id = app_id
        self.queue = []

class Simulator(object):
    def __init__(self, configfile: str):
        self.configfile = configfile
        self.appList = {}
        self.zoneSimRunning = False
        self.outdoorTempSimRunning = False
        self.diagSimRunning = False
        self.siblingSimRunning = False
        self.outdoorTempSim = False
        self.heatpumpLockoutSim = None
        self.zoneSim = False
        self.siblingSim = False
        self.diagSim = False
        self.equipment = None
        self.productType = None
        with open(configfile) as f:
            self.config_data = json.load(f)
            if "outdoorTempSim" in self.config_data:
                self.outdoorTempSim = self.config_data["outdoorTempSim"]
            if "zoneSim" in self.config_data:
                self.zoneSim = self.config_data["zoneSim"]
            if "siblingSim" in self.config_data:
                self.siblingSim = self.config_data["siblingSim"]
            if "diagSim" in self.config_data:
                self.diagSim = self.config_data["diagSim"]
            if "heatpumpLockoutSim" in self.config_data:
                self.heatpumpLockoutSim = self.config_data["heatpumpLockoutSim"]
            if "productType" in self.config_data:
                self.productType = self.config_data["productType"]

    async def heatpumpLockoutSimulator(self):
        active: bool = False
        while True:
            message = self.loadfile(self.heatpumpLockoutSim)
            await asyncio.sleep(15.0)
            message["Data"]["alerts"]["active"][0]["alert"]["isStillActive"] = active
            message["Data"]["alerts"]["active"][1]["alert"]["isStillActive"] = active
            if not active:
                message["Data"]["alerts"]["meta"]["numActiveAlerts"] = 0
            else:
                message["Data"]["alerts"]["meta"]["numActiveAlerts"] = 2

            active = not active
            for _, appObject in self.appList.items():
                appObject.queue.append(message)

    async def outdoorTempSimulator(self):
        if self.outdoorTempSim == False or self.outdoorTempSimRunning == True:
            return
        self.outdoorTempSimRunning = True
        await asyncio.sleep(15.0)
        temperature = 10
        while True:
            if temperature == 100:
                status = LENNOX_STATUS_NOT_AVAILABLE
            else:
                status = LENNOX_STATUS_GOOD
            message = {
                "MessageId": "637594500464320381|95a6cacebd94459dbe7538161628bdb6",
                "SenderId": "LCC",
                "TargetID": "mapp079372367644467046827098_myemail@email.com",
                "MessageType": "PropertyChange",
                "Data": {
                    "system": {
                        "status": {
                            "outdoorTemperatureStatus": status,
                            "outdoorTemperature": temperature,
                            "outdoorTemperatureC": 13.5,
                        },
                        "publisher": {"publisherName": "lcc"},
                    }
                },
            }
            for appName, appObject in self.appList.items():
                appObject.queue.append(message)
            if temperature == 100:
                temperature = 10
            else:
                temperature = temperature + 10
            await asyncio.sleep(5.0)

    async def diagSimulator(self):
        if self.diagSim == False or self.diagSimRunning == True:
            return
        self.diagSimRunning = True
        message = self.loadfile("tests/messages/equipments_diag_update.json")

        await asyncio.sleep(15.0)
        value: float = 0.0
        while True:
            message["Data"]["equipments"][0]["equipment"]["diagnostics"][1]["diagnostic"]["value"] = str(value)
            value += 1.2
            if value > 300:
                value = 0.0

            if message["Data"]["equipments"][0]["equipment"]["diagnostics"][0]["diagnostic"]["value"] == "Yes":
                message["Data"]["equipments"][0]["equipment"]["diagnostics"][0]["diagnostic"]["value"] = "No"
            else:
                message["Data"]["equipments"][0]["equipment"]["diagnostics"][0]["diagnostic"]["value"] = "Yes"

            for appName, appObject in self.appList.items():
                appObject.queue.append(message)
            await asyncio.sleep(1.0)

    async def parameterUpdate(self, pu: dict) -> None:
        await asyncio.sleep(8.0)
        message = {
            "MessageId": 0,
            "SenderID": "LCC",
            "TargetID": "ha_dev",
            "MessageType": "PropertyChange",
            "Data": {
                "system": {
                    "status": {"rsbusMode": "commissioning"},
                    "publisher": {"publisherName": "lcc"},
                }
            },
        }
        for appName, appObject in self.appList.items():
            appObject.queue.append(message)
        await asyncio.sleep(0.5)
        for eq in self.equipment["Data"]["equipments"]:
            equip = eq["equipment"]
            if pu["et"] == equip["equipType"]:
                message = {
                    "MessageId": 0,
                    "SenderID": "LCC",
                    "TargetID": "ha_dev",
                    "MessageType": "PropertyChange",
                    "Data": {
                        "equipments": [
                            {
                                "publisher": {"publisherName": "lcc"},
                                "equipment": {
                                    "parameters": [
                                        {
                                            "parameter": {
                                                "pid": pu["pid"],
                                                "enabled": True,
                                                "value": pu["value"],
                                            },
                                        }
                                    ],
                                    "equipType": pu["et"],
                                },
                                "id": eq["id"],
                            }
                        ]
                    },
                }
                for appName, appObject in self.appList.items():
                    appObject.queue.append(message)
                break

    async def zoneSimulator(self):
        if self.zoneSim == False or self.zoneSimRunning == True:
            return
        self.zoneSimRunning = True
        await asyncio.sleep(15.0)
        temperature = 10
        humidity = 50
        while True:
            if temperature == 100:
                status = LENNOX_STATUS_NOT_AVAILABLE
            else:
                status = LENNOX_STATUS_GOOD
            message = {
                "MessageId": "637594500464319661|7df1361acd764dce83fcbc776ae3f8dd",
                "SenderId": "LCC",
                "TargetID": "mapp079372367644467046827098_myemail@email.com",
                "MessageType": "PropertyChange",
                "Data": {
                    "zones": [
                        {
                            "publisher": {"publisherName": "lcc"},
                            "status": {
                                "fan": False,
                                "allergenDefender": False,
                                "humidity": humidity,
                                "humidityStatus": status,
                                "temperature": temperature,
                                "temperatureStatus": status,
                                "temperatureC": 26,
                            },
                            "id": 0,
                        }
                    ]
                },
                "AdditionalParameters": None,
            }
            for appName, appObject in self.appList.items():
                appObject.queue.append(message)
            if temperature == 100:
                temperature = 10
                humidity = 50
            else:
                temperature = temperature + 10
                humidity = humidity + 1
            await asyncio.sleep(5.0)

    async def siblingSimulator(self):
        if self.siblingSim == False or self.siblingSimRunning == True:
            return
        self.siblingSimRunning = True
        message = {
            "MessageId": 0,
            "SenderID": "LCC",
            "TargetID": "homeassistant",
            "MessageType": "PropertyChange",
            "Data": {
                "siblings": [
                    {
                        "publisher": {"publisherName": "lcc"},
                        "id": 0,
                        "selfIdentifier": "KL21J00001",
                        "sibling": {
                            "identifier": "KL21J00002",
                            "systemName": '"Bedrooms"',
                            "nodePresent": True,
                            "portNumber": 443,
                            "groupCountTracker": True,
                            "ipAddress": "10.0.0.2",
                        },
                    }
                ]
            },
        }
        for appName, appObject in self.appList.items():
            appObject.queue.append(message)
        await asyncio.sleep(15.0)

        temperature = 100
        while True:
            if temperature == 100:
                status = LENNOX_STATUS_NOT_AVAILABLE
            else:
                status = LENNOX_STATUS_GOOD
            message = {
                "MessageId": "637594500464320381|95a6cacebd94459dbe7538161628bdb6",
                "SenderId": "KL21J00002",
                "TargetID": "mapp079372367644467046827098_myemail@email.com",
                "MessageType": "PropertyChange",
                "Data": {
                    "system": {
                        "status": {
                            "outdoorTemperatureStatus": status,
                            "outdoorTemperature": temperature,
                            "outdoorTemperatureC": 13.5,
                        },
                        "publisher": {"publisherName": "lcc"},
                    }
                },
            }
            for appName, appObject in self.appList.items():
                appObject.queue.append(message)
            if temperature == 200:
                temperature = 100
            else:
                temperature = temperature + 10
            await asyncio.sleep(5.0)

    def loadfile(self, name) -> json:
        script_dir = os.path.dirname(__file__)
        file_path = os.path.join(script_dir, "../" + name)
        with open(file_path) as f:
            data = json.load(f)
        if "SenderId" in data:
            data["SenderId"] = "LCC"
        if "SenderID" in data:
            data["SenderID"] = "LCC"
        return data

    async def connect(self, request: Request):
        app_id = request.match_info["app_id"]
        if app_id in self.appList:
            pass
        else:
            self.appList[app_id] = AppConnection(app_id)
        return web.Response(text="Simulator Success")

    async def disconnect(self, request: Request):
        app_id = request.match_info["app_id"]
        self.appList.pop(app_id)
        return web.Response(text="Simulator Success")

    async def request_data(self, request: Request):
        data = await request.json()
        return self.process_request_data(data)

    def process_request_data(self, data):
        if "SenderID" in data:
            app_id = data["SenderID"]
            if app_id in self.appList:
                app: AppConnection = self.appList[app_id]
                if "configFile" in self.config_data:
                    data = self.loadfile(self.config_data["configFile"])
                    if self.productType != None:
                        data["Data"]["system"]["config"]["options"]["productType"] = self.productType
                    app.queue.append(data)
                if "rgwFile" in self.config_data:
                    data = self.loadfile(self.config_data["rgwFile"])
                    app.queue.append(data)
                if "zonesFile" in self.config_data:
                    data = self.loadfile(self.config_data["zonesFile"])
                    app.queue.append(data)
                if "equipmentFile" in self.config_data:
                    data = self.loadfile(self.config_data["equipmentFile"])
                    self.equipment = data
                    app.queue.append(data)
                if "deviceFile" in self.config_data:
                    data = self.loadfile(self.config_data["deviceFile"])
                    app.queue.append(data)
                if "bleFile" in self.config_data:
                    data = self.loadfile(self.config_data["bleFile"])
                    app.queue.append(data)
                if "iaqFile" in self.config_data:
                    data = self.loadfile(self.config_data["iaqFile"])
                    app.queue.append(data)
                if "systemFile" in self.config_data:
                    data = self.loadfile(self.config_data["systemFile"])
                    app.queue.append(data)
                if "alertFile" in self.config_data:
                    data = self.loadfile(self.config_data["alertFile"])
                    app.queue.append(data)

                asyncio.create_task(self.outdoorTempSimulator())
                asyncio.create_task(self.zoneSimulator())
                asyncio.create_task(self.siblingSimulator())
                asyncio.create_task(self.diagSimulator())
                asyncio.create_task(self.heatpumpLockoutSimulator())
                return web.Response(text="Simulator Success")
        return web.Response(status=404, text="Simulator Failuer")

    def perform_substitutions(self, message: str) -> str:
        if "substitutions" in self.config_data:
            for substitution in self.config_data["substitutions"]:
                message = message.replace(substitution["old_value"], substitution["new_value"])
        return message

    async def retrieve(self, request):
        app_id = request.match_info["app_id"]
        delay = 15
        if app_id in self.appList:
            app: AppConnection = self.appList[app_id]
            for i in range(delay):
                if len(app.queue) != 0:
                    message = app.queue.pop()
                    data = '{ "messages": [' + json.dumps(message) + "]}"
                    data = self.perform_substitutions(data)
                    return web.Response(status=200, body=data)
                await asyncio.sleep(1.0)
        else:
            data = {}
            self.appList[app_id] = AppConnection(app_id)
            data["SenderID"] = app_id
            self.process_request_data(data)
        return web.Response(status=204)

    def process_message(self, msg):
        if "Data" in msg:
            data = msg["Data"]
            if "system" in data:
                if "config" in data["system"]:
                    if "centralMode" in data["system"]["config"]:
                        mode = data["system"]["config"]["centralMode"]
                        if mode == True:
                            zm = "central"
                        else:
                            zm = "zoned"
                        msg["Data"] = {
                            "system": {
                                "status": {
                                    "zoningMode": zm,
                                },
                                "config": {"centralMode": mode},
                            }
                        }
            if "systemControl" in data:
                if "parameterUpdate" in data["systemControl"]:
                    parameterUpdate = data["systemControl"]["parameterUpdate"]
                    asyncio.create_task(self.parameterUpdate(parameterUpdate))
        return msg

    async def publish(self, request):
        data = await request.json()
        data["SenderID"] = "LCC"
        data["MessageType"] = "PropertyChange"
        message_to_send = self.process_message(data)
        for appName, appObject in self.appList.items():
            appObject.queue.append(message_to_send)

        body_json = {"code": 1, "message": "", "retry_after": 0}
        body_txt = json.dumps(body_json)
        return web.Response(status=200, body=body_txt)

def init_func(argv):
    if len(argv) == 2:
        if argv[0] == "-c":
            fileName = argv[1]
            simulator = Simulator(fileName)
            app = web.Application()
            app.add_routes(
                [
                    web.post("/Endpoints/{app_id}/Connect", simulator.connect),
                    web.post("/Endpoints/{app_id}/Disconnect", simulator.disconnect),
                    web.post("/Messages/RequestData", simulator.request_data),
                    web.get("/Messages/{app_id}/Retrieve", simulator.retrieve),
                    web.get("/v1/Messages/{app_id}/Retrieve", simulator.retrieve),
                    web.post("/Messages/Publish", simulator.publish),
                    web.post("/v1/messages/publish", simulator.publish),
                ]
            )
    return app


#!/usr/bin/env python
# Muyuan Chen 2020-03
from EMAN2 import *
import numpy as np
from sklearn import cluster,mixture
from sklearn.decomposition import PCA

def main():

	usage=" "
	parser = EMArgumentParser(usage=usage,version=EMANVERSION)
	parser.add_argument("--pts", type=str,help="point input", default="")
	parser.add_argument("--pcaout", type=str,help="pca output", default="")
	parser.add_argument("--ptclsin", type=str,help="ptcl input", default="")
	parser.add_argument("--ptclsout", type=str,help="ptcl out suffix", default="")
	parser.add_argument("--pad", type=int,help="pad for make3d", default=-1)
	parser.add_argument("--ncls", type=int,help="number of classes", default=3)
	parser.add_argument("--nbasis", type=int,help="PCA dimensionality", default=2)
	parser.add_argument("--setsf", type=str,help="setsf", default="")
	parser.add_argument("--threads", default=12,type=int,help="Number of threads to run in parallel on a single computer. This is the only parallelism supported by e2make3dpar")
	(options, args) = parser.parse_args()
	logid=E2init(sys.argv)

	pts=np.loadtxt(options.pts)

	pca=PCA(options.nbasis)
	p2=pca.fit_transform(pts[:,1:])
	if options.pcaout:
		np.savetxt(options.pcaout, p2)

	clust=cluster.KMeans(options.ncls)

	lbs=clust.fit_predict(p2)
	onames=[]
	fname=options.ptclsin
	lstinp=fname.endswith(".lst")

	if lstinp:
		lin=LSXFile("gmm_03/ptcls_set2.lst")

	for j,l in enumerate(np.unique(lbs)):
		ii=(lbs==l)
		idx=pts[ii,0].astype(int)

		onm="{}_{:02d}.lst".format(options.ptclsout, j)
		print(len(idx),onm)
		if os.path.isfile(onm):
			os.remove(onm)
		lout=LSXFile(onm, False)
		for i in idx:
			if lstinp:
				l=lin.read(i)
				lout.write(-1, l[0], l[1])
			else:
				lout.write(-1, i, fname)

		lout=None
		onames.append(onm)

	e=EMData(fname, 0, True)
	if options.pad<1: options.pad=good_size(e["nx"]*1.25)
	if options.setsf:
		options.setsf=" --setsf "+options.setsf

	for o in onames:
		t=o.replace("ptcl", "threed")[:-3]+"hdf"
		print(o,t)
		cmd="e2make3dpar.py --input {} --output {} --pad {} --mode trilinear --no_wt --keep 1 --threads {} {}".format(o,t, options.pad, options.threads, options.setsf)
		launch_childprocess(cmd)

	E2end(logid)

def run(cmd):
	print(cmd)
	launch_childprocess(cmd)

if __name__ == '__main__':
	main()


#Author: Ally Burke

import sys
sys.path.append('../../extra-files')
import copy
import numpy as np
from masses import get_charge
from masses import get_mass

class Molecule(object):

	#Used to initialize an instance of the Molecule class

	def __init__(self, geom_str, units):
		self.units = units				#Specifies units for spatial coordinates
		self.read(geom_str)				#Reads in the geometry file for the specific molecule

	#Returns a string representing the contents of the Molecule object in .xyz format

	def read(self, geom_str):
		#Read in the file containing the geometry of the molecule in question
		#print("\n" + "MOLECULE INFORMATION" + "\n")
		geom = []
		self.labels = []
		self.masses = []
		self.charges = []
		lines = geom_str.strip().splitlines()
		self.natom = int(lines[0])
		#print("Number of atoms: " + str(self.natom) + "\n")
		#print("Units are currently in: " + self.units + "\n")
		for line in lines[2:]:
			atom, x, y, z = line.split()
			self.labels.append(atom)
			geom.append([float(x), float(y), float(z)])
		self.geom = np.array(geom)
		#print("Atoms: " + str(self.labels)+ "\n")
		#Reading in the masses and charges of the atoms from the .xyz file

		for x in self.labels:
			self.masses.append(get_mass(x))
			self.charges.append(get_charge(x))
		y = 0
		for x in self.labels:
			#print("Mass of " + x + " is: " + str(self.masses[y]))
			#print("Charge of " + x + " is: " + str(self.charges[y]))
			y += 1
		#print("\n")
		#print("Molecular Geometry in: " + self.units + "\n")
		#print(self.geom)

		return self.geom, self.natom, self.labels

	def xyz_string(self):
		string = ''
		i=0
		string += str(self.natom) + '\n' + str(self.units) + '\n'
		for n in self.labels:
			string += n + "  " + str(self.geom[i]) + '\n'
			i+=1
		print(string)
		return string

	#UNIT CONVERSION FUNCTIONS

	def to_bohr(self):

	#Converts units from Angstrom to Bohr

		if self.units == "Angstrom":
			self.units = "Bohr"
			self.geom *= 1.889725989

	def to_angstrom(self):

	#Converts from Bohr to Angstrom

		if self.units == "Bohr":
			self.units = "Angstrom"
			self.geom /= 1.889725989

	#Create fresh copy of Molecule object

	def copy(self):
		return Molecule(self.xyz_string(), self.units)

#Used to test the functions above

if __name__ == "__main__":
	file1 = open("../../extra-files/molecule.xyz").read()
	mol = Molecule(file1, "Angstrom")
	mol.xyz_string()
	#Testing unit conversion functions
	mol.to_bohr()
	print("\n" + "Units have now been converted to: " + mol.units)
	print(mol.geom)
	mol.to_angstrom()
	print("\n" + "Units have now been converted back to: " + mol.units)
	print(mol.geom)


'''
-Medium-

You are given a 0-indexed integer array nums. For each index i (1 <= i <= nums.length - 2) the beauty of nums[i] equals:

2, if nums[j] < nums[i] < nums[k], for all 0 <= j < i and for all i < k <= nums.length - 1.
1, if nums[i - 1] < nums[i] < nums[i + 1], and the previous condition is not satisfied.
0, if none of the previous conditions holds.
Return the sum of beauty of all nums[i] where 1 <= i <= nums.length - 2.

Example 1:

Input: nums = [1,2,3]
Output: 2
Explanation: For each index i in the range 1 <= i <= 1:
- The beauty of nums[1] equals 2.
Example 2:

Input: nums = [2,4,6,4]
Output: 1
Explanation: For each index i in the range 1 <= i <= 2:
- The beauty of nums[1] equals 1.
- The beauty of nums[2] equals 0.
Example 3:

Input: nums = [3,2,1]
Output: 0
Explanation: For each index i in the range 1 <= i <= 1:
- The beauty of nums[1] equals 0.

Constraints:

3 <= nums.length <= 105
1 <= nums[i] <= 105

'''

from typing import List
from collections import deque

class Solution:
    def sumOfBeauties(self, nums: List[int]) -> int:
        A, n = nums, len(nums)
        f, b = [-1]*n, [10**5+1]*n
        for i in range(1, n):
            # f[i] max in [0, i-1]
            f[i] = max(f[i-1], A[i-1])
        for i in range(n-2, -1, -1):
            # b[i] min in [i+1, n-1]
            b[i] = min(b[i+1], A[i+1])
        ans = 0
        for i in range(1, len(A)-1):
            if A[i] > f[i] and A[i] < b[i]:
                ans += 2
            elif A[i-1] < A[i] < A[i+1]:
                ans += 1
        return ans

    def sumOfBeauties2(self, nums: List[int]) -> int:
        A, n = nums, max(nums)
        BIT = [0]*(n+1)
        left, right = [-1]*len(nums), [-1]*len(nums)
        def update(x, val):
            while x <= n:
                BIT[x] += val
                x += x & (-x)
        def query(x):
            sums = 0
            while x > 0:
                sums += BIT[x]
                x -= x & (-x)
            return sums
        for i, a in enumerate(A):
            left[i] = query(a-1)
            update(a, 1)
        BIT = [0]*(n+1)
        for i in range(len(A)-1, -1, -1):
            right[i] = query(n) - query(A[i])
            update(A[i], 1)
        ans = 0
        for i in range(1, len(A)-1):
            if left[i] == i and right[i] == (len(A)-i-1):
                ans += 2
            elif A[i-1] < A[i] < A[i+1]:
                ans += 1
        # print(left)
        # print(right)
        return ans

if __name__ == "__main__":
    print(Solution().sumOfBeauties(nums = [4,2,4,6,7,8]))
    print(Solution().sumOfBeauties(nums = [1,2,3]))
    print(Solution().sumOfBeauties(nums = [2,4,6,4]))
    print(Solution().sumOfBeauties(nums = [3,2,1]))
    print(Solution().sumOfBeauties2(nums = [4,2,4,6,7,8]))
    print(Solution().sumOfBeauties2(nums = [1,2,3]))
    print(Solution().sumOfBeauties2(nums = [2,4,6,4]))
    print(Solution().sumOfBeauties2(nums = [3,2,1]))


from bls import blsprice
def bsput(sigma):
	S=112.6;
	K=100;
	r=0.02;
	T=2/12;
	return blsprice('P',S,K,r,sigma,T)
def newtstepBS(x1):
	P=5;#known from the market
	u=10**-5
	df=(bsput(x1+u)-bsput(x1))/u; #approximation for f'

	return x1-(bsput(x1)-P)/df;#x1-f(x1)/f'(x1)


from manim import *
from manim_gearbox import *
from scipy.optimize import fsolve
from manim_cad_drawing_utils import *

class SlideRoll(MovingCameraScene):
    def construct(self):
        gear1 = Gear(12,module=2,profile_shift=0.6, fill_color=BLUE_A,fill_opacity=1,stroke_opacity=0)
        gear2 = gear1.copy()

        gear1.shift(UP*(gear1.rp+gear1.X*gear1.m/2))
        gear2.shift(DOWN*gear1.rp)
        gear2.mesh_to(gear1)

        # gear_small_1=Gear(12,module=1.5,profile_shift=0.6,
        #                   cutout_teeth_num=8,
        #                   fill_color=BLUE_A,fill_opacity=1,stroke_opacity=0)

        def sin_func(s, a=0.1, f=672):
            return a*(np.cos(s*f*TAU)-1)

        gear_wave1 = Path_Offset_Mobject(gear1,sin_func,num_of_samples=5000, color=RED_E,stroke_width=3)
        gear_wave2 = Path_Offset_Mobject(gear2,sin_func,num_of_samples=5000, color=DARK_BLUE,stroke_width=3)

        geargrp1 = VGroup(gear1,gear_wave1)
        geargrp2 = VGroup(gear2, gear_wave2)

        self.add(geargrp1, geargrp2)
        self.play(Rotate(geargrp1,gear1.pitch_angle*3),
                  Rotate(geargrp2,-gear1.pitch_angle*3),
                  run_time=30,
                  rate_func=linear)