#
# Data visualisation
#a

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

import torch
import torch.nn as nn
import torch.utils.data as data

from model import *

def visualise_data():
    test = RNN()
    df = load_data('train.csv')

    gb = df.groupby(["store", "product"])
    groups = {x: gb.get_group(x) for x in gb.groups}

    fig, axs = plt.subplots(7, 10, figsize=(40, 35))
    for index, store_axs in enumerate(axs):
        for index2, product_ax in enumerate(store_axs):
            X = groups[(index, index2)]
            X = X.drop(["store", "product"], axis=1).values
            X = [item for sublist in X for item in sublist]
            product_ax.plot(X, linewidth=0.5)
            product_ax.set_yticks([min(X), max(X)])
            if index == 6:
                product_ax.set_xticks([0, len(X)])
            else:
                product_ax.set_xticks([])
            product_ax.tick_params(labelsize=6)

    for index, ax in enumerate(axs[0]):
        ax.set_title(f"Product {index}")

    for index, ax in enumerate(axs[:, 0]):
        ax.set_ylabel(f"Store {index}", rotation=0, size='large', labelpad=20)

    plt.subplots_adjust(wspace=0.65, hspace=0.3)
    #fig.tight_layout()
    plt.show()

def visualize_training_groups():
    df = load_data('train.csv')
    train_groups, test_groups = split_data(df, 0.8)

    fig, axs = plt.subplots(7, 10, figsize=(40, 35))
    for index, store_axs in enumerate(axs):
        for index2, product_ax in enumerate(store_axs):
            X = train_groups[(index, index2)]
            X = X.drop(["store", "product"], axis=1).values
            X = [item for sublist in X for item in sublist]
            product_ax.plot(X, linewidth=0.5)
            product_ax.set_yticks([min(X), max(X)])
            if index == 6:
                product_ax.set_xticks([0, len(X)])
            else:
                product_ax.set_xticks([])
            product_ax.tick_params(labelsize=6)

    for index, ax in enumerate(axs[0]):
        ax.set_title(f"Product {index}")

    for index, ax in enumerate(axs[:, 0]):
        ax.set_ylabel(f"Store {index}", rotation=0, size='large', labelpad=20)

    plt.subplots_adjust(wspace=0.65, hspace=0.3)
    # fig.tight_layout()
    plt.show()

def visualise_prediction():
    model_name = 'Model lb=10, lr=0.0001, hs=128, epochs=500, tr=0.67, bs=64, nl=1.pt'  #
    model = torch.load('saved_models/' + model_name)  # load your model here
    model.eval()

    model_name_adpt = model_name.split('Model ')[1].split('.pt')[0]
    parameters = model_name_adpt.split(", ")
    par_dict = {par.split('=')[0]: float(par.split('=')[1]) for par in parameters}

    lookback = int(par_dict['lb'])
    train_test_ratio = par_dict['tr']
    batch_size = 1

    df = load_data('train.csv')

    scaler = MinMaxScaler(feature_range=(0, 1))
    scaler = scaler.fit(df[['number_sold']])
    value_column = scaler.transform(df[['number_sold']])
    df['number_sold'] = value_column

    train_groups, test_groups = split_data(df, train_test_ratio)
    test_features, test_targets = create_rolling_windows(test_groups, lookback, 5)

    index = np.random.randint(0, len(test_features), 1)
    index = [2400]
    print(index)

    feature, target = torch.Tensor(test_features[index]), torch.Tensor(test_targets[index])
    # print(f'Feature {feature}')
    # print(target)
    predictions = []
    #  Predict 5 time steps
    for i in range(5):
        pred_value = model(feature)
        predictions.append(pred_value)
        feat_list = feature.tolist()[0]
        feat_list.pop(0)
        feat_list.append(pred_value.tolist())
        feature = torch.tensor([feat_list])

    fig, ax = plt.subplots()
    with torch.no_grad():
        ax.plot(range(lookback), test_features[index].tolist()[0], color='blue')
        ax.plot(range(lookback, lookback + 5), predictions, color='red')
        ax.plot(range(lookback, lookback + 5), test_targets[index].tolist()[0], color='green', linestyle='dotted')

    plt.show()

if __name__ == "__main__":
    #visualise_data()
    #visualize_training_groups()
    visualise_prediction()


import pathlib
import re
import string

import nltk
import pandas as pd
from nltk.corpus import stopwords
from sklearn import neighbors

from src.configs import KAGGLE_DATASET_LOCATION, ENGLISH_LVLS, WORDS_WITH_LVLS_FOLDER
from src.load_data import load_txt_to_list_of_lines

def get_song_words(song_text: str):
    words = song_text.split()

    # приводим слова к "базовой" форме
    wnl = nltk.stem.WordNetLemmatizer()
    words = map(lambda word: wnl.lemmatize(word), words)

    # оставляем только валидные английские слова
    text_vocab = set(word for word in words if word.isalpha())
    english_vocab = set(word.lower() for word in nltk.corpus.words.words())
    valid_words = text_vocab & english_vocab

    # удаляем предлоги, местоимения и тд
    stop_words = stopwords.words()
    words = filter(lambda word: word not in stop_words, valid_words)

    words = pd.DataFrame(words)
    words.set_index(0, drop=True, inplace=True)

    return pd.DataFrame(words)

def get_manual_dataset():
    manual_dataset = {}

    for lvl in ENGLISH_LVLS:
        for number in [1, 2]:
            path = WORDS_WITH_LVLS_FOLDER / f'{lvl}{number}_слова.txt'
            words = load_txt_to_list_of_lines(path)

            # берем только первые 100 слов для сбалансированного датасета
            for word in words[:100]:
                # к сожалению, словосочетания не получится учитывать
                if len(word.split()) > 1:
                    continue
                word = word.lower()
                manual_dataset[word.lower()] = {
                    'lvl': lvl
                }

    manual_dataset = pd.DataFrame.from_dict(manual_dataset)
    manual_dataset = manual_dataset.transpose()

    return manual_dataset

def create_count_column(df_to_update: pd.DataFrame, kaggle_dataset: pd.DataFrame):
    not_intersecting = set(df_to_update.index) - set(kaggle_dataset.index)
    df_to_update.drop(not_intersecting, axis=0, inplace=True)
    df_to_update['count'] = kaggle_dataset.loc[df_to_update.index]['count']

def get_words_based_estimation(song_text: str) -> str:
    kaggle_dataset = pd.read_csv(KAGGLE_DATASET_LOCATION, index_col=0, header=0)

    # подгружаем вручную размеченный датасет
    manual_dataset = get_manual_dataset()
    create_count_column(manual_dataset, kaggle_dataset)

    # подготовка тренировочного датасета
    x = pd.DataFrame(manual_dataset['count'])
    y = manual_dataset['lvl']

    # обучение модели
    classifier = neighbors.KNeighborsClassifier(15)
    classifier.fit(x, y)

    # подгружаем и обрабатываем трек
    song_words = get_song_words(song_text)
    create_count_column(song_words, kaggle_dataset)

    song_words['lvl'] = classifier.predict(song_words)
    table = song_words['lvl'].value_counts() / len(song_words)

    # границы счета вычисляются эмпирически (после экспериментов)
    score = table['B'] + table['C'] * 2

    if score > 0.50:
        return 'C'

    if score > 0.35:
        return 'B'

    return 'A'


from django.urls import path, include
from .views import home,base,acceso, Reserva,huesped,cliente, agendar, index, listarCliente, listarHuesped, funcionario, listarFuncionarios, modificarCliente, modificarHuesped,calcularTarifa, base2, nosotros, estadia, listaReserva, modificarReservas, vacunas, listar_vacunas, modificarVacuna
from django.contrib.auth.decorators import login_required

urlpatterns = [
    path('', index, name="index"),
    path('acceso/', login_required (acceso), name="acceso"),
    path('reserva/', login_required (Reserva), name="reserva"),
    path('huesped/', login_required(huesped), name="huesped"),
    path('cliente/', login_required(cliente), name="cliente"),
    path('base/', login_required(base), name='base'),
    path('agenda/', login_required (agendar), name='agenda'),
    path('home/', login_required(home), name='home'),
    path('listar/', login_required(listarCliente), name='listar'),
    path('listarHuesped/', login_required(listarHuesped), name='listarHuesped'),
    path('funcionario/', login_required(funcionario), name='funcionario'),
    path('listarFuncionarios/', login_required(listarFuncionarios), name='listarFuncionarios'),
    path('modificarCliente/<id>/', login_required(modificarCliente), name='modificarCliente'),
    path('modificarHuesped/<id>/', login_required(modificarHuesped), name='modificarHuesped'),
    path('calcular_tarifa/', login_required(calcularTarifa), name='calcular_tarifa'),
    path('resultado/', login_required(calcularTarifa), name='resultado'),
    path('nosotros/', nosotros, name='nosotros'),
    path('base2/',base2, name='base2'),
    path('estadia/', login_required(estadia), name='estadia'),
    path('lista_reserva/', login_required(listaReserva), name='lista_reserva'),
    path('modificarReserva/<id>/', login_required(modificarReservas), name='modificarReserva'),
    path('vacuna/', login_required(vacunas), name='vacuna'),
    path('listar_vacuna/', login_required(listar_vacunas), name='listar_vacuna'),
    path('modificarVacuna/<id>/', login_required(modificarVacuna), name='modificarVacuna'),

    ]


from django.contrib.auth.models import AbstractUser
from django.db import models

GENDER_CHOICES = [
    ['male', u"Мужской"],
    ['female', u"Женский"],
]

REL_CHOICES = [
    ['none', u"Не определенно"],
    ['single', u"Холост"],
    ['in_a_rel', u"В отношениях"],
    ['engaged', u"Помолвлен(а)"],
    ['married', u"Женат/Замужем"],
    ['in_love', u"Влюблен(а)"],
    ['complicated', u"Все сложно"],
]

class UserNet(AbstractUser):
    """Custom user model"""

    first_login = models.DateTimeField(verbose_name='Первый вход', auto_now=True)
    phone = models.CharField(verbose_name='Номер телефона', max_length=20)
    avatar = models.ImageField(verbose_name='Фото пользователя', null=False, upload_to='resource')

    bio = models.TextField(max_length=500, blank=True, null=True, verbose_name=u"О себе")
    city = models.CharField(max_length=30, blank=True, null=True, verbose_name=u"Город")
    birth_date = models.DateField(null=True, blank=True, verbose_name=u"Дата рождения")
    gender = models.CharField(max_length=10, verbose_name=u"Пол", choices=GENDER_CHOICES, default="male")
    relationship = models.CharField(max_length=20, verbose_name=u"Статус отношений", choices=REL_CHOICES, default="none")

    class Meta:
        verbose_name = "Юзер"
        verbose_name_plural = "Юзеры"


import martian
import cellranger.preflight as cr_preflight

__MRO__ = """
stage SPACERANGER_PREFLIGHT_LOCAL(
    in map[]  sample_def,
    in string chemistry_name,
    in map    custom_chemistry_def,
    in path   reference_path,
    in bool   check_executables,
    in int    recovered_cells,
    in int    force_cells,
    in string[] allowed_chems,
    in int    r1_length,
    in int    r2_length,
    in path   tissue_image_path,
    in path   loupe_alignment_file,
    in gpr    gpr_file,
    in string slide_serial_capture_area,
    src py    "stages/common/spaceranger_preflight",
)
"""

def run_preflight_checks(args):
    cr_preflight.check_sample_info(args.sample_def, args.reference_path)
    cr_preflight.check_common_preflights(args.reference_path,
                            args.chemistry_name, args.custom_chemistry_def, args.allowed_chems,
                            args.r1_length, args.r2_length, args.check_executables,
                            args.recovered_cells, args.force_cells)
    cr_preflight.check_spatial_arguments(args.tissue_image_path,
                                         args.loupe_alignment_file,
                                         args.gpr_file,
                                         args.slide_serial_capture_area
                                         )
    cr_preflight.check_image_open(args.tissue_image_path, args.loupe_alignment_file)

