import logging
import os
import time
import inspect
import shutil
import threading
import traceback

from six.moves import queue

from ray.tune import TuneError, session
from ray.tune.trainable import Trainable, TrainableUtil
from ray.tune.result import (TIME_THIS_ITER_S, RESULT_DUPLICATE,
                             SHOULD_CHECKPOINT)

logger = logging.getLogger(__name__)

# Time between FunctionRunner checks when fetching
# new results after signaling the reporter to continue
RESULT_FETCH_TIMEOUT = 0.2

ERROR_REPORT_TIMEOUT = 10
ERROR_FETCH_TIMEOUT = 1

class StatusReporter:
    """Object passed into your function that you can report status through.

    Example:
        >>> def trainable_function(config, reporter):
        >>>     assert isinstance(reporter, StatusReporter)
        >>>     reporter(timesteps_this_iter=1)
    """

    def __init__(self,
                 result_queue,
                 continue_semaphore,
                 trial_name=None,
                 trial_id=None,
                 logdir=None):
        self._queue = result_queue
        self._last_report_time = None
        self._continue_semaphore = continue_semaphore
        self._trial_name = trial_name
        self._trial_id = trial_id
        self._logdir = logdir
        self._last_checkpoint = {}
        self._fresh_checkpoint = False

    def __call__(self, **kwargs):
        """Report updated training status.

        Pass in `done=True` when the training job is completed.

        Args:
            kwargs: Latest training result status.

        Example:
            >>> reporter(mean_accuracy=1, training_iteration=4)
            >>> reporter(mean_accuracy=1, training_iteration=4, done=True)

        Raises:
            StopIteration: A StopIteration exception is raised if the trial has
                been signaled to stop.
        """

        assert self._last_report_time is not None, (
            "StatusReporter._start() must be called before the first "
            "report __call__ is made to ensure correct runtime metrics.")

        # time per iteration is recorded directly in the reporter to ensure
        # any delays in logging results aren't counted
        report_time = time.time()
        if TIME_THIS_ITER_S not in kwargs:
            kwargs[TIME_THIS_ITER_S] = report_time - self._last_report_time
        self._last_report_time = report_time

        # add results to a thread-safe queue
        self._queue.put(kwargs.copy(), block=True)

        # This blocks until notification from the FunctionRunner that the last
        # result has been returned to Tune and that the function is safe to
        # resume training.
        self._continue_semaphore.acquire()

    def make_checkpoint_dir(self, step=None):
        checkpoint_dir = TrainableUtil.make_checkpoint_dir(
            self.logdir, index=step)
        logger.debug("Making checkpoint dir at %s", checkpoint_dir)
        return checkpoint_dir

    def save_checkpoint(self, checkpoint):
        if isinstance(checkpoint, str):
            try:
                TrainableUtil.find_checkpoint_dir(checkpoint)
            except FileNotFoundError:
                logger.error("Checkpoint must be created with path given from "
                             "make_checkpoint_dir.")
                raise
        self._last_checkpoint = checkpoint
        self._fresh_checkpoint = True

    def has_new_checkpoint(self):
        return self._fresh_checkpoint

    def get_checkpoint(self):
        self._fresh_checkpoint = False
        return self._last_checkpoint

    def _start(self):
        self._last_report_time = time.time()

    @property
    def logdir(self):
        return self._logdir

    @property
    def trial_name(self):
        """Trial name for the corresponding trial of this Trainable."""
        return self._trial_name

    @property
    def trial_id(self):
        """Trial id for the corresponding trial of this Trainable."""
        return self._trial_id

class _RunnerThread(threading.Thread):
    """Supervisor thread that runs your script."""

    def __init__(self, entrypoint, error_queue):
        threading.Thread.__init__(self)
        self._entrypoint = entrypoint
        self._error_queue = error_queue
        self.daemon = True

    def run(self):
        try:
            self._entrypoint()
        except StopIteration:
            logger.debug(
                ("Thread runner raised StopIteration. Interperting it as a "
                 "signal to terminate the thread without error."))
        except Exception as e:
            logger.exception("Runner Thread raised error.")
            try:
                # report the error but avoid indefinite blocking which would
                # prevent the exception from being propagated in the unlikely
                # case that something went terribly wrong
                err_tb_str = traceback.format_exc()
                self._error_queue.put(
                    err_tb_str, block=True, timeout=ERROR_REPORT_TIMEOUT)
            except queue.Full:
                logger.critical(
                    ("Runner Thread was unable to report error to main "
                     "function runner thread. This means a previous error "
                     "was not processed. This should never happen."))
            raise e

class FunctionRunner(Trainable):
    """Trainable that runs a user function reporting results.

    This mode of execution does not support checkpoint/restore."""

    _name = "func"

    def setup(self, config):
        # Semaphore for notifying the reporter to continue with the computation
        # and to generate the next result.
        self._continue_semaphore = threading.Semaphore(0)

        # Queue for passing results between threads
        self._results_queue = queue.Queue(1)

        # Queue for passing errors back from the thread runner. The error queue
        # has a max size of one to prevent stacking error and force error
        # reporting to block until finished.
        self._error_queue = queue.Queue(1)

        self._status_reporter = StatusReporter(
            self._results_queue,
            self._continue_semaphore,
            trial_name=self.trial_name,
            trial_id=self.trial_id,
            logdir=self.logdir)
        self._last_result = {}

        session.init(self._status_reporter)
        self._runner = None
        self._restore_tmpdir = None
        self.default_checkpoint_dir = None

    def _trainable_func(self):
        """Subclasses can override this to set the trainable func."""

        raise NotImplementedError

    def _start(self):
        def entrypoint():
            return self._trainable_func(self.config, self._status_reporter,
                                        self._status_reporter.get_checkpoint())

        # the runner thread is not started until the first call to _train
        self._runner = _RunnerThread(entrypoint, self._error_queue)
        # if not alive, try to start
        self._status_reporter._start()
        try:
            self._runner.start()
        except RuntimeError:
            # If this is reached, it means the thread was started and is
            # now done or has raised an exception.
            pass

    def step(self):
        """Implements train() for a Function API.

        If the RunnerThread finishes without reporting "done",
        Tune will automatically provide a magic keyword __duplicate__
        along with a result with "done=True". The TrialRunner will handle the
        result accordingly (see tune/trial_runner.py).
        """
        if self._runner and self._runner.is_alive():
            # if started and alive, inform the reporter to continue and
            # generate the next result
            self._continue_semaphore.release()
        else:
            self._start()

        result = None
        while result is None and self._runner.is_alive():
            # fetch the next produced result
            try:
                result = self._results_queue.get(
                    block=True, timeout=RESULT_FETCH_TIMEOUT)
            except queue.Empty:
                pass

        # if no result were found, then the runner must no longer be alive
        if result is None:
            # Try one last time to fetch results in case results were reported
            # in between the time of the last check and the termination of the
            # thread runner.
            try:
                result = self._results_queue.get(block=False)
            except queue.Empty:
                pass

        # check if error occured inside the thread runner
        if result is None:
            # only raise an error from the runner if all results are consumed
            self._report_thread_runner_error(block=True)

            # Under normal conditions, this code should never be reached since
            # this branch should only be visited if the runner thread raised
            # an exception. If no exception were raised, it means that the
            # runner thread never reported any results which should not be
            # possible when wrapping functions with `wrap_function`.
            raise TuneError(
                ("Wrapped function ran until completion without reporting "
                 "results or raising an exception."))

        else:
            if not self._error_queue.empty():
                logger.warning(
                    ("Runner error waiting to be raised in main thread. "
                     "Logging all available results first."))

        # This keyword appears if the train_func using the Function API
        # finishes without "done=True". This duplicates the last result, but
        # the TrialRunner will not log this result again.
        if "__duplicate__" in result:
            new_result = self._last_result.copy()
            new_result.update(result)
            result = new_result

        self._last_result = result
        if self._status_reporter.has_new_checkpoint():
            result[SHOULD_CHECKPOINT] = True
        return result

    def execute(self, fn):
        return fn(self)

    def create_default_checkpoint_dir(self):
        self.default_checkpoint_dir = TrainableUtil.make_checkpoint_dir(
            self.logdir, index="default")
        return self.default_checkpoint_dir

    def save(self, checkpoint_path=None):
        if checkpoint_path:
            raise ValueError(
                "Checkpoint path should not be used with function API.")

        checkpoint = self._status_reporter.get_checkpoint()
        state = self.get_state()

        if not checkpoint:
            state.update(iteration=0, timesteps_total=0, episodes_total=0)
            parent_dir = self.create_default_checkpoint_dir()
        elif isinstance(checkpoint, dict):
            parent_dir = TrainableUtil.make_checkpoint_dir(
                self.logdir, index=self.training_iteration)
        else:
            parent_dir = TrainableUtil.find_checkpoint_dir(checkpoint)
        checkpoint_path = TrainableUtil.process_checkpoint(
            checkpoint, parent_dir, state)
        return checkpoint_path

    def save_to_object(self):
        checkpoint_path = self.save()
        obj = TrainableUtil.checkpoint_to_object(checkpoint_path)
        return obj

    def load_checkpoint(self, checkpoint):
        # This should be removed once Trainables are refactored.
        if "tune_checkpoint_path" in checkpoint:
            del checkpoint["tune_checkpoint_path"]
        self._status_reporter.save_checkpoint(checkpoint)

    def restore_from_object(self, obj):
        if self.default_checkpoint_dir is not None and os.exists(
                self.default_checkpoint_dir):
            shutil.rmtree(self.default_checkpoint_dir)
            logger.debug("Clearing default checkpoint: %s",
                         self.default_checkpoint_dir)

        checkpoint_dir = self.create_default_checkpoint_dir()
        checkpoint_path = TrainableUtil.create_from_pickle(obj, checkpoint_dir)
        self.restore(checkpoint_path)

    def cleanup(self):
        # If everything stayed in synch properly, this should never happen.
        if not self._results_queue.empty():
            logger.warning(
                ("Some results were added after the trial stop condition. "
                 "These results won't be logged."))

        # Check for any errors that might have been missed.
        self._report_thread_runner_error()
        session.shutdown()

    def _report_thread_runner_error(self, block=False):
        try:
            err_tb_str = self._error_queue.get(
                block=block, timeout=ERROR_FETCH_TIMEOUT)
            raise TuneError(("Trial raised an exception. Traceback:\n{}"
                             .format(err_tb_str)))
        except queue.Empty:
            pass

def detect_checkpoint_function(train_func, abort=False):
    """Use checkpointing if any arg has "checkpoint_dir" and args = 2"""
    argspec = inspect.getfullargspec(train_func)
    func_args = argspec.args
    func_kwargs = argspec.kwonlyargs
    validated = len(func_args) == 2 and any("checkpoint_dir" in arg
                                            for arg in func_args)
    validated = validated or (len(func_args) == 1) and any(
        "checkpoint_dir" in arg for arg in func_kwargs)
    if abort and not validated:
        raise ValueError(
            "Provided training function must have 2 args "
            "in the signature, and the latter arg must "
            "contain `checkpoint_dir`. For example: "
            "`func(config, checkpoint_dir=None)`. Got {}".format(func_args))
    return validated

def wrap_function(train_func):
    if hasattr(train_func, "__mixins__"):
        inherit_from = train_func.__mixins__ + (FunctionRunner, )
    else:
        inherit_from = (FunctionRunner, )

    class ImplicitFunc(*inherit_from):
        _name = train_func.__name__ if hasattr(train_func, "__name__") \
            else "func"

        def _trainable_func(self, config, reporter, checkpoint_dir):
            func_args = inspect.getfullargspec(train_func).args
            if len(func_args) > 1:  # more arguments than just the config
                if "reporter" not in func_args and (
                        not detect_checkpoint_function(train_func)):
                    raise ValueError(
                        "Unknown argument found in the Trainable function. "
                        "Arguments other than the 'config' arg must be one "
                        "of ['reporter', 'checkpoint_dir']. Found: {}".format(
                            func_args))
            use_reporter = "reporter" in func_args
            use_checkpoint = detect_checkpoint_function(train_func)
            if not use_checkpoint and not use_reporter:
                logger.warning(
                    "Function checkpointing is disabled. This may result in "
                    "unexpected behavior when using checkpointing features or "
                    "certain schedulers. To enable, set the train function "
                    "arguments to be `func(config, checkpoint_dir=None)`.")
                output = train_func(config)
            elif use_checkpoint:
                output = train_func(config, checkpoint_dir=checkpoint_dir)
            else:
                output = train_func(config, reporter)

            # If train_func returns, we need to notify the main event loop
            # of the last result while avoiding double logging. This is done
            # with the keyword RESULT_DUPLICATE -- see tune/trial_runner.py.
            reporter(**{RESULT_DUPLICATE: True})
            return output

    return ImplicitFunc


