import os
import sys
import unittest
import difflib
import threading
import errno
import re
import glob
import io
import logging

try:
    MAXFD = os.sysconf("SC_OPEN_MAX")
except ValueError:
    MAXFD = 256

def rmTree(root):
    "remove a file hierarchy, root can be a file or a directory"
    if os.path.isdir(root):
        for dir, subdirs, files in os.walk(root, topdown=False):
            for f in files:
                os.unlink(dir + "/" + f)
            os.rmdir(dir)
    else:
        if os.path.lexists(root):
            os.unlink(root)

def ensureDir(dir):
    """Ensure that a directory exists, creating it (and parents) if needed."""
    try:
        os.makedirs(dir)
    except OSError as ex:
        if ex.errno != errno.EEXIST:
            raise ex

def ensureFileDir(fname):
    """Ensure that the directory for a file exists, creating it (and parents) if needed.
    Returns the directory path"""
    dir = os.path.dirname(fname)
    if len(dir) > 0:
        ensureDir(dir)
        return dir
    else:
        return "."

class LoggerForTests():
    """test logger that logs to memory, each instance has a new logger"""
    def __init__(self, level=logging.DEBUG):
        self.logger = logging.getLogger(str(id(self)))
        self.logger.setLevel(level)
        self.__buffer = io.StringIO()
        self.logger.addHandler(logging.StreamHandler(self.__buffer))

    @property
    def data(self):
        return self.__buffer.getvalue()

class TestCaseBase(unittest.TestCase):
    """Base class for test case with various test support functions"""

    def __init__(self, methodName):
        """initialize, removing old output files associated with the class"""
        super(TestCaseBase, self).__init__(methodName=methodName)
        clId = self.getClassId()
        od = self.getOutputDir()
        for f in glob.glob("{}/{}.*".format(od, clId)) + glob.glob("{}/tmp.*{}.*".format(od, clId)):
            rmTree(f)

    def getClassId(self):
        """Get the first part of the portable test id, consisting
        moduleBase.class.  This is the prefix to output files"""
        # module name is __main__ when run standalone, so get base file name
        mod = os.path.splitext(os.path.basename(sys.modules[self.__class__.__module__].__file__))[0]
        return mod + "." + self.__class__.__name__

    def getId(self):
        """get the fixed test id, which is in the form moduleBase.class.method
        which avoids different ids when test module is run as main or
        from a larger program"""
        # last part of unittest id is method
        return self.getClassId() + "." + self.id().split(".")[-1]

    def getTestDir(self):
        """find test directory, where concrete class is defined."""
        testDir = os.path.dirname(sys.modules[self.__class__.__module__].__file__)
        if testDir == "":
            testDir = "."
        testDir = os.path.realpath(testDir)
        # turn this into a relative directory
        cwd = os.getcwd()
        if testDir.startswith(cwd):
            testDir = testDir[len(cwd) + 1:]
            if len(testDir) == 0:
                testDir = "."
        return testDir

    def getTestRelProg(self, progName):
        "get path to a program in directory above the test directory"
        return os.path.join(self.getTestDir(), "..", progName)

    def getInputFile(self, fname):
        """Get a path to a file in the test input directory"""
        return self.getTestDir() + "/input/" + fname

    def getOutputDir(self):
        """get the path to the output directory to use for this test, create if it doesn't exist"""
        d = self.getTestDir() + "/output"
        ensureDir(d)
        return d

    def getOutputFile(self, ext):
        """Get path to the output file, using the current test id and append
        ext, which should contain a dot"""
        f = self.getOutputDir() + "/" + self.getId() + ext
        ensureFileDir(f)
        return f

    def getExpectedFile(self, ext, basename=None):
        """Get path to the expected file, using the current test id and append
        ext. If basename is used, it is inset of the test id, allowing share
        an expected file between multiple tests."""
        return self.getTestDir() + "/expected/" + (basename if basename is not None else self.getId()) + ext

    def __getLines(self, file):
        with open(file) as fh:
            return fh.readlines()

    def __getBytes(self, file):
        with open(file, "rb") as fh:
            return fh.read()

    def mustExist(self, path):
        if not os.path.exists(path):
            self.fail("file does not exist: " + path)

    def diffExpected(self, ext, expectedBasename=None):
        """diff expected and output files.  If expectedBasename is used, it is
        used insted of the test id to find the expected file, allowing share
        an expected file between multiple tests."""

        expFile = self.getExpectedFile(ext, expectedBasename)
        expLines = self.__getLines(expFile)

        outFile = self.getOutputFile(ext)
        outLines = self.__getLines(outFile)

        diff = difflib.unified_diff(expLines, outLines, expFile, outFile)
        cnt = 0
        for l in diff:
            sys.stdout.write(l)
            cnt += 1
        self.assertTrue(cnt == 0)

    def diffBinaryExpected(self, ext, expectedBasename=None):
        """diff expected and output binary files.  If expectedBasename is
        used, it is used insted of the test id to find the expected file,
        allowing share an expected file between multiple tests."""

        expFile = self.getExpectedFile(ext, expectedBasename)
        expBytes = self.__getBytes(expFile)

        outFile = self.getOutputFile(ext)
        outBytes = self.__getBytes(outFile)

        self.assertEqual(outBytes, expBytes)

    def createOutputFile(self, ext, contents=""):
        """create an output file, filling it with contents."""
        fpath = self.getOutputFile(ext)
        ensureFileDir(fpath)
        fh = open(fpath, "w")
        try:
            fh.write(contents)
        finally:
            fh.close()

    def verifyOutputFile(self, ext, expectContents=""):
        """verify an output file, if contents is not None, it is a string to
        compare to the expected contents of the file."""
        fpath = self.getOutputFile(ext)
        self.mustExist(fpath)
        self.assertTrue(os.path.isfile(fpath))
        fh = open(fpath)
        try:
            got = fh.read()
        finally:
            fh.close()
        self.assertEqual(got, expectContents)

    @staticmethod
    def numRunningThreads():
        "get the number of threads that are running"
        n = 0
        for t in threading.enumerate():
            if t.is_alive():
                n += 1
        return n

    def assertSingleThread(self):
        "fail if more than one thread is running"
        self.assertEqual(self.numRunningThreads(), 1)

    def assertNoChildProcs(self):
        "fail if there are any running or zombie child process"
        foundChild = True
        try:
            s = os.waitpid(0, os.WNOHANG)
        except OSError as ex:
            if ex.errno != errno.ECHILD:
                raise
            foundChild = False
        if foundChild:
            self.fail("pending child processes or zombies: " + str(s))

    @staticmethod
    def numOpenFiles():
        "count the number of open files"
        n = 0
        for fd in range(0, MAXFD):
            try:
                os.fstat(fd)
            except OSError:
                n += 1
        return MAXFD - n

    def assertNumOpenFilesSame(self, prevNumOpen):
        "assert that the number of open files has not changed"
        numOpen = self.numOpenFiles()
        if numOpen != prevNumOpen:
            self.fail("number of open files changed, was " + str(prevNumOpen) + ", now it's " + str(numOpen))

    def assertRegexpMatchesDotAll(self, obj, expectRe, msg=None):
        """Fail if the str(obj) does not match expectRe operator, including `.' matching newlines"""
        if not re.match(expectRe, str(obj), re.DOTALL):
            raise self.failureException(msg or "'{}' does not match '{}'".format(str(obj), expectRe))


### Type Hint/Annotation with Checking examples
"""
List is imported since I am using python 3.7 - 3.9+ includes a list type already
Type hinting or type annotation is important to ensure the type that is passed to a function arguments is correct.
Python is dynamically typed and this can cause issues where the type of a variable is overwritten or changed in a program.
Type checking helps validate the correct types. Mypy can check the types of functions with type hinting included.
To begin using type checking: pip install mypy
Run type checker by: mypy type_hinting.py
Can you find the issue present in this file?
"""
from typing import List

person = "Eleven"
person_fake = "11"
### No type hinting.
def hello_world(name):
    return "Hello " + name

### type hint to accept and return str
def hello_world_type(name: str) -> str:
    if name.isnumeric():
        return None
    else:
        return "Hello " + name

print(hello_world(person))

print(hello_world_type(person))

print(hello_world_type(person_fake))

### type hint take a int and return a list
def list_gen(n: int) -> List[int]:
    new_list = []
    for i in range(n):
        new_list.append(i)
    return new_list

print(list_gen(5))


# Import the OpenAI library
import openai

# Import the Gradio library for creating user interfaces
import gradio

# Set your OpenAI API key
openai.api_key = "####"  # Replace "####" with your actual OpenAI API key

# Initialize the conversation with a system message
messages = [{"role": "system", "content": "You are a financial expert that specializes in real estate investment and negotiation"}]

# Define a function for the Gradio interface
def CustomChatGPT(user_input):
    # Add the user's input to the list of messages
    messages.append({"role": "user", "content": user_input})

    # Use the OpenAI Chat API to generate a response
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages
    )

    # Extract the generated reply from the API response
    ChatGPT_reply = response["choices"][0]["message"]["content"]

    # Add the assistant's reply to the list of messages
    messages.append({"role": "assistant", "content": ChatGPT_reply})

    # Return the generated reply for display in the Gradio interface
    return ChatGPT_reply

# Create a Gradio interface with a custom function for the chatbot
demo = gradio.Interface(fn=CustomChatGPT, inputs="text", outputs="text", title="Real Estate Pro")

# Launch the Gradio interface and allow sharing
demo.launch(share=True)


'''
    Цель   урока: запрограммировать вторую часть игры «Танки»: добавить базы, врагов, а также сделать видимые рабочие полоски здоровья.

    + повторить команды прошлых уроков;
    + добавить базы для танков;
    + запрограммировать для них полоски здоровья;
    + добавить возможность наносить урон красной базе, играя за зеленый танк;
    + создать полоску здоровья для зеленого танка;
    + добавить красные танки и полоски здоровья для них;
    + сделать выводы урока;
    + получить домашнее задание.
'''
import arcade
import base
import green
from constants import *
import bullete
import red