def main(args, outs):
    try:
        run_preflight_checks(args)
    except cr_preflight.PreflightException as e:
        martian.exit(e.msg)

    cr_preflight.record_package_versions()


"""A parser for HCL2 implemented using the Lark parser"""
from pathlib import Path

from lark import Lark

PARSER_FILE = Path(__file__).absolute().resolve().parent / ".lark_cache.bin"

hcl2 = Lark.open(
    "hcl2.lark",
    parser="lalr",
    cache=str(PARSER_FILE),  # Disable/Delete file to effect changes to the grammar
    rel_to=__file__,
    propagate_positions=True,
)


from urequests import request
from models import LightState
import secrets
import config

def fetch_state():
    response = request("GET", secrets.api_endpoint + "states/" + config.entity_id, headers={
        "Authorization": "Bearer " + secrets.api_token,
    })

    if (response.status_code > 200):
        print("Failed to fetch recent state, error code: " + str(response.status_code))
        response.close()
        return None
    response_state = response.json()
    response.close()
    light_state = LightState(
        state=response_state["state"] == 'on',
        brightness = response_state["attributes"]["brightness"] if "brightness" in response_state["attributes"] else 100,
        color_temp = response_state["attributes"]["color_temp"] if "color_temp" in response_state["attributes"] else 300,
    )
    return light_state

def turn_on(toast_print):
    toast_print("Turning on")
    data = {"entity_id": config.entity_id}
    response = request("POST", secrets.api_endpoint + "services/light/turn_on", headers={
        "Authorization": "Bearer " + secrets.api_token,
    }, json=data)
    response.close()

def update_state(state, toast_print, busy_pin = None):
    toast_print("Applying")
    data = {"entity_id": config.entity_id} if not state.state else {
        "entity_id": config.entity_id,
        "brightness": state.brightness.value,
        "color_temp": state.color_temp.value,
    }
    if busy_pin is not None:
        busy_pin.on()
    response = request("POST", secrets.api_endpoint + "services/light/" + ("turn_on" if state.state else "turn_off"), headers={
        "Authorization": "Bearer " + secrets.api_token,
    }, json=data)
    print("Update response code: " + str(response.status_code))
    toast_print("Updated (" + str(response.status_code) + ")", True)
    response.close()
    if busy_pin is not None:
        busy_pin.off()


import pathlib
import shutil
import sys
import os

from recipes.common import execute, tell_user, HOME, SCRIPT_PATH
from recipes.ohmyzsh import setup_oh_my_zsh
from recipes.pyenv import install_pyenv
from recipes.kitty import setup_kitty_term
from recipes.node import setup_node_npm_n
from recipes.spaceship import install_spaceship_prompt
from recipes.fonts import install_fonts

VSCODE_GPG_KEY_CMD = """
sudo sh -c 'echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/vscode.repo'
"""

PKGS_TO_INSTALL = [
    "zlib-devel",
    "bzip2",
    "bzip2-devel",
    "readline-devel",
    "sqlite",
    "sqlite-devel",
    "openssl-devel",
    "xz",
    "xz-devel",
    "libffi-devel",
    "python3-devel",
    "zsh",
    "util-linux-user",
    "golang",
    "powerline-fonts",
    "nvim",
    "kitty",
    "flameshot",
    "npm",
    "libpq-devel",
    "protobuf-compiler",
]

def install_base_pkgs(pkgs=None):
    """Install basic system packages (dev headers, tools, lang compilers, etc.)"""
    if not pkgs:
        pkgs = PKGS_TO_INSTALL
    tell_user("Going to install base pkgs...")
    execute(f"sudo dnf install -y {' '.join(pkg for pkg in pkgs)}")

def install_vs_code():
    """Import Microsoft vscode gpg key, adds microsoft repository and then install vscode."""
    tell_user("Going to install vscode...")
    tell_user("Importing vscode repo...")
    execute("sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc")
    tell_user("Adding Microsoft vscode gpg key...")
    execute(VSCODE_GPG_KEY_CMD)
    tell_user("Going to install vscode...")
    execute("sudo dnf install -y code")

def setup_fisa_vim():
    """Setup fisa vim."""
    tell_user("Going to install fisa vim deps...")
    fisa_requirements = [
        "ctags-etags",
        "python3-flake8",
        "python3-pylint",
        "python3-isort",
    ]
    execute(f"sudo dnf install -y {' '.join(pkg for pkg in fisa_requirements)}")
    execute("pip3 install --user pynvim")

    nvim_dir = f"{HOME}/.config/nvim"
    tell_user("Downloading fisa vim config...")
    if not os.path.isdir(f"{nvim_dir}"):
        os.makedirs(f"{nvim_dir}")
    execute(
        f"wget -O {nvim_dir}/init.vim https://raw.github.com/fisadev/fisa-vim-config/master/config.vim"
    )

def setup_golang():
    gohome = f"{HOME}/Code/go"
    pathlib.Path(gohome).mkdir(parents=True, exist_ok=True)
    with open(f"{HOME}/.zshrc", "a") as zshrc:
        zshrc.write("\n")
        zshrc.write("# Fedora restore :: setup GOHOME\n")
        zshrc.write(f'export GOPATH="{gohome}"\n')
        zshrc.write(f'export PATH="$PATH:$GOPATH/bin"\n')
        zshrc.write(f'export GO111MODULE="auto"\n')

    tell_user("Downloading protoc golang plugin...")
    execute("go get -u github.com/golang/protobuf/protoc-gen-go")


import util
from collections import defaultdict
from itertools import pairwise

grid = defaultdict(int)

lines = util.read_lines("inputs/day14.txt")

max_rock_y = 0
for line in lines:
    ints = util.extract_ints(line)
    coords = [(ints[i], ints[i+1]) for i in range(0, len(ints), 2)]
    for a, b in pairwise(coords):
        from_x, to_x = min(a[0], b[0]), max(a[0], b[0])
        from_y, to_y = min(a[1], b[1]), max(a[1], b[1])
        max_rock_y = max(max_rock_y, to_y)
        for x in range(from_x, to_x+1):
            for y in range(from_y, to_y+1):
                grid[(x, y)] = 1

ans = 0
sand_pos = (500, 0)
while True:
    if grid[(500, 0)] == 1:
        break

    if sand_pos[1] < max_rock_y + 1:
        test_pos = (sand_pos[0], sand_pos[1] + 1)
        if grid[test_pos] == 0:
            sand_pos = test_pos
            continue
        test_pos = (sand_pos[0] - 1, sand_pos[1] + 1)
        if grid[test_pos] == 0:
            sand_pos = test_pos
            continue
        test_pos = (sand_pos[0] + 1, sand_pos[1] + 1)
        if grid[test_pos] == 0:
            sand_pos = test_pos
            continue

    grid[sand_pos] = 1
    ans += 1
    sand_pos = (500, 0)

print(ans)


# Solution 1 directly from the solutions of leetcode---> O(n)T | O(n)S

def isValid(s):

    # The stack to keep track of opening brackets.
    stack = []
    # Hash map for keeping track of mappings. This keeps the code very clean.
    # Also makes adding more types of parenthesis easier
    parantheses_map = {')':'(', ']':'[', '}':'{'}
    # s instead of range(len(s)) because we wanna go through the value of s not the index. This always gets me confused lol.
    # For every bracket in the expression.
    for i in s:
        # If the character is a closing bracket, i.e., key of the dict
        if i in parantheses_map:
            # Pop the topmost element from the stack, if it is non empty... this means you are popping off one matching opening parantheses.
            # Otherwise assign a dummy value of '#' to the top_element variable
            top_element = stack.pop() if stack else '#'

            # The mapping for the opening bracket in our hash and the top
            # element of the stack don't match, return False
            if parantheses_map[i] != top_element:
                return False

        # We have an opening bracket, simply push it onto the stack.
        else:
            stack.append(i)
    # In the end, if the stack is empty, then we have a valid expression.
    # The stack won't be empty for cases like ((()
    return not stack

# Adding my own solution 2---> O(n)T | O(n)S
def isValid_2(s):
    stack = []
    parantheses_map = {'(':')', '[':']', '{':'}'}
    for i in s:
        # if it is opening bracket, then append it to stack
        if (i in parantheses_map):
            stack.append(i)
        # otherwise if it's closing bracket, then we check the stack for matching opening bracket or if it being empty
        elif(len(stack) == 0 or parantheses_map[stack.pop()] != i):
            return False
    # checking if the stack is empty or not
    return (len(stack)==0)

# copied from leetcode for the sole reason of the runtime speed. This a very nice solution.
def isValid_3(s):
        stack = []
        if len(s) == 1:
            return False

        for character in s:
            if character == '(' or character == '[' or character == '{':
                stack.append(character)

            elif len(stack) == 0:
                return False

            elif character == ')':
                poppedCharacter = stack.pop()
                if poppedCharacter != '(':
                    return False

            elif character == '}':
                poppedCharacter = stack.pop()
                if poppedCharacter != '{':
                    return False

            elif character == ']':
                poppedCharacter = stack.pop()
                if poppedCharacter != '[':
                    return False

        return len(stack) == 0

strTest = "()[]{}"
print(isValid(strTest))
print(isValid_2(strTest))
print(isValid_3(strTest))


from __future__ import (
    absolute_import,
    unicode_literals,
    with_statement,
)

__all__ = [
    'DoctestReviewer',
]

import _ast
import os
import re
import sys
from difflib import unified_diff
from doctest import DocTestParser, Example
from optparse import OptionParser
from textwrap import wrap

from pocketlint.reporter import Reporter
try:
    from pyflakes.checker import Checker as PyFlakesChecker
    PyFlakesChecker
except ImportError:
    from pocketlint import PyFlakesChecker