""" 4. La gestión de un concesionario de coches está informatizada porque
disponen de una gran cartera de clientes y un gran stock.
Para facilitar las búsquedas en la tabla de stock, los vehículos se encuentran ordenados por matrícula,
de cada vehículo nos interesa la matrícula, marca, modelo y precio,
los nuevos vehículos se insertan en su posición correspondiente.
El sistema también almacena los datos de los clientes que se han interesado por un vehículo,
de cada cliente se almacena nombre, apellidos, dirección y teléfono.
Un cliente puede estar interesado en varios coches (o ninguno aún),
y por un coche se pueden interesar varios clientes (o ninguno).
Cuando un coche se vende, desaparece del stock, sin embargo,
los datos de un cliente nunca desaparecen de sistema y su información se almacena en orden de aparición.
El 18 de septiembre de 2000 Tráfico instauró el actual sistema de matrículas,
que constan de cuatro dígitos y tres letras consonantes (suprimiéndose las cinco vocales, y las letras Ñ y Q).
Las estructuras de datos diseñadas para la aplicación son:"""

from recordclass import recordclass

tCoche = recordclass('Coche', 'matricula marca modelo precio')
#tStock = lista [variable] de tCoche ordenados alfabéticamente
tCliente = recordclass('Cliente', 'nombre, apellidos, direccion, telefono')
#tClientes = lista[variable] de tCliente
tInteresado = recordclass('Interesado', 'coche, usuario')
	#coche es una matrícula, usuario es su posición en la lista de clientes.
#tInteresados = lista[variable] de tInteresado

# A. (3 puntos): Haga una función que localice y devuelva un coche del stock conocida su matrícula.
#Debe emplear el algoritmo más eficiente posible y justificar su elección.

def busqueda_matricula(stock, matricula):
    inicio = 0
    fin = len(stock)-1

    while inicio <= fin:
        mitad = (inicio + fin) // 2
        coche = stock[mitad]

        if matricula == coche.matricula:
            return mitad
        if matricula < coche.matricula:
            fin = mitad - 1
        else: inicio = mitad + 1
    return None

# PROBADOR

stock = [tCoche(matricula='4562CSD', marca='Toyota', modelo='Corolla', precio=25000),
        tCoche(matricula='8095HGM', marca='Ford', modelo='Mustang', precio=45000),
        tCoche(matricula='8156DFB', marca='Honda', modelo='Civic', precio=22000),
        tCoche(matricula='9156GGB', marca='Chevrolet', modelo='Camaro', precio=48000),
        tCoche(matricula='9959YJN', marca='Volkswagen', modelo='Golf', precio=20000)]

print(busqueda_matricula(stock, '4562CSD'), 0)
print(busqueda_matricula(stock, '8156DFB'), 2)
print(busqueda_matricula(stock, '9959YJN'), 4)
print(busqueda_matricula(stock, '1111YJN'), 'None')

# B. (2 puntos): Diseñe un algoritmo recursivo que, dada la lista de interesados y una matrícula,
#muestre los datos de cada cliente interesado en ese vehículo.

clientes = [tCliente('JUAN', 'GARCIA', 'CALLE X', '972833829'),
            tCliente('MARIA', 'FERNANDEZ', 'CALLE Y', '8574185861'),
            tCliente('PEPE', 'GONZALEZ', 'CALLE Z', '8916513796'),
            tCliente('FRAN', 'LOPEZ', 'CALLE R', '308U3241'),
            tCliente('LUCIA', 'MARTINEZ', 'CALLE T', '463241232')]

interesados = [tInteresado('4562CSD', 0),
               tInteresado('8095HGM', 1),
               tInteresado('9959YJN', 2),
               tInteresado('4562CSD', 3),
               tInteresado('8156DFB', 4)]

def mostrar_interesados(lista, matricula, index = 0):
    if index < len(lista):

        if lista[index].coche == matricula:
            print(clientes[index])

        mostrar_interesados(lista, matricula, index + 1)

# PROBADOR

print(mostrar_interesados(interesados, '9959YJN'))
print(mostrar_interesados(interesados, '8888YJN'))

# C. (2 puntos): Haga una función que reciba una cadena de texto y devuelva si es una matrícula válida o no.

def matricula_valida(matricula):
    matricula = matricula.upper()

    if len(matricula) != 7: # TIENE QUE TENER 7 CARACTERES
        return False

    contador_letras = 0
    contador_numeros = 0

    letras_posibles = 'WRTYPSDFGHJKLZXCVBNM'
    numeros_posibles = '0123456789'

    for i in range(0, 4): # LAS CUATRO PRIMEROS CARACTERES TIENEN QUE SER NUMEROS
        if matricula[i] in numeros_posibles:
            contador_numeros +=1

    for i in range(4, 7): # LOS ULTIMOS TRES CARACTERES TIENEN QUE SER LETRAS
        if matricula[i] in letras_posibles:
            contador_letras += 1

    return contador_letras == 3 and contador_numeros == 4

# PROBADOR

print(matricula_valida('4545YJN'), 'TRUE')
print(matricula_valida('YJN4545'), 'FALSE')
print(matricula_valida('45455JN'), 'FALSE')
print(matricula_valida('4545AJN'), 'FALSE')
print(matricula_valida('4545FAJN'), 'FALSE')

# D. (3 puntos): Haga un subprograma que devuelve una matrícula solicitada al usuario (pedida tantas veces como sea necesario).

def matricula_pedida(msg):
    a = input(msg)
    if not matricula_valida(a):
        a = input(msg)
    return a.upper()

# PROBADOR

print(matricula_pedida('INTRODUCE UNA MATRICULA: '))


from backend.db import db
from sqlalchemy import text, ForeignKey
from marshmallow import Schema, fields
from sqlalchemy.orm import relationship

class Tax(db.Model):
    __tablename__ = 'taxes'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=True)
    initial_date = db.Column(db.Date, nullable=True)
    final_date = db.Column(db.Date, nullable=True)
    purchase_pct = db.Column(db.Float, default=0)
    sale_pct = db.Column(db.Float, default=0)
    account_id = db.Column(db.Integer, ForeignKey("accounts.id"))
    installation_id = db.Column(db.Integer, default=0)
    created_at = db.Column(db.TIMESTAMP, nullable=True, server_default=text('CURRENT_TIMESTAMP'))
    updated_at = db.Column(db.TIMESTAMP, nullable=True, server_default=text('CURRENT_TIMESTAMP'))

    account = relationship("Account", foreign_keys=[account_id])

    @property
    def account_name(self):
        if self.account is not None:
            return self.account.code
        return None

class TaxSchema(Schema):
    id = fields.Number()
    name = fields.Str()
    account_name = fields.Str()
    initial_date = fields.Date()
    final_date = fields.Date()
    purchase_pct = fields.Number()
    sale_pct = fields.Number()
    account_id = fields.Number()
    installation_id = fields.Number()
    created_at = fields.DateTime()
    updated_at = fields.DateTime()


#!/usr/bin/env python3
import rospy
from std_msgs.msg import String
import cv2 as cv
import time
import numpy as np

rospy.init_node("LaneDetection_node")
rospy.loginfo ("Lane detectio node has been Started !")
pub = rospy.Publisher('command', String, queue_size=10)

def canny(image):
    gray_img = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
    blur_img = cv.GaussianBlur(gray_img, (1, 1), 0)
    canny_img = cv.Canny(blur_img, 50, 200, None, 3)
    return canny_img
def line_detection (masked_img):
    lines_list = []
    lines = cv.HoughLinesP(
        masked_img,  # Input edge image
        1,  # Distance resolution in pixels
        np.pi / 180,  # Angle resolution in radians
        threshold=50,  # Min number of votes for valid line
        minLineLength=30,  # Min allowed length of line
        maxLineGap=1  # Max allowed gap between line for joining them
    )
    return lines
def region_of_interest(image):
    height = 288
    width = 512
    polygons = np.array([[(0, 288), (512, 288), (256,180)]])
    #polygons2 = np.array([[(0, 350), (0, height), (width, 350), (width, height)]])
    mask = np.zeros_like(image)
    #cv.rectangle( mask, (0, 350), (width, height), 255, -1)
    cv.fillPoly(mask, polygons, 255)
    #cv.fillPoly(mask, polygons2, 255)
    masked_image = cv.bitwise_and(image, mask)

    return masked_image
def error(image, offset):
    # x - y37/105 - 193 = 0
    e = 0
    t = 0
    #print(image[287][511])
    for x in range(0,511):
        for y in range (180, 287):
            if image[y][x] ==  255 :
                t = t + 1
                if x > 256 :
                    e = e + 1
                else:
                    e = e - 1

    if t ==  0:
        return 0

    return e/t + offset

def decode(V ,off):
    v2 = V + off*V
    v1 = V - off*V

    return v1, v2

def discrete_pid(Kp, Ki, Kd, dt, max_output, min_output):
    # Khởi tạo các biến
    error_sum = 0
    last_error = 0

    def pid(error):
        nonlocal error_sum, last_error

        # Tính toán tổng lỗi tích phân
        error_sum += error * dt

        # Tính toán đạo hàm của lỗi
        d_error = (error - last_error) / dt
        last_error = error

        # Tính toán giá trị điều khiển mới
        output = Kp * error + Ki * error_sum + Kd * d_error

        # Giới hạn giá trị điều khiển trong khoảng cho phép
        if output > max_output:
            output = max_output
        elif output < min_output:
            output = min_output

        return output

    return pid

# Khởi tạo hàm PID
pid = discrete_pid(Kp=0.02, Ki=0.004, Kd= 0, dt=0.33, max_output= 1 , min_output= -1)

#cap = cv.VideoCapture("/home/pi/Desktop/backup_9_1/video_record6.h264")
cap = cv.VideoCapture(0)
cap.set(3,512)
cap.set(4,288)
count = 0
while cap.isOpened() and not rospy.is_shutdown():
    ret, frame = cap.read()
    #start = time.time()
    if ret == False:
        break

    img = frame
    gray_img = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    gray_img = region_of_interest(gray_img)
    gray_img = cv.equalizeHist(gray_img)
    mask_gray = cv.inRange(gray_img, 230, 255)
    kernel = np.ones((8, 5), np.uint8)
    mask_gray = cv.erode(mask_gray, kernel)
    mask_gray = cv.dilate(mask_gray, kernel)

        # lines = line_detection(mask_gray)
        # if lines is not None:
        #     for points in lines:
        #         # Extracted points nested in the list
        #         x1, y1, x2, y2 = points[0]
        #         cv.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
    cv.line(img, (256, 288), (256, 200),(0, 255, 0), 2 )
    cv.imshow("line", img)
    cv.imshow("mask", mask_gray)
        #cv.imshow("gray", gray_img)

    e = error(mask_gray, 0)
    rospy.loginfo(e)
    control = pid(e)
    V1, V2 = decode(60, control)
    #print(V1, "\n", V2)

    command = "!V"+ str(int(V1)) + ";"+str(int(V2)) + "#"
    #print(command)
    pub.publish(command)

    #end = time.time()
    #second = end - start
    #print("fps =",1/second)
    if cv.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv.destroyAllWindows()


import os
import shutil
from os.path import join

from kinoknecht import config
config.video_dirs = ['tests/testdir']
config.log_file = 'tests/logdir/dummy.log'
config.db_file = 'tests/dummy.db'

from kinoknecht.database import init_db, shutdown_db
from kinoknecht.models import Videofile, Movie