class Game(arcade.Window):
    def __init__(self, width, height, title):
        super().__init__(width, height, title)
        #Текстуры
        self.background = arcade.load_texture("background.png")
        #Спрайты
        self.green = green.Green_Tank(self)
        self.green_base = base.Base("green_base.png", self, (255, 255, 0))
        self.red_base = base.Base("red_base.png", self,(255, 165, 0))
        #Спрайтлисты
        self.projectiles = arcade.SpriteList()
        self.red_tanks = []
        #Поля
        self.left_pressed = False
        self.right_pressed = False
        self.up_pressed = False
        self.down_pressed = False
        #Инициализация координат спрайтов
        self.setup()

    def setup(self):
        self.green.center_x = 90
        self.green.center_y = 190
        self.green_base.center_x = 165
        self.green_base.center_y = 350
        self.red_base.center_x = 1035
        self.red_base.center_y = 350
        for i in range(1, 4):
            tank = red.Red_Tank(self)
            tank.center_x = 800
            tank.center_y = 200 * i - 50
            self.red_tanks.append(tank)

    def on_draw(self):
        self.clear()
        arcade.draw_texture_rectangle(SCREEN_WIDTH//2, SCREEN_HEIGHT//2, SCREEN_WIDTH, SCREEN_HEIGHT, self.background)
        self.green.draw()
        self.projectiles.draw()
        self.green_base.draw()
        self.red_base.draw()
        for tank in self.red_tanks:
            tank.draw()

    def update(self, delta_time):
        self.green.update()
        self.projectiles.update()
        self.red_base.update()
        self.green_base.update()
        for tank in self.red_tanks:
            tank.update()

    def on_key_press(self, key, modifiers):
        if key == arcade.key.LEFT:
            self.green.change_angle = 2.5
            self.left_pressed = True
            self.right_pressed = False
        if key == arcade.key.UP:
            self.green.change_x = 4
            self.green.change_y = 4
            self.up_pressed = True
            self.down_pressed = False

        if key == arcade.key.DOWN:
            self.green.change_x = -3
            self.green.change_y = -3
            self.up_pressed = False
            self.down_pressed = True

        if key == arcade.key.RIGHT:
            self.green.change_angle = -2.5
            self.left_pressed = False
            self.right_pressed = True

        if key == arcade.key.SPACE:
            shell = bullete.Bullet("green_bullet.png", self.green, 1)
            self.projectiles.append(shell)

    def on_key_release(self, key, modifiers):
        if key == arcade.key.LEFT and not self.right_pressed:
            self.green.change_angle = 0
        if key == arcade.key.RIGHT and not self.left_pressed:
            self.green.change_angle = 0
        if key == arcade.key.UP and not self.down_pressed:
                self.green.change_x = 0
                self.green.change_y = 0
        if key == arcade.key.DOWN and not self.up_pressed:
            self.green.change_x = 0
            self.green.change_y = 0

window = Game(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
arcade.run()


import pyudev
from .device_data import DeviceData

def get_device_list() -> list[DeviceData]:
    """
    Creates a list of information of connected usb devices.
    The included information is the vendor id, model id, serial number, path and devpath.

    Returns:
        List of DeviceData objects
    """
    devices = []

    context = pyudev.Context()
    for device in context.list_devices(subsystem='tty'):
        path = device.get("ID_PATH", None)

        # find better check if device is connected
        if path is None:
            continue

        vendor_id = device.get("ID_VENDOR_ID", None)
        model_id = device.get("ID_MODEL_ID", None)
        serial = device.get("ID_SERIAL", None)

        devpath = device.attributes.get("devpath", None)
        for parent in device.ancestors:
            if devpath is not None:
                devpath = devpath.decode('ascii')
                break

            devpath = parent.attributes.get("devpath", None)

        devices.append(DeviceData(path, vendor_id, model_id, serial, devpath))

    return devices


import json, os, sys

def merge_dols(dol1, dol2):
    keys = set(dol1).union(dol2)
    no = []
    return dict((k, dol1.get(k, no) + dol2.get(k, no)) for k in keys)

data1 = None
data2 = None
data_final = None

if len(sys.argv) < 4:
    exit("Please provide at least three files.\nThe program has ended.")

file1 = sys.argv[1]
file2 = sys.argv[2]
file_final = None

if len(sys.argv) == 4:
    file_final = sys.argv[3]

if not file1.endswith(".txt"):
    file1 = file1 + ".txt"

if not file2.endswith(".txt"):
    file2 = file2 + ".txt"

if not file_final.endswith(".txt"):
    file_final = file_final + ".txt"

while(True):
    try:
        with open(file1, 'r') as textfile1:
            data1 = json.load(textfile1)

        with open(file2, 'r') as textfile2:
            data2 = json.load(textfile2)

        if data1 is not None and data2 is not None:
            break

    except (FileNotFoundError, json.decoder.JSONDecodeError):   #if there is no file, end
        print(f"An error has occured.")
        exit("\nThe program has ended.")

for item in ["url", "name", "address", "max players"]:
    if data1[item] != data2[item]:
        print(f"Data mismatch.")
        exit("\nThe program has ended.")

#combined = {key:data1["hours"][key] + data2["hours"][key] for key in data1["hours"]}
data_final = data1
data_final["hours"] = merge_dols(data1["hours"], data2["hours"])

with open(file_final, 'w+') as outfile:
    json.dump(data_final, outfile, indent=4)
    print("\nMerging files was successful!")


import torch
import numpy as np

class NP(torch.nn.Module):
    def __init__(self, x_dim, y_dim, r_dim, z_dim, encoder_specs, decoder_specs, init_func):
        super().__init__()
        self.x_dim = x_dim
        self.y_dim = y_dim
        self.r_dim = r_dim
        self.z_dim = z_dim
        self.encoder_specs = encoder_specs
        self.decoder_specs = decoder_specs
        self.init_func = init_func
        self.softplus_act = torch.nn.Softplus()
        self.r_to_z_mean = torch.nn.Linear(self.r_dim, self.z_dim)
        self.r_to_z_logvar = torch.nn.Linear(self.r_dim, self.z_dim)

        # Create the encoder
        for i in range(len(self.encoder_specs)):
            if i == 0:
                encoder_input_dim = self.x_dim + self.y_dim
                self.add_module('h_layer' + str(i), \
                        torch.nn.Linear(encoder_input_dim, self.encoder_specs[i][0]))

                if self.encoder_specs[i][1]:
                    self.add_module('h_layer' + str(i) + '_act', self.encoder_specs[i][1])

            else:
                self.add_module('h_layer' + str(i), \
                        torch.nn.Linear(self.encoder_specs[i-1][0], self.encoder_specs[i][0]))

                if self.encoder_specs[i][1]:
                    self.add_module('h_layer' + str(i) + '_act', self.encoder_specs[i][1])

        # Create the decoder
        for i in range(len(self.decoder_specs)):
            if i == 0:
                decoder_input_dim = self.x_dim + self.z_dim
                self.add_module('g_layer' + str(i), \
                    torch.nn.Linear(decoder_input_dim, self.decoder_specs[i][0]))

                if self.decoder_specs[i][1]:
                    self.add_module('g_layer' + str(i) + '_act', self.decoder_specs[i][1])

            else:
                self.add_module('g_layer' + str(i), \
                    torch.nn.Linear(self.decoder_specs[i-1][0], self.decoder_specs[i][0]))

                if self.decoder_specs[i][1]:
                    self.add_module('g_layer' + str(i) + '_act', self.decoder_specs[i][1])

        if init_func:
            for layer_name,_ in self._modules.items():
                if layer_name.endswith('act') == False:
                    init_func(getattr(getattr(self, layer_name), 'weight'))

    def h(self, x, y):
        x_y = torch.cat([x, y], dim=1)
        for layer_name, layer_func in self._modules.items():
            if layer_name.startswith('h'):
                x_y = layer_func(x_y)
        return x_y

    def aggregate(self, r):
        return torch.mean(r, dim=0)

    def xy_to_z_params(self, x, y):
        r = self.h(x, y)
        r = self.aggregate(r)

        mean = self.r_to_z_mean(r)
        logvar = self.r_to_z_logvar(r)

        return mean.unsqueeze(-1), logvar.unsqueeze(-1)

    def sample_z(self, z, how_many):
        """
        Returns a sample from z of size (z_dim, how_many)
        """
        mean, logvar = z
        std = torch.exp(0.5 * logvar)

        eps = torch.randn([self.z_dim, how_many])
        z_samples = mean + std * eps
        return z_samples

    def g(self, x, z):
        z_reshape =  z.t().unsqueeze(1).expand(-1, x.shape[0], -1)
        x_reshape = x.unsqueeze(0).expand(z_reshape.shape[0], x.shape[0], x.shape[1])
        x_z = torch.cat([x_reshape, z_reshape], dim=2)

        y_mean = x_z
        for layer_name, layer_func in self._modules.items():
            if layer_name.startswith('g'):
                y_mean = layer_func(y_mean)

        return y_mean

    def forward(self, x_context, y_context, x_target, y_target):
        z_context = self.xy_to_z_params(x_context, y_context)
        print(self.training)
        if self.training:
            z_target = self.xy_to_z_params(x_target, y_target)
        else:
            z_target = z_context

        z_sample = self.sample_z(z_target, how_many=1)
        y_hat = self.g(x_target, z_sample)

        return y_hat, z_target, z_context

def KL_div(mu_q, logvar_q, mu_p, logvar_p):
    KL = (torch.exp(logvar_q) + (mu_q - mu_p) ** 2) / torch.exp(logvar_p) \
             - 1.0 \
             + logvar_p - logvar_q
    KL = 0.5 * KL.sum()
    return KL

def ELBO(y_hat, y, z_target, z_context):
    log_lik = torch.nn.functional.mse_loss(y_hat, y)
    KL = KL_div(z_target[0], z_target[1], z_context[0], z_context[1])
    return - log_lik + KL

# Log-likelihood
def MC_loglikelihood(inputs, outputs, decoder, z_mean, z_std, how_many, device=None):
    """
    Returns a Monte Carlo estimate of the log-likelihood
    z_mean: mean of the distribution from which to sample z
    z_std: std of the distribution from which to sample z
    how_many: number of monte carlo samples
    decoder: the decoder to be used to produce estimates of mean
    """
    # sample z
    if device:
        z_samples = sample_z(z_mean, z_std, how_many, device=device)
    else:
        z_samples = sample_z(z_mean, z_std, how_many)
    # produce the 10 estimated of the mean and std
    y_mean, y_std = decoder(inputs, z_samples)
    # define likelihood for each value of z
    likelihood = torch.distributions.Normal(y_mean, y_std)
        # for each value of z:
            # evaluate log-likelihood for each data point
            # sum these per-data point log-likelihoods
        # compute the mean
    log_likelihood = likelihood.log_prob(outputs).sum(dim=1).mean()
    return log_likelihood

# KL divergence
def KL_div(mean_1, std_1, mean_2, std_2):
    """Analytical KLD between 2 Gaussians."""
    KL = (torch.log(std_2) - torch.log(std_1) + \
        (std_1**2/ (2*std_2**2)) + \
        ((mean_1 - mean_2)**2 / (2*std_2**2)) - 1).sum()*0.5
    return KL

def predict(inputs, decoder, z_mean, z_std, how_many, numpy=True, device=None):
    """
    Generates prediction from the NP
    inputs: inputs to the NP
    decoder: the specific decoder employed
    z_mean: the mean of the latent variable distribution
    z_std: the mean of the latent variable distribution
    how_many: the number of functions to predict
    numpy: convert torch tensor to numpy array
    """
    if device:
        z = sample_z(z_mean, z_std, how_many, device=device)
        y_pred, _ = decoder(inputs, z)
        if numpy:
            return y_pred.cpu().detach().numpy()
        else:
            return y_pred
    else:
        z = sample_z(z_mean, z_std, how_many)
        y_pred, _ = decoder(inputs, z)
        if numpy:
            return y_pred.detach().numpy()
        else:
            return y_pred


"""
Original Authors: Sanjeevan Ahilan, Julian Villella, David Rusu
Modified By: Benedikt Kolbeinsson, Jiaze Sun, Pedro Castro
"""
import os, sys

import gym
import numpy as np
import math
import time

from ray.rllib.models import ModelCatalog
from ray.rllib.models.tf.tf_modelv2 import TFModelV2
from ray.rllib.models.tf.fcnet_v2 import FullyConnectedNetwork

from ray.rllib.utils import try_import_tf
tf = try_import_tf()

MODEL_NAME = 'model'

# This action space should match the input to the action(..) function below.
ACTION_SPACE = gym.spaces.Box(low=np.array([-1.0, -1.0]),
                              high=np.array([1.0, 1.0]),
                              dtype=np.float32)

# The maximum number of lanes we expect to see in any scenario.
MAX_LANES = 5

ACTIONS = [[0, 0, 0], [0, 0, 0]] # information fo residual actions
crash_flag = False # used for training to signal a flipped car

# This observation space should match the output of observation(..) below
## Check our 1-page summary to know more about each
OBSERVATION_SPACE = gym.spaces.Dict({
    'distance_from_center': gym.spaces.Box(low=-1e10, high=1e10, shape=(1,)),
    'heading_errors': gym.spaces.Box(low=-1.0, high=1.0, shape=(10,)),
    'speed': gym.spaces.Box(low=-1e10, high=1e10, shape=(1,)),
    'steering': gym.spaces.Box(low=-1e10, high=1e10, shape=(1,)),
    'ego_lane_dist': gym.spaces.Box(low=-1e10, high=1e10, shape=(5,)),
    'ego_ttc': gym.spaces.Box(low=-1e10, high=1e10, shape=(5,)),
    'speed_of_closest': gym.spaces.Box(low=-1e10, high=1e10, shape=(1,)),
    'proximity': gym.spaces.Box(low=-1e10, high=1e10, shape=(6,)),
    'headings_of_cars': gym.spaces.Box(low=-1e10, high=1e10, shape=(3,)),
})

def sign(x):
    return 1-(x<0)*2

def vec_2d(v):
    assert len(v) >= 2
    return np.array(v[:2])

def reset():
    global ACTIONS
    ACTIONS = [[0, 0, 0], [0, 0, 0]]

def proximity_detection(OGM):
    """
    Detects other vehicles in the vicinity of the ego vehicle
    """
    boxes = []
    boxes += [OGM[11:25, 23:27], #front left
              OGM[11:25, 27:37], #front centre
              OGM[11:25, 37:41], #front right
              OGM[25:39, 23:27], #left
              OGM[25:39, 37:41], #right
              OGM[39:53, 27:37], #back
              ]
    output = np.array([b.max()>0 for b in boxes], np.float32)
    return output

# fix taken from https://gist.github.com/davidrusu/d144a2646c9597a0d412c7e795ada548#file-nv_heading_to_ego_heading-py
def nv_heading_to_ego_heading(nv_heading):
    heading = nv_heading + 90
    if heading < 0:
        heading += 360
    return heading

def ttc_by_path(ego, waypoint_paths, neighborhood_vehicle_states, ego_closest_wp):
    # ttc stands for 'time to collision'
    # also return relative lane distance in front

    global crash_flag
    crash_flag = False
    wps_with_lane_dist = []
    for path_idx, path in enumerate(waypoint_paths):
        lane_dist = 0.
        for w1, w2 in zip(path, path[1:]):
            wps_with_lane_dist.append((w1, path_idx, lane_dist))
            lane_dist += np.linalg.norm(w2.pos - w1.pos)
        wps_with_lane_dist.append((path[-1], path_idx, lane_dist))

    # next we compute the TTC along each of the paths
    ttc_by_path_index = [1] * len(waypoint_paths)
    lane_dist_by_path_index = [1] * len(waypoint_paths)
    headings_of_cars = [0] * len(waypoint_paths)
    ####
    speed_of_closest = 1
    wps = [path[0] for path in waypoint_paths]
    ego_closest_wp = min(wps, key=lambda wp: wp.dist_to(ego.position))

    for v in neighborhood_vehicle_states:
        # find all waypoints that are on the same lane as this vehicle
        wps_on_lane = \
            [(wp, path_idx, dist) for wp, path_idx, dist in wps_with_lane_dist
             if wp.lane_id == v.lane_id]

        if wps_on_lane == []:
            # this vehicle is not on a nearby lane
            continue

        # find the closest waypoint on this lane to this vehicle
        nearest_wp, path_idx, lane_dist = \
            min(wps_on_lane, key=lambda tup: np.linalg.norm(tup[0].pos - vec_2d(v.position)))

        if np.linalg.norm(nearest_wp.pos - vec_2d(v.position)) > 2:
            # this vehicle is not close enough to the path, this can happen
            # if the vehicle is behind the ego, or ahead past the end of
            # the waypoints
            continue

        if ego_closest_wp.lane_index == nearest_wp.lane_index:
            if np.linalg.norm(vec_2d(ego.position) - vec_2d(v.position)) < 6:
                crash_flag = True
        relative_speed_m_per_s = (ego.speed - v.speed) * 1000 / 3600
        if abs(relative_speed_m_per_s) < 1e-5:
            relative_speed_m_per_s = 1e-5
        dist_wp_vehicle_vector = vec_2d(v.position) - vec_2d(nearest_wp.pos)
        # take into account the position of the car instead of its nearest waypoint
        direction_vector = np.array([math.cos(math.radians(nearest_wp.heading)), math.sin(math.radians(nearest_wp.heading))]).dot(dist_wp_vehicle_vector)
        dist_to_vehicle = lane_dist + sign(direction_vector)*(np.linalg.norm(vec_2d(nearest_wp.pos) - vec_2d(v.position)))
        ttc = dist_to_vehicle / relative_speed_m_per_s
        ttc = ttc/10
        lane_dist = dist_to_vehicle/100

        if lane_dist_by_path_index[path_idx] > lane_dist:
            if nearest_wp.lane_index == v.lane_index:
                headings_of_cars[path_idx] = math.sin(math.radians(nearest_wp.relative_heading(nv_heading_to_ego_heading(v.heading))))

                ## speed
            if ego_closest_wp.lane_index == v.lane_index:
                speed_of_closest = (v.speed - ego.speed)/120

        lane_dist_by_path_index[path_idx] = min(lane_dist_by_path_index[path_idx], lane_dist)
        if ttc <= 0:
            # discard collisions that would have happened in the past
            continue
        ttc_by_path_index[path_idx] = min(ttc_by_path_index[path_idx], ttc)

    return ttc_by_path_index, lane_dist_by_path_index, headings_of_cars, speed_of_closest

## original function extended to support 5 lanes
def ego_ttc_calc(ego, ego_lane_index, ttc_by_path, lane_dist_by_path):
    #ttc, lane distance from ego perspective

    ego_ttc = [0]*5
    ego_lane_dist = [0]*5

    # current lane is centre
    ego_ttc[2] = ttc_by_path[ego_lane_index]
    ego_lane_dist[2] = lane_dist_by_path[ego_lane_index]

    max_lane_index = len(ttc_by_path)-1
    min_lane_index = 0
    if ego_lane_index+1 > max_lane_index:
        ego_ttc[3] = 0
        ego_lane_dist[3] = 0
        ego_ttc[4] = 0
        ego_lane_dist[4] = 0
    elif ego_lane_index+2 > max_lane_index:
        ego_ttc[3] = ttc_by_path[ego_lane_index+1]
        ego_lane_dist[3] = lane_dist_by_path[ego_lane_index+1]
        ego_ttc[4] = 0
        ego_lane_dist[4] = 0
    else:
        ego_ttc[3] = ttc_by_path[ego_lane_index+1]
        ego_lane_dist[3] = lane_dist_by_path[ego_lane_index+1]
        ego_ttc[4] = ttc_by_path[ego_lane_index+2]
        ego_lane_dist[4] = lane_dist_by_path[ego_lane_index+2]

    if ego_lane_index-1 < min_lane_index:
        ego_ttc[0] = 0
        ego_lane_dist[0] = 0
        ego_ttc[1] = 0
        ego_lane_dist[1] = 0
    elif ego_lane_index-2 < min_lane_index:
        ego_ttc[0] = 0
        ego_lane_dist[0] = 0
        ego_ttc[1] = ttc_by_path[ego_lane_index-1]
        ego_lane_dist[1] = lane_dist_by_path[ego_lane_index-1]
    else:
        ego_ttc[0] = ttc_by_path[ego_lane_index-2]
        ego_lane_dist[0] = lane_dist_by_path[ego_lane_index-2]
        ego_ttc[1] = ttc_by_path[ego_lane_index-1]
        ego_lane_dist[1] = lane_dist_by_path[ego_lane_index-1]
    return ego_ttc, ego_lane_dist

def observation(env_obs, update=True):
    """
    Transform the environment's observation into something more suited for your model
    """
    ego = env_obs.ego_vehicle_state
    waypoint_paths = env_obs.waypoint_paths
    wps = [path[0] for path in waypoint_paths]

    # distance of vehicle from center of lane
    closest_wp = min(wps, key=lambda wp: wp.dist_to(ego.position))
    signed_dist_from_center = closest_wp.signed_lateral_error(ego.position)
    lane_hwidth = closest_wp.lane_width * 0.5
    norm_dist_from_center = signed_dist_from_center / lane_hwidth

    # heading errors in current lane in front of vehicle
    indices = [0,1,2,3,5,8,13,21,34,50]
    closest_path = [waypoint_paths[closest_wp.lane_index][i] for i in indices]
    heading_errors = [math.sin(math.radians(wp.relative_heading(ego.heading)))
                      for wp in closest_path]

    # get number of lanes in the start of the environment because the car is spawned in the air
    global NUM_LANES
    if env_obs.ego_vehicle_state.position[2] > 0.85:
        NUM_LANES = len(waypoint_paths)

    ego_lane_index = closest_wp.lane_index

    ttc_by_p, lane_dist_by_p, headings_of_cars_all_lanes, speed_of_closest = ttc_by_path(ego, waypoint_paths, env_obs.neighborhood_vehicle_states, closest_wp)
    ego_ttc, ego_lane_dist = ego_ttc_calc(ego, ego_lane_index, ttc_by_p, lane_dist_by_p)

    ego_ttc = np.array(ego_ttc)
    ego_lane_dist = np.array(ego_lane_dist)

    # model was trained on max 3 lanes, remove extra lane observations if lane > 3 for safety reasons (can be fixed by training on +3 lane environments)
    if sum(ego_ttc>0) > 3:
        ego_ttc[0] = 0
        ego_ttc[-1] = 0
    if sum(ego_lane_dist>0) > 3:
        ego_lane_dist[0] = 0
        ego_lane_dist[-1] = 0

    proximity = proximity_detection(env_obs.occupancy_grid_map[1])

    headings_of_cars = [0] * 3
    # current lane is centre
    headings_of_cars[1] = headings_of_cars_all_lanes[ego_lane_index]
    if headings_of_cars[1] == 0:
        headings_of_cars[1] = headings_of_cars_all_lanes[ego_lane_index]
    if ego_lane_index+1 > len(headings_of_cars_all_lanes) - 1:
        headings_of_cars[2] = 0
    else:
        headings_of_cars[2] = headings_of_cars_all_lanes[ego_lane_index+1]

    if ego_lane_index-1 < 0:
        headings_of_cars[0] = 0
    else:
        headings_of_cars[0] = headings_of_cars_all_lanes[ego_lane_index-1]

    # reset steering history
    if update:
        if env_obs.ego_vehicle_state.position[2] > 0.85:
            reset()

    closest_path = [waypoint_paths[closest_wp.lane_index][i] for i in np.arange(51)]
    headings = [math.sin(math.radians(wp.heading))
                      for wp in closest_path]
    headings = np.array(headings)

    return {
        'distance_from_center': np.array([norm_dist_from_center]),
        'heading_errors': np.array(heading_errors),
        'speed': np.array([ego.speed/120]),
        'steering': np.array([ego.steering]),
        'ego_lane_dist': np.array(ego_lane_dist),
        'ego_ttc': np.array(ego_ttc),
        'speed_of_closest': np.array([speed_of_closest]),
        'proximity': proximity,
        'headings_of_cars': np.array(headings_of_cars)
        }

def reward(env_obs, env_reward):
    """
    Here you can perform your reward shaping.

    The default reward provided by the environment is the increment in
    distance travelled. Your model will likely require a more
    sophisticated reward function
    """
    global crash_flag
    obs = observation(env_obs, False)

    center_penalty = -np.abs(obs['distance_from_center'])
    speed_reward = obs['speed']

    # penalize flip occurences (taking into account that the vehicle spawns in the air)
    if env_obs.ego_vehicle_state.speed >= 25:
        if env_obs.ego_vehicle_state.position[2] > 0.85:
            flip_penalty = -2 * env_obs.ego_vehicle_state.speed
        else:
            flip_penalty = 0
    else:
        flip_penalty = 0

    # penalise sharp turns done at high speeds
    if env_obs.ego_vehicle_state.speed > 60:
        steering_penalty = -pow((env_obs.ego_vehicle_state.speed-60)/20 * (env_obs.ego_vehicle_state.steering)*45/4, 2)
    else:
        steering_penalty = 0

    # penalise close proximity to other cars
    if crash_flag:
        crash_penalty = -5
    else:
        crash_penalty = 0

    total_reward = np.sum([1.0 * env_reward,
                           ])
    total_penalty = np.sum([0.1 * center_penalty,
                           1 * steering_penalty,
                           crash_penalty
                           ])

    if flip_penalty != 0:
        return float((-total_reward + total_penalty) / 200.0)
    else:
        return  float((total_reward + total_penalty) / 200.0)

def action(model_action):
    """
    Here you can perform you action space shaping.

    The built in action space may not be suited for all approaches, for
    example you may like to use a discrete action space.
    """

    global ACTIONS
    ACTIONS[1] = ACTIONS[0]

    acceleration, residual_steering = model_action
    if acceleration >= 0:
        throttle = acceleration
        brake = 0
    else:
        throttle = 0
        brake = -acceleration

    # add residual steering and save it for next time step
    new_steering = ACTIONS[1][2] + (np.clip(residual_steering, -1.0, 1.0) * 25.0)
    new_steering = np.clip(new_steering, -45, 45)

    ACTIONS[0] = [throttle, brake, new_steering]

    return np.array([throttle, brake, new_steering])

# #See: https://github.com/ray-project/ray/blob/b89cac976ae171d6d9b3245394e4932288fc6f11/rllib/models/tf/fcnet_v2.py#L14
class Model(FullyConnectedNetwork):
    pass

ModelCatalog.register_custom_model(MODEL_NAME, Model)

class EvaluationModel(TFModelV2):
    def __init__(self, suffix):
        super().__init__(
            obs_space=OBSERVATION_SPACE,
            action_space=ACTION_SPACE,
            num_outputs=ACTION_SPACE.shape[0],
            model_config={},
            name="evaluation-model")

        self._prep = ModelCatalog \
            .get_preprocessor_for_space(OBSERVATION_SPACE)

        self._sess = tf.Session(graph=tf.Graph())

        model_path = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'model'.format(suffix))

        self.base_model = tf.saved_model.load(self._sess,
                                              export_dir=model_path,
                                              tags=['serve'])

    def forward(self, obs, state, seq_lens):
        obs = self._prep.transform(obs)
        graph = self._sess.graph
        # These tensor names were found by inspecting the trained model
        # We use Tensor("split") instead of Tensor("add") to force PPO to be deterministic, CRUCIAL FOR SAFETY
        output_node = graph.get_tensor_by_name("default_policy/split:0")
        input_node = graph.get_tensor_by_name("default_policy/observation:0")
        res = self._sess.run(output_node, feed_dict={input_node: [obs]})
        action = res[0]
        return action, state

class Policy():
    def setup(self):
        self.model = EvaluationModel("normal")

    def teardown(self):
        pass

    def act(self, observation):
        action, _ = self.model.forward(observation, None, None)

        return action


import os
import numpy as np

train_folder = "trainset"

# dictionary for the pixel rgb data
data_dict = {
    'COLOR_STOP_SIGN_RED': np.empty(shape=[0, 3]),
    'COLOR_OTHER_RED'    : np.empty(shape=[0, 3]),
    'COLOR_BROWN'        : np.empty(shape=[0, 3]),
    'COLOR_ORANGE'       : np.empty(shape=[0, 3]),
    'COLOR_BLUE'         : np.empty(shape=[0, 3]),
    'COLOR_OTHER'        : np.empty(shape=[0, 3])
}

# dictionary for the pixel mean values, converting to numpy arrays for faster computation.
mean_dict = {
    'COLOR_STOP_SIGN_RED': np.array([0, 0, 0]),
    'COLOR_OTHER_RED'    : np.array([0, 0, 0]),
    'COLOR_BROWN'        : np.array([0, 0, 0]),
    'COLOR_ORANGE'       : np.array([0, 0, 0]),
    'COLOR_BLUE'         : np.array([0, 0, 0]),
    'COLOR_OTHER'        : np.array([0, 0, 0])
}

# dictionary for the pixel covariance values, converting to numpy arrays for faster computation.
cov_dict = {
    'COLOR_STOP_SIGN_RED': np.empty(shape=[3, 3]),
    'COLOR_OTHER_RED'    : np.empty(shape=[3, 3]),
    'COLOR_BROWN'        : np.empty(shape=[3, 3]),
    'COLOR_ORANGE'       : np.empty(shape=[3, 3]),
    'COLOR_BLUE'         : np.empty(shape=[3, 3]),
    'COLOR_OTHER'        : np.empty(shape=[3, 3])
}

# dictionary to store prior probability of each color classes
prior_dict = {
    'COLOR_STOP_SIGN_RED': 0,
    'COLOR_OTHER_RED'    : 0,
    'COLOR_BROWN'        : 0,
    'COLOR_ORANGE'       : 0,
    'COLOR_BLUE'         : 0,
    'COLOR_OTHER'        : 0
}

def get_mean_cov(class_name):
    """Calculate mean and covariance of different color classes

    Args:
        class_name(string): COLOR_STOP_SIGN_RED, COLOR_OTHER_RED, COLOR_BROWN, COLOR_ORANGE, COLOR_BLUE, COLOR_OTHER

    Returns:
        mean and covariance dictionary
    """
    # load npz files
    for file in os.listdir(train_folder):
        if file.endswith(".npz"):
            file_path = os.path.join(train_folder, file)
            npz_file = np.load(file_path)

            # if contains class data
            if(len(npz_file[class_name])):
                data_dict[class_name] = np.append(data_dict[class_name], np.array(npz_file[class_name]), axis=0)

    mean_dict[class_name] = np.mean(data_dict[class_name], axis=0)
    cov_dict[class_name]  = np.cov(data_dict[class_name].T)

    return mean_dict, cov_dict

def prior(class_name):
    """Calculate prior probablity of different color classes for Naive Bayes Classifier

    Args:
        class_name(string): COLOR_STOP_SIGN_RED, COLOR_OTHER_RED, COLOR_BROWN, COLOR_ORANGE, COLOR_BLUE, COLOR_OTHER

    Returns:
        prior dictionary
    """
    total_points = len(data_dict['COLOR_STOP_SIGN_RED']) + len(data_dict['COLOR_OTHER_RED']) \
                   + len(data_dict['COLOR_BROWN']) + len(data_dict['COLOR_ORANGE']) \
                   + len(data_dict['COLOR_BLUE']) + len(data_dict['COLOR_OTHER'])

    prior_dict[class_name] = len(data_dict[class_name]) / total_points

    return prior_dict

if __name__ == '__main__':
    # calculate gaussian parameters for different classes
    get_mean_cov('COLOR_STOP_SIGN_RED')
    get_mean_cov('COLOR_OTHER_RED')
    get_mean_cov('COLOR_BROWN')
    get_mean_cov('COLOR_ORANGE')
    get_mean_cov('COLOR_BLUE')
    get_mean_cov('COLOR_OTHER')

    # calculate prior probability for different classes
    prior('COLOR_STOP_SIGN_RED')
    prior('COLOR_OTHER_RED')
    prior('COLOR_BROWN')
    prior('COLOR_ORANGE')
    prior('COLOR_BLUE')
    prior('COLOR_OTHER')

    print(mean_dict)
    print(cov_dict)
    print(prior_dict)


"""
Unit tests for the Deis scheduler module.

Run the tests with './manage.py test scheduler'
"""
from scheduler import KubeHTTPException
from scheduler.tests import TestCase
from scheduler.utils import generate_random_name

class ReplicationControllersTest(TestCase):
    """Tests scheduler rc calls"""

    def create(self, namespace=None, name=generate_random_name(), **kwargs):
        """
        Helper function to create and verify a rc on the namespace
        """
        namespace = self.namespace if namespace is None else namespace
        # these are all required even if it is kwargs...
        kwargs = {
            'app_type': kwargs.get('app_type', 'web'),
            'version': kwargs.get('version', 'v99'),
            'replicas': kwargs.get('replicas', 4),
            'pod_termination_grace_period_seconds': 2,
            'image': 'quay.io/fake/image',
            'entrypoint': 'sh',
            'command': 'start',
        }

        rc = self.scheduler.rc.create(namespace, name, **kwargs)
        data = rc.json()
        self.assertEqual(rc.status_code, 201, data)
        return name

    def scale_rc(self, namespace=None, name=generate_random_name(), **kwargs):
        """
        Helper function to scale and verify a deployment on the namespace
        """
        namespace = self.namespace if namespace is None else namespace
        # these are all required even if it is kwargs...
        kwargs = {
            'app_type': kwargs.get('app_type', 'web'),
            'version': kwargs.get('version', 'v99'),
            'replicas': kwargs.get('replicas', 4),
            'deploy_timeout': 120,
            'pod_termination_grace_period_seconds': 2,
            'image': 'quay.io/fake/image',
            'entrypoint': 'sh',
            'command': 'start',
        }

        self.scheduler.scale_rc(namespace, name, **kwargs)
        return name

    def test_create_failure(self):
        with self.assertRaises(
            KubeHTTPException,
            msg='failed to create ReplicationController doesnotexist in Namespace {}: 404 Not Found'.format(self.namespace)  # noqa
        ):
            self.create('doesnotexist', 'doesnotexist')

    def test_create(self):
        self.create()

    def test_update_rc_failure(self):
        # test failure
        with self.assertRaises(
            KubeHTTPException,
            msg='failed to update ReplicationController foo in Namespace {}: 404 Not Found'.format(self.namespace)  # noqa
        ):
            self.scheduler.rc.update(self.namespace, 'foo', {})

    def test_update(self):
        # test success
        name = self.create()
        rc = self.scheduler.rc.get(self.namespace, name).json()
        self.assertEqual(rc['spec']['replicas'], 4, rc)

        rc['spec']['replicas'] = 2
        response = self.scheduler.rc.update(self.namespace, name, rc)
        self.assertEqual(response.status_code, 200, response.json())

        rc = self.scheduler.rc.get(self.namespace, name).json()
        self.assertEqual(rc['spec']['replicas'], 2, rc)

    def test_delete_failure(self):
        # test failure
        with self.assertRaises(
            KubeHTTPException,
            msg='failed to delete ReplicationController foo in Namespace {}: 404 Not Found'.format(self.namespace)  # noqa
        ):
            self.scheduler.rc.delete(self.namespace, 'foo')

    def test_delete(self):
        # test success
        name = self.create()
        response = self.scheduler.rc.delete(self.namespace, name)
        data = response.json()
        self.assertEqual(response.status_code, 200, data)

    def test_get_rcs(self):
        # test success
        name = self.create()
        response = self.scheduler.rc.get(self.namespace)
        data = response.json()
        self.assertEqual(response.status_code, 200, data)
        self.assertIn('items', data)
        self.assertEqual(1, len(data['items']), data['items'])
        # simple verify of data
        self.assertEqual(data['items'][0]['metadata']['name'], name)

    def test_get_rc_failure(self):
        # test failure
        with self.assertRaises(
            KubeHTTPException,
            msg='failed to get ReplicationController doesnotexist in Namespace {}: 404 Not Found'.format(self.namespace)  # noqa
        ):
            self.scheduler.rc.get(self.namespace, 'doesnotexist')

    def test_get_rc(self):
        # test success
        name = self.create()
        response = self.scheduler.rc.get(self.namespace, name)
        data = response.json()
        self.assertEqual(response.status_code, 200, data)
        self.assertEqual(data['apiVersion'], 'v1')
        self.assertEqual(data['kind'], 'ReplicationController')
        self.assertEqual(data['metadata']['name'], name)
        self.assertDictContainsSubset(
            {
                'app': self.namespace,
                'heritage': 'deis'
            },
            data['metadata']['labels']
        )


import pandas as pd
import json
import os
import pickle

class Logger:
    def __init__(self):
        self.features = False

    def set_features(self, df):
        """
        :param df: a dataframe
        :return:
        """
        self.features = df.columns

    def log_run(self, log_name, model, precision_score, confusion_matrix=0,
                  cls_report="", notes=""):

        model_name = type(model).__name__
        params = model.get_params()

        log = {}

        log['model_name'] = model_name
        log['log_name'] = log_name
        log['params'] = params
        log['features'] = list(self.features)
        log['precision_score'] = precision_score
        log['confusion_matrix'] = confusion_matrix
        log['classification_report'] = cls_report
        log['notes'] = notes

        dir_path = "logs/" + log_name + "/"

        try:
            os.mkdir(dir_path)
        except OSError:
            print("couldn't create log directory")

        json_path = dir_path + "details.json"
        with open(json_path, "w+") as file:
            json_obj = json.dumps(log, indent=4)
            file.write(json_obj)
            print("logged model")
            file.close()

        model_path = dir_path + "model.pkl"
        with open(model_path, 'wb') as file:
            pickle.dump(model, file)

def compare_models():
    dir = "logs/"

    for filename in os.listdir(dir):
        with open(dir + filename, 'r') as f_log:
            log = json.load(f_log)
            model_name = log['model_name']
            pres_err = log['precision_error']
            print(model_name)
            print(pres_err)
            print("*")


#3009

xsum = 0
ysum = 0
xset = set()
yset = set()

for i in range(3):
    x, y = map(int, input().split())
    xsum += x
    ysum += y
    xset.add(x)
    yset.add(y)

print(sum(xset) * 2 - xsum, sum(yset) * 2 - ysum)


class Solution:
    def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
        q = []
        dist = [1000000000] * (n + 1)
        adj = collections.defaultdict(list)
        for t in times:
            adj[t[0]].append((t[1], t[2]))
        dist[k] = 0
        heapq.heappush(q, (0, k))
        while q:
            cost, now = heapq.heappop(q)
            if dist[now] < cost:
                continue
            for next, c in adj[now]:
                if dist[next] > cost + c:
                    dist[next] = cost + c
                    heapq.heappush(q, (cost+c, next))
        ans = dist[1]
        for i in range(2, n + 1):
            ans = dist[i] if dist[i] > ans else ans
        if ans == 1000000000:
            return -1
        return ans


import base64

import json
import time
from PIL import Image, ImageChops
from PIL import ImageFile
import io
import numpy as np
import math

ImageFile.LOAD_TRUNCATED_IMAGES = True

def binaryToNumpyArray(data):
    if type(data) is not bytes:
        return None
    image = Image.open(io.BytesIO(data))
    return np.array(image)

def binaryToPILImage(data):
    if type(data) is not bytes:
        return None
    image = Image.open(io.BytesIO(data))
    return image

def bas64ToNumpyArray(data):

    if type(data) is not str:
        return
    try:
        data = json.loads(data)
        b64 = data['frame']
        b64_decoded = base64.b64decode(b64)
        image = Image.open(io.BytesIO(b64_decoded))
    except Exception:
        return None
    return np.array(image)

# import cv2

class MotionDetector:
    def __init__(self, numFrameToUse=2, threshold=6.0, debug=False) -> None:
        self.numFramesToUse = numFrameToUse
        self.frames = []
        self.threshold = threshold
        self.debug = debug
        pass
    def setNewThreshold(self, th):
        self.threshold = th
    def nextFrame(self, frame):
        self.frames.append(frame)
        if len(self.frames) > self.numFramesToUse:
            self.frames.pop(0)
        if self.debug:
            print("nextFrame method: ", self.frames)
    def clearFrames(self):
        self.frames = []

    def detectMotion(self):
        if len(self.frames) >= self.numFramesToUse:

            frame1 = np.array(self.frames[0])  #first frame
            frame2 = np.array(self.frames[self.numFramesToUse - 1]) #last frame
            frame2_copy_for_contour = frame2
            frame2_copy = frame2

            frame1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
            frame2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)

            frame1 = cv2.GaussianBlur(src=frame1, ksize=(5,5), sigmaX=0)
            frame2 = cv2.GaussianBlur(src=frame2, ksize=(5,5), sigmaX=0)

            diff_frame = cv2.absdiff(src1=frame1, src2=frame2)
            kernel = np.ones((5, 5))
            diff_frame = cv2.dilate(diff_frame, kernel, 1)
            thresh_frame = cv2.threshold(src=diff_frame, thresh=60, maxval=255, type=cv2.THRESH_BINARY)[1]

            contours, _ = cv2.findContours(image=thresh_frame, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
            # cv2.drawContours(image=frame2_copy, contours=contours, contourIdx=-1, color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
            isMotion = False
            for contour in contours:
                if cv2.contourArea(contour) < 50:
                    # too small: skip!
                    continue
                isMotion = True
                (x, y, w, h) = cv2.boundingRect(contour)
                cv2.rectangle(img=frame2_copy_for_contour, pt1=(x, y), pt2=(x + w, y + h), color=(0, 255, 0), thickness=2)

            if isMotion:
                cv2.imwrite(f"./saved/images/{time.time()}.jpg", frame2_copy_for_contour)

            return isMotion, frame2_copy_for_contour, frame2_copy
        return False, None, None

        #     diff = ImageChops.difference(frame1, frame2)
        #     entropy = self.__image_entropy(diff)
        #     if self.debug:
        #         print("detectMotion, entorpy:", entropy)
        #     if entropy > self.threshold:
        #         return True
        #     return False

        # return False

    def __image_entropy(self, img):
        """calculate the entropy of an image"""
        # this could be made more efficient using numpy
        histogram = img.histogram()
        histogram_length = sum(histogram)
        samples_probability = [float(h) / histogram_length for h in histogram]
        return -sum([p * math.log(p, 2) for p in samples_probability if p != 0])


import numpy as np
import torch.nn as nn

# Layer Initialization
def hidden_init(layer):
    fan_in = layer.weight.data.size()[0]
    lim = 1. / np.sqrt(fan_in)
    return (-lim, lim)

def weights_init(model):
    if isinstance(model, nn.Linear):
        print(model)
        model.weight.data.uniform_(*hidden_init(model))


import pygame

from random import randint

import config as c
import auxiliary as a

# enemy - класс врагов
class enemy(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, group):
        pygame.sprite.Sprite.__init__(self)
        self.image = a.load_image("virus.png").convert_alpha()
        self.rect = self.image.get_rect(center=(x, y))
        self.add(group)
        self.rect.x = x
        self.rect.y = y
        self.width = width - 50
        self.height = height - 50
        self.velocity = 10
        self.counter = 0
        self.points = 0

    def draw(self):
        c.WIN.blit(self.image, (self.rect.x, self.rect.y))

    def move(self):
        if self.rect.x < 0:
            self.points += 1
            self.rect.x = 900 + randint(0, 3000)
        self.rect.x -= self.velocity
        self.counter += 1

        # увеличиваем скорость
        if self.counter == 5 * c.FPS:
            self.velocity += 1
            self.counter = 0

    def get_points(self):
        return self.points

    def start_position(self):
        self.rect.x = 900
        self.velocity = 10
        self.counter = 0


def delete_many(string, rms):
    """
    Takes a string and a list of strings to delete.
    If the list of strings are all single characters,
    they can be passed as a single string (e.g., "[]() ").
    """

    for rm in rms:
        string = string.replace(rm, '')
    return string

def replace_pairwise(string, args, repls):
    """
    Takes a string, a substring to replace, and a paired replacement.
    Equivalent to multiple string.replace() calls.
    """
    if len(args) != len(repls):
        raise KeyError("Find and replace lists must be the same length!")
    else:
        for i in range(0, len(args)):
            string = string.replace(args[i], repls[i])
    return string


from marketbot import util
import os
import logging
import re

logger = logging.getLogger()

headers = {
    'APCA-API-KEY-ID':os.environ.get("ALPACA_ID") or logger.warning("You must set the ALPACA_ID environment variable"),
    'APCA-API-SECRET-KEY':os.environ.get("ALPACA_SECRET") or logger.warning("You must set the ALPACA_SECRET environment variable"),
}

async def get_profile(ticker):
    profile = await util.fetch_json("https://financialmodelingprep.com/api/v3/company/profile/" + ticker)
    return profile['profile'] if "profile" in profile else None

async def get_rating(ticker):
    rating = await util.fetch_json("https://financialmodelingprep.com/api/v3/company/rating/" + ticker)
    return rating['rating'] if "rating" in rating else None

async def get_asset(symbol):
    asset = await util.fetch_json("https://api.alpaca.markets/v2/assets/" + symbol, headers)
    return asset

async def get_quote(symbol):
    symbol = symbol.upper()
    params = {
        'symbols':symbol,
        'limit': 1
    }
    price = await util.fetch_json("https://data.alpaca.markets/v1/bars/day", headers, params)

    try:
        close = price[symbol][0]['c']
        open = price[symbol][0]['o']
        change = (close - open) / close
        return {
            'price':round(close, 2),
            'change%': f"{round( change * 100, 2)}%"
        }
    except Exception as e:
        logger.error(f"{e}: Could not fetch quote for [{symbol}]: JSON {price}")

async def get_change(symbol, limit, timespan):
    params = {
        'symbols':symbol,
        'limit': limit
    }
    prices = await util.fetch_json("https://data.alpaca.markets/v1/bars/" + timespan, headers, params)
    try:
        s = prices[symbol]
        begin = s[0]['c']
        end = s[-1]['c']

        print(f"BEGIN: {begin}, END: {end}")
        change = ( end - begin ) / end
        return {
            "change%": round(change * 100, 2),
            "period":f"{limit} {timespan}",
            "current":end
        }
    except Exception as e:
        logger.error(e)


"""
选择题：
1、下面代码运行会输出什么？ (B)
a = 10
b = 20
c = [a]
a = 15
print(c)

A. 15                 B.10
C．20                 D.报错
2、以下不能创建一个字典的语句是 (C)
A、dict1 = {}                    B、dict2 = { 3 : 5 }
C、dict3 ={[1,2,3]: “uestc”}      D、dict4 = {(1,2,3): “uestc”}

3、下面程序的输出结果是  ( A)

li = [1,1,2,3,4,5,6,7,8,9]
for i in li:
if i%2!=0:
        li.remove(i)
print(li)

A. [1, 2, 4 ,6,8]    B. [3, 5, 7, 9]
C. [2, 4, 6, 8]      D. [1, 3, 5 ,7 ,9]

"""

# 第四题：
"""
请一行代码将字符串"1,2,3"变成["1","2","3"]
"""
print("1,2,3".split(","))

# 第五题：

def handle_function_5():
    mapping1 = {
        "品牌坚果": 199,
        "最新耐克鞋": 699,
        "安踏坚果鞋": 799,
    }

    mapping2 = {
        "坚果": "三只松鼠",
        "耐克鞋": "Nike",
        "安踏": "Anta"
    }

    result = []
    for k2, v2 in mapping2.items():
        for k1, v1 in mapping1.items():
            if k2 in k1:
                result.append((k1, v1, k2, v2))

    return result

print(handle_function_5())

# 第六题 观察下面的表格，完成Table1到Table2的转换

list1 = [
    ('鞋', 'Anta,Nike,Adidas', 3),
    ('新能源', 'tesla', 1)
]

def handle_func(li: list):
    """
    type li: list
    rtype : list
    """
    result = []
    for item in li:
        new_val = item[1].split(",")
        for val in new_val:
            result.append((item[0], val, 1))
    return result

print(handle_func(list1))

# 第七题

def handle_function_7():
    str1 = "sfadbadbasdjfoisdjfoaidsf"
    str2 = "abcdefghijkmlopqrstuvwxyz"
    init_con = dict.fromkeys(str2, 0)
    for i in str1:
        init_con[i] += 1
    return sorted(init_con.items(), key=lambda x: x[1], reverse=True)

from pprint import pprint
pprint(handle_function_7())

# 第八题
def handle_function_8():
    table1 = [(11, 12, 13), (10, 10, 10)]
    table2 = [(11, 12, 13), (11, 11, 11)]
    return set(table1) & set(table2), set(table1) - set(table2), set(table2) - set(table1)

print(handle_function_8())

# 第九题
# 观察Table1和Table2，写一段SQL找出子产品个数都大于4个的客户。

"""
SELECT
	a.client_name
FROM
	Table1 AS a
	INNER JOIN Table2 AS b ON a.product_name = b.product_name
WHERE
	a.client_name != ''
GROUP BY
	a.client_name
HAVING
	count( b.sector_brand_key ) > 4
"""


import os
import subprocess

import shellenv
import sublime

def get_env():
    _, env = shellenv.get_env()
    return env

def get_startupinfo():
    startupinfo = None
    if os.name == 'nt':
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    return startupinfo

def which(command):
    try:
        exec_path = subprocess.check_output(["which", command], env=get_env())
    except subprocess.CalledProcessError as e:
        raise EnvironmentError(e)
    return exec_path

def prompt(message):
    if sublime.ok_cancel_dialog(message, 'Open Documentation'):
        sublime.run_command('open_url',
                            {'url': 'https://github.com/wy-z/Golite'})

def show_golite_panel(win, message):
    view = win.create_output_panel("golite_panel")
    view.set_scratch(True)
    view.run_command('append', {'characters': message})
    view.set_read_only(True)
    win.run_command("show_panel", {"panel": "output.golite_panel"})

def close_golite_panel(win):
    win.destroy_output_panel("golite_panel")


import socket
import time
import sys

#Raspi's IP
SERVER_IP = '192.168.191.3'
SERVER_PORT = 8001

def SayHi_function(msg):
    print("%s" %msg)

print("Starting socket: TCP\n")
server_addr = (SERVER_IP, SERVER_PORT)
sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

if __name__ == "__main__":
    while True:
        try:
            print("Connecting to server",SERVER_IP,':',SERVER_PORT,'...')
            sock_tcp.connect(server_addr)
            break
        except Exception:
            print("Can't connect to server,try it later!")
            time.sleep(1)
            continue

    start_data = sock_tcp.recv(512).decode()
    print("%s" %start_data)

    while True:
        try:
            cmd = input("Send your command:")
            if cmd == 'SayHi':
                sock_tcp.send(cmd.encode())
                Greet_data = sock_tcp.recv(512).decode()             # 函数本身会阻塞等待数据到来
                SayHi_function(Greet_data)
            elif cmd == 'q' or cmd == 'quit':
                sock_tcp.send(cmd.encode())
                bye_data = sock_tcp.recv(512).decode()
                print("%s" %bye_data)
                raise Exception
        except Exception:
            print("Connect break")
            sock_tcp.close()
            sock_tcp = None
            sys.exit(1)


import numpy as np
import torch
import glob
import os

DATA_DIR = "./data/"
WEMB_DIR = "./embeddings/glove.6B.300d.txt"

def find_ckpt_path(exp_name, epoch_id):
    """Find model checkpoint path given the exp_name and epoch_id"""
    if epoch_id == -1:
        glob_pattern = "epoch_*_"
    else:
        glob_pattern = f"epoch_{epoch_id}_"

    candidates = glob.glob(f"checkpoints/{exp_name}/{glob_pattern}*")

    def get_epoch_id_from_path(path):
        file_name = os.path.basename(path)
        e_id = file_name.split("_")[1]
        return int(e_id)

    sorted_cands = sorted(candidates, key=lambda x: get_epoch_id_from_path(x),
                          reverse=True)
    return sorted_cands[0]

def load_glove_emb(vocab):
    """
    Load pre-trained GloVe embeddings for words in the vocabulary. If no
    embedding exists, initialize randomly.
    Args:
        vocab (Vocab): a Vocabulary object contains
    """

    random_init = np.random.uniform(-.25, .25, [len(vocab), 300])
    random_init[0] = np.zeros(300) # padding

    for ln in open(WEMB_DIR):
        lsplit = ln.strip().split('\t')
        if len(lsplit) < 300:
            continue

        word = lsplit[0]
        word_idx = vocab.get_idx(word)
        if word_idx == vocab.unk_idx:
            continue

        vec = np.array([float(x) for x in lsplit[1:]])
        random_init[word_idx] = vec
    return random_init

def collate_tokens(values, pad_idx):
    """Convert a list of 1d tensors into a padded 2d tensor."""
    size = max(v.size(0) for v in values)
    res = values[0].new(len(values), size).fill_(pad_idx)

    def copy_tensor(src, dst):
        assert dst.numel() == src.numel()
        dst.copy_(src)

    for i, v in enumerate(values):
        copy_tensor(v, res[i][:len(v)])
    return res

def move_to_cuda(sample):

    def _move_to_cuda(tensor):
        return tensor.cuda()

    return apply_to_sample(_move_to_cuda, sample)

def apply_to_sample(f, sample):
    if len(sample) == 0:
        return {}

    def _apply(x):
        if torch.is_tensor(x):
            return f(x)
        elif isinstance(x, dict):
            r = {key: _apply(value) for key, value in x.items()}
            return r
            # return {
            #     key: _apply(value)
            #     for key, value in x.items()
            # }
        elif isinstance(x, list):
            return [_apply(x) for x in x]
        else:
            return x

    return _apply(sample)

def aeq(*args):
    """
    Assert all arguments have the same value
    """
    arguments = (arg for arg in args)
    first = next(arguments)
    assert all(arg == first for arg in arguments)

def sequence_mask(lengths, max_len=None):
    batch_size = lengths.numel()
    max_len = max_len or lengths.max()
    return (torch.arange(0, max_len)
            .type_as(lengths)
            .repeat(batch_size, 1)
            .lt(lengths.unsqueeze(1)))

def get_sequence_mask_from_length(seq_len, max_len):
    if max_len is None:
        max_len = seq_len.data.max()

    batch_size = seq_len.size(0)
    seq_range = torch.arange(0, max_len).long()
    seq_range_expand = seq_range.unsqueeze(0).expand(batch_size, max_len)
    if seq_len.is_cuda:
        seq_range_expand = seq_range_expand.cuda()
    seq_len_expand = (seq_len.unsqueeze(1).expand_as(seq_range_expand))
    return seq_range_expand < seq_len_expand


import unittest
import os
import numpy as np
import tempfile
import sqlite3
import shutil
import numbers
import gc
import lsst.utils.tests

from lsst.utils import getPackageDir
import lsst.obs.lsst.phosim as obs_lsst_phosim
from lsst.sims.utils.CodeUtilities import sims_clean_up
from lsst.sims.catalogs.decorators import register_method
from lsst.sims.catalogs.db import CatalogDBObject
from lsst.sims.catalogs.db import DBObject
from lsst.sims.catUtils.utils import ObservationMetaDataGenerator
from lsst.sims.catUtils.utils import AlertStellarVariabilityCatalog
from lsst.sims.catUtils.utils import AlertDataGenerator
from lsst.sims.catUtils.utils import StellarAlertDBObjMixin

from lsst.sims.utils import applyProperMotion
from lsst.sims.utils import ModifiedJulianDate
from lsst.sims.utils import findHtmid
from lsst.sims.utils import angularSeparation
from lsst.sims.photUtils import Sed
from lsst.sims.coordUtils import chipNameFromRaDec
from lsst.sims.coordUtils import pixelCoordsFromRaDec
from lsst.sims.photUtils import calcSNR_m5, BandpassDict
from lsst.sims.photUtils import PhotometricParameters
from lsst.sims.catUtils.mixins import CameraCoords
from lsst.sims.catUtils.mixins import AstrometryStars
from lsst.sims.catUtils.mixins import Variability
from lsst.sims.catalogs.definitions import InstanceCatalog
from lsst.sims.catalogs.decorators import compound, cached

ROOT = os.path.abspath(os.path.dirname(__file__))

def setup_module(module):
    lsst.utils.tests.init()

class AlertDataGeneratorTestCase(unittest.TestCase):

    longMessage = True

    @classmethod
    def setUpClass(cls):
        print('setting up %s' % sims_clean_up.targets)

        cls.camera = obs_lsst_phosim.PhosimMapper().camera

        # These represent the dimmest magnitudes at which objects
        # are considered visible in each of the LSST filters
        # (taken from Table 2 of the overview paper)
        cls.obs_mag_cutoff = (23.68, 24.89, 24.43, 24.0, 24.45, 22.60)

        cls.opsim_db = os.path.join(getPackageDir('sims_data'),
                                    'OpSimData',
                                    'opsimblitz1_1133_sqlite.db')

        rng = np.random.RandomState(8123)

        obs_gen = ObservationMetaDataGenerator(database=cls.opsim_db)
        cls.obs_list = obs_gen.getObservationMetaData(night=(0, 2))
        cls.obs_list = rng.choice(cls.obs_list, 10, replace=False)
        fieldid_list = []
        for obs in cls.obs_list:
            fieldid_list.append(obs.OpsimMetaData['fieldID'])

        # make sure we have selected observations such that the
        # same field is revisited more than once
        assert len(np.unique(fieldid_list)) < len(fieldid_list)

        cls.input_dir = tempfile.mkdtemp(prefix='alertDataGen',
                                         dir=ROOT)

        cls.star_db_name = tempfile.mktemp(prefix='alertDataGen_star_db',
                                           dir=cls.input_dir,
                                           suffix='.db')

        conn = sqlite3.connect(cls.star_db_name)
        cursor = conn.cursor()
        cursor.execute('''CREATE TABLE stars
                          (simobjid int, htmid int, ra real, dec real,
                           umag real, gmag real, rmag real,
                           imag real, zmag real, ymag real,
                           px real, pmra real, pmdec real,
                           vrad real, varParamStr text)''')
        conn.commit()

        n_stars = 10

        cls.ra_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        cls.dec_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        u_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        g_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        r_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        i_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        z_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        y_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        cls.px_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        cls.pmra_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        cls.pmdec_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        cls.vrad_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        cls.amp_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)
        cls.period_truth = np.zeros(n_stars*len(cls.obs_list), dtype=float)

        id_offset = -n_stars
        for obs in cls.obs_list:
            id_offset += n_stars
            ra_0 = obs.pointingRA
            dec_0 = obs.pointingDec
            rr = rng.random_sample(n_stars)
            theta = rng.random_sample(n_stars)*2.0*np.pi
            ra = ra_0 + rr*np.cos(theta)
            dec = dec_0 + rr*np.sin(theta)
            var_period = rng.random_sample(n_stars)*0.25
            var_amp = rng.random_sample(n_stars)*1.0 + 0.01

            subset = rng.randint(0, high=len(var_amp)-1, size=3)
            var_amp[subset[:2]] = 0.0
            var_amp[subset[-1]] = -1.0

            umag = rng.random_sample(n_stars)*5.0 + 15.0
            gmag = rng.random_sample(n_stars)*5.0 + 15.0
            rmag = rng.random_sample(n_stars)*5.0 + 15.0
            imag = rng.random_sample(n_stars)*5.0 + 15.0
            zmag = rng.random_sample(n_stars)*5.0 + 15.0
            ymag = rng.random_sample(n_stars)*5.0 + 15.0
            px = rng.random_sample(n_stars)*0.1  # say it is arcsec
            pmra = rng.random_sample(n_stars)*50.0+100.0  # say it is arcsec/yr
            pmdec = rng.random_sample(n_stars)*50.0+100.0  # say it is arcsec/yr
            vrad = rng.random_sample(n_stars)*600.0 - 300.0

            subset = rng.randint(0, high=n_stars-1, size=3)
            umag[subset] = 40.0
            gmag[subset] = 40.0
            rmag[subset] = 40.0
            imag[subset] = 40.0
            zmag[subset] = 40.0
            ymag[subset] = 40.0

            cls.ra_truth[id_offset:id_offset+n_stars] = np.round(ra, decimals=6)
            cls.dec_truth[id_offset:id_offset+n_stars] = np.round(dec, decimals=6)
            u_truth[id_offset:id_offset+n_stars] = np.round(umag, decimals=4)
            g_truth[id_offset:id_offset+n_stars] = np.round(gmag, decimals=4)
            r_truth[id_offset:id_offset+n_stars] = np.round(rmag, decimals=4)
            i_truth[id_offset:id_offset+n_stars] = np.round(imag, decimals=4)
            z_truth[id_offset:id_offset+n_stars] = np.round(zmag, decimals=4)
            y_truth[id_offset:id_offset+n_stars] = np.round(ymag, decimals=4)
            cls.px_truth[id_offset:id_offset+n_stars] = np.round(px, decimals=4)
            cls.pmra_truth[id_offset:id_offset+n_stars] = np.round(pmra, decimals=4)
            cls.pmdec_truth[id_offset:id_offset+n_stars] = np.round(pmdec, decimals=4)
            cls.vrad_truth[id_offset:id_offset+n_stars] = np.round(vrad, decimals=4)
            cls.amp_truth[id_offset:id_offset+n_stars] = np.round(var_amp, decimals=4)
            cls.period_truth[id_offset:id_offset+n_stars] = np.round(var_period, decimals=4)

            cls.max_str_len = -1

            for i_star in range(n_stars):
                if var_amp[i_star] >= -0.1:
                    varParamStr = ('{"m":"alert_test", "p":{"amp":%.4f, "per": %.4f}}'
                                   % (var_amp[i_star], var_period[i_star]))
                else:
                    varParamStr = 'None'

                if len(varParamStr) > cls.max_str_len:
                    cls.max_str_len = len(varParamStr)

                htmid = findHtmid(ra[i_star], dec[i_star], 21)

                query = ('''INSERT INTO stars VALUES(%d, %d, %.6f, %.6f,
                                                    %.4f, %.4f, %.4f, %.4f, %.4f, %.4f,
                                                    %.4f, %.4f, %.4f, %.4f, '%s')'''
                         % (i_star+id_offset+1, htmid, ra[i_star], dec[i_star],
                            umag[i_star], gmag[i_star], rmag[i_star],
                            imag[i_star], zmag[i_star], ymag[i_star],
                            px[i_star], pmra[i_star], pmdec[i_star],
                            vrad[i_star], varParamStr))

                cursor.execute(query)
        conn.commit()
        conn.close()

        cls.output_dir = tempfile.mkdtemp(dir=ROOT, prefix='alert_gen_output')
        cls.mag0_truth_dict = {}
        cls.mag0_truth_dict[0] = u_truth
        cls.mag0_truth_dict[1] = g_truth
        cls.mag0_truth_dict[2] = r_truth
        cls.mag0_truth_dict[3] = i_truth
        cls.mag0_truth_dict[4] = z_truth
        cls.mag0_truth_dict[5] = y_truth

    @classmethod
    def tearDownClass(cls):
        sims_clean_up()
        if os.path.exists(cls.star_db_name):
            os.unlink(cls.star_db_name)
        if os.path.exists(cls.input_dir):
            shutil.rmtree(cls.input_dir)
        for file_name in os.listdir(cls.output_dir):
            os.unlink(os.path.join(cls.output_dir, file_name))
        shutil.rmtree(cls.output_dir)

    def test_alert_data_generation(self):

        dmag_cutoff = 0.005
        mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z' : 4, 'y': 5}

        _max_var_param_str = self.max_str_len

        class StarAlertTestDBObj(StellarAlertDBObjMixin, CatalogDBObject):
            objid = 'star_alert'
            tableid = 'stars'
            idColKey = 'simobjid'
            raColName = 'ra'
            decColName = 'dec'
            objectTypeId = 0
            columns = [('raJ2000', 'ra*0.01745329252'),
                       ('decJ2000', 'dec*0.01745329252'),
                       ('parallax', 'px*0.01745329252/3600.0'),
                       ('properMotionRa', 'pmra*0.01745329252/3600.0'),
                       ('properMotionDec', 'pmdec*0.01745329252/3600.0'),
                       ('radialVelocity', 'vrad'),
                       ('variabilityParameters', 'varParamStr', str, _max_var_param_str)]

        class TestAlertsVarCatMixin(object):

            @register_method('alert_test')
            def applyAlertTest(self, valid_dexes, params, expmjd, variability_cache=None):
                if len(params) == 0:
                    return np.array([[], [], [], [], [], []])

                if isinstance(expmjd, numbers.Number):
                    dmags_out = np.zeros((6, self.num_variable_obj(params)))
                else:
                    dmags_out = np.zeros((6, self.num_variable_obj(params), len(expmjd)))

                for i_star in range(self.num_variable_obj(params)):
                    if params['amp'][i_star] is not None:
                        dmags = params['amp'][i_star]*np.cos(params['per'][i_star]*expmjd)
                        for i_filter in range(6):
                            dmags_out[i_filter][i_star] = dmags

                return dmags_out

        class TestAlertsVarCat(TestAlertsVarCatMixin, AlertStellarVariabilityCatalog):
            pass

        class TestAlertsTruthCat(TestAlertsVarCatMixin, CameraCoords, AstrometryStars,
                                 Variability, InstanceCatalog):
            column_outputs = ['uniqueId', 'chipName', 'dmagAlert', 'magAlert']

            camera = obs_lsst_phosim.PhosimMapper().camera

            @compound('delta_umag', 'delta_gmag', 'delta_rmag',
                      'delta_imag', 'delta_zmag', 'delta_ymag')
            def get_TruthVariability(self):
                return self.applyVariability(self.column_by_name('varParamStr'))

            @cached
            def get_dmagAlert(self):
                return self.column_by_name('delta_%smag' % self.obs_metadata.bandpass)

            @cached
            def get_magAlert(self):
                return self.column_by_name('%smag' % self.obs_metadata.bandpass) + \
                       self.column_by_name('dmagAlert')

        star_db = StarAlertTestDBObj(database=self.star_db_name, driver='sqlite')

        # assemble the true light curves for each object; we need to figure out
        # if their np.max(dMag) ever goes over dmag_cutoff; then we will know if
        # we are supposed to simulate them
        true_lc_dict = {}
        true_lc_obshistid_dict = {}
        is_visible_dict = {}
        obs_dict = {}
        max_obshistid = -1
        n_total_observations = 0
        for obs in self.obs_list:
            obs_dict[obs.OpsimMetaData['obsHistID']] = obs
            obshistid = obs.OpsimMetaData['obsHistID']
            if obshistid > max_obshistid:
                max_obshistid = obshistid
            cat = TestAlertsTruthCat(star_db, obs_metadata=obs)

            for line in cat.iter_catalog():
                if line[1] is None:
                    continue

                n_total_observations += 1
                if line[0] not in true_lc_dict:
                    true_lc_dict[line[0]] = {}
                    true_lc_obshistid_dict[line[0]] = []

                true_lc_dict[line[0]][obshistid] = line[2]
                true_lc_obshistid_dict[line[0]].append(obshistid)

                if line[0] not in is_visible_dict:
                    is_visible_dict[line[0]] = False

                if line[3] <= self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]]:
                    is_visible_dict[line[0]] = True

        obshistid_bits = int(np.ceil(np.log(max_obshistid)/np.log(2)))

        skipped_due_to_mag = 0

        objects_to_simulate = []
        obshistid_unqid_set = set()
        for obj_id in true_lc_dict:

            dmag_max = -1.0
            for obshistid in true_lc_dict[obj_id]:
                if np.abs(true_lc_dict[obj_id][obshistid]) > dmag_max:
                    dmag_max = np.abs(true_lc_dict[obj_id][obshistid])

            if dmag_max >= dmag_cutoff:
                if not is_visible_dict[obj_id]:
                    skipped_due_to_mag += 1
                    continue

                objects_to_simulate.append(obj_id)
                for obshistid in true_lc_obshistid_dict[obj_id]:
                    obshistid_unqid_set.add((obj_id << obshistid_bits) + obshistid)

        self.assertGreater(len(objects_to_simulate), 10)
        self.assertGreater(skipped_due_to_mag, 0)

        log_file_name = tempfile.mktemp(dir=self.output_dir, suffix='log.txt')
        alert_gen = AlertDataGenerator(testing=True)

        alert_gen.subdivide_obs(self.obs_list, htmid_level=6)

        for htmid in alert_gen.htmid_list:
            alert_gen.alert_data_from_htmid(htmid, star_db,
                                            photometry_class=TestAlertsVarCat,
                                            output_prefix='alert_test',
                                            output_dir=self.output_dir,
                                            dmag_cutoff=dmag_cutoff,
                                            log_file_name=log_file_name)

        dummy_sed = Sed()

        bp_dict = BandpassDict.loadTotalBandpassesFromFiles()

        phot_params = PhotometricParameters()

        # First, verify that the contents of the sqlite files are all correct

        n_tot_simulated = 0

        alert_query = 'SELECT alert.uniqueId, alert.obshistId, meta.TAI, '
        alert_query += 'meta.band, quiescent.flux, alert.dflux, '
        alert_query += 'quiescent.snr, alert.snr, '
        alert_query += 'alert.ra, alert.dec, alert.chipNum, '
        alert_query += 'alert.xPix, alert.yPix, ast.pmRA, ast.pmDec, '
        alert_query += 'ast.parallax '
        alert_query += 'FROM alert_data AS alert '
        alert_query += 'INNER JOIN metadata AS meta ON meta.obshistId=alert.obshistId '
        alert_query += 'INNER JOIN quiescent_flux AS quiescent '
        alert_query += 'ON quiescent.uniqueId=alert.uniqueId '
        alert_query += 'AND quiescent.band=meta.band '
        alert_query += 'INNER JOIN baseline_astrometry AS ast '
        alert_query += 'ON ast.uniqueId=alert.uniqueId'

        alert_dtype = np.dtype([('uniqueId', int), ('obshistId', int),
                                ('TAI', float), ('band', int),
                                ('q_flux', float), ('dflux', float),
                                ('q_snr', float), ('tot_snr', float),
                                ('ra', float), ('dec', float),
                                ('chipNum', int), ('xPix', float), ('yPix', float),
                                ('pmRA', float), ('pmDec', float), ('parallax', float)])

        sqlite_file_list = os.listdir(self.output_dir)

        n_tot_simulated = 0
        obshistid_unqid_simulated_set = set()
        for file_name in sqlite_file_list:
            if not file_name.endswith('db'):
                continue
            full_name = os.path.join(self.output_dir, file_name)
            self.assertTrue(os.path.exists(full_name))
            alert_db = DBObject(full_name, driver='sqlite')
            alert_data = alert_db.execute_arbitrary(alert_query, dtype=alert_dtype)
            if len(alert_data) == 0:
                continue

            mjd_list = ModifiedJulianDate.get_list(TAI=alert_data['TAI'])
            for i_obj in range(len(alert_data)):
                n_tot_simulated += 1
                obshistid_unqid_simulated_set.add((alert_data['uniqueId'][i_obj] << obshistid_bits) +
                                                  alert_data['obshistId'][i_obj])

                unq = alert_data['uniqueId'][i_obj]
                obj_dex = (unq//1024)-1
                self.assertAlmostEqual(self.pmra_truth[obj_dex], 0.001*alert_data['pmRA'][i_obj], 4)
                self.assertAlmostEqual(self.pmdec_truth[obj_dex], 0.001*alert_data['pmDec'][i_obj], 4)
                self.assertAlmostEqual(self.px_truth[obj_dex], 0.001*alert_data['parallax'][i_obj], 4)

                ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                                        self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex],
                                                        self.px_truth[obj_dex], self.vrad_truth[obj_dex],
                                                        mjd=mjd_list[i_obj])
                distance = angularSeparation(ra_truth, dec_truth,
                                             alert_data['ra'][i_obj], alert_data['dec'][i_obj])

                distance_arcsec = 3600.0*distance
                msg = '\ntruth: %e %e\nalert: %e %e\n' % (ra_truth, dec_truth,
                                                          alert_data['ra'][i_obj],
                                                          alert_data['dec'][i_obj])

                self.assertLess(distance_arcsec, 0.0005, msg=msg)

                obs = obs_dict[alert_data['obshistId'][i_obj]]

                chipname = chipNameFromRaDec(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                             pm_ra=self.pmra_truth[obj_dex],
                                             pm_dec=self.pmdec_truth[obj_dex],
                                             parallax=self.px_truth[obj_dex],
                                             v_rad=self.vrad_truth[obj_dex],
                                             obs_metadata=obs,
                                             camera=self.camera)

                chipnum = int(chipname.replace('R', '').replace('S', '').
                              replace(' ', '').replace(';', '').replace(',', '').
                              replace(':', ''))

                self.assertEqual(chipnum, alert_data['chipNum'][i_obj])

                xpix, ypix = pixelCoordsFromRaDec(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                                  pm_ra=self.pmra_truth[obj_dex],
                                                  pm_dec=self.pmdec_truth[obj_dex],
                                                  parallax=self.px_truth[obj_dex],
                                                  v_rad=self.vrad_truth[obj_dex],
                                                  obs_metadata=obs,
                                                  camera=self.camera)

                self.assertAlmostEqual(alert_data['xPix'][i_obj], xpix, 4)
                self.assertAlmostEqual(alert_data['yPix'][i_obj], ypix, 4)

                dmag_sim = -2.5*np.log10(1.0+alert_data['dflux'][i_obj]/alert_data['q_flux'][i_obj])
                self.assertAlmostEqual(true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]],
                                       dmag_sim, 3)

                mag_name = ('u', 'g', 'r', 'i', 'z', 'y')[alert_data['band'][i_obj]]
                m5 = obs.m5[mag_name]

                q_mag = dummy_sed.magFromFlux(alert_data['q_flux'][i_obj])
                self.assertAlmostEqual(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex],
                                       q_mag, 4)

                snr, gamma = calcSNR_m5(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex],
                                        bp_dict[mag_name],
                                        self.obs_mag_cutoff[alert_data['band'][i_obj]],
                                        phot_params)

                self.assertAlmostEqual(snr/alert_data['q_snr'][i_obj], 1.0, 4)

                tot_mag = self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex] + \
                          true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]]

                snr, gamma = calcSNR_m5(tot_mag, bp_dict[mag_name],
                                        m5, phot_params)
                self.assertAlmostEqual(snr/alert_data['tot_snr'][i_obj], 1.0, 4)

        for val in obshistid_unqid_set:
            self.assertIn(val, obshistid_unqid_simulated_set)
        self.assertEqual(len(obshistid_unqid_set), len(obshistid_unqid_simulated_set))

        astrometry_query = 'SELECT uniqueId, ra, dec, TAI '
        astrometry_query += 'FROM baseline_astrometry'
        astrometry_dtype = np.dtype([('uniqueId', int),
                                     ('ra', float),
                                     ('dec', float),
                                     ('TAI', float)])

        tai_list = []
        for obs in self.obs_list:
            tai_list.append(obs.mjd.TAI)
        tai_list = np.array(tai_list)

        n_tot_ast_simulated = 0
        for file_name in sqlite_file_list:
            if not file_name.endswith('db'):
                continue
            full_name = os.path.join(self.output_dir, file_name)
            self.assertTrue(os.path.exists(full_name))
            alert_db = DBObject(full_name, driver='sqlite')
            astrometry_data = alert_db.execute_arbitrary(astrometry_query, dtype=astrometry_dtype)

            if len(astrometry_data) == 0:
                continue

            mjd_list = ModifiedJulianDate.get_list(TAI=astrometry_data['TAI'])
            for i_obj in range(len(astrometry_data)):
                n_tot_ast_simulated += 1
                obj_dex = (astrometry_data['uniqueId'][i_obj]//1024) - 1
                ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex],
                                                        self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex],
                                                        self.px_truth[obj_dex], self.vrad_truth[obj_dex],
                                                        mjd=mjd_list[i_obj])

                distance = angularSeparation(ra_truth, dec_truth,
                                             astrometry_data['ra'][i_obj],
                                             astrometry_data['dec'][i_obj])

                self.assertLess(3600.0*distance, 0.0005)

        del alert_gen
        gc.collect()
        self.assertGreater(n_tot_simulated, 10)
        self.assertGreater(len(obshistid_unqid_simulated_set), 10)
        self.assertLess(len(obshistid_unqid_simulated_set), n_total_observations)
        self.assertGreater(n_tot_ast_simulated, 0)

class MemoryTestClass(lsst.utils.tests.MemoryTestCase):
    pass

if __name__ == "__main__":
    lsst.utils.tests.init()
    unittest.main()


'''Задача 32: Определить индексы элементов массива (списка), значения которых принадлежат заданному
диапазону (т.е. не меньше заданного минимума и не больше заданного максимума)'''
import random
arr = []
res = []
n = int(input())
mn = int(input())
mx = int(input())
for i in range(n):
    a = random.randint(0, n)
    arr.append(a)
print(arr)
for i in range(len(arr)):
    if arr[i] > mn and arr[i] < mx:
        el = i
        res.append(el)
print(res)