class DoctestReviewer(object):
    """Check and reformat doctests."""
    rule_pattern = re.compile(r'([=~-])+[ ]*$')
    moin_pattern = re.compile(r'^(=+)[ ](.+)[ ](=+[ ]*)$')

    SOURCE = 'source'
    WANT = 'want'
    NARRATIVE = 'narrative'

    def __init__(self, file_path, doctest, reporter=None, options=None):
        self.doctest = doctest
        self.file_path = file_path
        self.base_dir = os.path.dirname(file_path)
        self.file_name = os.path.basename(file_path)
        self.blocks = []
        self.block = []
        self.block_method = self.preserve_block
        self.code_lines = []
        self.example = None
        self.last_bad_indent = 0
        self.has_printed_filename = False
        self._reporter = reporter or Reporter(Reporter.CONSOLE)
        self.options = options

    def get_parts(self):
        parser = DocTestParser()
        try:
            return parser.parse(self.doctest, self.file_path)
        except ValueError as error:
            # Output code without unicode literals needs to be normalised
            # largely for the test suite, and somewhat for the person reading
            # message.
            message = str(error).replace("u'", "'")
            self._print_message(message, 0)
            return []

    def _print_message(self, message, lineno):
        """Print the error message with the lineno.

        :param message: The message to print.
        :param lineno: The line number the message pertains to.
        """
        self._reporter(
            int(lineno), message,
            base_dir=self.base_dir, file_name=self.file_name)

    def _is_formatted(self, text):
        """Return True if the text is pre-formatted, otherwise False.

        :param: text a string, or a list of strings.
        """
        if isinstance(text, list):
            text = text[0]
        return text.startswith(' ')

    def _walk(self, doctest_parts):
        """Walk the doctest parts; yield the line and kind.

        Yield the content of the line, and its kind (SOURCE, WANT, NARRATIVE).
        SOURCE and WANT lines are stripped of indentation, SOURCE is also
        stripped of the interpreter symbols.

        :param doctest_parts: The output of DocTestParser.parse.
        """
        for part in doctest_parts:
            if part == '':
                continue
            if isinstance(part, Example):
                self.example = part
                for line in part.source.splitlines():
                    kind = DoctestReviewer.SOURCE
                    yield line, kind
                for line in part.want.splitlines():
                    kind = DoctestReviewer.WANT
                    yield line, kind
            else:
                self.example = None
                kind = DoctestReviewer.NARRATIVE
                for line in part.splitlines():
                    yield line, kind

    def _apply(self, line_methods):
        """Call each line_method for each line in the doctest.

        :param line_methods: a list of methods that accept lineno, line,
            and kind as arguments. Each method must return the line for
            the next method to process.
        """
        self.blocks = []
        self.block = []
        lineno = 0
        previous_kind = DoctestReviewer.NARRATIVE
        for line, kind in self._walk(self.get_parts()):
            lineno += 1
            # Some method could check if the line number is one that
            # is skipped by doctest parser and increment the number again.
            # line probably needs to get a \n add to it too.
            self._append_source(kind, line)
            if kind != previous_kind and kind != DoctestReviewer.WANT:
                # The WANT block must adjoin the preceding SOURCE block.
                self._store_block(previous_kind)
            for method in line_methods:
                line = method(lineno, line, kind, previous_kind)
                if line is None:
                    break
            if not line:
                continue
            self.block.append(line)
            previous_kind = kind
        # Capture the last block and a blank line.
        self.block.append('\n')
        self._store_block(previous_kind)

    def _append_source(self, kind, line):
        """Update the list of source code lines seen."""
        if kind == self.SOURCE:
            self.code_lines.append(line)
        else:
            self.code_lines.append('')

    def _store_block(self, kind):
        """Append the block to blocks, re-wrap unformatted narrative.

        :param kind: The block's kind (SOURCE, WANT, NARRATIVE)
        """
        if len(self.block) == 0:
            return
        block = self.block_method(kind, self.block, self.blocks)
        self.blocks.append('\n'.join(block))
        self.block = []

    def check(self):
        """Check the doctest for style and code issues.

        1. Check line lengths.
        2. Check that headings are not in Moin format.
        3. Check indentation.
        4. Check trailing whitespace.
        """
        self.code_lines = []
        self.last_bad_indent = 0
        self.block_method = self.preserve_block
        self.example = None
        self.has_printed_filename = False
        self.check_source_comments()
        line_checkers = [
            self.check_length,
            self.check_heading,
            self.check_indentation,
            self.check_trailing_whitespace,
        ]
        self._apply(line_checkers)
        code = '\n'.join(self.code_lines)
        self.check_source_code(code)

    def format(self):
        """Reformat doctest.

        1. Tests are reindented to 4 spaces.
        2. Simple narrative is rewrapped to 78 character width.
        3. Formatted (indented) narrative is preserved.
        4. Moin headings are converted to RSR =, == , and === levels.
        5. There is one blank line between blocks,
        6. Except for headers which have two leading blank lines.
        7. All trailing whitespace is removed.

        SOURCE and WANT long lines are not fixed--this is a human operation.
        """
        self.code_lines = []
        line_checkers = [
            self.fix_trailing_whitespace,
            self.fix_indentation,
            self.fix_heading,
            self.fix_narrative_paragraph,
        ]
        self.block_method = self.format_block
        self._apply(line_checkers)
        self.block_method = self.preserve_block
        return '\n\n'.join(self.blocks)

    def preserve_block(self, kind, block, blocks):
        """Do nothing to the block.

        :param kind: The block's kind (SOURCE, WANT, NARRATIVE)
        :param block: The list of lines that should remain together.
        :param blocks: The list of all collected blocks.
        """
        return block

    def format_block(self, kind, block, blocks):
        """Format paragraph blocks.

        :param kind: The block's kind (SOURCE, WANT, NARRATIVE)
        :param block: The list of lines that should remain together.
        :param blocks: The list of all collected blocks.
        """
        if kind != DoctestReviewer.NARRATIVE or self._is_formatted(block):
            return block
        try:
            rules = ('===', '---', '...')
            last_line = block[-1]
            is_heading = last_line[0:3] in rules and last_line[-3:] in rules
        except IndexError:
            is_heading = False
        if len(blocks) != 0 and is_heading:
            # Headings should have an extra leading blank line.
            block.insert(0, '')
        elif is_heading:
            # Do nothing. This is the first heading in the file.
            pass
        else:
            long_line = ' '.join(block).strip()
            block = wrap(long_line, 72)
        return block

    def check_source_comments(self):
        """Comments are not appropiate in source examples."""
        for lineno, line in enumerate(self.doctest.splitlines()):
            if '>>> #' in line or '... #' in line:
                self._print_message(
                    'Comment belongs in narrative.', lineno + 1)

    def is_code_comment(self, line):
        """Return True if the line is a code comment."""
        comment_pattern = re.compile(r'^\s+#')
        return comment_pattern.match(line) is not None

    def check_length(self, lineno, line, kind, previous_kind):
        """Check the length of the line.

        Each kind of line has a maximum length:

        * NARRATIVE: 78 characters.
        * SOURCE: 70 characters (discounting indentation and interpreter).
        * WANT: 74 characters (discounting indentation).
        """
        if kind == DoctestReviewer.NARRATIVE and self.is_code_comment(line):
            # comments follow WANT rules because they are in code.
            kind = DoctestReviewer.WANT
            line = line.lstrip()
        length = len(line)
        if kind == DoctestReviewer.NARRATIVE and length > 78:
            self._print_message('%s exceeds 78 characters.' % kind, lineno)
        elif kind == DoctestReviewer.WANT and length > 74:
            self._print_message('%s exceeds 78 characters.' % kind, lineno)
        elif kind == DoctestReviewer.SOURCE and length > 70:
            self._print_message('%s exceeds 78 characters.' % kind, lineno)
        else:
            # This line has a good length.
            pass
        return line

    def check_indentation(self, lineno, line, kind, previous_kind):
        """Check the indentation of the SOURCE or WANT line."""
        if kind == DoctestReviewer.NARRATIVE:
            return line
        if self.example.indent != 4:
            if self.last_bad_indent != lineno - 1:
                self._print_message('%s has bad indentation.' % kind, lineno)
            self.last_bad_indent = lineno
        return line

    def check_trailing_whitespace(self, lineno, line, kind, previous_kind):
        """Check for the presence of trailing whitespace in the line."""
        if line.endswith(' '):
            self._print_message('%s has trailing whitespace.' % kind, lineno)
        return line

    def check_heading(self, lineno, line, kind, previous_kind):
        """Check for narrative lines that use moin headers instead of RST."""
        if kind != DoctestReviewer.NARRATIVE:
            return line
        moin = self.moin_pattern.match(line)
        if moin is not None:
            self._print_message('%s uses a moin header.' % kind, lineno)
        return line

    def check_source_code(self, code):
        """Check for source code problems in the doctest using pyflakes.

        The most common problem found are unused imports. `UndefinedName`
        errors are suppressed because the test setup is not known.
        """
        if code == '':
            return
        try:
            tree = compile(
                code, self.file_path, "exec", _ast.PyCF_ONLY_AST)
        except (SyntaxError, IndentationError) as exc:
            lineno = exc.lineno or 0
            line = exc.text or ''
            if line.endswith("\n"):
                line = line[:-1]
            self._print_message(
                'Could not compile:\n    %s' % line, lineno)
        else:
            warnings = PyFlakesChecker(tree)
            for warning in warnings.messages:
                if 'undefined name ' in str(warning):
                    continue
                dummy, lineno, message = str(warning).split(':')
                self._print_message(message.strip(), lineno)

    def fix_trailing_whitespace(self, lineno, line, kind, previous_kind):
        """Return the line striped of trailing whitespace."""
        return line.rstrip()

    def fix_indentation(self, lineno, line, kind, previous_kind):
        """set the indentation to 4-spaces."""
        if kind == DoctestReviewer.NARRATIVE:
            return line
        elif kind == DoctestReviewer.WANT:
            return '    %s' % line
        else:
            if line.startswith(' '):
                # This is a continuation of DoctestReviewer.SOURCE.
                return '    ... %s' % line
            else:
                # This is a start of DoctestReviewer.SOURCE.
                return '    >>> %s' % line

    def fix_heading(self, lineno, line, kind, previous_kind):
        """Switch Moin headings to RST headings."""
        if kind != DoctestReviewer.NARRATIVE:
            return line
        moin = self.moin_pattern.match(line)
        if moin is None:
            return line
        heading_level = len(moin.group(1))
        heading = moin.group(2)
        rule_length = len(heading)
        if heading_level == 1:
            rule = '=' * rule_length
        elif heading_level == 2:
            rule = '-' * rule_length
        else:
            rule = '.' * rule_length
        # Force the heading on to the block of lines.
        self.block.append(heading)
        return rule

    def fix_narrative_paragraph(self, lineno, line, kind, previous_kind):
        """Break narrative into paragraphs."""
        if kind != DoctestReviewer.NARRATIVE or len(self.block) == 0:
            return line
        if line == '':
            # This is the start of a new paragraph in the narrative.
            self._store_block(previous_kind)
        if self._is_formatted(line) and not self._is_formatted(self.block):
            # This line starts a pre-formatted paragraph.
            self._store_block(previous_kind)
        return line

    def format_and_save(self, is_interactive=False):
        new_doctest = self.format()
        if new_doctest != self.doctest:
            if is_interactive:
                diff = unified_diff(
                    self.doctest.splitlines(), new_doctest.splitlines())
                sys.stdout.write('\n'.join(diff))
                sys.stdout.write('\n\n')
                if sys.version_info >= (3,):
                    user_input = input
                else:
                    user_input = raw_input
                do_save = user_input(
                    'Do you wish to save the changes? S(ave) or C(ancel)?')
            else:
                do_save = 'S'
            self.doctest = new_doctest
            if do_save.upper() == 'S':
                with open(self.file_path, 'wt') as doctest_file:
                    doctest_file.write(new_doctest)

def get_option_parser():
    """Return the option parser for this program."""
    usage = "usage: %prog [options] doctest.txt"
    parser = OptionParser(usage=usage)
    parser.add_option(
        "-f", "--format", dest="is_format", action="store_true",
        help="Reformat the doctest.")
    parser.add_option(
        "-i", "--interactive", dest="is_interactive", action="store_true",
        help="Approve each change.")
    parser.set_defaults(
        is_format=False,
        is_interactive=False)
    return parser

def main(argv=None):
    """Run the operations requested from the command line."""
    if argv is None:
        argv = sys.argv
    parser = get_option_parser()
    (options, args) = parser.parse_args(args=argv[1:])
    if len(args) == 0:
        parser.error("A doctest must be specified.")

    for file_path in args:
        with open(file_path) as doctest_file:
            doctest_data = doctest_file.read().decode('utf-8')
        reviewer = DoctestReviewer(file_path, doctest_data)
        if options.is_format:
            reviewer.format_and_save()
        reviewer.check()

if __name__ == '__main__':
    sys.exit(main())


import pytest
from test_data.request_test_data import create_test_request, example_requests
from test_data.tree_decomposition_test_data import (
    create_test_tree_decomposition,
    VALID_TREE_DECOMPOSITIONS,
    INVALID_TREE_DECOMPOSITION_INTERSECTION_PROPERTY,
    INVALID_TREE_DECOMPOSITIONS_NOT_A_TREE,
    INVALID_TREE_DECOMPOSITIONS,
    POST_ORDER_TRAVERSALS,
    CHECK_COMPATIBLE_MAPPINGS_VALID_EXAMPLES,
    CHECK_COMPATIBLE_MAPPINGS_INVALID_EXAMPLES,
    NICE_TREE_DECOMPOSITIONS,
)
from vnep_approx import treewidth_model