TESTVIDSRC = 'tests/test.avi'
TESTDIR = 'tests/testdir'
TESTMOV = 'The Meaning of Life.avi'
TESTSHOW = join(TESTDIR, 'How.I.Met.Your.Mother.S01')
TESTCD1 = 'Spam and Eggs CD1.avi'
TESTCD2 = 'Spam and Eggs CD2.avi'
TESTMOVSUB = 'Spam and Eggs CD1.srt'
TESTEPI1 = 'How.I.Met.Your.Mother.S01E04.avi'
TESTEPI2 = 'How.I.Met.Your.Mother.108.avi'

def create_dummy_env():
    # Clean up if previous tests failed to do so
    if os.path.exists(TESTDIR):
        shutil.rmtree(TESTDIR)
    # Set up test directories and files
    os.mkdir(TESTDIR)
    os.mkdir(TESTSHOW)
    shutil.copyfile(TESTVIDSRC, join(TESTDIR, TESTMOV))
    shutil.copyfile(TESTVIDSRC, join(TESTDIR, TESTCD1))
    shutil.copyfile(TESTVIDSRC, join(TESTDIR, TESTCD2))
    open(join(TESTDIR, TESTMOVSUB), 'w').close()
    shutil.copyfile(TESTVIDSRC, join(TESTSHOW, TESTEPI1))
    shutil.copyfile(TESTVIDSRC, join(TESTSHOW, TESTEPI2))

def remove_dummy_env():
    shutil.rmtree(TESTDIR)

class TestModel(object):
    def setUp(self):
        create_dummy_env()
        init_db()
        Videofile.update_all()

    def tearDown(self):
        remove_dummy_env()
        shutdown_db()

    def testSubtitleScan(self):
        assert (Videofile.search(Videofile.name == TESTCD1).one().subfilepath
                == os.path.abspath(join(TESTDIR, TESTMOVSUB)))

    def testSpecExtraction(self):
        assert (Videofile.search(Videofile.name == TESTMOV).one()
                .video_width == 704)

    def testRootBrowse(self):
        assert Videofile.browse() == [['tests/testdir'], []]

    def testSubdirBrowse(self):
        result = Videofile.browse(
                os.path.abspath('tests/testdir/How.I.Met.Your.Mother.S01'))
        assert (
            result[1][0].name == u'How.I.Met.Your.Mother.108.avi' and
            result[1][1].name == u'How.I.Met.Your.Mother.S01E04.avi'
        )

    def testNonexistBrowse(self):
        assert Videofile.browse(
            'tests/testdir/The.Walking.Dead.S01') == [[], []]

    def testVideofileStatistics(self):
        assert Videofile.statistics() == {
            u'total_size': 7110580,
            u'total_length': 118.2,
            u'vidfile_count': 5
        }

    def testListVideos(self):
        result = Videofile.search()
        assert (
            result[0].name == u'The Meaning of Life.avi' and
            result[1].name == u'Spam and Eggs CD2.avi' and
            result[2].name == u'Spam and Eggs CD1.avi' and
            result[3].name == u'How.I.Met.Your.Mother.108.avi' and
            result[4].name == u'How.I.Met.Your.Mother.S01E04.avi'
        )

    def testVideofileInfodict(self):
        expected = {
            'audio_bitrate': None, 'audio_format': None,
            'id': 5, 'last_pos': None, 'length': 23.640000000000001,
            'name': u'How.I.Met.Your.Mother.S01E04.avi', 'num_played': None,
            'path': os.path.abspath('tests/testdir/How.I.Met.Your.Mother.S01'),
            'playeropts': None, 'size': 1422116, 'subfilepath': None,
            'video_bitrate': None, 'video_format': u'mpeg4', 'video_fps': 25.0,
            'video_height': 320, 'video_width': 704,
            'title': u'How.I.Met.Your.Mother.S01E04.avi',
            'sha1hash': u'de4167ee4347fda2796e2d5fe99183828e41bf61'
        }
        results = Videofile.get(5).get_infodict()
        # We need to omit 'creation_date' from the assert, as its value
        # changes with each testrun
        for k, v in results.iteritems():
            if not k == 'creation_date':
                match = bool(results[k] == expected[k])
                if not match:
                    assert False
        assert True

    def testGetInvalidVideofile(self):
        assert bool(Videofile.get(12)) == False

    def testCreateMovie(self):
        mov = Movie(videofiles=[Videofile.get(3), Videofile.get(2)],
                    imdb_id=85959)
        assert len(mov.videofiles) == 2 and mov.year == 1983

    def testSearchVideofileByName(self):
        result = Videofile.search(
            Videofile.name.like('%how.i.met.your.mother%')
        )
        assert result.count() == 2

    def testSearchVideofileByLength(self):
        result = Videofile.search(Videofile.length > 20)
        assert result.count() == 5

    def testSearchVideofileByLengthAndName(self):
        result = Videofile.search(
            Videofile.length > 20,
            Videofile.length < 25,
            Videofile.name.like('%meaning of life%')
        ).one().get_infodict()
        expected = {
                'audio_bitrate': None, 'audio_format': None,
                'id': 1, 'last_pos': None, 'length': 23.640000000000001,
                'name': u'The Meaning of Life.avi', 'num_played': None,
                'path': unicode(os.path.abspath('tests/testdir')),
                'playeropts': None, 'size': 1422116, 'subfilepath': None,
                'video_bitrate': None, 'video_format': u'mpeg4',
                'sha1hash': u'de4167ee4347fda2796e2d5fe99183828e41bf61',
                'video_fps': 25.0, 'video_height': 320, 'video_width': 704
        }
        # We need to omit 'creation_date' from the assert, as its value
        # changes with each testrun
        for k, v in result.iteritems():
            if not k == 'creation_date':
                match = bool(result[k] == expected[k])
                if not match:
                    assert False
        assert True

    def testUpdateVideofiles(self):
        Videofile.update_all()
        assert Videofile.search().count() == 5


'''
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
'''
'''
Method: Brute Force O(n) time O(n) space
'''
class Solution():
    def partition(self, head, x): # notice that the title requests preservation of original list
        small = ListNode(x-1)
        ts = small
        large = ListNode(x)
        tl = large
        temp = head
        while temp:
            if temp.val < x:
                ts.next = temp
                ts = ts.next
            else:
                tl.next = temp
                tl = tl.next
            temp = temp.next
        ts.next = large.next
        tl.next = None
        return small.next

'''
In-place Method, O(n) time O(1) space
1) find 1st node that has val >= x, set pointer BEFORE it
2) once a node with val < x found after 1), insert it after the pointer and update the pointer
'''
class Solution():
    def partition(self, head, x):
        tempHead = ListNode(x-1) # set val as x-1, so we can start current from tempHead, otherwise we need to discuss whether current
                                 # exists before using its val
        tempHead.next = head
        start = tempHead
        current = tempHead
        while current.next:
            if current.next.val < x and start != current:
                temp = current.next
                current.next = current.next.next
                temp.next = start.next
                start.next = temp
                start = temp # need to update start pointer
            else:
                if current.next.val < x and current == start:
                    start = start.next
                current = current.next
        return tempHead.next


class Car():
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
    def get_descriptive_name(self):
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_used_car = Car('subaru', 'outback', 2013)
print(my_used_car.get_descriptive_name())
class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery_size = 70
        self.weight=50
    def describe_battery(self):
        print("This car has a ",int(self.battery_size),"-kWh battery.")
        print("This car has a",int(self.weight),'Kg')
my_tesla = ElectricCar('tesla', 'model s', 2016)
tesla=ElectricCar('tesla', 'model F', 2018)
print(tesla.get_descriptive_name())
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()


import collections
class Solution:
    def maxCandies(self, status: List[int], candies: List[int], keys: List[List[int]], containedBoxes: List[List[int]], initialBoxes: List[int]) -> int:
        num = 0
        Q = collections.deque([box for box in initialBoxes if status[box] == 1])
        possible = set([box for box in initialBoxes if status[box] == 0])
        while Q:
            box = Q.popleft()
            num += candies[box]
            for key in keys[box]:
                status[key] = 1
                if key in possible:
                    possible.remove(key)
                    Q.append(key)

            for cb in containedBoxes[box]:
                if status[cb] == 1:
                    Q.append(cb)
                else:
                    possible.add(cb)

        return num

1201-1300/1298-Maximum Candies You Can Get from Boxes/1298-Maximum Candies You Can Get from Boxes.py


import pygame
import math
from pygame.locals import *
from pygame.sprite import Group
import global_var
import background
from screenSettings import screen_settings
import pic

def shakeScreen():
    shakeFrame=global_var.get_value('shakeFrame')
    if shakeFrame>0:
        global_var.set_value('ifShaking',True)
        global_var.set_value('shakeFrame',shakeFrame-1)
    else:
        global_var.set_value('ifShaking',False)

def drawRotation(image,pos,angle,screen):
    w, h = image.get_size()
    pivot = pygame.math.Vector2(w/2, -h/2)
    pivot_rotate = pivot.rotate(angle)
    pivot_move   = pivot_rotate - pivot
    box = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
    box_rotate = [p.rotate(angle) for p in box]
    min_box = (min(box_rotate, key=lambda p: p[0])[0], min(box_rotate, key=lambda p: p[1])[1])
    max_box = (max(box_rotate, key=lambda p: p[0])[0], max(box_rotate, key=lambda p: p[1])[1])
    origin = (pos[0]+ min_box[0] - pivot_move[0], pos[1] - max_box[1] + pivot_move[1])
    rotated_image = pygame.transform.rotate(image, angle)
    #rotated_image.set_colorkey((0, 0, 0))
    screen.blit(rotated_image, origin)

def returnPosition(w,h,pos,angle):
    pivot = pygame.math.Vector2(w/2, -h/2)
    pivot_rotate = pivot.rotate(angle)
    pivot_move   = pivot_rotate - pivot
    box = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
    box_rotate = [p.rotate(angle) for p in box]
    min_box = (min(box_rotate, key=lambda p: p[0])[0], min(box_rotate, key=lambda p: p[1])[1])
    max_box = (max(box_rotate, key=lambda p: p[0])[0], max(box_rotate, key=lambda p: p[1])[1])
    origin = (pos[0]+ min_box[0] - pivot_move[0], pos[1] - max_box[1] + pivot_move[1])
    return origin

def drawBackground(screen):

    screen.blit(global_var.get_value('left'),(0,0))
    screen.blit(global_var.get_value('up'),(60,0))
    screen.blit(global_var.get_value('down'),(60,690))
    screen.blit(global_var.get_value('right'),(620,30))

    #screen.blit(global_var.get_value('stage_background'),(0,0))

def fill(surface, color):
    """Fill all pixels of the surface with color, preserve transparency."""
    w, h = surface.get_size()
    r, g, b, _ = color
    for x in range(w):
        for y in range(h):
            a = surface.get_at((x, y))[3]
            surface.set_at((x, y), pygame.Color(r, g, b, a))