@pytest.mark.parametrize("request_id",
                         example_requests)
def test_trivial_decomposition_is_always_valid(request_id):
    req = create_test_request(request_id)
    tree_decomp = treewidth_model.TreeDecomposition("test")
    tree_decomp.add_node("bag_1", frozenset(req.nodes))
    assert tree_decomp.is_tree_decomposition(req)

@pytest.mark.parametrize("request_id",
                         VALID_TREE_DECOMPOSITIONS)
def test_hardcoded_decompositions_are_valid(request_id):
    req = create_test_request(request_id=request_id)
    tree_decomp = create_test_tree_decomposition(VALID_TREE_DECOMPOSITIONS[request_id])
    assert tree_decomp.is_tree_decomposition(req)

# @pytest.mark.parametrize("request_id",
#                          NICE_TREE_DECOMPOSITIONS)
# def test_nice_tree_decompositions_are_recognized(request_id):
#     req = create_test_request(request_id=request_id)
#     tree_decomp = create_test_tree_decomposition(NICE_TREE_DECOMPOSITIONS[request_id])
#     arborescence = tree_decomp.convert_to_arborescence(NICE_TREE_DECOMPOSITIONS[request_id]["root"])
#
#     assert tree_decomp.is_tree_decomposition(req)
#     assert treewidth_model.is_nice_tree_decomposition(tree_decomp, arborescence)

#DEFERRED
# @pytest.mark.parametrize("request_id",
#                          ["simple path"])
# def test_nice_tree_decomposition_conversion(request_id):
#     req = create_test_request(request_id=request_id)
#
#     initial_td = treewidth_model.compute_tree_decomposition(req)
#     nice_td_generator = treewidth_model.NiceTDConversion(req, initial_td=initial_td)
#     root = sorted(initial_td.nodes)[0]
#     nice_td_generator.initialize(root=root)
#     nice_td = nice_td_generator.make_nice_tree_decomposition()
#     assert nice_td.is_tree_decomposition(req)
#     assert treewidth_model.is_nice_tree_decomposition(nice_td, nice_td.convert_to_arborescence(root))

@pytest.mark.parametrize("tree_decomposition_dict",
                         INVALID_TREE_DECOMPOSITION_INTERSECTION_PROPERTY)
def test_invalid_decompositions_intersection_property(tree_decomposition_dict):
    tree_decomp = create_test_tree_decomposition(tree_decomposition_dict)
    assert not tree_decomp._verify_intersection_property()

@pytest.mark.parametrize("tree_decomposition_dict",
                         INVALID_TREE_DECOMPOSITIONS_NOT_A_TREE)
def test_invalid_decompositions_not_a_tree(tree_decomposition_dict):
    tree_decomp = create_test_tree_decomposition(tree_decomposition_dict)
    assert not tree_decomp._is_tree()

@pytest.mark.parametrize("request_id",
                         VALID_TREE_DECOMPOSITIONS)
def test_hardcoded_decompositions_can_convert_to_arborescence(request_id):
    tree_decomp = create_test_tree_decomposition(VALID_TREE_DECOMPOSITIONS[request_id])
    arborescence = tree_decomp.convert_to_arborescence()

    # check node & edge sets
    assert arborescence.root in arborescence.nodes
    assert arborescence.nodes == tree_decomp.nodes
    for edge in arborescence.edges:
        assert frozenset(edge) in tree_decomp.edges
    for edge in tree_decomp.edges:
        t1, t2 = edge
        assert (t1, t2) in arborescence.edges or (t2, t1) in arborescence.edges

    # verify reachability from root
    q = {arborescence.root}
    visited = set()
    while q:
        t1 = q.pop()
        visited.add(t1)
        neighbors = arborescence.get_out_neighbors(t1)
        assert len(set(neighbors) & visited) <= 1  # Should be tree-like: at most one ancestor
        for t2 in neighbors:
            if t2 in visited:
                continue
            assert t2 not in q
            q.add(t2)
    return visited == set(arborescence.nodes)

@pytest.mark.parametrize("tree_decomposition_dict",
                         INVALID_TREE_DECOMPOSITIONS)
def test_converting_invalid_decomposition_to_arborescence_raises_valueerror(tree_decomposition_dict):
    tree_decomp = create_test_tree_decomposition(tree_decomposition_dict)
    with pytest.raises(ValueError):
        tree_decomp.convert_to_arborescence()

@pytest.mark.parametrize("traversal",
                         POST_ORDER_TRAVERSALS)
def test_post_order_traversal(traversal):
    tree_decomp = create_test_tree_decomposition(VALID_TREE_DECOMPOSITIONS[traversal["request_id"]])
    arborescence = tree_decomp.convert_to_arborescence(root=traversal["root"])

    assert list(arborescence.post_order_traversal()) == traversal["order"]

@pytest.mark.parametrize("mapping_pair_tuple",
                         CHECK_COMPATIBLE_MAPPINGS_VALID_EXAMPLES)
def test_check_compatible_mappings_valid_examples(mapping_pair_tuple):
    assert treewidth_model.check_if_mappings_are_compatible(*mapping_pair_tuple)

@pytest.mark.parametrize("mapping_pair_tuple",
                         CHECK_COMPATIBLE_MAPPINGS_INVALID_EXAMPLES)
def test_check_compatible_mappings_invalid_examples(mapping_pair_tuple):
    assert not treewidth_model.check_if_mappings_are_compatible(*mapping_pair_tuple)


import ctypes
import numpy as np
import tvm._ffi

from tvm._ffi.base import _LIB, check_call, c_array, string_types, _FFI_MODE
from tvm._ffi.runtime_ctypes import DataType, TVMContext, TVMArray, TVMArrayHandle
from tvm._ffi.runtime_ctypes import DataTypeCode, tvm_shape_index_t

try:
    # pylint: disable=wrong-import-position
    if _FFI_MODE == "ctypes":
        raise ImportError()
    from tvm._ffi._cy3.core import _set_class_ndarray, _make_array, _from_dlpack
    from tvm._ffi._cy3.core import NDArrayBase
except (RuntimeError, ImportError):
    # pylint: disable=wrong-import-position
    from tvm._ffi._ctypes.ndarray import _set_class_ndarray, _make_array, _from_dlpack
    from tvm._ffi._ctypes.ndarray import NDArrayBase

@tvm._ffi.register_object("runtime.NDArray")
class NDArray(NDArrayBase):
    """Lightweight NDArray class of TVM runtime.

    Strictly this is only an Array Container (a buffer object)
    No arthimetic operations are defined.
    All operations are performed by TVM functions.

    The goal is not to re-build yet another array library.
    Instead, this is a minimal data structure to demonstrate
    how can we use TVM in existing project which might have their own array containers.
    """

    @property
    def dtype(self):
        """Type of this array"""
        return str(self.handle.contents.dtype)

    @property
    def ctx(self):
        """context of this array"""
        return self.handle.contents.ctx

    @property
    def context(self):
        """context of this array"""
        return self.ctx

    def __hash__(self):
        return ctypes.cast(self.handle, ctypes.c_void_p).value

    def __eq__(self, other):
        return self.same_as(other)

    def __ne__(self, other):
        return not self.__eq__(other)

    def same_as(self, other):
        """Check object identity equality

        Parameters
        ----------
        other : object
            The other object to compare to

        Returns
        -------
        same : bool
            Whether other is same as self.
        """
        if not isinstance(other, NDArrayBase):
            return False
        return self.__hash__() == other.__hash__()

    def __setitem__(self, in_slice, value):
        """Set ndarray value"""
        if (
            not isinstance(in_slice, slice)
            or in_slice.start is not None
            or in_slice.stop is not None
        ):
            raise ValueError("Array only support set from numpy array")
        if isinstance(value, NDArrayBase):
            if value.handle is not self.handle:
                value.copyto(self)
        elif isinstance(value, (np.ndarray, np.generic)):
            self.copyfrom(value)
        else:
            raise TypeError("type %s not supported" % str(type(value)))

    def copyfrom(self, source_array):
        """Peform an synchronize copy from the array.

        Parameters
        ----------
        source_array : array_like
            The data source we should like to copy from.

        Returns
        -------
        arr : NDArray
            Reference to self.
        """
        if isinstance(source_array, NDArrayBase):
            source_array.copyto(self)
            return self

        if not isinstance(source_array, np.ndarray):
            try:
                source_array = np.array(source_array, dtype=self.dtype)
            except:
                raise TypeError(
                    "array must be an array_like data,"
                    + "type %s is not supported" % str(type(source_array))
                )

        t = DataType(self.dtype)
        shape, dtype = self.shape, self.dtype
        if t.lanes > 1:
            shape = shape + (t.lanes,)
            t.lanes = 1
            dtype = str(t)

        if source_array.shape != shape:
            raise ValueError(
                "array shape do not match the shape of NDArray {0} vs {1}".format(
                    source_array.shape, shape
                )
            )
        source_array = np.ascontiguousarray(source_array, dtype=dtype)
        assert source_array.flags["C_CONTIGUOUS"]
        data = source_array.ctypes.data_as(ctypes.c_void_p)
        nbytes = ctypes.c_size_t(source_array.size * source_array.dtype.itemsize)
        check_call(_LIB.TVMArrayCopyFromBytes(self.handle, data, nbytes))
        return self

    def __repr__(self):
        res = "<tvm.nd.NDArray shape={0}, {1}>\n".format(self.shape, self.context)
        res += self.asnumpy().__repr__()
        return res

    def __str__(self):
        return str(self.asnumpy())

    def asnumpy(self):
        """Convert this array to numpy array

        Returns
        -------
        np_arr : numpy.ndarray
            The corresponding numpy array.
        """
        t = DataType(self.dtype)
        shape, dtype = self.shape, self.dtype
        if t.lanes > 1:
            shape = shape + (t.lanes,)
            t.lanes = 1
            dtype = str(t)
        np_arr = np.empty(shape, dtype=dtype)
        assert np_arr.flags["C_CONTIGUOUS"]
        data = np_arr.ctypes.data_as(ctypes.c_void_p)
        nbytes = ctypes.c_size_t(np_arr.size * np_arr.dtype.itemsize)
        check_call(_LIB.TVMArrayCopyToBytes(self.handle, data, nbytes))
        return np_arr

    def copyto(self, target):
        """Copy array to target

        Parameters
        ----------
        target : NDArray
            The target array to be copied, must have same shape as this array.
        """
        if isinstance(target, NDArrayBase):
            return self._copyto(target)
        if isinstance(target, TVMContext):
            res = empty(self.shape, self.dtype, target)
            return self._copyto(res)
        raise ValueError("Unsupported target type %s" % str(type(target)))

def context(dev_type, dev_id=0):
    """Construct a TVM context with given device type and id.

    Parameters
    ----------
    dev_type: int or str
        The device type mask or name of the device.

    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx: tvm.runtime.TVMContext
        The corresponding context.

    Examples
    --------
    Context can be used to create reflection of context by
    string representation of the device type.

    .. code-block:: python

      assert tvm.context("cpu", 1) == tvm.cpu(1)
      assert tvm.context("gpu", 0) == tvm.gpu(0)
      assert tvm.context("cuda", 0) == tvm.gpu(0)
    """
    if isinstance(dev_type, string_types):
        if "-device=micro_dev" in dev_type:
            dev_type = TVMContext.STR2MASK["micro_dev"]
        else:
            dev_type = dev_type.split()[0]
            if dev_type not in TVMContext.STR2MASK:
                raise ValueError("Unknown device type %s" % dev_type)
            dev_type = TVMContext.STR2MASK[dev_type]
    return TVMContext(dev_type, dev_id)

def numpyasarray(np_data):
    """Return a TVMArray representation of a numpy array."""
    data = np_data
    assert data.flags["C_CONTIGUOUS"]
    arr = TVMArray()
    shape = c_array(tvm_shape_index_t, data.shape)
    arr.data = data.ctypes.data_as(ctypes.c_void_p)
    arr.shape = shape
    arr.strides = None
    arr.dtype = DataType(np.dtype(data.dtype).name)
    arr.ndim = data.ndim
    # CPU device
    arr.ctx = context(1, 0)
    return arr, shape

def empty(shape, dtype="float32", ctx=context(1, 0)):
    """Create an empty array given shape and device

    Parameters
    ----------
    shape : tuple of int
        The shape of the array

    dtype : type or str
        The data type of the array.

    ctx : TVMContext
        The context of the array

    Returns
    -------
    arr : tvm.nd.NDArray
        The array tvm supported.
    """
    shape = c_array(tvm_shape_index_t, shape)
    ndim = ctypes.c_int(len(shape))
    handle = TVMArrayHandle()
    dtype = DataType(dtype)
    check_call(
        _LIB.TVMArrayAlloc(
            shape,
            ndim,
            ctypes.c_int(dtype.type_code),
            ctypes.c_int(dtype.bits),
            ctypes.c_int(dtype.lanes),
            ctx.device_type,
            ctx.device_id,
            ctypes.byref(handle),
        )
    )
    return _make_array(handle, False, False)

def from_dlpack(dltensor):
    """Produce an array from a DLPack tensor without memory copy.
    Retreives the underlying DLPack tensor's pointer to create an array from the
    data. Removes the original DLPack tensor's destructor as now the array is
    responsible for destruction.

    Parameters
    ----------
    dltensor : DLPack tensor
        Input DLManagedTensor, can only be consumed once.

    Returns
    -------
    arr: tvm.nd.NDArray
        The array view of the tensor data.
    """
    return _from_dlpack(dltensor)

def cpu(dev_id=0):
    """Construct a CPU device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(1, dev_id)

def gpu(dev_id=0):
    """Construct a GPU device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(2, dev_id)

def rocm(dev_id=0):
    """Construct a ROCM device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(10, dev_id)

def opencl(dev_id=0):
    """Construct a OpenCL device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(4, dev_id)

def metal(dev_id=0):
    """Construct a metal device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(8, dev_id)

def vpi(dev_id=0):
    """Construct a VPI simulated device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(9, dev_id)

def vulkan(dev_id=0):
    """Construct a Vulkan device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(7, dev_id)

def ext_dev(dev_id=0):
    """Construct a extension device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context

    Note
    ----
    This API is reserved for quick testing of new
    device by plugin device API as ext_dev.
    """
    return TVMContext(12, dev_id)

def micro_dev(dev_id=0):
    """Construct a micro device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(13, dev_id)