def displayScene(frame,screen):
    sceneNum=(frame//2)%(1540)
    c=sceneNum
    dig=0
    while (c>0):
        c=c//10
        dig+=1
    i=4-dig
    address="pic2/background_2_"
    for j in range(0,i):
        address=address+"0"
    if sceneNum!=0:
        address=address+str(sceneNum)
    address=address+".png"
    sceneImage=pygame.image.load(address)
    screen.blit(sceneImage,(30,20))
    screen.blit(sceneImage,(430,20))

def displayMenu(screen,stars):
    screen.blit(global_var.get_value('levelText01'),(716,30))
    screen.blit(global_var.get_value('mainText'),(670,500))
    for star in stars:
        star.draw(screen)

def loadImage():
    gunAlpha=150
    amplified_times=global_var.get_value('amplified_times')

    stage_background=pygame.image.load('resource/mainback.jpeg').convert_alpha()
    stage_background=pygame.transform.smoothscale(stage_background,(round(640*amplified_times),round(480*amplified_times)))
    global_var.set_value('stage_background',stage_background)

    green=pygame.image.load('resource/playerFire/mainFire_green.png').convert_alpha()
    green=pygame.transform.scale(green,(48,48))
    green.set_alpha(gunAlpha)
    global_var.set_value('playerFire_green',green)
    blue=pygame.image.load('resource/playerFire/mainFire_blue.png').convert_alpha()
    blue=pygame.transform.scale(blue,(48,48))
    blue.set_alpha(gunAlpha)
    global_var.set_value('playerFire_blue',blue)
    red=pygame.image.load('resource/playerFire/mainFire_red.png').convert_alpha()
    red=pygame.transform.scale(red,(48,48))
    red.set_alpha(gunAlpha)
    global_var.set_value('playerFire_red',red)
    yellow=pygame.image.load('resource/playerFire/mainFire_yellow.png').convert_alpha()
    yellow=pygame.transform.scale(yellow,(48,48))
    yellow.set_alpha(gunAlpha)
    global_var.set_value('playerFire_yellow',yellow)
    orange=pygame.image.load('resource/playerFire/mainFire_orange.png').convert_alpha()
    orange=pygame.transform.scale(orange,(48,48))
    orange.set_alpha(gunAlpha)
    global_var.set_value('playerFire_orange',orange)
    reimu_fire=pygame.image.load('resource/playerFire/reimu_fire.png').convert_alpha()
    reimu_fire=pygame.transform.smoothscale(reimu_fire,(384,168))
    global_var.set_value('reimu_fire',reimu_fire)

    global_var.set_value('levelText01',pygame.image.load('resource/text/levelText01.png').convert_alpha())
    global_var.set_value('pl00',pygame.image.load('resource/player/pl00/playerImage.png').convert_alpha())
    global_var.set_value('pl01',pygame.image.load('resource/player/pl01/playerImage.png').convert_alpha())
    global_var.set_value('mainText',pygame.image.load('resource/text/mainText01.png').convert_alpha())
    global_var.set_value('cloud_bg',pygame.image.load('resource/background/cloud.png').convert_alpha())
    global_var.set_value('lake_bg',pygame.image.load('resource/background/lake.png').convert_alpha())
    global_var.set_value('star_bg',pygame.image.load('resource/background/star.png').convert_alpha())

    spirit=pygame.image.load('resource/enemy/spirit.png').convert_alpha()
    spirit=pygame.transform.scale(spirit,(576,384))
    global_var.set_value('spirit',spirit)
    ghost=pygame.image.load('resource/enemy/ghost.png').convert_alpha()
    ghost=pygame.transform.scale(ghost,(384,192))
    global_var.set_value('ghost',ghost)
    nimbus=pygame.image.load('resource/enemy/nimbus1.png').convert_alpha()
    nimbus=pygame.transform.scale(nimbus,(192,48))
    global_var.set_value('nimbus',nimbus)
    item=pygame.image.load('resource/item/item.png').convert_alpha()
    item=pygame.transform.scale(item,(384,24))
    global_var.set_value('itemImage',item)

    boss_1=pygame.image.load('resource/boss/satori.png').convert_alpha()
    boss_1=pygame.transform.smoothscale(boss_1,(288,297))
    global_var.set_value('boss_1',boss_1)
    bossTracker=pygame.image.load('resource/text/bossTracker.png').convert_alpha()
    global_var.set_value('bossTracker',bossTracker)

    global_var.set_value('lifeSign',pygame.image.load('resource/text/lifeSign.png'))
    global_var.set_value('spellSign',pygame.image.load('resource/text/spellSign1.png'))
    global_var.set_value('lifeText',pygame.image.load('resource/text/lifeText.png'))
    global_var.set_value('spellText',pygame.image.load('resource/text/spellText.png'))
    front00=pygame.image.load('resource/text/front00.png')
    front00=pygame.transform.smoothscale(front00,(768,768))
    global_var.set_value('front00',front00)
    front01=pygame.image.load('resource/text/front00.png')
    textArea=pygame.Surface((80,220)).convert_alpha()
    textArea.fill((0,0,0,0))
    #Hiscore
    textArea.blit(front01,(0,0),(256,0,80,19))
    #score
    textArea.blit(front01,(0,30),(256,19,80,19))
    #player
    textArea.blit(front01,(0,70),(256,38,80,19))
    #power
    textArea.blit(front01,(0,143),(256,57,80,19))
    #graze
    textArea.blit(front01,(0,176),(336,0,80,19))
    global_var.set_value('textArea',textArea)
    powerText=pygame.image.load('resource/text/powerText.png')
    powerText=pygame.transform.scale(powerText,(99,24))
    global_var.set_value('powerText',powerText)
    hogwarts_background=pygame.image.load('resource/background/hogwarts.png').convert_alpha()
    global_var.set_value('hogwarts_background',hogwarts_background)
    stars_background=pygame.image.load('resource/background/stars.jpg').convert()#_alpha()
    global_var.set_value('stars_background',stars_background)
    spell_background=pygame.image.load('resource/background/spellBack.jpg').convert()
    #spell_background=pygame.transform.smoothscale(spell_background,(850,850)).convert()
    global_var.set_value('spell_background',spell_background)
    moon=pygame.image.load('resource/background/moon.png').convert()
    global_var.set_value('moon',moon)

    etama=pygame.image.load('resource/bullet/etama.png')
    etama=etama.convert_alpha()
    global_var.set_value('etama',etama)
    star_bullet_image=pygame.Surface((256,16))
    star_bullet_image=star_bullet_image.convert_alpha()
    star_bullet_image.fill((0,0,0,0))
    star_bullet_image.blit(etama, (0, 0), (0,160, 256, 16))
    #pygame.image.load('resource/bullet/big_star_bullet.png')
    star_bullet_image=pygame.transform.smoothscale(star_bullet_image,(384,24))
    global_var.set_value('star_bullet_image',star_bullet_image)
    mid_bullet_image=pygame.Surface((256,16))
    mid_bullet_image=mid_bullet_image.convert_alpha()
    mid_bullet_image.fill((0,0,0,0))
    mid_bullet_image.blit(etama, (0, 0), (0,48, 256, 16))
    #pygame.image.load('resource/bullet/big_star_bullet.png')
    mid_bullet_image=pygame.transform.smoothscale(mid_bullet_image,(384,24))
    global_var.set_value('mid_bullet_image',mid_bullet_image)
    orb_bullet_image=pygame.Surface((256,16))
    orb_bullet_image=orb_bullet_image.convert_alpha()
    orb_bullet_image.fill((0,0,0,0))
    orb_bullet_image.blit(etama, (0, 0), (0,32, 256, 16))
    #pygame.image.load('resource/bullet/big_star_bullet.png')
    orb_bullet_image=pygame.transform.scale(orb_bullet_image,(384,24))
    global_var.set_value('orb_bullet_image',orb_bullet_image)

    laser_image=pygame.Surface((256,16))
    laser_image=laser_image.convert_alpha()
    laser_image.fill((0,0,0,0))
    laser_image.blit(etama, (0, 0), (0,0, 256, 16))
    #pygame.image.load('resource/bullet/big_star_bullet.png')
    global_var.set_value('laser_image',laser_image)

    big_star_bullet_image=pygame.image.load('resource/bullet/big_star_bullet.png')
    big_star_bullet_image=pygame.transform.smoothscale(big_star_bullet_image,(384,48))
    global_var.set_value('big_star_bullet_image',big_star_bullet_image)
    laser_bullet_image=pygame.image.load('resource/bullet/laser_bullet.png')
    global_var.set_value('laser_bullet_image',laser_bullet_image)
    circle_bullet_image=pygame.image.load('resource/bullet/circle_bullet.png')
    circle_bullet_image=pygame.transform.smoothscale(circle_bullet_image,(384,48))
    global_var.set_value('circle_bullet_image',circle_bullet_image)
    bullet_create_image=pygame.image.load('resource/bullet/bullet_create.png')
    global_var.set_value('bullet_create_image',bullet_create_image)
    butterfly_bullet_image=pygame.image.load('resource/bullet/butterfly_bullet.png')
    butterfly_bullet_image=pygame.transform.smoothscale(butterfly_bullet_image,(384,48))
    global_var.set_value('butterfly_bullet_image',butterfly_bullet_image)
    rice_bullet_image=pygame.image.load('resource/bullet/rice_bullet.png')
    rice_bullet_image=pygame.transform.smoothscale(rice_bullet_image,(384,24))
    global_var.set_value('rice_bullet_image',rice_bullet_image)
    satsu_bullet_image=pygame.image.load('resource/bullet/satsu_bullet.png')
    satsu_bullet_image=pygame.transform.smoothscale(satsu_bullet_image,(384,24))
    global_var.set_value('satsu_bullet_image',satsu_bullet_image)
    bact_bullet_image=pygame.image.load('resource/bullet/bact_bullet.png')
    bact_bullet_image=pygame.transform.smoothscale(bact_bullet_image,(384,24))
    global_var.set_value('bact_bullet_image',bact_bullet_image)
    effect_temp1=pygame.image.load('resource/boss/eff01.png')
    effect_temp1=pygame.transform.smoothscale(effect_temp1,(192,96))
    global_var.set_value('effect_temp1',effect_temp1)
    satoriImg=pygame.image.load('resource/boss/face04ct.png')
    satoriImg=pygame.transform.smoothscale(satoriImg,(384,768)).convert_alpha()
    global_var.set_value('satoriImg',satoriImg)
    sanaeImg=pygame.image.load('resource/boss/sanaeFace.png')
    sanaeImg=pygame.transform.smoothscale(sanaeImg,(384,650)).convert_alpha()
    global_var.set_value('sanaeImg',sanaeImg)

    pauseImg=pygame.image.load('resource/text/pause.png')
    pauseImg=pygame.transform.smoothscale(pauseImg,(384,384)).convert_alpha()
    global_var.set_value('pauseImg',pauseImg)
    pauseRound=pygame.Surface((72,312)).convert_alpha()
    pauseRound.fill((0,0,0,0))
    pauseRound.blit(pauseImg,(0,0),(0,0,72,312))
    global_var.set_value('pauseRound',pauseRound)
    titleLogo=pygame.image.load('resource/title/title_logo.png')
    kanjiLogo=pygame.Surface((610,144)).convert_alpha()
    kanjiLogo.fill((0,0,0,0))
    kanjiLogo.blit(titleLogo,(0,0),(0,0,610,144))
    kanjiLogo=pygame.transform.smoothscale(kanjiLogo,(round(405*amplified_times),round(96*amplified_times)))
    global_var.set_value('kanjiLogo',kanjiLogo)
    engLogo=pygame.Surface((500,96)).convert_alpha()
    engLogo.fill((0,0,0,0))
    engLogo.blit(titleLogo,(0,0),(500,160,500,96))
    engLogo=pygame.transform.smoothscale(engLogo,(round(333*amplified_times),round(64*amplified_times)))
    global_var.set_value('engLogo',engLogo)
    lightLogo=pygame.Surface((500,96)).convert_alpha()
    lightLogo.fill((0,0,0,0))
    lightLogo.blit(titleLogo,(0,0),(0+5,160,500,96))
    lightLogo=pygame.transform.smoothscale(lightLogo,(round(333*amplified_times),round(64*amplified_times)))
    global_var.set_value('lightLogo',lightLogo)
    reimuLogo=pygame.image.load('resource/title/tachie.png').convert_alpha()
    reimuLogo=pygame.transform.smoothscale(reimuLogo,(round(240*amplified_times),round(426*amplified_times)))
    global_var.set_value('reimuLogo',reimuLogo)
    pauseSign=[]
    pauseLim=[315,240,168,192,300,300]
    for i in range(0,6):
        new_image=pygame.Surface((312,48)).convert_alpha()
        new_image.fill((0,0,0,0))
        new_image.blit(pauseImg,(0,0),(72,i*48,pauseLim[i],48))
        pauseSign.append(new_image)
    new_image=pygame.Surface((312,48)).convert_alpha()
    new_image.fill((0,0,0,0))
    new_image.blit(pauseImg,(0,0),(192,336,192,48))
    pauseSign.append(new_image)
    pauseCate=[]
    for i in range(0,3):
        new_image=pygame.Surface((105,48)).convert_alpha()
        new_image.fill((0,0,0,0))
        new_image.blit(pauseImg,(0,0),(72+i*105,0,105,48))
        pauseCate.append(new_image)
    global_var.set_value('pauseSign',pauseSign)
    global_var.set_value('pauseCate',pauseCate)
    selectSurf=pygame.Surface((312,48)).convert_alpha()
    selectSurf.fill((200,200,200,100))
    global_var.set_value('selectSurf',selectSurf)
    global_var.set_value('pauseSelectNum',0)
    levelImg=[]
    for i in range(1,2):
        new_image=pygame.image.load('resource/title/level0'+str(i)+'.png')
        new_image=pygame.transform.smoothscale(new_image,(round(256*amplified_times),round(128*amplified_times)))
        levelImg.append(new_image)
    global_var.set_value('levelImg',levelImg)
    menuImg=pygame.image.load('resource/title/title01.png')
    menuImg=pygame.transform.smoothscale(menuImg,(round(512*amplified_times),round(512*amplified_times)))
    menuSign=[]
    menuShadow=[]
    for i in range(0,8):
        for j in range(0,2):
            new_image=pygame.Surface((round(128*amplified_times),round(32*amplified_times))).convert_alpha()
            new_image.fill((0,0,0,0))
            new_image.blit(menuImg,(0,0),(round(j*128*amplified_times),round(i*32*amplified_times),round(128*amplified_times),round(32*amplified_times)))
            if j==0:
                menuSign.append(new_image)
            else:
                menuShadow.append(new_image)
    menuSelectImg=[]
    selectImg=pygame.image.load('resource/title/select01.png')
    for i in range(0,8):
        new_image=pygame.Surface((256,49)).convert_alpha()
        new_image.fill((0,0,0,0))
        new_image.blit(selectImg,(0,0),(0,i*49,256,49))
        new_image=pygame.transform.smoothscale(new_image,(round(256*amplified_times),round(49*amplified_times)))
        menuSelectImg.append(new_image)
    global_var.set_value('menuSelectImg',menuSelectImg)
    global_var.set_value('menuSign',menuSign)
    global_var.set_value('menuShadow',menuShadow)
    playerTitle=pygame.image.load('resource/title/sl_pl00.png')
    playerTitle=pygame.transform.smoothscale(playerTitle,(round(512*amplified_times),round(512*amplified_times)))
    playerTitleImg=[]
    new_image=pygame.Surface((round(300*amplified_times),round(512*amplified_times))).convert_alpha()
    new_image.fill((0,0,0,0))
    new_image.blit(playerTitle,(0,0),(0,0,round(300*amplified_times),round(512*amplified_times)))
    playerTitleImg.append(new_image)
    new_image=pygame.Surface((round(212*amplified_times),round(512*amplified_times))).convert_alpha()
    new_image.fill((0,0,0,0))
    new_image.blit(playerTitle,(0,0),(round(300*amplified_times),0,round(212*amplified_times),round(512*amplified_times)))
    playerTitleImg.append(new_image)
    global_var.set_value('playerTitleImg',playerTitleImg)
    effFlameImg=pygame.Surface((72,72)).convert_alpha()
    effFlameImg.fill((0,0,0,0))
    effFlameImg.blit(global_var.get_value('effect_temp1').convert_alpha(), (0, 0), (0,0, 72, 72))
    flameColor=(255,62,255,0)
    fill(effFlameImg,flameColor)
    effFlameImg.set_alpha(150)
    global_var.set_value('effFlameImg',effFlameImg)

    effLightImg=pygame.Surface((72,72)).convert_alpha()
    effLightImg.fill((0,0,0,0))
    effLightImg.blit(global_var.get_value('effect_temp1').convert_alpha(), (0, 0), (72,0, 72, 72))
    #flameColor=(255,255,255,0)
    fill(effLightImg,flameColor)
    effLightImg.set_alpha(150)
    global_var.set_value('effLightImg',effLightImg)

    graze_text=pygame.Surface((96,24))
    graze_text=graze_text.convert_alpha()
    graze_text.fill((0,0,0,0))
    graze_text.blit(front00, (0, 0), (525,0,96,24))
    global_var.set_value('graze_text',graze_text)

    orb_bullet_img=[]
    c_list=['blue','darkBlue','green','grey','jade','lakeBlue','lightGreen','lightRed','lightYellow','orange','pink','purple','red','skyBlue','white','yellow']
    for i in range(0,16):
        new_image=pygame.image.load('resource/bullet/orb_bullet_'+c_list[i]+'.png').convert_alpha()
        orb_bullet_img.append(new_image)
    global_var.set_value('orb_bullet_img',orb_bullet_img)
    mid_bullet_img=[]
    c_list2=['blue','darkBlue','darkGreen','darkYellow','green','grey','lightGreen','lightRed','orange','pink','purple','red','seaBlue','skyBlue','white','yellow']
    for i in range(0,16):
        new_image=pygame.image.load('resource/bullet/mid_bullet_'+c_list2[i]+'.png').convert_alpha()
        mid_bullet_img.append(new_image)
    global_var.set_value('mid_bullet_img',mid_bullet_img)
    scale_bullet_img=[]
    c_list3=['blue','green','grey','lemonYellow','lightBlue','lightGreen','lightRed','lightYellow','orange','pink','purple','red','skyBlue','white','yellow']
    for i in range(0,15):
        new_image=pygame.image.load('resource/bullet/scale_bullet_'+c_list3[i]+'.png').convert_alpha()
        scale_bullet_img.append(new_image)
    global_var.set_value('scale_bullet_img',scale_bullet_img)
    small_bullet_img=[]
    c_list4=['blue','darkBlue','green','greenish','grey','lightBlue','lightGreen','lightYellow','orange','pink','purple','red','skyBlue','violet','white','yellow']
    for i in range(0,16):
        new_image=pygame.image.load('resource/bullet/small_bullet_'+c_list4[i]+'.png').convert_alpha()
        small_bullet_img.append(new_image)
    global_var.set_value('small_bullet_img',small_bullet_img)

    sharpBulletImageList=[]
    for i in range(0,16):
        new_surf=pygame.Surface((16,16)).convert_alpha()
        new_surf.fill((0,0,0,0))
        new_surf.blit(etama,(0,0),(i*16,96,16,16))
        new_surf=pygame.transform.smoothscale(new_surf,(24,24))
        sharpBulletImageList.append(new_surf)
    global_var.set_value('sharpBulletImageList',sharpBulletImageList)

    kunaiBulletImageList=[]
    for i in range(0,16):
        new_surf=pygame.Surface((16,16)).convert_alpha()
        new_surf.fill((0,0,0,0))
        new_surf.blit(etama,(0,0),(i*16,80,16,16))
        new_surf=pygame.transform.smoothscale(new_surf,(24,24))
        kunaiBulletImageList.append(new_surf)
    global_var.set_value('kunaiBulletImageList',kunaiBulletImageList)

    titleStar=pygame.image.load('resource/title/titleStar.png')
    titleStar=pygame.transform.smoothscale(titleStar,(round(42*amplified_times),round(42*amplified_times))).convert_alpha()
    global_var.set_value('titleStar',titleStar)

    effectBar=pygame.image.load('resource/boss/etama3.png')
    effectBar=pygame.transform.smoothscale(effectBar,(192,192)).convert_alpha()
    global_var.set_value('effectBar',effectBar)

    watcher=pygame.image.load('resource/bullet/small_bullet_grey.png').convert_alpha()
    global_var.set_value('watcher',watcher)

    lightnessBossBack=pygame.image.load('resource/background/lightnessBossBack.png').convert()
    global_var.set_value('lightnessBossBack',lightnessBossBack)

    originBossCardPattern=pygame.image.load('resource/background/bossCardBackPattern.png').convert_alpha()
    bossCardPatternPic=pic.doPic(originBossCardPattern)
    global_var.set_value('bossCardPatternPic',bossCardPatternPic)

    etama2=pygame.image.load('resource/bullet/etama2.png').convert_alpha()
    global_var.set_value('etama2',etama2)

    crowImage=pygame.image.load('resource/enemy/crow.png').convert_alpha()
    crowSpriteMap=[]
    movingMap=[]
    idleMap=[]
    for i in range(4):
        new_surf=pygame.Surface((32,32)).convert_alpha()
        new_surf.fill((0,0,0,0))
        new_surf.blit(crowImage,(0,0),(i*32,0,32,32))
        new_surf=pygame.transform.smoothscale(new_surf,(48,48))
        movingMap.append(new_surf)
    for i in range(4,8):
        new_surf=pygame.Surface((32,32)).convert_alpha()
        new_surf.fill((0,0,0,0))
        new_surf.blit(crowImage,(0,0),(i*32,0,32,32))
        new_surf=pygame.transform.smoothscale(new_surf,(48,48))
        idleMap.append(new_surf)
    crowSpriteMap.append(movingMap)
    crowSpriteMap.append(idleMap)
    global_var.set_value('crowSpriteMap',crowSpriteMap)

    enemyImage=pygame.image.load('resource/enemy/enemy.png').convert_alpha()
    yinyangyuSpriteMap=[]
    for i in range(0,4):
        new_surf=pygame.Surface((32,32)).convert_alpha()
        new_surf.fill((0,0,0,0))
        new_surf.blit(enemyImage,(0,0),(128+i*32,192,32,32))
        new_surf=pygame.transform.smoothscale(new_surf,(48,48))
        new_nimbus=pygame.Surface((32,32)).convert_alpha()
        new_nimbus.fill((0,0,0,0))
        new_nimbus.blit(enemyImage,(0,0),(128+i*32,192+32,32,32))
        new_nimbus=pygame.transform.smoothscale(new_nimbus,(48,48))
        yinyangyuSpriteMap.append((new_surf,new_nimbus))
    global_var.set_value('yinyangyuSpriteMap',yinyangyuSpriteMap)

    kedamaSpriteMap=[]
    for i in range(2):
        for j in range(2):
            new_surf=pygame.Surface((32,32)).convert_alpha()
            new_surf.fill((0,0,0,0))
            new_surf.blit(enemyImage,(0,0),(64+i*32,128+j*32,32,32))
            new_surf=pygame.transform.smoothscale(new_surf,(48,48))
            kedamaSpriteMap.append(new_surf)
    global_var.set_value('kedamaSpriteMap',kedamaSpriteMap)

    sanaeImage=pygame.image.load('resource/boss/sanae.png').convert_alpha()
    sanaeSpriteMap=[]
    sanaeIdle=[]
    sanaeMove=[]
    sanaeAttack=[]
    for i in range(2):
        for j in range(4):
            new_surf=pygame.Surface((64,64)).convert_alpha()
            new_surf.fill((0,0,0,0))
            new_surf.blit(sanaeImage,(0,0),(j*64,64*i,64,64))
            new_surf=pygame.transform.smoothscale(new_surf,(96,96))
            if i==0:
                sanaeIdle.append(new_surf)
            elif i==1:
                sanaeMove.append(new_surf)
    for i in range(4):
        new_surf=pygame.Surface((64,80)).convert_alpha()
        new_surf.fill((0,0,0,0))
        new_surf.blit(sanaeImage,(0,0),(64*i,128,64,80))
        new_surf=pygame.transform.smoothscale(new_surf,(96,120))
        sanaeAttack.append(new_surf)

    sanaeSpriteMap.append(sanaeIdle)
    sanaeSpriteMap.append(sanaeMove)
    sanaeSpriteMap.append(sanaeAttack)
    print(sanaeSpriteMap)
    global_var.set_value('sanaeSpriteMap',sanaeSpriteMap)

    orinSpriteMap=[]
    orinImage=pygame.image.load('resource/boss/stg5enm.png')
    lightEffect=pygame.Surface((64,64)).convert_alpha()
    lightEffect.fill((0,0,0,0))
    lightEffect.blit(orinImage,(0,0),(192,128,64,64))
    lightEffect.set_alpha(150)
    global_var.set_value('orinLightEffect',lightEffect)

    duelLevelBack=pygame.image.load('resource/background/duelClassLevelBack.jpg')
    duelLevelBack=duelLevelBack.convert()
    duelLevelBack=pygame.transform.smoothscale(duelLevelBack,(280,280))
    global_var.set_value('duelLevelBack',duelLevelBack)

    duelSpellBack=pygame.image.load('resource/background/duelClassSpellBack.jpg')
    duelSpellBack=duelSpellBack.convert()
    duelSpellBack=pygame.transform.smoothscale(duelSpellBack,(280,280))
    global_var.set_value('duelSpellBack',duelSpellBack)

    level2Title=pygame.image.load('resource/title/level2_title.png').convert_alpha()
    global_var.set_value('level2Title',level2Title)

class star_effect(pygame.sprite.Sprite):
    def __init__(self):
        super(star_effect,self).__init__()
        self.surf=pygame.image.load('resource/text/stars.png')
        self.surf.set_alpha(200)
        self.rect = self.surf.get_rect()
        self.frame=0
        self.angle=0
    def initial(self,centerx,centery):
        self.rect.centerx=centerx
        self.rect.centery=centery

    def update(self,screen):
        self.frame+=1

    def draw(self,screen):
        self.angle=self.frame*3
        drawRotation(self.surf,self.rect,self.angle,screen)

def showFpsBullet(screen,myfont,frame,bulletSum,log):
    #FPS
    t = pygame.time.get_ticks()
    #print(t)
    # deltaTime in seconds.
    deltaTime = (t - global_var.get_value('getTicksLastFrame')) / 1000.0
    global_var.set_value('getTicksLastFrame',t)
    fp=round(1/deltaTime,1)
    temp=global_var.get_value('fpSec')
    if not global_var.get_value('pause'):
        temp=temp+fp
    global_var.set_value('fpSec',temp)
    if frame%60==1:
        avgFp=round(global_var.get_value('fpSec')/60.0,1)
        fpText=myfont.render('FPS: '+str(avgFp), True, (255, 255, 255))
        global_var.set_value('fpText',fpText)
        global_var.set_value('fpSec',0)
        #log recording

        print(str(round((frame-1)/60))+','+str(avgFp)+','+str(bulletSum),file=log)
    screen.blit(global_var.get_value('fpText'),(820,692))
    bulletText=myfont.render('Bullets: '+str(bulletSum), True, (255, 255, 255))
    screen.blit(bulletText,(820,672))

def doBackground(screen,backgrounds):
    for i in range(0,3):
        for j in range(0,4):
            new_background=background.lake_bg()
            new_background.initial(128+i*256,128+j*256)
            backgrounds.add(new_background)

def doBackground2(screen,backgrounds):
    for i in range(0,2):
        for j in range(0,4):
            new_background=background.duelLevelBackObj()
            new_background.initial(60+140+i*280,140+j*280)
            backgrounds.add(new_background)

def doSpellBackground(screen,backgrounds):
    for i in range(0,3):
        for j in range(0,4):
            new_background=background.duelSpellBackObj()
            new_background.initial(60+140+i*280,140+j*280)
            backgrounds.add(new_background)

def doBossCardBackground(screen,backgrounds):
    for i in range(0,2):
        for j in range(0,3):
            new_background=background.bossCardPattern()
            new_background.initial(30+192+i*384,30+192+j*384)
            backgrounds.add(new_background)

def drawBlinder(screen,surf):
    screen.blit(surf,(0,720))

def doPause(pressed_keys,screen):
    if pressed_keys[K_ESCAPE]!=global_var.get_value('escPressing') and pressed_keys[K_ESCAPE]:
        if global_var.get_value('pause') and not global_var.get_value('ifGameOver'):
            global_var.set_value('pause',False)
            pygame.mixer.music.unpause()
        elif not global_var.get_value('ifGameOver'):
            global_var.set_value('pause',True)
            pygame.mixer.music.pause()
            global_var.get_value('pause_sound').stop()
            global_var.get_value('pause_sound').play()
            global_var.get_value('nep_sound').stop()
            new_image=pygame.Surface((960,720)).convert_alpha()
            new_image.fill((0,0,0))
            new_image.blit(screen,(0,0))
            new_image=pygame.transform.smoothscale(new_image,(480,360))
            new_image=pygame.transform.smoothscale(new_image,(960,720))
            global_var.set_value('pauseScreen',new_image)
            #print(global_var.get_value('pauseScreen').get_size())

def pauseScreen(pressed_keys,pressed_keys_last,screen,frame,enemys,bullets,slaves,items,effects,backgrounds,bosses,player,booms,playerGuns,myfont):
    pause=global_var.get_value('pause')
    if pause:
        ifStopPressing=global_var.get_value('ifStopPressing')
        screen.blit(global_var.get_value('pauseScreen'),(0,0))
        #screen.blit(global_var.get_value('pauseImg'),(60,300))
        screen.blit(global_var.get_value('pauseRound'),(75,300))
        selectNum=global_var.get_value('pauseSelectNum')
        if not (pressed_keys[K_UP] and pressed_keys_last[K_UP]):
            if pressed_keys[K_UP]:
                selectNum-=1
                global_var.get_value('select_sound').stop()
                global_var.get_value('select_sound').play()
        if not (pressed_keys[K_DOWN] and pressed_keys_last[K_DOWN]):
            if pressed_keys[K_DOWN]:
                selectNum+=1
                global_var.get_value('select_sound').stop()
                global_var.get_value('select_sound').play()
        if not global_var.get_value('levelPassSign'):
            if selectNum>2:
                selectNum=0
            elif selectNum<0:
                selectNum=2
        else:
            if selectNum>2:
                selectNum=0
            elif selectNum<1:
                selectNum=2

        global_var.set_value('pauseSelectNum',selectNum)
        screen.blit(global_var.get_value('selectSurf'),(72,398+48*selectNum))
        for i in range(0,4):
            if i==0:
                if not global_var.get_value('ifGameOver'):
                    screen.blit(global_var.get_value('pauseCate')[0],(60,300+48*i))
                else:
                    screen.blit(global_var.get_value('pauseCate')[1],(60,300+48*i))
            else:
                if i==1:
                    if not global_var.get_value('levelPassSign'):
                        if not global_var.get_value('ifGameOver'):
                            screen.blit(global_var.get_value('pauseSign')[i],(100,398-48+48*i))
                        else:
                            screen.blit(global_var.get_value('pauseSign')[6],(100,398-48+48*i))
                    else:
                        passText=myfont.render("Congratulations! You Pass the level!",True,(255,255,255))
                        scoreStr="Your overall Score is "+str(player.score)+" !"
                        if global_var.get_value('levelSign')==0:
                            highScore=global_var.get_value('highScore_0')
                        elif global_var.get_value('levelSign')==1:
                            highScore=global_var.get_value('highScore_1')
                        if highScore<=player.score:
                            recordStr="You beat the record! New HighScore!"
                        else:
                            recordStr=" "
                        scoreText=myfont.render(scoreStr,True,(255,255,255))
                        recordText=myfont.render(recordStr,True,(255,255,255))
                        screen.blit(recordText,(100,348))
                        screen.blit(passText,(100,378))
                        screen.blit(scoreText,(100,408))
                else:
                    screen.blit(global_var.get_value('pauseSign')[i],(100,398-48+48*i))
        if pressed_keys[K_z]!=pressed_keys_last[K_z] and pressed_keys[K_z] and ifStopPressing and selectNum==0:
            if not global_var.get_value('ifGameOver'):
                global_var.get_value('ok_sound').play()
                global_var.set_value('pause',False)
                pygame.mixer.music.unpause()
                global_var.set_value('pauseSelectNum',0)
            else:
                global_var.get_value('ok_sound').play()
                global_var.set_value('pause',False)
                pygame.mixer.music.stop()
                if not global_var.get_value('ifBoss'):
                    if global_var.get_value('levelSign')==0:
                        pygame.mixer.music.load('resource/bgm/lightnessOnTheWay.mp3')
                    elif global_var.get_value('levelSign')==1:
                        pygame.mixer.music.load('resource/bgm/yujiMidpath.mp3')
                    start1=global_var.get_value('bgmContinuePos')[0]
                    pygame.mixer.music.play(loops=-1,start=start1/1000)
                else:
                    if global_var.get_value('levelSign')==0:
                        pygame.mixer.music.load('resource/bgm/金卡雷 - 引燃夜空的星火.mp3')
                    elif global_var.get_value('levelSign')==1:
                        pygame.mixer.music.load('resource/bgm/金卡雷 - 风中花，雪中月.mp3')
                    start1=global_var.get_value('bgmContinuePos')[1]
                    pygame.mixer.music.play(loops=-1,start=start1/1000)
                global_var.set_value('pauseSelectNum',0)

                if global_var.get_value('levelSign')==0:
                    highScore=global_var.get_value('highScore_0')
                elif global_var.get_value('levelSign')==1:
                    highScore=global_var.get_value('highScore_1')

                if highScore<=player.score:
                    if global_var.get_value('levelSign')==0:
                        global_var.set_value('highScore_0',player.score)
                        with open('resource/data/highScore_0.dat','w') as file:
                            file.write(str(player.score))
                    elif global_var.get_value('levelSign')==1:
                        global_var.set_value('highScore_1',player.score)
                        with open('resource/data/highScore_1.dat','w') as file:
                            file.write(str(player.score))

                px=player.tx
                py=player.ty
                midPath=player.midPath
                player.__init__()
                player.midPath=midPath
                player.tx=px
                player.ty=py
                player.power=400
                player.spellBonus=False
                global_var.set_value('ifGameOver',False)
                player.score=0
                player.unhitSetter(120)

        elif (pressed_keys[K_z]!=pressed_keys_last[K_z] and pressed_keys[K_z] and ifStopPressing and selectNum==1):
            global_var.set_value('restarting',True)
            global_var.get_value('ok_sound').play()
            global_var.set_value('pause',False)
            global_var.set_value('levelPassSign',False)

            if global_var.get_value('levelSign')==0:
                highScore=global_var.get_value('highScore_0')
            elif global_var.get_value('levelSign')==1:
                highScore=global_var.get_value('highScore_1')

            if highScore<=player.score:
                if global_var.get_value('levelSign')==0:
                    global_var.set_value('highScore_0',player.score)
                    with open('resource/data/highScore_0.dat','w') as file:
                        file.write(str(player.score))
                elif global_var.get_value('levelSign')==1:
                    global_var.set_value('highScore_1',player.score)
                    with open('resource/data/highScore_1.dat','w') as file:
                        file.write(str(player.score))

            restart(frame,enemys,bullets,slaves,items,effects,backgrounds,bosses,player,screen,booms,playerGuns)
            pygame.mixer.music.stop()
            global_var.set_value('pauseSelectNum',0)
            global_var.set_value('menu',True)
            pygame.mixer.music.stop()
            pygame.mixer.music.load('resource/bgm/mainTitle.mp3')
            pygame.mixer.music.play(loops=-1)

        elif (pressed_keys[K_z]!=pressed_keys_last[K_z] and pressed_keys[K_z] and ifStopPressing and selectNum==2) or (pressed_keys[K_r]!=pressed_keys_last[K_r] and pressed_keys[K_r] and not global_var.get_value('levelPassSign')):
            #print('do')
            global_var.set_value('restarting',True)
            global_var.get_value('ok_sound').play()
            global_var.set_value('pause',False)
            global_var.set_value('levelPassSign',False)
            pygame.mixer.music.stop()

            global_var.set_value('pauseSelectNum',0)
            if global_var.get_value('levelSign')==0:
                highScore=global_var.get_value('highScore_0')
            elif global_var.get_value('levelSign')==1:
                highScore=global_var.get_value('highScore_1')

            if highScore<=player.score:
                if global_var.get_value('levelSign')==0:
                    global_var.set_value('highScore_0',player.score)
                    with open('resource/data/highScore_0.dat','w') as file:
                        file.write(str(player.score))
                elif global_var.get_value('levelSign')==1:
                    global_var.set_value('highScore_1',player.score)
                    with open('resource/data/highScore_1.dat','w') as file:
                        file.write(str(player.score))

            restart(frame,enemys,bullets,slaves,items,effects,backgrounds,bosses,player,screen,booms,playerGuns)
        if not pressed_keys[K_z]:
            ifStopPressing=True
            global_var.set_value('ifStopPressing',True)

def restart(frame,enemys,bullets,slaves,items,effects,backgrounds,bosses,player,screen,booms,playerGuns):
    #frame=0
    for enemy in enemys:
        enemy.kill()
    for bullet in bullets:
        bullet.kill()
    for slave in slaves:
        slave.kill()
    for item in items:
        item.kill()
    for effect in effects:
        effect.kill()
    for background in backgrounds:
        background.kill()
    for boss in bosses:
        boss.kill()
    for boom in booms:
        boom.kill()
    for playerGun in playerGuns:
        playerGun.kill()
    player.__init__()
    player.tx=337.0
    player.ty=600.0
    player.power=100
    if global_var.get_value('ifTest'):
        player.power=400
    global_var.set_value('getTicksLastFrame',0)
    pygame.mixer.music.load('resource/bgm/lightnessOnTheWay.mp3')
    pygame.mixer.music.play(loops=-1)
    global_var.set_value('ifBoss',False)
    global_var.set_value('pressingX',False)
    global_var.set_value('DELTA_T',17)
    global_var.set_value('ifShaking',False)
    global_var.set_value('shakeFrame',0)
    global_var.set_value('boomStatu',0)
    global_var.set_value('grazeNum',0)
    global_var.set_value('fpSec',0)
    global_var.set_value('enemyPos',(0,0,10000))
    global_var.set_value('shift_down',False)
    global_var.set_value('pause',False)
    global_var.set_value('escPressing',False)
    global_var.set_value('pauseScreen',0)
    global_var.set_value('ifStopPressing',False)
    global_var.set_value('ifGameOver',False)
    global_var.set_value('bgmContinuePos',[0,0])#[0]->for mid stage,[1]->for boss fight
    #doBackground(screen,backgrounds)


# -*- coding: utf-8 -*-
"""
Created on Thu Oct 29 15:13:36 2020

@author: deyiwang@qq.com

实现功能: 选取两张图片的控制点, 完成对应视角的转换

参考代码: https://blog.csdn.net/fanzy1234/article/details/103072723?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param
以及: https://blog.csdn.net/qq_36281080/article/details/103928487
"""

from imutils import perspective
from skimage.filters import threshold_local
import cv2
import imutils
import numpy as np

def SetPoints(windowname, img):
    """
    输入图片，打开该图片进行标记点，返回的是标记的几个点的字符串
    """
    print('(提示：单击需要标记的坐标，Enter确定，Esc跳过，其它重试。)')
    points = []

    def onMouse(event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            cv2.circle(temp_img, (x, y), 10, (102, 217, 239), -1)
            points.append([x, y])
            cv2.imshow(windowname, temp_img)

    temp_img = img.copy()
    cv2.namedWindow(windowname)
    cv2.imshow(windowname, temp_img)
    cv2.setMouseCallback(windowname, onMouse)
    key = cv2.waitKey(0)
    if key == 13:  # Enter
        print('坐标为：', points)
        del temp_img
        cv2.destroyAllWindows()
        return points
    elif key == 27:  # ESC
        print('跳过该张图片')
        del temp_img
        cv2.destroyAllWindows()
        return
    else:
        print('重试!')
        return SetPoints(windowname, img)

def extra_point(aol,img):
    points = SetPoints(str(aol), img)
    temp = np.array(points)
    pts = temp.reshape(4, 2).astype(np.float32)
    return pts

def read_img(path):
    image = cv2.imread(path)
    w=image.shape[0]
    h=image.shape[1]
    ratio = image.shape[0] / 500.0  # 比例
    orig = image.copy()
    image = imutils.resize(image, height=500)
    return image

def main():

    image1 = read_img("real.jpg")
    image2 = read_img("satellite.png")

    point1 = extra_point('real',image1)
    point2 = extra_point("sat", image2)

    #实际坐标点和提取的角点必须一一对应呀，
    M = cv2.getPerspectiveTransform(point1,point2)
    out_img = cv2.warpPerspective(image1,M,(image1.shape[0],700))
    dst=cv2.perspectiveTransform(point2.reshape(1,4,2), M)

    cv2.imshow("Original", image1)
    cv2.imshow("Scanned",cv2.resize(out_img,(image1.shape[0],700)))

if __name__ == "__main__":
    main()


from time import sleep
from typing import Dict, List

import boto3
from botocore.exceptions import ClientError

from api.common.config.aws import (
    AWS_REGION,
    GLUE_CATALOGUE_DB_NAME,
    GLUE_TABLE_PRESENCE_CHECK_INTERVAL,
    GLUE_TABLE_PRESENCE_CHECK_RETRY_COUNT,
)
from api.common.custom_exceptions import (
    AWSServiceError,
    TableAlreadyExistsError,
    TableCreationError,
    TableDoesNotExistError,
)
from api.common.logger import AppLogger
from api.domain.dataset_metadata import DatasetMetadata
from api.domain.schema import Schema

class GlueAdapter:
    def __init__(
        self,
        glue_client=boto3.client("glue", region_name=AWS_REGION),
        glue_catalogue_db_name=GLUE_CATALOGUE_DB_NAME,
    ):
        self.glue_client = glue_client
        self.glue_catalogue_db_name = glue_catalogue_db_name

    def create_table(self, schema: Schema):
        try:
            self.glue_client.create_table(
                DatabaseName=self.glue_catalogue_db_name,
                TableInput={
                    "Name": schema.metadata.glue_table_name(),
                    "Owner": "hadoop",
                    "StorageDescriptor": {
                        "Columns": schema.get_non_partition_columns_for_glue(),
                        "Location": schema.metadata.s3_file_location(),
                        "InputFormat": "org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat",
                        "OutputFormat": "org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat",
                        "Compressed": False,
                        "SerdeInfo": {
                            "SerializationLibrary": "org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe",
                            "Parameters": {"serialization.format": "1"},
                        },
                        "NumberOfBuckets": -1,
                        "StoredAsSubDirectories": False,
                    },
                    "PartitionKeys": schema.get_partition_columns_for_glue(),
                    "TableType": "EXTERNAL_TABLE",
                    "Parameters": {
                        "classification": "parquet",
                        "typeOfData": "file",
                        "compressionType": "none",
                        "EXTERNAL": "TRUE",
                    },
                },
                PartitionIndexes=[
                    {
                        "Keys": [
                            col["Name"]
                            for col in schema.get_partition_columns_for_glue()
                        ],
                        "IndexName": "rapid-creation-partition",
                    },
                ]
                if schema.get_partition_columns_for_glue()
                else [],
            )
        except ClientError as error:
            self._handle_table_create_error(error)

    def _handle_table_create_error(self, error: ClientError):
        if error.response["Error"]["Code"] == "AlreadyExistsException":
            raise TableAlreadyExistsError("Table already exists with same name")
        else:
            raise TableCreationError("Table creation error")

    def get_table_when_created(self, table_name: str) -> Dict:
        for _ in range(GLUE_TABLE_PRESENCE_CHECK_RETRY_COUNT):
            try:
                return self._get_table(table_name)
            except TableDoesNotExistError:
                AppLogger.info(
                    f"Waiting {GLUE_TABLE_PRESENCE_CHECK_INTERVAL}s for table [{table_name}] to be created"
                )
                sleep(GLUE_TABLE_PRESENCE_CHECK_INTERVAL)
                continue
        raise AWSServiceError(
            f"[{table_name}] was not created after {GLUE_TABLE_PRESENCE_CHECK_RETRY_COUNT * GLUE_TABLE_PRESENCE_CHECK_INTERVAL}s"
        )  # noqa: E501

    def get_tables_for_dataset(self, dataset: DatasetMetadata) -> List[str]:
        tables = [
            item["Name"] for item in self._search_tables(dataset.glue_table_prefix())
        ]
        return tables

    def delete_tables(self, table_names: List[str]):
        try:
            self.glue_client.batch_delete_table(
                DatabaseName=GLUE_CATALOGUE_DB_NAME, TablesToDelete=table_names
            )
        except ClientError:
            raise AWSServiceError("Failed to delete tables")

    def _get_table(self, table_name: str) -> Dict:
        try:
            table = self.glue_client.get_table(
                DatabaseName=self.glue_catalogue_db_name, Name=table_name
            )
            return table
        except ClientError as error:
            if error.response["Error"]["Code"] == "EntityNotFoundException":
                raise TableDoesNotExistError(f"The table [{table_name}] does not exist")

    def _search_tables(self, search_term: str) -> Dict:
        try:
            paginator = self.glue_client.get_paginator("get_tables")
            page_iterator = paginator.paginate(
                DatabaseName=GLUE_CATALOGUE_DB_NAME,
            )
            tables = []
            for page in page_iterator:
                tables.extend(page["TableList"])

            return [table for table in tables if table["Name"].startswith(search_term)]
        except ClientError:
            raise AWSServiceError(f"Failed to search tables with term={search_term}")


def solution(inputString):
    a = list(set(inputString))
    a.sort(reverse=True)
    prev = inputString.count(a[0])
    if a[-1] != 'a':
        return False
    for i in range(len(a)-1):
        act = inputString.count(a[i+1])
        if act < prev:
            return False
        if ord(a[i])-1 != ord(a[i+1]):
            return False
        prev = act
    return True

"""
def solution(inputString):

    r = [inputString.count(i) for i in string.ascii_lowercase]

    return r[::-1] == sorted(r)

    """


from flask import Flask
from flask import request
from flask_cors import CORS, cross_origin
from blink1.blink1 import Blink1

app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'

b1 = Blink1()

def rgb_to_hex(rgb):
    return "#" + str('%02x%02x%02x' % rgb)

def call_blink_function(method, color_value, transition_time=1000):
    if method == "fade":
        b1.fade_to_color(transition_time, color_value)
    if method == "blink":
        b1.write_pattern_line(transition_time, color_value, 1)
        b1.write_pattern_line(transition_time, '#000000', 2)
        b1.play(1,2)

    return

def handle_color(method, color_value, transition_time=1000):
    error_output = ""

    try:
        call_blink_function(method, color_value, transition_time)

        return f"Blink changed with color {color_value} with method {method}."
    except:
        pass

    try:
        tempval = color_value
        red_value = tempval[0:tempval.index(",")]
        tempval = tempval[(tempval.index(",") + 1): len(tempval)]
        green_value = tempval[0:tempval.index(",")]
        tempval = tempval[(tempval.index(",") + 1): len(tempval)]
        blue_value = tempval

        red_value = int(red_value)
        green_value = int(green_value)
        blue_value = int(blue_value)

        tempval = rgb_to_hex((red_value, green_value, blue_value))

        call_blink_function(method, tempval, transition_time)

        return f"Blink changed with rgb value ({red_value}, {green_value}, {blue_value}) with method {method}."
    except:
        pass

    try:
        hexval = color_value
        if len(hexval) == 7:
            hexval = hexval[1: len(hexval)]
        hexval = "#" + hexval

        call_blink_function(method, hexval, transition_time)

        return f"Blink changed with hex value {hexval} with method {method}."
    except:
        pass

    return f"You've provided an invalid color\n{error_output}"

@app.route("/")
@cross_origin()
def home():
    return f"To change the light color, query /fade. To have it blink, /blink. To turn it off, /off"

@app.route("/off")
@cross_origin()
def off():
    b1.off()
    return f"Blink turned off"

@app.route("/fade")
@cross_origin()
def fade():
    method = "fade"

    transition_time = request.args.get('time')
    if transition_time is not None:
        transition_time = int(transition_time)
    else:
        transition_time = 1000

    color_value = request.args.get('color')
    if color_value is None:
        return f"Please specify a color value. Example: /{method}?color=red or /{method}?color=5523f2 or /{method}?color=13,22,192. You can also specify an optional time argument."

    return handle_color(method, color_value, transition_time)

@app.route("/blink")
@cross_origin()
def blink():
    method = "blink"

    transition_time = request.args.get('time')
    if transition_time is not None:
        transition_time = int(transition_time)
    else:
        transition_time = 1000

    color_value = request.args.get('color')
    if color_value is None:
        return f"Please specify a color value. Example: /{method}?color=red or /{method}?color=5523f2 or /{method}?color=13,22,192. You can also specify an optional time argument."

    return handle_color(method, color_value, transition_time)

if __name__ == "__main__":
    app.run(port=5000, host="0.0.0.0")


import math

class Node:
    def __init__(self, id_number):
        """
        Initialize a Node object with an ID number.

        Args:
            id_number (int): The ID number of the node.

        Returns:
            None
        """
        self.id = id_number
        self.layer = 0  # Initialize layer as 0
        self.input_value = 0  # Initialize input value as 0
        self.output_value = 0  # Initialize output value as 0
        self.connections = []  # Create an empty list to store connections

    def activate(self):
        """
        Activate the node by applying the sigmoid activation function to the input value.

        Args:
            None

        Returns:
            None
        """
        def sigmoid(x):  # Define a sigmoid activation function
            """
            Compute the sigmoid function.

            Args:
                x (float): Input value.

            Returns:
                float: Result of the sigmoid function.
            """
            return 1 / (1 + math.exp(-x))

        if self.layer == 1:  # Check if the node is in layer 1
            self.output_value = sigmoid(self.input_value)  # Apply sigmoid activation to the input value

        for i in range(0, len(self.connections)):  # Iterate over the connections
            self.connections[i].to_node.input_value += \
                self.connections[i].weight * self.output_value  # Add the weighted output value to the connected node's input value

    def clone(self):
        """
        Create a clone of the node with the same ID and layer.

        Args:
            None

        Returns:
            Node: A clone of the node.
        """
        clone = Node(self.id)  # Create a new instance of Node with the same ID
        clone.id = self.id  # Set the ID of the clone to the ID of the original node
        clone.layer = self.layer  # Set the layer of the clone to the layer of the original node
        return clone  # Return the clone instance


import numpy as np

from lib.data import get_dataset
from lib.classifier import SVM
from lib.bag_of_words import get_features
from lib.descriptors import get_keypoints_orb
from lib.mask import mask_apple_tomato

def get_data_and_voc(infos, val_ratio, voc_path1, voc_path2):
    (data, y), (data_test, y_test) = get_dataset('dataset/fruits',
                                                infos, val_ratio=val_ratio)
    vocabulary1 = np.load(voc_path1)
    vocabulary2 = np.load(voc_path2)
    vocabulary = np.concatenate((vocabulary1, vocabulary2), axis=0)
    return (data, y), (data_test, y_test), vocabulary

def random_cross_validation(n_folds, X, y):
    mean_acc = 0.0
    for _ in range(n_folds):
        val_idx = np.random.choice(len(X), int(len(X) * data_prop),
                                replace=False)
        train_idx = np.array([i for i in range(len(X)) if i not
                                in val_idx])
        X_val, y_val = X[val_idx], y[val_idx]
        X_train, y_train = X[train_idx], y[train_idx]
        svm = SVM(C=C, kernel='rbf', gamma=gamma, verbose=False)
        svm.fit(X_train, y_train)
        preds = svm.predict(X_val)
        mean_acc += np.mean(preds == y_val) / n_folds
    return mean_acc

def test_classifier(svm, X_train, y_train, X_test, y_test):
    svm.fit(X_train, y_train)
    preds = svm.predict(X_test)
    return np.mean(preds == y_test)

if __name__ == '__main__':
    ## Configs
    # Dataset / vocabulary / masking function
    infos = {'apple_a': (0, 500), 'apple_b': (1, 500), 'apple_c': (1, 0),
                    'tomato': (1, 0)}
    val_ratio = 0.15
    voc_path1 = 'vocabulary/fruits/apple_a_50_orb.npy'
    voc_path2 = 'vocabulary/fruits/apple_b_50_orb.npy'
    mask_func = mask_apple_tomato
    # Descriptors
    n_desc = 500
    dist = 'euclidian'
    # Cross validation
    data_prop = 0.2
    n_folds = 20
    C_range = [1, 10, 100, 1000]
    gamma_range = [1e-5, 1e-4, 1e-3, 1e-2, 0.1, 1]
    # Test
    test = True
    test_svm = SVM(C=100, kernel='rbf', gamma=0.1, verbose=False)

    (data, y), (data_test, y_test), vocabulary = get_data_and_voc(
        infos, val_ratio, voc_path1, voc_path2
        )
    print('Train & validation set:', len(data), 'samples.')
    print('Test set:', len(data_test), 'samples.')

    # Get descriptors and make bag of words features
    desc, _ = get_keypoints_orb(data, select=n_desc,
                                    mask_func=mask_func)
    desc_test, _ = get_keypoints_orb(data_test, select=n_desc,
                                    mask_func=mask_func)
    X = get_features(desc, vocabulary)
    X_test = get_features(desc_test, vocabulary, dist=dist)
    print('Features extracted.')

    # Cross-validation and gridsearch for SVM
    for C in C_range:
        for gamma in gamma_range:
            mean_acc = random_cross_validation(n_folds, X, y)
            print(f'C={C}, gamma={gamma:.6f} - val acc={100 * mean_acc:.2f}%')

    if test:
        # Test SVM on test set
        accuracy = test_classifier(test_svm, X, y, X_test, y_test)
        print(f'test accuracy: {100 * accuracy:.2f}%')


import osmnx as ox
import os
import networkx as nx
import json
import numpy as np
from rasterio.sample import sample_gen
from haversine import haversine, Unit
import geopandas as gpd
import shapely
import plotly.express as px
import plotly.graph_objects as go
import rasterio
import re
from typing import Optional, Union

p = re.compile(r"[^a-zA-Z0-9_ -]")

def path_to_coords_list(G: nx.Graph, path: list):
    coords_list = []
    for u, v in zip(path[:-1], path[1:]):
        # if there are parallel edges, select the shortest
        data = G.get_edge_data(u, v)
        if "geometry" in data:
            # if geometry attribute exists, add all its coords to list
            xs, ys = data["geometry"].xy
            pts = [[ys[i], xs[i]] for i in range(len(xs))]
            coords_list += pts
        else:
            # otherwise, the edge is a straight line from node to node
            coords_list.append([G.nodes[u]["y"], G.nodes[u]["x"]])
    return coords_list

def path_length(G: nx.Graph, path: list):
    dist = sum([G.edges[path[i], path[i + 1]]["length"] for i in range(len(path) - 1)]) / 1609
    return dist

def find_best_loop(G: nx.Graph, root, target_dist, tol=1.0, min_elev: Optional[Union[int, float]] = None,
                   dataset: Optional[rasterio.DatasetReader] = None):
    if min_elev and not dataset:
        raise ValueError("If asking for elevation data, you must include a rasterio dataset")
    error = 1e8
    best_path = []
    for n in G.nodes():
        if nx.has_path(G, root, n):
            shortest_path = nx.shortest_path(G, root, n)
            paths = nx.all_simple_paths(G, root, n, cutoff=10)
            for path in paths:
                if path == shortest_path:
                    continue

                path_loop = path + nx.shortest_path(G, n, root, weight="length")[1:]

                path_diversity = len(set(path_loop)) / len(path_loop)

                dist = path_length(G, path_loop)
                e_new = np.abs(dist - target_dist) / path_diversity
                if e_new < error:
                    error = e_new
                    best_path = path_loop
                if error < tol:
                    if min_elev:
                        coords_list = path_to_coords_list(G, path_loop)
                        _, elev = get_elevation_profile_of_segment(dataset, coords_list)
                        elev_gain = elevation_gain(elev)
                        if elev_gain < min_elev:
                            continue
                    return best_path
    return best_path

def get_elevation_profile_of_segment(dataset: rasterio.DatasetReader, coords: list[list]):
    """
    Get the elevation profile (distance vs. altitude) of a path segment from the list of coordinates.
    Args:
        dataset: The opened rasterio dataset for the SRTM global topography data.
        coords: The path coordinates in [[lon1, lat1], [lon2, lat2], ...] format.

    Returns: The distance (in miles) and elevation (in feet) vectors.
    """
    # coordinates are [lon, lat], flip for rasterio
    coords = [[c[1], c[0]] for c in coords]
    # convert meters to feet and use rasterio.sample.sample_gen to query each point
    elev = [e[0] * 3.28084 for e in sample_gen(dataset, coords)]
    d = [0.0]
    for j in range(len(coords) - 1):
        # use haversine distance
        d.append(d[j] + haversine((coords[j][1], coords[j][0]), (coords[j + 1][1], coords[j + 1][0]), Unit.MILES))
    return d, elev

def coords_to_distance_vector(coords: list[list], reverse_coords: bool = True) -> list:
    if reverse_coords: # needs to be [lat, lon]
        coords = [c[::-1] for c in coords]
    return [haversine(coords[i], coords[i+1], Unit.MILES) for i in range(len(coords) - 1)]

def elevation_gain(elev, thresh=70):
    last_pt = elev[0]
    elev_gain = 0
    for e in elev:
        if np.abs(e - last_pt) >= thresh:
            if e - last_pt > 0:
                elev_gain += (e - last_pt)
            last_pt = e
    return elev_gain
    # return sum([max(e, 0) for e in np.diff(elev)])

def plot_gdf(geo_df: gpd.GeoDataFrame):
    lats = []
    lons = []
    names = []

    for feature, name in zip(geo_df.geometry, geo_df.name):
        if isinstance(feature, shapely.geometry.linestring.LineString):
            linestrings = [feature]
        elif isinstance(feature, shapely.geometry.multilinestring.MultiLineString):
            linestrings = feature.geoms
        else:
            continue
        for linestring in linestrings:
            x, y = linestring.xy
            lats = np.append(lats, y)
            lons = np.append(lons, x)
            names = np.append(names, [name] * len(y))
            lats = np.append(lats, None)
            lons = np.append(lons, None)
            names = np.append(names, None)

    fig = go.FigureWidget(px.line_mapbox(lat=lats, lon=lons,
                         mapbox_style="outdoors", zoom=10))

    return fig

def load_map(place: str, graph_only: bool = False) -> (nx.MultiDiGraph, dict):
    """
    Load OSM trail data for a given region. Initially check if the graph has already been cached on disk, otherwise it will be downloaded.
    Args:
        place: The geocode of the region of interest, e.g. 'Shenandoah National Park, Virginia, USA'
        graph_only: If true, return only the NetworkX graph, not the geojson.

    Returns: The dataset as a NetworkX MultiGraph, the nodes geojson, the edges geojson

    """
    filename = p.sub("", place).lower().replace(" ", "_")
    graph_fp = f"static/graphs/{filename}.graphml"
    edges_fp = f"static/edges/{filename}.geojson"
    nodes_fp = f"static/nodes/{filename}.geojson"
    try:
        G = ox.load_graphml(graph_fp)
        print("Graph loaded from disk")
    except FileNotFoundError:
        print("Downloading and caching graph from OSM")
        # custom filter to only include walkable segments - see: https://support.alltrails.com/hc/en-us/articles/360019246411-OSM-Derivative-Database-Derivation-Methodology
        cf = '["highway"~"path|track|footway|steps|bridleway|cycleway"]'
        G = ox.graph_from_place(place, custom_filter=cf)
        ox.save_graphml(G, graph_fp)
    if graph_only:
        return G
    if os.path.isfile(edges_fp) is False or os.path.isfile(nodes_fp) is False:
        # convert Graph to GeoDataFrames and save as GeoJSON
        nodes, edges = ox.graph_to_gdfs(G)
        edges = edges[["name", "geometry", "length"]]
        edges["name"] = edges["name"].apply(lambda x: x[0] if type(x) is list else x)
        edges.to_file(edges_fp)
        nodes.to_file(nodes_fp)
    with open(nodes_fp, "r") as f:
        nodes = json.load(f)
    with open(edges_fp, "r") as f:
        edges = json.load(f)
    for feat in edges["features"]:
        # add custom tooltip property for Leaflet visualization
        tooltip = f"{feat['properties']['name']}, {round(feat['properties']['length'] / 1609, 1)} mi"
        feat["properties"]["tooltip"] = tooltip
    return G, nodes, edges