def hexagon(dev_id=0):
    """Construct a Hexagon device

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(14, dev_id)

def webgpu(dev_id=0):
    """Construct a webgpu device.

    Parameters
    ----------
    dev_id : int, optional
        The integer device id

    Returns
    -------
    ctx : TVMContext
        The created context
    """
    return TVMContext(15, dev_id)

cl = opencl
mtl = metal

def array(arr, ctx=cpu(0)):
    """Create an array from source arr.

    Parameters
    ----------
    arr : numpy.ndarray
        The array to be copied from

    ctx : TVMContext, optional
        The device context to create the array

    Returns
    -------
    ret : NDArray
        The created array
    """
    if not isinstance(arr, (np.ndarray, NDArray)):
        arr = np.array(arr)
    return empty(arr.shape, arr.dtype, ctx).copyfrom(arr)

# Register back to FFI
_set_class_ndarray(NDArray)


# This Python file uses the following encoding: utf-8

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from timess import Ui_Time
from PyQt5.Qt import *
from PyQt5.QtCore import pyqtSignal,Qt
import datetime
import calendar

class TimePageWindow(QWidget,Ui_Time):
 #定义点击信号
    chooseSignal = pyqtSignal(str)
    current_year = datetime.datetime.now().year
    current_month = datetime.datetime.now().month
    current_day = datetime.datetime.now().day
    select_time0y = current_year
    select_time0m = current_month
    select_time0d = current_day
    select_time1y = current_year
    select_time1m = current_month
    select_time1d = current_day
    starttimes = 0
    def __init__(self,parent=None):
        super(TimePageWindow, self).__init__(parent)
        self.setupUi(self)
        self.initUI()

    def initUI(self):
        self.border.hide()
        self.select.hide()
        self.result.setStyleSheet("background:transparent;border-width:0;border-style:outset;color:black;")
        self.border.setStyleSheet("background:transparent;border:none;")
        self.init_add()
        self.selectwindow.currentIndexChanged.connect(self.showDialog)
        self.selectmodel.currentIndexChanged.connect(self.show_model)
        self.year.currentIndexChanged.connect(self.result_add)
        self.month.currentIndexChanged.connect(self.result_add)
        self.day.currentIndexChanged.connect(self.result_add)
        self.starttime.clicked.connect(lambda:self.init_select(1))
        self.endtime.clicked.connect(lambda:self.init_select(2))
        self.border.clicked.connect(lambda:self.dispper_select())
        self.add.clicked.connect(lambda:self.result_add())
        self.sub.clicked.connect(lambda:self.result_add())
        self.select.clicked.connect(lambda:self.day_click())

    def showDialog(self):
        ss = self.selectwindow.currentText()
        if ss == 'time':
 #发射点击信号
            self.chooseSignal.emit('time')
        elif ss == 'standard':
            self.chooseSignal.emit('standard')
        elif ss == 'graph':
            self.chooseSignal.emit('graph')
        elif ss == 'scientific':
            self.chooseSignal.emit('scientific')
        elif ss == 'programmer':
            self.chooseSignal.emit('programmer')

    def show_model(self):
        ss = self.selectmodel.currentText()
        if ss == 'The val between dates':
            self.init_between()
        elif ss == 'Add or subtract the number of days':
            self.init_add()

    def init_add(self):
        self.endtime.hide()
        self.endlabel.hide()
        self.rday.hide()
        self.add.show()
        self.sub.show()
        self.year.show()
        self.month.show()
        self.day.show()
        self.yearlabel.show()
        self.monthlabel.show()
        self.daylabel.show()
        self.add.setChecked(True)
        self.sub.setChecked(False)
        self.selectmodel.setCurrentIndex(1)
        self.resultlabel.setText("date")
        self.starttime.setText(self.appear_day(self.select_time0y,self.select_time0m,self.select_time0d))
        self.result_add()

    def init_between(self):
        self.endtime.show()
        self.endlabel.show()
        self.rday.show()
        self.add.hide()
        self.sub.hide()
        self.year.hide()
        self.month.hide()
        self.day.hide()
        self.yearlabel.hide()
        self.monthlabel.hide()
        self.daylabel.hide()
        self.selectmodel.setCurrentIndex(0)
        self.resultlabel.setText("interval")
        self.rday.setText("")
        self.starttime.setText(self.appear_day(self.select_time0y,self.select_time0m,self.select_time0d))
        self.endtime.setText(self.appear_day(self.select_time1y,self.select_time1m,self.select_time1d))
        self.result_between()

    def dispper_select(self):
        self.border.hide()
        self.select.hide()
        if self.starttimes == 1:
            self.starttime.setFocus()
            self.starttime.setText(self.appear_day(self.select_time0y,self.select_time0m,self.select_time0d))
        elif self.starttimes == 2:
            self.endtime.setFocus()
            self.endtime.setText(self.appear_day(self.select_time1y,self.select_time1m,self.select_time1d))
        self.starttimes = 0

    def init_select(self,m):
        if m == 1:
            self.starttimes = 1
            self.init_month(self.select_time0y,self.select_time0m,self.select_time0d)
        if m == 2:
            self.starttimes = 2
            self.init_month(self.select_time1y,self.select_time1m,self.select_time1d)
        self.border.show()
        self.select.show()
    def init_month(self,y,m,d):
        self.select.setSelectedDate(QDate(y,m,d))

    def appear_week(self,y,m,w,d):
        s = ""
        if y != 0:
            s = str(y)
            s = s + '年'
            s = s + ','
        if m != 0:
            s = s + str(m)
            s = s + '月'
            s = s + ','
        if w != 0:
            s = s + str(w)
            s = s + '周'
            s = s + ','
        if d != 0:
            s = s + str(d)
            s = s + '天'
        if len(s) > 0 and s[-1] == ',':
            s = s[0:-1]
        return s

    def appear_day(self,y,m,d):
        s = str(y)
        s = s + '年'
        s = s + str(m)
        s = s + '月'
        s = s + str(d)
        s = s + '日'
        return s

    def day_click(self):
        if self.starttimes == 1:
            self.select_time0y = self.select.yearShown()
            self.select_time0m = self.select.monthShown()
            self.select_time0d = self.select.selectedDate().day()
        elif self.starttimes == 2:
            self.select_time1y = self.select.yearShown()
            self.select_time1m = self.select.monthShown()
            self.select_time1d = self.select.selectedDate().day()
        self.dispper_select()
        ss = self.selectmodel.currentText()
        if ss == 'The val between dates':
            self.result_between()
        elif ss == 'Add or subtract the number of days':
            self.result_add()

    def result_add(self):
        y = int(eval(self.year.currentText()))
        m = int(eval(self.month.currentText()))
        d = int(eval(self.day.currentText()))
        if self.add.isChecked() == True:
            m = m + self.select_time0m
            f = int(m % 12)
            if f == 0:
                f = 12
            i = int((m - 1) / 12)
            y = y + i
            year =self.select_time0y + y
            month = f
            d1 = datetime.datetime(year,month,self.select_time0d)
            delt = datetime.timedelta(days=d)
            delta = d1 + delt
            y = delta.year
            m = delta.month
            d = delta.day

        elif self.sub.isChecked() == True:
            f = int(m % 12)
            i = int((m - 1) / 12)
            if self.select_time0m - f <= 0:
                f = self.select_time0m - f + 12
                i += 1
            else:
                f = self.select_time0m - f
            y = y + i
            year =self.select_time0y - y
            month = f
            d1 = datetime.datetime(year,month,self.select_time0d)
            delt = datetime.timedelta(days=d)
            delta = d1 - delt
            y = delta.year
            m = delta.month
            d = delta.day
        self.result.setText(self.appear_day(y,m,d))

    def result_between(self):
        d1 = datetime.datetime(self.select_time0y,self.select_time0m,self.select_time0d)
        d2 = datetime.datetime(self.select_time1y,self.select_time1m,self.select_time1d)
        delt = d1 - d2
        delta = delt.days
        if delta > 0:
            y = self.select_time0y - self.select_time1y
            m = self.select_time0m - self.select_time1m
            d = self.select_time0d - self.select_time1d
            if m < 0:
                y -= 1
                m += 12
                if d < 0:
                    m -= 1
                    year = self.select_time1y + y
                    month = self.select_time1m + m
                    if month > 12:
                        year += 1
                    month = int(month % 12)
                    if month == 0:
                        month = 12
                    b1 = datetime.datetime(year,month,self.select_time1d)
                    d = (d1 - b1).days
            elif m == 0:
                if y > 0:
                    if d < 0:
                        y -= 1
                        m += 11
                        year = self.select_time1y + y
                        month = self.select_time1m + m
                        if month > 12:
                            year += 1
                        month = int(month % 12)
                        if month == 0:
                            month = 12
                        b1 = datetime.datetime(year,month,self.select_time1d)
                        d = (d1 - b1).days
                elif y == 0:
                    d = delta
            elif m > 0:
                if d < 0:
                    m -= 1
                    year = self.select_time1y + y
                    month = self.select_time1m + m
                    month = int(month % 12)
                    if month == 0:
                        month = 12
                    b1 = datetime.datetime(year,month,self.select_time1d)
                    d = (d1 - b1).days
            w = int(d / 7)
            d = d % 7
            self.result.setText(self.appear_week(y,m,w,d))
            if y == 0 and m == 0 and w == 0:
                self.rday.setText("")
            else:
                self.rday.setText(str(abs(delta)) + '天')
        elif delta < 0:
            y = self.select_time1y - self.select_time0y
            m = self.select_time1m - self.select_time0m
            d = self.select_time1d - self.select_time0d
            if m < 0:
                y -= 1
                m += 12
                if d < 0:
                    m -= 1
                    year = self.select_time0y + y
                    month = self.select_time0m + m
                    if month > 12:
                        year += 1
                    month = int(month % 12)
                    if month == 0:
                        month = 12
                    b1 = datetime.datetime(year,month,self.select_time0d)
                    d = (d2 - b1).days
            elif m == 0:
                if y > 0:
                    if d < 0:
                        y -= 1
                        m += 11
                        year = self.select_time0y + y
                        month = self.select_time0m + m
                        if month > 12:
                            year += 1
                        month = int(month % 12)
                        if month == 0:
                            month = 12
                        b1 = datetime.datetime(year,month,self.select_time0d)
                        d = (d2 - b1).days
                elif y == 0:
                    d = abs(delta)
            elif m > 0:
                if d < 0:
                    m -= 1
                    year = self.select_time0y + y
                    month = self.select_time0m + m
                    month = int(month % 12)
                    if month == 0:
                        month = 12
                    b1 = datetime.datetime(year,month,self.select_time0d)
                    d = (d2 - b1).days
            w = int(d / 7)
            d = d % 7
            self.result.setText(self.appear_week(y,m,w,d))
            if y == 0 and m == 0 and w == 0:
                self.rday.setText("")
            else:
                self.rday.setText(str(abs(delta)) + '天')
        elif delta == 0:
            self.result.setText("相同日期")
            self.rday.setText("")


import torch
import os
torch.autograd.set_detect_anomaly(True)
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

# most of this script is adapted from iNeRF https://github.com/salykovaa/inerf
# and NeRF-Pytorch https://github.com/yenchenlin/nerf-pytorch/blob/master/load_llff.py

def load_nerf(nerf_params, device):
    """Instantiate NeRF's MLP model.
    """
    embed_fn, input_ch = get_embedder(nerf_params['multires'], nerf_params['i_embed'])
    embeddirs_fn, input_ch_views = get_embedder(nerf_params['multires_views'], nerf_params['i_embed'])
    output_ch = 4
    skips = [4]
    model = NeRF(D=nerf_params['netdepth'], W=nerf_params['netwidth'],
                 input_ch=input_ch, output_ch=output_ch, skips=skips,
                 input_ch_views=input_ch_views, use_viewdirs=nerf_params['use_viewdirs']).to(device)

    model_fine = NeRF(D=nerf_params['netdepth_fine'], W=nerf_params['netwidth_fine'],
                      input_ch=input_ch, output_ch=output_ch, skips=skips,
                      input_ch_views=input_ch_views, use_viewdirs=nerf_params['use_viewdirs']).to(device)

    network_query_fn = lambda inputs, viewdirs, network_fn: run_network(inputs, viewdirs, network_fn,
                                                                        embed_fn=embed_fn,
                                                                        embeddirs_fn=embeddirs_fn,
                                                                        netchunk=nerf_params['netchunk'])

    # Load checkpoint, order tar files and pick the most trained if multiple exist.
    ckpt_dir = nerf_params['ckpt_dir']
    ckpt_name = ""
    ckpts = [os.path.join(ckpt_dir, ckpt_name, f) for f in sorted(os.listdir(os.path.join(ckpt_dir, ckpt_name))) if 'tar' in f]
    ckpt_path = ckpts[-1]
    print('Found ckpts', ckpts)
    print('Reloading from', ckpt_path)
    ckpt = torch.load(ckpt_path)

    # Load model

    model.load_state_dict(ckpt['network_fn_state_dict'], strict=False)
    model_fine.load_state_dict(ckpt['network_fine_state_dict'], strict=False)

    render_kwargs = {
        'network_query_fn': network_query_fn,
        'perturb': nerf_params['perturb'],
        'N_importance': nerf_params['fine_samples'],
        'network_fine': model_fine,
        'N_samples': nerf_params['course_samples'],
        'network_fn': model,
        'use_viewdirs': nerf_params['use_viewdirs'],
        'white_bkgd': nerf_params['white_bkgd'],
        'raw_noise_std': nerf_params['raw_noise_std']
    }

    # NDC only good for LLFF-style forward facing data
    if nerf_params['dataset_type'] != 'llff' or nerf_params['no_ndc']:
        print('Not ndc!')
        render_kwargs['ndc'] = False
        render_kwargs['lindisp'] = nerf_params['lindisp']

    if nerf_params['dataset_type'] != 'llff' and not nerf_params['no_ndc']:
        print("WARNING YOU CANNOT USE NDC WITH NON LLFF DATA - NDC WILL NOT BE USED")

    # Disable updating of the weights
    for param in model.parameters():
        param.requires_grad = False
    for param in model_fine.parameters():
        param.requires_grad = False

    return render_kwargs

# Positional encoding (section 5.1)
class Embedder:
    def __init__(self, **kwargs):
        self.kwargs = kwargs
        self.create_embedding_fn()

    def create_embedding_fn(self):
        embed_fns = []
        d = self.kwargs['input_dims']
        out_dim = 0
        if self.kwargs['include_input']:
            embed_fns.append(lambda x: x)
            out_dim += d

        max_freq = self.kwargs['max_freq_log2']
        N_freqs = self.kwargs['num_freqs']

        if self.kwargs['log_sampling']:
            freq_bands = 2. ** torch.linspace(0., max_freq, steps=N_freqs)
        else:
            freq_bands = torch.linspace(2. ** 0., 2. ** max_freq, steps=N_freqs)

        for freq in freq_bands:
            for p_fn in self.kwargs['periodic_fns']:
                embed_fns.append(lambda x, p_fn=p_fn, freq=freq: p_fn(x * freq))
                out_dim += d

        self.embed_fns = embed_fns
        self.out_dim = out_dim

    def embed(self, inputs):
        return torch.cat([fn(inputs) for fn in self.embed_fns], -1)

def get_embedder(multires, i=0):
    if i == -1:
        return nn.Identity(), 3

    embed_kwargs = {
        'include_input': True,
        'input_dims': 3,
        'max_freq_log2': multires - 1,
        'num_freqs': multires,
        'log_sampling': True,
        'periodic_fns': [torch.sin, torch.cos],
    }

    embedder_obj = Embedder(**embed_kwargs)
    embed = lambda x, eo=embedder_obj: eo.embed(x)
    return embed, embedder_obj.out_dim

# Model
class NeRF(nn.Module):
    def __init__(self, D=8, W=256, input_ch=3, input_ch_views=3, output_ch=4, skips=[4], use_viewdirs=False):
        """
        """
        super(NeRF, self).__init__()
        self.D = D
        self.W = W
        self.input_ch = input_ch
        self.input_ch_views = input_ch_views
        self.skips = skips
        self.use_viewdirs = use_viewdirs

        self.pts_linears = nn.ModuleList(
            [nn.Linear(input_ch, W)] + [nn.Linear(W, W) if i not in self.skips else nn.Linear(W + input_ch, W) for i in
                                        range(D - 1)])

        ### Implementation according to the official code release (https://github.com/bmild/nerf/blob/master/run_nerf_helpers.py#L104-L105)
        self.views_linears = nn.ModuleList([nn.Linear(input_ch_views + W, W // 2)])

        ### Implementation according to the paper
        # self.views_linears = nn.ModuleList(
        #     [nn.Linear(input_ch_views + W, W//2)] + [nn.Linear(W//2, W//2) for i in range(D//2)])

        if use_viewdirs:
            self.feature_linear = nn.Linear(W, W)
            self.alpha_linear = nn.Linear(W, 1)
            self.rgb_linear = nn.Linear(W // 2, 3)
        else:
            self.output_linear = nn.Linear(W, output_ch)

    def forward(self, x):
        input_pts, input_views = torch.split(x, [self.input_ch, self.input_ch_views], dim=-1)
        h = input_pts
        for i, l in enumerate(self.pts_linears):
            h = self.pts_linears[i](h)
            h = F.relu(h)
            if i in self.skips:
                h = torch.cat([input_pts, h], -1)

        if self.use_viewdirs:
            alpha = self.alpha_linear(h)
            feature = self.feature_linear(h)
            h = torch.cat([feature, input_views], -1)

            for i, l in enumerate(self.views_linears):
                h = self.views_linears[i](h)
                h = F.relu(h)

            rgb = self.rgb_linear(h)
            outputs = torch.cat([rgb, alpha], -1)
        else:
            outputs = self.output_linear(h)

        return outputs

    def load_weights_from_keras(self, weights):
        assert self.use_viewdirs, "Not implemented if use_viewdirs=False"
        print("here")

        # Load pts_linears
        for i in range(self.D):
            idx_pts_linears = 2 * i
            self.pts_linears[i].weight.data = torch.from_numpy(np.transpose(weights[idx_pts_linears]))
            self.pts_linears[i].bias.data = torch.from_numpy(np.transpose(weights[idx_pts_linears + 1]))

        # Load feature_linear
        idx_feature_linear = 2 * self.D
        self.feature_linear.weight.data = torch.from_numpy(np.transpose(weights[idx_feature_linear]))
        self.feature_linear.bias.data = torch.from_numpy(np.transpose(weights[idx_feature_linear + 1]))

        # Load views_linears
        idx_views_linears = 2 * self.D + 2
        self.views_linears[0].weight.data = torch.from_numpy(np.transpose(weights[idx_views_linears]))
        self.views_linears[0].bias.data = torch.from_numpy(np.transpose(weights[idx_views_linears + 1]))

        # Load rgb_linear
        idx_rbg_linear = 2 * self.D + 4
        self.rgb_linear.weight.data = torch.from_numpy(np.transpose(weights[idx_rbg_linear]))
        self.rgb_linear.bias.data = torch.from_numpy(np.transpose(weights[idx_rbg_linear + 1]))

        # Load alpha_linear
        idx_alpha_linear = 2 * self.D + 6
        self.alpha_linear.weight.data = torch.from_numpy(np.transpose(weights[idx_alpha_linear]))
        self.alpha_linear.bias.data = torch.from_numpy(np.transpose(weights[idx_alpha_linear + 1]))

def batchify(fn, chunk):
    """Constructs a version of 'fn' that applies to smaller batches.
    """
    if chunk is None:
        return fn
    def ret(inputs):
        return torch.cat([fn(inputs[i:i+chunk]) for i in range(0, inputs.shape[0], chunk)], 0)
    return ret

def run_network(inputs, viewdirs, fn, embed_fn, embeddirs_fn, netchunk=1024*64):
    """Prepares inputs and applies network 'fn'.
    """
    inputs_flat = torch.reshape(inputs, [-1, inputs.shape[-1]])
    embedded = embed_fn(inputs_flat)

    if viewdirs is not None:
        input_dirs = viewdirs[:,None].expand(inputs.shape)
        input_dirs_flat = torch.reshape(input_dirs, [-1, input_dirs.shape[-1]])
        embedded_dirs = embeddirs_fn(input_dirs_flat)
        embedded = torch.cat([embedded, embedded_dirs], -1)

    outputs_flat = batchify(fn, netchunk)(embedded)
    outputs = torch.reshape(outputs_flat, list(inputs.shape[:-1]) + [outputs_flat.shape[-1]])
    return outputs


import time
from micropython import const
from machine import Pin,UART

# Configure the serial port
uart = UART(1, baudrate=19200, tx=Pin(4), rx=Pin(5))
uart.init(bits=8, parity=None, stop=1)

while True:
    # Poll the serial port
    if uart.any():
        inData = uart.readline()
        print(inData)

    time.sleep_ms(500)


import lvgl as lv
import lvgl_helper as lv_h
import lcd
import time
from machine import Timer
from machine import I2C
from touch import Touch, TouchLow
import KPU as kpu
import gc

config_touchscreen_support = True
board_m1n = False

lcd.init()

TOUCH = None
DEBUG = False

def read_cb(drv, ptr):
    # print(ptr, b)
    data = lv.indev_data_t.cast(ptr)
    TOUCH.event()
    if DEBUG:
        print(TOUCH.state, TOUCH.points)
    data.point = lv.point_t({'x': TOUCH.points[1][0], 'y': TOUCH.points[1][1]})
    data.state = lv.INDEV_STATE.PR if TOUCH.state == 1 else lv.INDEV_STATE.REL
    return False

if config_touchscreen_support:
    i2c = I2C(I2C.I2C0, freq=1000*1000, scl=24, sda=27)  # 24 27)
    devices = i2c.scan()
    print("devs", devices)  # devs 0 [16, 38, 52, 56]
    TouchLow.config(i2c)
    TOUCH = Touch(480, 320, 200)

lv.init()

disp_buf1 = lv.disp_buf_t()
buf1_1 = bytearray(320*10)
lv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)//4)
disp_drv = lv.disp_drv_t()
lv.disp_drv_init(disp_drv)
disp_drv.buffer = disp_buf1

disp_drv.flush_cb = lv_h.flush
if board_m1n:
    disp_drv.hor_res = 240
    disp_drv.ver_res = 240
else:
    disp_drv.hor_res = 480
    disp_drv.ver_res = 320
lv.disp_drv_register(disp_drv)

if config_touchscreen_support:
    indev_drv = lv.indev_drv_t()
    lv.indev_drv_init(indev_drv)
    indev_drv.type = lv.INDEV_TYPE.POINTER
    indev_drv.read_cb = read_cb
    lv.indev_drv_register(indev_drv)

lv.log_register_print_cb(lambda level,path,line,msg: print('%s(%d): %s' % (path, line, msg)))

def event_handler(obj, event):
    global btn, box, bg

    if event == lv.EVENT.CLICKED:
        if obj == btn:
            box.set_hidden(0)
            bg.set_hidden(0)
        elif obj == box:
            box.set_hidden(1)
            bg.set_hidden(1)

#create screen object
scr = lv.obj()

#create button in center with callback
btn = lv.btn(scr)
btn.align(scr, lv.ALIGN.CENTER, 0, 0)
btn.set_event_cb(event_handler)
label = lv.label(btn)
label.set_text("Press me")
label.set_size(20,20)

#create semi-transparrent background and set it to hidden
bg = lv.obj(scr)
bg.set_pos(0, 0)
bg.set_size(scr.get_width(), scr.get_height())
modal_style = lv.style_t()
lv.style_copy(modal_style, lv.style_plain_color)
modal_style.body.main_color = modal_style.body.grad_color = lv.color_make(0,0,50)
modal_style.body.opa = 75
bg.set_style(modal_style)
bg.set_hidden(1)

#create message box and set it to hidden
box = lv.mbox(scr)
box.set_text("Congratulations, you pressed the button! Now do it again, here");
box.add_btns(["OK", ""])
box.set_width(200)
box.set_event_cb(event_handler)
box.align(None, lv.ALIGN.CENTER, 0, 0)
box.set_hidden(1)

lv.scr_load(scr)

def on_timer(timer):
    lv.tick_inc(5)
    lv.task_handler()
    gc.collect()

timer = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PERIODIC, period=5, unit=Timer.UNIT_MS, callback=on_timer, arg=None)

while True:
    pass


__author__ = 'Lucas-Fievet'

from celery import task

from us_loader.models import UsManager
import logging

logger = logging.getLogger("UsLoader")

@task()
def updateUs(date=None):
    logger.info("Update Us task started.")
    usManager = UsManager()
    if date is not None:
        usManager.update_to = date
    return usManager.update()


from setuptools import setup, find_namespace_packages
from tethys_apps.app_installation import find_resource_files

### Apps Definition ###
app_package = 'embalses'
release_package = 'tethysapp-' + app_package

# -- Get Resource File -- #
resource_files = find_resource_files('tethysapp/' + app_package + '/templates', 'tethysapp/' + app_package)
resource_files += find_resource_files('tethysapp/' + app_package + '/public', 'tethysapp/' + app_package)
resource_files += find_resource_files('tethysapp/' + app_package + '/workspaces', 'tethysapp/' + app_package)

### Python Dependencies ###
dependencies = []

setup(
    name=release_package,
    version='1.0.0',
    description='An application for forecasting future reservoir levels in the Dominican Republic',
    long_description='Uses the Streamflow Prediction Tool, user supplied water release information, and rule curves to '
                     'forecast the levels of any reservoir in the Domincan Republic. Developed in 2018 and 2019 by two '
                     'groups of BYU Civil Engineering Capstone students.',
    keywords='Reservoir',
    author='Riley Hales',
    author_email='',
    url='https://www.github.com/rileyhales/embalses',
    license='MIT License',
    packages=find_namespace_packages(),
    package_data={'': resource_files},
    include_package_data=True,
    zip_safe=False,
    install_requires=dependencies,
)


import sys
sys.stdin = open("줄.txt")

T = int(input())
for tc in range(1, T + 1):
    N = int(input())
    dp = [0 for _ in range(N + 1)]

    arr = list(map(int, input().split()))
    result = N

    for val in arr:
        #최장 증가 수열
        dp[val] = dp[val - 1] + 1
        #전체에서 감산
        result = min(result, N - dp[val])

    print('#{} {}'.format(tc, result))


import subprocess, time, sys, os, tool, json, configparser, requests, logging
from threading import Thread, Lock
from PyQt6 import QtWidgets, QtCore, QtGui, uic, QtQml
from PyQt6.QtWidgets import QMessageBox, QFileDialog, QApplication
from PyQt6.QtCore import QRunnable, pyqtSlot, QThreadPool

logging.basicConfig(level=logging.INFO, filename="Logs\\Update.log",filemode="a+",
                    format="[%(asctime)s] %(levelname)s: %(message)s")

def LoadCfg():
    global Config, THREADS, HOME_FOLDER, SAVE_FOLDER, LANGUAGE, Speed, Tune, Codec, Langs, config, Check_ver_link, Version
    Config = configparser.ConfigParser()
    Config.read("Settings.ini")

    THREADS = Config["PERFORMANCE"].getint("THREADS", os.cpu_count())
    HOME_FOLDER = Config["OTHER"].get("HOME_FOLDER", os.path.dirname(os.path.realpath(__file__)))
    SAVE_FOLDER = Config["OTHER"].get("SAVE_FOLDER", os.path.dirname(os.path.realpath(__file__)))
    LANGUAGE = Config["OTHER"].get("LANGUAGE", "EN")

    with open("config.json") as f:
        config = json.load(f)
    Speed = config["Presets"]
    Tune = config["Tune"]
    Codec = config["Codecs"]
    Langs = config["Langs"]
    Check_ver_link = config["Update"]["check_url"]
    Version = config["Update"]["version"]

LoadCfg()

# monkey-patch/replace Popen
subprocess.Popen = tool.new_Popen

def check_for_updates():
    logging.info("Looking for updates")
    for i in range(3):
        try:
            logging.info("Trying to connect to update server...")
            r = requests.get(Check_ver_link,timeout=0.5)
            if r.json()["version"] != Version:
                logging.info("Found an update!")
                MainWindow.Ask_for_update(MainWindow,r.json()["version"])
                return
            else:
                logging.info("Update not founded")
                return
        except requests.exceptions.RequestException:
            logging.error(f"Connection failed. #{i} try")
    logging.error("Failed to reach server")

#Delay which not freezing program
def Delay(sec : int):
    for i in range(0, sec*10, 1):
        QApplication.processEvents()
        time.sleep(0.1)

#Main Conversion Function
def ConvertPrep():
    global args, done
    LoadCfg()
    args = [                             #Command line formation
        "ffmpeg\\bin\\ffmpeg.exe",
        "-i", "",
        "-c:v", "",
        "-tune", "",
        "-preset", "",
        "-crf", "",
        "-threads", "",
        ""
    ]
    try:args[2] = Screen.CurrentVideo[0].replace("/","\\") # Get path of selected input video
    except AttributeError: # If user not selected input video
        Screen.ErrorNoFileSelected()
        return
    if Screen.radioButton.isChecked(): args[4] = Codec[0]  # If user choose "Default" codec
    else: args[4] = Codec[1]                                  # If user choose HEVC
    args[6] = Tune[Screen.comboBox_2.currentIndex()]       # Insert tune in command line
    args[8] = Speed[Screen.comboBox.currentIndex()]        # Insert speed preset in command line
    args[10] = str(Screen.spinBox.value())                 # Insert quality level in command line
    args[12] = str(24)
    args[13] = Screen.Save_File()[0].replace("/","\\")        # Open Save As window
    if args[11].replace(" ", "") == "":                       # If user didn't choose destination
        Screen.ErrorNoSave()
        return

    #Start conversion process
    Screen.setDisabled(True)    # Disable all widgets on main window
    done = False
    thread = Converter(args)
    Screen.threadpool.start(thread) # Start ffmpeg thread
    TimePass = 0
    while True: # Loop checking
        if not done: Screen.statusbar.showMessage(f"Converting {Screen.CurrentVideo[0]}. Passed seconds: {str(TimePass)}")  # If conversion proceeding
        else:                                                                                # If conversion ended
            Screen.statusbar.showMessage(f"Converted {Screen.CurrentVideo[0]}. Conversion took: {str(TimePass)} seconds")
            Screen.EndConversionDialog(TimePass)
            break
        Delay(1)
        TimePass +=1

class Converter(QRunnable): # FFMpeg Thread
    def __init__(self, args):
        super(Converter, self).__init__()
        self.args = args

    @pyqtSlot()
    def run(self):
        global done
        p = subprocess.Popen(args=args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) # Start FFMpeg
        p.wait()
        done = True

class Settings(QtWidgets.QWidget):
    def __init__(self):
        super(Settings, self).__init__()
        uic.loadUi("design\\Settings.ui", self)
        self.UpdateValues()
        self.pushButton_2.clicked.connect(self.Apply)
        self.pushButton.clicked.connect(self.close)
        self.pushButton_3.clicked.connect(self.close)
        self.trans = QtCore.QTranslator(self)
        self.ChangeLanguage(LANGUAGE)
        self.toolButton.clicked.connect(lambda e: self.lineEdit.setText(self.choose1()))
        self.toolButton_2.clicked.connect(lambda e: self.lineEdit_2.setText(self.choose2()))

    def Apply(self):
        if LANGUAGE != Langs[self.comboBox.currentIndex()]:
            MainWindow.ChangeLanguage(Screen, Langs[self.comboBox.currentIndex()])
            self.ChangeLanguage(Langs[self.comboBox.currentIndex()])

        Config["PERFORMANCE"]["THREADS"] = str(self.horizontalSlider.value())
        Config["OTHER"]["HOME_FOLDER"] = self.lineEdit.text()
        Config["OTHER"]["SAVE_FOLDER"] = self.lineEdit_2.text()
        Config["OTHER"]["LANGUAGE"] = Langs[self.comboBox.currentIndex()]
        with open("Settings.ini", "w") as configfile:
            Config.write(configfile)
        self.close()

    def UpdateValues(self):
        Config = configparser.ConfigParser()
        Config.read(".\\Settings.ini")

        THREADS = Config["PERFORMANCE"].getint("THREADS", os.cpu_count())
        HOME_FOLDER = Config["OTHER"].get("HOME_FOLDER", os.path.dirname(os.path.realpath(__file__)).replace("\\", "/"))
        SAVE_FOLDER = Config["OTHER"].get("SAVE_FOLDER", os.path.dirname(os.path.realpath(__file__)).replace("\\", "/"))
        LANGUAGE = Config["OTHER"].get("LANGUAGE", "EN")
        if LANGUAGE == "EN":
            LANGUAGE = 0
        elif LANGUAGE == "UA":
            LANGUAGE = 1

        self.horizontalSlider.setValue(int(THREADS))
        self.lineEdit.setText(HOME_FOLDER)
        self.lineEdit_2.setText(SAVE_FOLDER)
        self.comboBox.setCurrentIndex(LANGUAGE)

    def ChangeLanguage(self, lang):
        if lang == "UA":
            self.trans.load(config["Localization"]["UA"])
            QtWidgets.QApplication.installTranslator(self.trans)
        else:
            QtWidgets.QApplication.removeTranslator(self.trans)
        self.retranslateUi()

    def choose1(self): return QFileDialog.getExistingDirectory(self, "Open Default Video Directory",HOME_FOLDER)
    def choose2(self): return QFileDialog.getExistingDirectory(self, "Open Default Save Directory",SAVE_FOLDER)
    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("Form", "Settings"))
        self.groupBox.setTitle(_translate("Form", "Performance"))
        self.label.setToolTip(_translate("Form", "
Count of CPUs used for conversion
"))
        self.label.setText(_translate("Form", "CPU count"))
        self.groupBox_2.setTitle(_translate("Form", "Other"))
        self.label_2.setToolTip(_translate("Form", "
Language of programm
"))
        self.label_2.setText(_translate("Form", "Language"))
        self.comboBox.setItemText(0, _translate("Form", "English"))
        self.comboBox.setItemText(1, _translate("Form", "Ukrainian"))
        self.toolButton.setToolTip(_translate("Form", "
Browse
"))
        self.toolButton.setText(_translate("Form", "..."))
        self.label_3.setToolTip(_translate("Form", "
Default path of videos
"))
        self.label_3.setText(_translate("Form", "Input Video Folder"))
        self.label_4.setToolTip(_translate("Form", "
Default path to save converted video
"))
        self.label_4.setText(_translate("Form", "Output Video Folder"))
        self.toolButton_2.setToolTip(_translate("Form", "
Browse
"))
        self.toolButton_2.setText(_translate("Form", "..."))
        self.pushButton.setText(_translate("Form", "Cancel"))
        self.pushButton_2.setToolTip(_translate("Form", "
Apply changes
"))
        self.pushButton_2.setText(_translate("Form", "Apply"))
        self.pushButton_3.setText(_translate("Form", "Ok"))

class MainWindow(QtWidgets.QMainWindow): #Main Window
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        uic.loadUi("design\\MainWindow.ui", self)
        self.pushButton.clicked.connect(ConvertPrep) # "Convert" button clicked
        self.actionOpen.triggered.connect(self.OpenFile) # "Open" menu button clicked
        self.threadpool = QThreadPool() #Create Thread pool
        self.actionSettings.triggered.connect(self.ShowSettings)
        self.trans = QtCore.QTranslator(self)
        self.ChangeLanguage(LANGUAGE)
        check_for_updates()
    def ShowSettings(self):
        LoadCfg()
        self.settings = Settings()
        self.settings.show()

    def EndConversionDialog(self, t): #End Conversion Dialog
        LoadCfg()
        Screen.setDisabled(False)
        msgBox = QMessageBox()
        msgBox.setIcon(QMessageBox.Icon.Information)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("Vid.ico"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
        msgBox.setWindowIcon(icon)
        msgBox.setText(f"File {self.CurrentVideo[0]} was converted successfully!\nThe conversion took {t} seconds\nDo you want to open output folder?")
        msgBox.setWindowTitle("Conversion ended")
        msgBox.setStandardButtons(QMessageBox.StandardButton.Cancel | QMessageBox.StandardButton.Open)
        button = hex(msgBox.exec())
        f = self.SaveFile[0].replace("/", "\\").split("\\")
        f.pop()
        if button == "0x2000":
            os.system('explorer "{0}"'.format('\\'.join(f))) #Open Explorer where video saved
    def Save_File(self):
        LoadCfg()
        self.SaveFile = QFileDialog.getSaveFileName(self, "Save File As",SAVE_FOLDER, "Video Files (*.mp4 *.mov *.mkv)")
        return self.SaveFile
    def OpenFile(self):
        LoadCfg()
        self.CurrentVideo = QFileDialog.getOpenFileName(self, "Open File",HOME_FOLDER, "Video Files (*.mp4 *.mov *.mkv)")

    def ChangeLanguage(self, lang):
        if lang == "UA":
            self.trans.load(config["Localization"]["UA"])
            QtWidgets.QApplication.instance().installTranslator(self.trans)
        else: QtWidgets.QApplication.removeTranslator(self.trans)
        self.retranslateUi()

    def ErrorNoFileSelected(self):
        LoadCfg()
        msgBox = QMessageBox()
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("Vid.ico"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
        msgBox.setWindowIcon(icon)
        msgBox.setIcon(QMessageBox.Icon.Critical)
        msgBox.setText("Error! You don't selected any video to convert!")
        msgBox.setWindowTitle("Error! No Video Selected!")
        msgBox.setStandardButtons(QMessageBox.StandardButton.Cancel)
        msgBox.exec()

    def ErrorNoSave(self):
        LoadCfg()
        msgBox = QMessageBox()
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("Vid.ico"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
        msgBox.setWindowIcon(icon)
        msgBox.setIcon(QMessageBox.Icon.Critical)
        msgBox.setText("Dialog","Error! You must select destination and name of output video to conversion!")
        msgBox.setWindowTitle("Error! No Save Destination Selected!")
        msgBox.setStandardButtons(QMessageBox.StandardButton.Cancel)
        msgBox.exec()

    def Ask_for_update(self, ver):
        msgBox = QMessageBox()
        msgBox.setIcon(QMessageBox.Icon.Information)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("Vid.ico"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
        msgBox.setWindowIcon(icon)
        msgBox.setText(f"New version available!\n{ver}\nInstall now?")
        msgBox.setWindowTitle("Update")
        msgBox.setStandardButtons(QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel)

        returnValue = msgBox.exec()
        if returnValue == QMessageBox.StandardButton.Ok:
            DETACHED_PROCESS = 0x00000008
            subprocess.Popen(["Update.exe", f"{ver}", "-backup"], creationflags=DETACHED_PROCESS, close_fds=True, shell=True)
            exit()

    def retranslateUi(self):
        self.setWindowTitle(QtCore.QCoreApplication.translate("MainWindow", "Ultimate Video Converter"))
        self.groupBox_2.setTitle(QtCore.QCoreApplication.translate("MainWindow", "Video Quality"))
        self.spinBox.setToolTip(QtCore.QCoreApplication.translate("MainWindow", "
From 0 to 51.

(0 - best quality, 51 - the worst quality)
"))
        self.label.setText(QtCore.QCoreApplication.translate("MainWindow", "Ultimate Video Converter"))
        self.pushButton.setToolTip(QtCore.QCoreApplication.translate("MainWindow", "
Start Video Conversion
"))
        self.pushButton.setText(QtCore.QCoreApplication.translate("MainWindow", "Convert"))
        self.groupBox_4.setTitle(QtCore.QCoreApplication.translate("MainWindow", "Conversion Speed"))
        self.comboBox.setToolTip(QtCore.QCoreApplication.translate("MainWindow", "
The slower the conversion

the better the quality
"))
        self.comboBox.setPlaceholderText(QtCore.QCoreApplication.translate("MainWindow", "None"))
        self.comboBox.setItemText(0, QtCore.QCoreApplication.translate("MainWindow", "Ultra Fast"))
        self.comboBox.setItemText(1, QtCore.QCoreApplication.translate("MainWindow", "Super Fast"))
        self.comboBox.setItemText(2, QtCore.QCoreApplication.translate("MainWindow", "Very Fast"))
        self.comboBox.setItemText(3, QtCore.QCoreApplication.translate("MainWindow", "Faster"))
        self.comboBox.setItemText(4, QtCore.QCoreApplication.translate("MainWindow", "Fast"))
        self.comboBox.setItemText(5, QtCore.QCoreApplication.translate("MainWindow", "Medium"))
        self.comboBox.setItemText(6, QtCore.QCoreApplication.translate("MainWindow", "Slow"))
        self.comboBox.setItemText(7, QtCore.QCoreApplication.translate("MainWindow", "Slower"))
        self.comboBox.setItemText(8, QtCore.QCoreApplication.translate("MainWindow", "Very Slow"))
        self.groupBox_3.setTitle(QtCore.QCoreApplication.translate("MainWindow", "Video Tune"))
        self.comboBox_2.setToolTip(QtCore.QCoreApplication.translate("MainWindow", "
Choose Video Tune
"))
        self.comboBox_2.setPlaceholderText(QtCore.QCoreApplication.translate("MainWindow", "None"))
        self.comboBox_2.setItemText(0, QtCore.QCoreApplication.translate("MainWindow", "Film"))
        self.comboBox_2.setItemText(1, QtCore.QCoreApplication.translate("MainWindow", "Animation"))
        self.comboBox_2.setItemText(2, QtCore.QCoreApplication.translate("MainWindow", "Grain"))
        self.comboBox_2.setItemText(3, QtCore.QCoreApplication.translate("MainWindow", "Still image"))
        self.comboBox_2.setItemText(4, QtCore.QCoreApplication.translate("MainWindow", "Fast decode"))
        self.comboBox_2.setItemText(5, QtCore.QCoreApplication.translate("MainWindow", "Zero Latency"))
        self.groupBox.setTitle(QtCore.QCoreApplication.translate("MainWindow", "Encoding Codec"))
        self.radioButton.setToolTip(QtCore.QCoreApplication.translate("MainWindow", "
H264
"))
        self.radioButton.setText(QtCore.QCoreApplication.translate("MainWindow", "Default"))
        self.radioButton_2.setToolTip(QtCore.QCoreApplication.translate("MainWindow", "
H265
"))
        self.radioButton_2.setText(QtCore.QCoreApplication.translate("MainWindow", "HEVC"))
        self.menuChoose_file.setTitle(QtCore.QCoreApplication.translate("MainWindow", "File"))
        self.menuSettings.setTitle(QtCore.QCoreApplication.translate("MainWindow", "Settings"))
        self.menuHelp.setTitle(QtCore.QCoreApplication.translate("MainWindow", "Help"))
        self.actionOpen.setText(QtCore.QCoreApplication.translate("MainWindow", "Open"))
        self.actionOpen.setToolTip(QtCore.QCoreApplication.translate("MainWindow", "Load new file "))
        self.actionHelp.setText(QtCore.QCoreApplication.translate("MainWindow", "Help"))
        self.actionSettings.setText(QtCore.QCoreApplication.translate("MainWindow", "Settings"))

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    Screen = MainWindow()
    Screen.show()
    sys.exit(app.exec())