from PIL import Image, ImageFilter
import numpy as np

def imageprepare(img):
    """
    This function returns a 28x28 pixel value matrix
    The input is an image
    """
    im = img.convert('L') #convert to gray scale
    width = float(im.size[0])
    height = float(im.size[1])
    newImage = Image.new('L', (28, 28), (255))  # creates white canvas of 28x28 pixels

    if width > height:  # check which dimension is bigger
        # Width is bigger. Width becomes 28 pixels.
        nheight = int(round((28.0 / width * height), 0))  # resize height according to ratio width
        if (nheight == 0):  # rare case but minimum is 1 pixel
            nheight = 1
            # resize and sharpen
        img = im.resize((28, nheight), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
        wtop = int(round(((28 - nheight) / 2), 0))  # calculate horizontal position
        newImage.paste(img, (0, wtop))  # paste resized image on white canvas
    else:
        # Height is bigger. Heigth becomes 20 pixels.
        nwidth = int(round((28.0 / height * width), 0))  # resize width according to ratio height
        if (nwidth == 0):  # rare case but minimum is 1 pixel
            nwidth = 1
            # resize and sharpen
        img = im.resize((nwidth, 28), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
        wleft = int(round(((28 - nwidth) / 2), 0))  # caculate vertical position
        newImage.paste(img, (wleft, 0))  # paste resized image on white canvas

    x = list(newImage.getdata())  # get pixel values
    x = np.asarray(x) #convert to an array
    x = np.reshape(x,(1,28,28,1))
    x = x.astype('float32')/255

    return x

#Credits : https://stackoverflow.com/questions/35842274/convert-own-image-to-mnists-image


from datetime import date
from pytest import mark
from definitions import SpacetimePoint
from gateways import FileGateway

@mark.parametrize('filename', [
    '123432_2018-09-03_json.csv',
    '234234_2017-12-01_json.csv'
    ])
def test_identifies_valid_files(filename):
    assert FileGateway._valid_file(filename)

@mark.parametrize('filename', [
    'NA_2016-12-11_json.csv',
    'cancelled_2015-01-01_json.csv'
    ])
def test_identifies_invalid_files(filename):
    assert not FileGateway._valid_file(filename)

def test_makes_filename():
    point = SpacetimePoint(123.43, -54.345, date(2018, 1, 1))
    file_path = '/home/gklatte'
    filename = FileGateway._create_filename(point, file_path)
    expected_filename = '/home/gklatte/123.43_-54.345_2018-01-01.json'

    assert expected_filename == filename


import pytest
import smt_switch as ss
import pono
from typing import Set

@pytest.mark.parametrize("create_solver", ss.solvers.values())
def test_counter_system_safe(create_solver):
    solver = create_solver(False)
    solver.set_opt("produce-models", "true")
    solver.set_opt("incremental", "true")
    fts = pono.FunctionalTransitionSystem(solver)
    bvsort8 = fts.make_sort(ss.sortkinds.BV, 8)
    x = fts.make_statevar("x", bvsort8)
    one = fts.make_term(1, bvsort8)
    ten = fts.make_term(10, bvsort8)
    fts.assign_next(x, solver.make_term(ss.primops.Ite,
                                        solver.make_term(ss.primops.BVUlt,
                                                         x,
                                                         ten),
                                        solver.make_term(ss.primops.BVAdd,
                                                         x,
                                                         one),
                                        x))
    fts.set_init(solver.make_term(ss.primops.Equal,
                                  x,
                                  solver.make_term(0, bvsort8)))
    prop_term = fts.make_term(ss.primops.BVUle, x, ten)
    rts_new = pono.pseudo_init_and_prop(fts, prop_term)
    p = pono.Property(solver, prop_term)

    kind = pono.KInduction(p, rts_new, solver)
    res = kind.check_until(11)
    assert res

@pytest.mark.parametrize("create_solver", ss.solvers.values())
def test_trivial_unsafe(create_solver):
    solver = create_solver(False)
    solver.set_opt("produce-models", "true")
    solver.set_opt("incremental", "true")
    rts = pono.RelationalTransitionSystem(solver)
    bvsort8 = rts.make_sort(ss.sortkinds.BV, 8)
    x = rts.make_statevar('x', bvsort8)
    prop_term = solver.make_term(ss.primops.BVUle, x, solver.make_term(10, bvsort8))

    rts.set_trans(rts.make_term(False))

    rts_new = pono.pseudo_init_and_prop(rts, prop_term)
    p = pono.Property(solver, prop_term)

    kind = pono.KInduction(p, rts_new, solver)
    res = kind.check_until(11)
    assert not res


class Solution:
    def getMaximumGold(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        maxGold = 0
        def dfs(row, col):
            orig = grid[row][col]
            gold = orig
            grid[row][col] = 0

            for nr, nc in (row - 1, col), (row + 1, col), (row, col - 1), (row, col + 1):
                if 0 <= nr < m and 0 <= nc < n and grid[nr][nc] > 0:
                    gold = max(gold, orig + dfs(nr, nc))

            grid[row][col] = orig
            return gold

        for i in range(m):
            for j in range(n):
                if grid[i][j] > 0:
                    maxGold = max(maxGold, dfs(i, j))

        return maxGold

1201-1300/1219-Path with Maximum Gold/1219-Path with Maximum Gold.py


import sys
input = sys.stdin.readline

x, y = map(int, input().split())
turn = (x + y) * 2

value = 1
while True:
    if value * (value + 1) == turn:
        turn = value
        break
    elif value * (value + 1) > turn:
        turn = -1
        break
    else:
        value += 1

if turn == -1:
    print(-1)
else:
    a = 0
    b = 0
    cnt = 0
    for i in range(turn, 0, -1):
        if a + i <= x:
            a += i
            cnt += 1
        else:
            b += i

    print(cnt)


import sys

# Test A
# with open(sys.argv[1], "r") as fh:
#    tests = [_.split() for _ in fh.readlines()[1:]]
#
# for test in tests:
#    print(int(test[0]) + int(test[1]))

# Test B

def find_substring_indexes(s, t):
    indexes = []
    for i, letter in enumerate(s):
        if len(s) - i < len(t):
            break
        if s[i : i + len(t)] == t:
            indexes.append(i)
    return [_ + 1 for _ in indexes]

current_s = ""
current_t = ""
with open(sys.argv[1], "r") as fh:
    for line_num, line in enumerate(fh.readlines()[1:]):
        if line_num % 2 == 0:
            current_s = line.strip()
        else:
            current_t = line.strip()
        if current_s and current_t:
            print(
                " ".join([str(_) for _ in find_substring_indexes(current_s, current_t)])
            )


# -*- coding: utf-8 -*-

import uuid
import re

from django.utils.translation import gettext_lazy as _
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import (AbstractUser,
                                        Permission,
                                        PermissionsMixin)
from django.core import validators
from userauth.managers import (ElectorUserManager,
                               ElectorDynamicUserManager)

class ElectoralUser(AbstractUser,
                    PermissionsMixin):
    """
    User model for electoral application
    Required Fields :: (email, full_name)
    """
    ROLES = (
        ('AD', 'Admin'),
        ('WK', 'Worker'),
        ('MN', 'Manager'),
        ('ST', 'Support'),
        ('IN', 'Internal')
    )
    uuid = models.UUIDField(default=uuid.uuid4,
                            editable=False)
    username = models.CharField(_("user name"),
                                max_length=32,
                                unique=True,
                                null=True,
                                blank=True,
                                help_text='Required. 30 characters or fewer. Letters, numbers and /./-/_characters',
                                validators=[validators.RegexValidator(re.compile(r"^[\w.-]+$"),
                                                                      "Enter a valid username.",
                                                                      "invalid")])
    email = models.EmailField(_("email"),
                              max_length=255,
                              null=False,
                              blank=False,
                              unique=True)
    role = models.CharField(max_length=10,
                            choices=ROLES,
                            default='IN')
    full_name = models.CharField(_("full name"),
                                 max_length=256,
                                 blank=False)
    is_superuser = models.BooleanField(default=False,
                                       verbose_name='superuser status',
                                       help_text="Designates whether the user can have access"
                                                 "to all permissions on every model."
                                       )
    is_active = models.BooleanField(_('active status'),
                                    default=True,
                                    help_text="Designates whether this user should be treated as active."
                                              "Unselect this instead of deleting accounts.")
    is_staff = models.BooleanField(_('staff status'),
                                   default=False,
                                   help_text="Designates whether the user can log into this admin site.")
    full_name = models.CharField(_("full name"),
                                 max_length=256,
                                 blank=True)
    bio = models.TextField(_("biography"),
                           null=False,
                           blank=True,
                           default="")
    photo = models.ImageField(upload_to='profile-pictures',
                              blank=True,
                              null=True)
    date_joined = models.DateTimeField(verbose_name='date joined',
                                       default=timezone.now)
    added_by = models.ForeignKey('ElectoralUser',
                                 related_name='added_by_elector_users',
                                 on_delete=models.SET_NULL,
                                 null=True,
                                 blank=True)

    objects = ElectorUserManager()

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['full_name']

    class Meta:
        verbose_name = 'Electoral User'
        verbose_name_plural = 'Electoral Users'
        ordering = ['full_name', '-date_joined']

class AdminUser(ElectoralUser):
    objects = ElectorDynamicUserManager('AD')

    class Meta:
        proxy = True
        verbose_name = "Admin User"
        verbose_name_plural = "Admin Users"

class ManagerUser(ElectoralUser):
    objects = ElectorDynamicUserManager('MN')

    class Meta:
        proxy = True
        verbose_name = "Manager User"
        verbose_name_plural = "Manager Users"

class WorkerUser(ElectoralUser):
    objects = ElectorDynamicUserManager('WK')

    class Meta:
        proxy = True
        verbose_name = "Worker User"
        verbose_name_plural = "Worker Users"


import shutil
import tempfile
from typing import Any, Dict, cast

import importlib_resources

from gt4sd.training_pipelines import (
    TRAINING_PIPELINE_MAPPING,
    PaccMannVAETrainingPipeline,
)

template_config = {
    "model_args": {
        "n_layers": 1,
        "bidirectional": False,
        "rnn_cell_size": 64,
        "latent_dim": 32,
        "stack_width": 8,
        "stack_depth": 8,
        "decoder_search": "sampling",
        "dropout": 0.2,
        "generate_len": 50,
        "kl_growth": 0.003,
        "input_keep": 0.85,
        "test_input_keep": 1.0,
        "temperature": 0.8,
        "embedding": "one_hot",
        "vocab_size": 380,
        "pad_index": 0,
        "embedding_size": 380,
    },
    "dataset_args": {
        "add_start_stop_token": True,
        "selfies": True,
        "num_workers": 1,
        "pin_memory": False,
    },
    "training_args": {
        "epochs": 1,
        "batch_size": 4,
        "learning_rate": 0.0005,
        "optimizer": "adam",
        "log_interval": 2,
        "save_interval": 2,
        "eval_interval": 2,
        "model_path": "/tmp/paccmann_vae",
        "training_name": "paccmann-vae-test",
    },
}

def test_train():

    pipeline = TRAINING_PIPELINE_MAPPING.get("paccmann-vae-trainer")

    assert pipeline is not None

    TEMPORARY_DIRECTORY = tempfile.mkdtemp()

    test_pipeline = cast(PaccMannVAETrainingPipeline, pipeline())

    config: Dict[str, Any] = template_config.copy()

    config["training_args"]["model_path"] = TEMPORARY_DIRECTORY
    with importlib_resources.as_file(
        importlib_resources.files("gt4sd") / "training_pipelines/tests/molecules.smi",
    ) as file_path:

        config["dataset_args"]["train_smiles_filepath"] = file_path
        config["dataset_args"]["test_smiles_filepath"] = file_path
        test_pipeline.train(**config)

        shutil.rmtree(TEMPORARY_DIRECTORY)


#1- Escreva um programa que leia a quantidade de dias, horas, minutos e segundos do usuário e calcule o total em segundos.

dia = int(input("Dia(s):"))
hora = int(input("Hora(s):"))
minuto = int(input("Minuto(s):"))
segundo = int(input("Segundo(s):"))
print(f"{dia} dia(s), {hora} hora(s), {minuto} minuto(s) e {segundo} segundo(s)")
dia = dia * 86400
hora = hora * 3600
minuto = minuto * 60
segundo = segundo + minuto + hora + dia
print(f"Equivale a {segundo} segundo(s)")


goods = {
    'Лампа': '12345',
    'Стол': '23456',
    'Диван': '34567',
    'Стул': '45678',
}

store = {
    '12345': [
        {'quantity': 27, 'price': 42},
    ],
    '23456': [
        {'quantity': 22, 'price': 510},
        {'quantity': 32, 'price': 520},
    ],
    '34567': [
        {'quantity': 2, 'price': 1200},
        {'quantity': 1, 'price': 1150},
    ],
    '45678': [
        {'quantity': 50, 'price': 100},
        {'quantity': 12, 'price': 95},
        {'quantity': 43, 'price': 97},
    ],
}

for good in goods:

    curr_good = goods.get(good)
    summ_amount = 0
    summ_price = 0

    for value in store[curr_good]:
        summ_amount += value.get('quantity')
        summ_price += value.get('price') * value.get('quantity')

    print('{label} - {quantity} шт, '
          'стоимость {total_price} руб.'.format(
        label=good,
        quantity=summ_amount,
        total_price=summ_price
    ))


with open('data.txt') as f:
    dat = [int(x) for x in f.read().split('\n') if x != '']
    dat.sort()
    dat = [0] + dat + [dat[-1]+3]

def one(arr):
    d = [0, 0, 0]
    for i in range(len(arr)-1):
        d[arr[i+1] - arr[i] - 1] += 1
    return d[0] * d[2]

def two(arr):
    from_point = [0] * len(arr)
    from_point[len(arr)-1] = 1
    for i in reversed(range(len(arr)-1)):
        for j in (1, 2, 3):
            if i+j < len(arr) and arr[i+j] - arr[i] <= 3:
                from_point[i] += from_point[i+j]
            else:
                break
    return from_point[0]

print("one: ", one(dat))
print("two: ", two(dat))

# Valid but super_slow
# def two(arr):
#     if len(arr) == 1:
#         return 1
#     return sum(two(arr[i:]) for i in range(1, min(len(arr), 4)) if arr[i] - arr[0] <= 3)


"""2nd migration

Revision ID: b7e44c457eec
Revises:
Create Date: 2022-09-27 17:17:47.785161

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'b7e44c457eec'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('authors',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=32), nullable=True),
    sa.Column('book_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['book_id'], ['books.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_authors_name'), 'authors', ['name'], unique=True)
    op.create_table('association',
    sa.Column('book_id', sa.Integer(), nullable=False),
    sa.Column('author_id', sa.Integer(), nullable=False),
    sa.ForeignKeyConstraint(['author_id'], ['authors.id'], ),
    sa.ForeignKeyConstraint(['book_id'], ['books.id'], ),
    sa.PrimaryKeyConstraint('book_id', 'author_id')
    )
    op.create_index(op.f('ix_books_title'), 'books', ['title'], unique=False)
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_books_title'), table_name='books')
    op.drop_table('association')
    op.drop_index(op.f('ix_authors_name'), table_name='authors')
    op.drop_table('authors')
    # ### end Alembic commands ###


from django.urls import path

from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("following", views.following, name="following"),
    path("user/<str:username>", views.user, name="user"),

    path("login", views.login_view, name="login"),
    path("logout", views.logout_view, name="logout"),
    path("register", views.register, name="register"),

    path("create", views.create_post, name="create"),
    path("edit", views.edit, name="edit"),
    path("like/<int:id>", views.likes, name="like"),
    path("follow/<str:username>", views.follow, name="follow"),

    path("posts/page<int:pagenumber>", views.posts, name="posts"),
    path("followposts/page<int:pagenumber>", views.followposts, name="followposts"),
    path("userposts/<str:username>/page<int:pagenumber>", views.userposts, name="userposts"),

    path("getlikes", views.get_likes, name="getlikes"),
    path("getuser", views.getuser, name="getuser"),
    path("getpages", views.getpages, name="getpages"),

    path("flock", views.flock, name="flock")
]


import RPi.GPIO as GPIO
import time
import socketio
from socketio.exceptions import ConnectionError

def main():
    sio = None

    GPIO.setmode(GPIO.BOARD)

    # Setup PowerLED + input listener on PIN 3
    input_channel = 3
    GPIO.setup(input_channel, GPIO.IN)

    # Setup PowerSwitch RELAY control on PIN 12
    output_channel = 12
    GPIO.setup(output_channel, GPIO.OUT, initial=GPIO.LOW)

    count = 0

    while True:
        try:
            # Read voltage value from PIN 3
            input_voltage = GPIO.input(input_channel)

            if input_voltage == GPIO.LOW:
                # Detect power off, count once
                count += 1
            else:
                # Reset count to zero if value is GPIO.HIGH
                count = 0

            time.sleep(0.1)

            # Press Power Switch for 0.3 seconds when system is powered off for 10 seconds.
            if count > 100:
                # Simulate cold boot
                GPIO.output(output_channel, GPIO.HIGH)
                time.sleep(0.3)
                GPIO.output(output_channel, GPIO.LOW)

                # Update success operation count to Flask WebServer
                if sio:
                    sio.emit("count_plus_one")
                else:
                    try:
                        sio = socketio.Client()
                        sio.connect("http://localhost/")
                        sio.emit("count_plus_one")
                    except ConnectionError:
                        sio = None
                count = 0
        except KeyboardInterrupt:
            GPIO.cleanup()
            exit(0)

if __name__ == "__main__":
    main()


# coding: utf-8
from django.conf.urls import patterns, url

urlpatterns = patterns(
    'estofadora.statement.views',
    url(r'^caixa/$', 'cash', name='cash'),
    url(r'^caixa-mensal/$', 'cash_month', name='cash_month'),
    url(r'^caixa-anual/$', 'cash_annual', name='cash_annual'),
    url(r'^caixa/(?P<pk>\d+)/remover/', 'delete', name='delete'),
    url(r'^caixa/(?P<pk>\d+)/editar/', 'edit', name='edit'),
    url(r'^$', 'home', name='home'),
)


from rich import print
from rich.prompt import Prompt
from .base import Environment
from adala.skills import SkillSet
from adala.utils.internal_data import InternalDataFrame
from adala.utils.logs import print_series
from typing import Optional
from collections import defaultdict
from adala.environments.base import EnvironmentFeedback

class ConsoleEnvironment(Environment):
    def get_feedback(
        self,
        skills: SkillSet,
        predictions: InternalDataFrame,
        num_feedbacks: Optional[int] = None,
    ):
        if num_feedbacks is not None:
            predictions = predictions.sample(n=num_feedbacks)

        feedback = defaultdict(list)
        match = defaultdict(list)
        for skill_output, skill_name in skills.get_skill_outputs():
            for _, prediction in predictions.iterrows():
                print_series(prediction)
                print(
                    f'Prediction for "{skill_name}": {skill_output} = {prediction[skill_output]}'
                )
                fb = Prompt.ask(
                    "Your feedback: (Correct/Incorrect/Provide your answer)",
                    default="Correct",
                )
                if fb == "Correct":
                    match[skill_output].append(True)
                else:
                    match[skill_output].append(False)
                feedback[skill_output].append(fb)

        return EnvironmentFeedback(
            match=InternalDataFrame(match, index=predictions.index),
            feedback=InternalDataFrame(feedback, index=predictions.index),
        )


class BinarySearchTree(object):
    """
    Represents Binary Search TNode.
    """
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

    def get_root(self):
        """
        Return the value of self.
        """
        return self.value

    def add(self, value: object) -> None:
        """Add value to BSTNode."""
        if value > self.value:
            if self.right is None:
                self.right = BinarySearchTree(value)
            else:
                self.right.add(value)
        else:
            if self.left is None:
                self.left = BinarySearchTree(value)
            else:
                self.left.add(value)

    def size(self):
        """
        Return the number of elements in self.
        """
        count = 1
        if self.left:
            count += self.value.left.size()
        if self.right:
            count += self.value.right.size()
        return count

    def bin_search(self, info):
        """
        Non-recursively find whether info is in self.
        """
        try:
            if self.value == info:
                return self.value
            else:
                if info < self.value:
                    return self.left.bin_search(info)
                else:
                    return self.right.bin_search(info)
        except AttributeError:
            print('No such node found.')

    def is_empty(self):
        """
        Return whether self is empty.
        """
        return self.value is None

    def __str__(self, indent=0):
        """
        Return the string representation of self.
        """
        st = str(self.value) + '\n'
        indent += 1
        if self.right:
            st += '\t' * indent + self.right.__str__(indent)
        if self.left:
            st += '\t' * indent + self.left.__str__(indent)
        return st

class AVLNode(BinarySearchTree):
    """Represents a node for AVL tree."""

    def __init__(self, value: object) -> None:
        """Create an instance of AVL TNode."""

        BinarySearchTree.__init__(self, value)
        self.parent = None

    def insert(self, value: object) -> None:
        """Insert an item in the AVL tree."""

        # do a BST insert.
        if value > self.value:
            if self.right is None:
                new_node = AVLNode(value)
                new_node.parent = self
                self.right = new_node
                # check AVL property going up the parents
                parent = new_node.parent
                while parent is not None:
                    # print(parent)
                    if get_height(parent.left) > get_height(parent.right) + 1:
                        if get_height(parent.left.right) > \
                                get_height(parent.left.left):
                            lr(parent.left)
                        rr(parent)
                    elif get_height(parent.right) > get_height(parent.left) + 1:
                        if get_height(parent.right.left) > \
                                get_height(parent.right.right):
                            rr(parent.right)
                        lr(parent)
                    parent = parent.parent
            else:
                self.right.insert(value)
        elif value < self.value:
            if self.left is None:
                new_node = AVLNode(value)
                new_node.parent = self
                self.left = new_node
                # check AVL property going up the parents
                parent = new_node.parent
                while parent is not None:
                    # print(parent)
                    # print("height of left is", get_height(parent.left),"height of right is", get_height(parent.right))
                    if get_height(parent.left) > get_height(parent.right) + 1:
                        if get_height(parent.left.right) > \
                                get_height(parent.left.left):
                            lr(parent.left)
                        rr(parent)
                    elif get_height(parent.right) > get_height(parent.left) + 1:
                        if get_height(parent.right.left) > \
                                get_height(parent.right.right):
                            rr(parent.right)
                        lr(parent)
                    parent = parent.parent

            else:
                self.left.insert(value)

def lr(n: AVLNode) -> None:
    """Perform a left rotation of BSTNode n."""

    n.value, n.right.value = n.right.value, n.value
    right = n.right
    n.right = right.right
    right.right = right.left
    right.left = n.left
    n.left = right

def rr(n: AVLNode) -> None:
    """Perform a right rotation of BSTNode n."""

    n.value, n.left.value = n.left.value, n.value
    left = n.left
    n.left = left.left
    left.left = left.right
    left.right = n.right
    n.right = left

def get_height(node: AVLNode) -> int:
    """
    Return the height of node.
    """
    if node is None:
        return -1
    if node.left is None and node.right is None:
        return 0
    else:
        return 1 + max(get_height(node.left), get_height(node.right))

avl8 = AVLNode(8)
avl8.insert(10)
avl8.insert(3)
avl8.insert(2)
avl8.insert(1)
avl8.insert(6)
avl8.insert(4)
avl8.insert(5)
avl8.insert(7)
avl8.insert(14)
avl8.insert(13)
avl8.insert(15)
avl8.insert(16)
avl8.insert(17)
avl8.insert(9)
print(avl8)


from sys import argv

script, filename, = argv
ice = "{} {} {}"

print(f"We are going to erase {filename}.")
print("If you don't want that press Ctrl-C.")
print("If you want that, hit RETURN.")

input("What do you wanna do ? ")

print("Opening the file....")
txt = open(filename, 'w')

print("Truncating the file.... Now don't regret that.")
txt.truncate()

print("Now please state 3 lines to put it in the txt file.")

line1 = input("line1 : ")
line2 = input("line2 : ")
line3 = input("line3 : ")
#Here there is repetition of file so we try it with other options.....
#txt.write(line1)
#txt.write('\n')
#txt.write(line2)
#txt.write('\n')
#txt.write(line3)
#txt.write('\n')

#Trying it with format feature....
#line = "{}\n{}\n{}\n" .format(line1, line2, line3)
#txt.write(line)

#Trying with join() function..
#line = (line1, line2, line3)
#txt.write('\n'.join(line) +'\n')

#Another way of doing this....
txt.write("%s\n%s\n%s\n" %(line1,line2,line3))

print("Now we are closing the file...")
txt.close()

#You can use any of the above methods for writing to the file....


from type import *
from time import *

def intro():
    #Intro
    type("Cool Title")
    type("A production by...")
    type("Garage Couch Gaming Corp.")

    #Name adventurer. W/backstory --> Child kidnapped by Black Table, going to rescue them.
    type("Name your adventurer")
    name = input()

    type("As a young man, "+ name + " met the love of his life. They settled down in the small village \
of Villageville and had a young boy named Kristofferson. On his first birthday, Kristofferson was \
kidnapped by the shadowy orginazation known to a select few as the Concrete Fountain. The villagers \
of Villageville advised "+ name + " not to pursue the criminals, but to forget the incident. And he did.")
    sleep(0.75)
    type("20 years later...")
    sleep(0.75)
    type("As "+ name + " returned from a day of hard labor crafting wooden dice, he saw a crowd of \
Villageville villagers around his hut. His wife had been murdered by the Concrete Fountain! \
"+ name + " ran to the village leader for guidance.")
    type('"What should I do, O great village leader?" questioned '+ name + '.')
    type('"Follow your heart, young one", he replied.')
    type('"I will pay back the Concrete Fountain for all of the hardship in my life!" exclaimed ' + name + '.')
    type('"Take this pouch of our finest wooden dice, it should fetch a good price at our neighboring town, \
Blackwater. Good luck on your quest, ' + name + ' you will bring Villageville much honor and glory! \
But first, look inside you and tell me your strengths and weaknesses."')

    #Variables given values so 'while' loop doesn't crash
    strgth = 0
    spd = 0
    chrsma = 0
    hlth = 0
    pnts = 20
    type('*You have 4 major attributes; strength, speed, charisma, and constitution.*')
    type('*You have 20 points to allocate between the different attributes*')
    while not pnts == 0 or not 0 <= strgth <= 10 or not 0 <= spd <= 10 \
          or not 0 <= chrsma <= 10 or not 0 <= hlth <= 10:
        type("How much strength do you have? (0 - 10): ")
        strgth = int(input())
        pnts -= strgth
        type("*You have " + str(pnts) + " points left to allocate*")
        type("How much speed do you have? (0 - 10): ")
        spd = int(input())
        pnts -= spd
        type("*You have " + str(pnts) + " points left to allocate*")
        type("How much charisma do you have? (0 - 10): ")
        chrsma = int(input())
        pnts -= chrsma
        type("*You have " + str(pnts) + " points left to allocate*")
        type("How much constitution do you have? (0 - 10): ")
        hlth = int(input())
        pnts -= hlth

        if not pnts == 0 or not 0 <= strgth <= 10 or not 0 <= spd <= 10 \
           or not 0 <= chrsma <= 10 or not 0 <= hlth <= 10:
            type("Make sure your total is 20 and no value is negative.")
            pnts = 20

    return(name, strgth, spd, chrsma, hlth)


from os import listdir, getcwd, mkdir, remove
from os.path import isfile
from math import ceil, sqrt

import scipy.io as spio
import numpy as np
from tensorflow import reset_default_graph

from read_data import read_data, read_data_15k
from train import train
from train_rand_forest import train_rand_forest

############################################
#### functions to load training results ####
############################################
def loadmat(filename):
    data = spio.loadmat(filename, struct_as_record=False, squeeze_me=True)
    return _check_keys(data)

#### checks if entries in dictionary are mat-objects
def _check_keys(dict):
    for key in dict:
        if isinstance(dict[key], np.ndarray):
            if isinstance(dict[key][0], spio.matlab.mio5_params.mat_struct):
                #### cell of structure case
                tmp = np.zeros((len(dict[key]),), dtype=np.object)
                for cnt in range(len(dict[key])):
                    tmp[cnt] = _todict(dict[key][cnt])
                dict[key] = tmp
            else:
                #### just array case
                dict[key] = list(dict[key])
        if isinstance(dict[key], spio.matlab.mio5_params.mat_struct):
            dict[key] = _todict(dict[key])
    return dict

#### recursive function constructing nested dictionaries from matobjects
def _todict(matobj):
    dict = {}
    for strg in matobj._fieldnames:
        elem = matobj.__dict__[strg]
        if isinstance(elem, spio.matlab.mio5_params.mat_struct):
            dict[strg] = _todict(elem)
        elif isinstance(elem, unicode):
            dict[strg] = str(elem)
        elif isinstance(elem, np.ndarray):
            if isinstance(elem[0], spio.matlab.mio5_params.mat_struct):
                #### cell of structure case
                tmp = np.zeros((len(elem),), dtype=np.object)
                for cnt in range(len(elem)):
                    tmp[cnt] = _todict(elem[cnt])
                dict[strg] = tmp
            else:
                #### just array case
                dict[strg] = list(elem)
        elif strg == 'hidden_layer':
            dict[strg] = [elem]
        else:
            dict[strg] = elem
    return dict

#### compare two model_info_summary
#### cannot check whether two models are equal because floating number in Python and MATLABare different
def check_model_equivalency(model_info1, model_info2):
    check_keys1 = [(model_info1_elem in model_info2) for model_info1_elem in model_info1]
    check_keys2 = [(model_info2_elem in model_info1) for model_info2_elem in model_info2]
    if all(check_keys1) and all(check_keys2):
        return all([(model_info1[key] == model_info2[key]) for key in model_info1])
    else:
        return False

def print_model_info(model_dict):
    key_list = model_dict.keys()
    key_list.sort()
    for key in key_list:
        print(key + " : ", model_dict[key])

############################################
#### functions to save training results ####
############################################
def mean_of_list(list_input):
    return float(sum(list_input))/len(list_input)

def stddev_of_list(list_input):
    list_mean = mean_of_list(list_input)
    sq_err = [(x-list_mean)**2 for x in list_input]

    if len(list_input)<2:
        return 0.0
    else:
        return sqrt(sum(sq_err)/float(len(list_input)-1))

def model_info_summary(model_architecture, model_hyperpara, train_hyperpara, num_para_in_model=-1):
    tmp_dict = {}
    tmp_dict['architecture'] = model_architecture
    tmp_dict['learning_rate'] = train_hyperpara['lr']
    tmp_dict['improvement_threshold'] = train_hyperpara['improvement_threshold']
    tmp_dict['early_stopping_para'] = [train_hyperpara['patience'], train_hyperpara['patience_multiplier']]

    for model_hyperpara_elem in model_hyperpara:
        tmp_dict[model_hyperpara_elem] = model_hyperpara[model_hyperpara_elem]

    if num_para_in_model > -1:
        tmp_dict['number_of_trainable_parameters'] = num_para_in_model
    return tmp_dict

def reformat_result_for_mat(model_architecture, model_hyperpara, train_hyperpara, result_from_train_run, data_group_list, num_para_in_model=-1, doLifelong=False):
    result_of_curr_run = {}
    #### 'model_specific_info' element
    result_of_curr_run['model_specific_info'] = model_info_summary(model_architecture, model_hyperpara, train_hyperpara, num_para_in_model)

    num_run_per_model, best_valid_error_list, best_test_error_list, train_time_list = len(result_from_train_run), [], [], []
    result_of_curr_run['result_of_each_run'] = np.zeros((num_run_per_model,), dtype=np.object)
    if doLifelong:
        best_test_error_each_task_list, test_error_at_last_epoch_list = [], []
        best_test_error_each_task_avg_list, test_error_at_last_epoch_avg_list = [], []

    for cnt in range(num_run_per_model):
        result_of_curr_run['result_of_each_run'][cnt] = result_from_train_run[cnt]
        best_valid_error_list.append(result_from_train_run[cnt]['best_validation_error'])
        best_test_error_list.append(result_from_train_run[cnt]['test_error_at_best_epoch'])
        train_time_list.append(result_from_train_run[cnt]['training_time'])
        if doLifelong:
            chk_epoch = [x-1 for x in result_from_train_run[cnt]['task_changed_epoch'][1:]]+[result_from_train_run[cnt]['num_epoch']]
            best_test_error_each_task_list.append([result_from_train_run[cnt]['history_best_test_error'][x] for x in chk_epoch])
            best_test_error_each_task_avg_list.append(mean_of_list(best_test_error_each_task_list[cnt]))

            test_error_at_last_epoch_list.append(result_from_train_run[cnt]['history_test_error'][-1][0:-1])
            test_error_at_last_epoch_avg_list.append(mean_of_list(test_error_at_last_epoch_list[cnt]))

    result_of_curr_run['best_valid_error'] = best_valid_error_list
    result_of_curr_run['best_valid_error_mean'] = mean_of_list(best_valid_error_list)
    result_of_curr_run['best_valid_error_stddev'] = stddev_of_list(best_valid_error_list)
    result_of_curr_run['best_test_error'] = best_test_error_list
    result_of_curr_run['best_test_error_mean'] = mean_of_list(best_test_error_list)
    result_of_curr_run['best_test_error_stddev'] = stddev_of_list(best_test_error_list)
    result_of_curr_run['training_time'] = train_time_list
    result_of_curr_run['training_time_mean'] = mean_of_list(train_time_list)
    result_of_curr_run['training_time_stddev'] = stddev_of_list(train_time_list)
    result_of_curr_run['train_valid_data_group'] = data_group_list
    if doLifelong:
        result_of_curr_run['best_test_error_each_task'] = best_test_error_each_task_list
        result_of_curr_run['best_test_error_each_task_mean'] = mean_of_list(best_test_error_each_task_avg_list)
        result_of_curr_run['best_test_error_each_task_std'] = stddev_of_list(best_test_error_each_task_avg_list)
        result_of_curr_run['test_error_at_last_epoch'] = test_error_at_last_epoch_list
        result_of_curr_run['test_error_at_last_epoch_mean'] = mean_of_list(test_error_at_last_epoch_avg_list)
        result_of_curr_run['test_error_at_last_epoch_std'] = stddev_of_list(test_error_at_last_epoch_avg_list)

    return result_of_curr_run

#### functions for Random Forest model
def model_info_summary_rndforest(model_type, model_hyperpara):
    tmp_dict = {}
    tmp_dict['type'] = model_type
    tmp_dict['num_estimators'] = model_hyperpara["num_estimators"]
    tmp_dict['split_criterion'] = model_hyperpara["split_crit"]

    return tmp_dict

def reformat_result_for_mat_rndforest(model_type, model_hyperpara, result_from_train_run):
    result_of_curr_run = {}
    #### 'model_specific_info' element
    result_of_curr_run['model_specific_info'] = model_info_summary_rndforest(model_type, model_hyperpara)

    num_run_per_model, train_error_list, valid_error_list, test_error_list, train_time_list = len(result_from_train_run), [], [], [], []
    result_of_curr_run['result_of_each_run'] = np.zeros((num_run_per_model,), dtype=np.object)

    for cnt in range(num_run_per_model):
        result_of_curr_run['result_of_each_run'][cnt] = result_from_train_run[cnt]
        train_error_list.append(result_from_train_run[cnt]['train_error'][-1])
        valid_error_list.append(result_from_train_run[cnt]['validation_error'][-1])
        test_error_list.append(result_from_train_run[cnt]['test_error'][-1])
        train_time_list.append(result_from_train_run[cnt]['training_time'])

    result_of_curr_run['train_error'] = train_error_list
    result_of_curr_run['train_error_mean'] = mean_of_list(train_error_list)
    result_of_curr_run['train_error_stddev'] = stddev_of_list(train_error_list)
    result_of_curr_run['valid_error'] = valid_error_list
    result_of_curr_run['valid_error_mean'] = mean_of_list(valid_error_list)
    result_of_curr_run['valid_error_stddev'] = stddev_of_list(valid_error_list)
    result_of_curr_run['test_error'] = test_error_list
    result_of_curr_run['test_error_mean'] = mean_of_list(test_error_list)
    result_of_curr_run['test_error_stddev'] = stddev_of_list(test_error_list)
    result_of_curr_run['training_time'] = train_time_list
    result_of_curr_run['training_time_mean'] = mean_of_list(train_time_list)
    result_of_curr_run['training_time_stddev'] = stddev_of_list(train_time_list)

    return result_of_curr_run

############################################
#### functions to run several training  ####
####       with same model setting      ####
############################################
def train_run_for_each_model(model_architecture, model_hyperpara, train_hyperpara, data_hyperpara, mat_file_name, saved_result=None, useGPU=False, GPU_device=0, doLifelong=False):
    if not 'Result' in listdir(getcwd()):
        mkdir('Result')

    max_run_cnt = train_hyperpara['num_run_per_model']

    #### process results of previous training
    if (saved_result is None) and not (isfile('./Result/'+mat_file_name)):
        saved_result = np.zeros((1,), dtype=np.object)
    elif (saved_result is None):
        saved_result_tmp = spio.loadmat('./Result/'+mat_file_name)
        num_prev_test_model = len(saved_result_tmp['training_summary'][0])
        saved_result = np.zeros((num_prev_test_model+1,), dtype=np.object)
        for cnt in range(num_prev_test_model):
            saved_result[cnt] = saved_result_tmp['training_summary'][0][cnt]
    else:
        num_prev_result, prev_result_tmp = len(saved_result), saved_result
        saved_result = np.zeros((num_prev_result+1,), dtype=np.object)
        for cnt in range(num_prev_result):
            saved_result[cnt] = prev_result_tmp[cnt]

    #### process results saved in temporary file
    if not (isfile('./Result/temp_'+mat_file_name)):
        temp_result_exist = False
    else:
        saved_temp_result_tmp = loadmat('./Result/temp_'+mat_file_name)
        saved_temp_result = saved_temp_result_tmp['training_summary_temp']
        print('\nModel in temp file')
        print_model_info(saved_temp_result['model_specific_info'])
        print('\nModel for current train')
        print_model_info(model_info_summary(model_architecture, model_hyperpara, train_hyperpara))
        #use_temp_result = input('\nUse temp result? (T/F): ')
        use_temp_result = 't'
        if (use_temp_result is 'T') or (use_temp_result is 't') or (use_temp_result is 'True') or (use_temp_result is 'true'):
            temp_result_exist = True
        else:
            temp_result_exist = False

    result_from_train_run = []
    if temp_result_exist:
        if not (isinstance(saved_temp_result['train_valid_data_group'], np.ndarray) or isinstance(saved_temp_result['train_valid_data_group'], list)):
            result_from_train_run.append(saved_temp_result['result_of_each_run'])
        else:
            for elem in saved_temp_result['result_of_each_run']:
                result_from_train_run.append(elem)
        run_cnt_init = len(result_from_train_run)
        print("\nTemporary Result Exists! Start from %d\n" %(run_cnt_init+1))
    else:
        run_cnt_init = 0
        print("\nTemporary Result is Discarded! Overwrite Temp File\n")

    #### run training procedure with different dataset
    for run_cnt in range(run_cnt_init, max_run_cnt):
        # dataset, datainfo = read_data_15k(data_hyperpara['folder_name'], data_hyperpara['train_file_name'], data_hyperpara['test_file_name'], data_hyperpara['train_valid_test_ratio'], data_hyperpara['all_output'])
        dataset, datainfo = read_data(data_hyperpara['folder_name'], data_hyperpara['train_file_name'], data_hyperpara['test_file_name'], data_hyperpara['train_valid_ratio'], data_hyperpara['all_output'])
        print("Training/Validation data group : %d\n" %(run_cnt))
        if 'rndforest' in model_architecture:
            train_result_tmp, num_model_para = train_rand_forest(model_architecture, model_hyperpara, dataset, datainfo)
        else:
            train_result_tmp, num_model_para = train(model_architecture, model_hyperpara, train_hyperpara, dataset, datainfo, useGPU, GPU_device, doLifelong)
        result_from_train_run.append(train_result_tmp)

        if run_cnt < max_run_cnt-1:
            if 'rndforest' in model_architecture:
                result_of_curr_run = reformat_result_for_mat_rndforest(model_architecture, model_hyperpara, result_from_train_run)
            else:
                result_of_curr_run = reformat_result_for_mat(model_architecture, model_hyperpara, train_hyperpara, result_from_train_run, range(run_cnt+1), num_model_para, doLifelong)
            spio.savemat('./Result/temp_'+mat_file_name, {'training_summary_temp':result_of_curr_run})
        elif isfile('./Result/temp_'+mat_file_name):
            remove('./Result/temp_'+mat_file_name)

        print("%d-th training run\n\n" % (run_cnt+1))
        reset_default_graph()

    #### save training summary
    if 'rndforest' in model_architecture:
        result_of_curr_run = reformat_result_for_mat_rndforest(model_architecture, model_hyperpara, result_from_train_run)
    else:
        result_of_curr_run = reformat_result_for_mat(model_architecture, model_hyperpara, train_hyperpara, result_from_train_run, range(max_run_cnt), num_model_para, doLifelong)
    saved_result[-1] = result_of_curr_run
    spio.savemat('./Result/'+mat_file_name, {'training_summary':saved_result})

    return saved_result


from dart.engine.redshift.mappings import mapped_column_definition
from dart.engine.redshift.metadata import RedshiftActionTypes

def get_target_schema_and_table_name(action, dataset):
    schema_name = action.data.args.get('target_schema_name') or 'public'
    table_name = action.data.args.get('target_table_name') or dataset.data.table_name
    return schema_name, table_name

def get_stage_schema_and_table_name(action, dataset):
    schema_name, table_name = get_target_schema_and_table_name(action, dataset)
    return 'dart_stage', schema_name + '_' + table_name + '_' + action.id

def get_tracking_schema_and_table_name(action):
    table_name = 's3_files_for_action_%s' % action.id
    if action.data.action_type_name == RedshiftActionTypes.consume_subscription.name:
        table_name = 's3_files_for_subscription_%s' % action.data.args['subscription_id']
    return 'dart_tracking', table_name

def create_tracking_schema_and_table(conn, action):
    schema_name, table_name = get_tracking_schema_and_table_name(action)
    conn.execute("CREATE SCHEMA IF NOT EXISTS %s" % schema_name)
    sql = "CREATE TABLE IF NOT EXISTS %s.%s (s3_path VARCHAR(1024), updated TIMESTAMP)" % (schema_name, table_name)
    if action.data.action_type_name == RedshiftActionTypes.consume_subscription.name:
        sql = "CREATE TABLE IF NOT EXISTS %s.%s (s3_path VARCHAR(1024), updated TIMESTAMP, batch_id VARCHAR(36))" % (schema_name, table_name)
    conn.execute(sql)

def create_schemas_and_tables(conn, action, dataset):
    """
    :type action: dart.model.action.Action
    :type dataset: dart.model.dataset.Dataset
    """
    args = action.data.args
    dd = dataset.data
    dist_key = args.get('target_distribution_key') or (dd.distribution_keys[0] if dd.distribution_keys else None)
    dist_style = 'KEY' if dist_key else (args.get('distribution_style') or 'EVEN')
    sk_keyword = 'INTERLEAVED SORTKEY' if args.get('sort_keys_interleaved') else 'SORTKEY'
    sort_keys = args.get('target_sort_keys') or dd.sort_keys
    schema_name, table_name = get_target_schema_and_table_name(action, dataset)

    table_sql = 'CREATE TABLE IF NOT EXISTS {schema_name}.{table_name}'
    table_options_sql = ' ({columns}{pk}){dist_style}{dist_key}{sort_keys}'.format(
        columns=', '.join([mapped_column_definition(c) for c in dataset.data.columns]),
        pk=', PRIMARY KEY (%s)' % ', '.join(dd.primary_keys) if dd.primary_keys else '',
        dist_style=' DISTSTYLE %s' % dist_style if dist_style else '',
        dist_key=' DISTKEY (%s)' % dist_key if dist_key else '',
        sort_keys=' %s (%s)' % (sk_keyword, ', '.join(sort_keys)) if sort_keys else '',
    )

    # create the schema and target table
    conn.execute("CREATE SCHEMA IF NOT EXISTS %s" % schema_name)
    sql = table_sql.format(schema_name=schema_name, table_name=table_name) + table_options_sql
    conn.execute(sql)

    # create the schema and stage table
    schema_name, table_name = get_stage_schema_and_table_name(action, dataset)
    conn.execute("CREATE SCHEMA IF NOT EXISTS %s" % schema_name)
    sql = table_sql.format(schema_name=schema_name, table_name=table_name) + table_options_sql
    conn.execute(sql)


# Day 3 - TreasureIsland

# Control flow and logical operators

print("Welcome to the rollercoaster!")
height = int(input("What is your height? "))

if height > 120:
    print("You can ride!")
    age = int(input("What is your age? "))
    if age < 12:
        price = 5
    elif age <= 18:
        price = 7
    elif age >= 45 and age <= 55:
        price = 0
    else:
        price = 12

    photo = input("Do you want a photo (Y/N)? ")

    if photo.upper() == "Y":
        price += 3

    print(f"Please pay ${price}.")
else:
    print("Sorry, you're not tall enough.")

number = int(input("Which number do you want to check? "))
#  Don't change the code above

#Write your code below this line

if number % 2 == 0:
    print("This is an even number.")
else:
    print("This is an odd number.")

height = float(input("enter your height in m: "))
weight = float(input("enter your weight in kg: "))
# Don't change the code above

#Write your code below this line

bmi = round(weight / (height ** 2))

if bmi < 18.5:
    msg = "are underweight"
elif bmi < 25:
    msg = "have a normal weight"
elif bmi < 30:
    msg = "are slightly overweight"
elif bmi < 35:
    msg = "are obese"
else:
    msg = "are clinically obese"

print(f"Your BMI is {bmi}, you {msg}.")

year = int(input("Which year do you want to check? "))
#  Don't change the code above

#Write your code below this line

if year % 4 != 0:
    print("Not leap year.")
else:
    if year % 100 == 0 and year % 400 != 0:
        print("Not leap year.")
    else:
        print("Leap year.")

print("Welcome to Python Pizza Deliveries!")
size = input("What size pizza do you want? S, M, or L ")
add_pepperoni = input("Do you want pepperoni? Y or N ")
extra_cheese = input("Do you want extra cheese? Y or N ")
#  Don't change the code above

#Write your code below this line

if size == "S":
    if add_pepperoni == "Y":
        price = 17
    else:
        price = 15
elif size == "M":
    if add_pepperoni == "Y":
        price = 23
    else:
        price = 20
else:
    if add_pepperoni == "Y":
        price = 28
    else:
        price = 25

if extra_cheese == "Y":
    price += 1

print(f"Your final bill is: ${price}.")

print("Welcome to the Love Calculator!")
name1 = input("What is your name? \n")
name2 = input("What is their name? \n")
#  Don't change the code above

#Write your code below this line

combinedName = name1.lower() + name2.lower()
firstDigit = 0
secondDigit = 0

for s in "true":
    firstDigit += combinedName.count(s)
for s in "love":
    secondDigit += combinedName.count(s)

score = int(str(firstDigit) + str(secondDigit))

if score < 10 or score > 90:
    print(f"Your score is {score}, you go together like coke and mentos.")
elif score >= 40 and score <= 50:
    print(f"Your score is {score}, you are alright together.")
else:
    print(f"Your score is {score}.")

# Treasure Island

print("Welcome to Treasure Island.")

firstChoice = input("You wash up on a path across a sandy beach. head 'Left' or 'Right'? ").lower()

if firstChoice == "right":
    print("You head right and feel the beach give way beneath your feet. As you slide below the quicksand you realise this is GAME OVER!")
else:
    secondChoice = input("You emerge at a huge oasis with a temple atop a central island. Will you 'Wait' for a boat, or 'Swim'? ").lower()

    if secondChoice == "swim":
        print("Already tired from your harrowing journey, you quickly realise you underestimated the vastness of the oasis. Sinking beneath the water, you realise this is GAME OVER!")
    else:
        thirdChoice = input("A boat takes you to the 3 painted doors of the temple. 'Yellow', 'Red', or 'Blue'?").lower()

        if thirdChoice == "yellow":
            print("The doors' yellow colour was the gleam of gold! you sail the boat home to enjoy your riches.")
        else:
            print("RNG finally turns against you, the door leads to an unending pit! As you tumble to oblivion, you realise this is GAME OVER!")


from pyorbit.subroutines.common import *
from pyorbit.classes.model_container_abstract import ModelContainer

class ModelContainerOptimize(ModelContainer):

    def __init__(self):
        super(self.__class__, self).__init__()

        self.optimize_dir_output = None
        self.optimize_parameters = {'method': 'Nelder-Mead',
                                    'maxiter': 1000000.0,
                                    'adaptive': True,
                                    'disp': True}

        self.current_neg_loglikelihood = 10000000.0
        """
        Check SciPy documentation for available methods:
        https://docs.scipy.org/doc/scipy/reference/optimize.html
        """

    def negative_log_priors_likelihood(self, theta):

        neg_loglikelihood = -self.__call__(theta)

        # workaround to avoid RuntimeWarning when the one of the variable is outside the boundaries
        if np.isfinite(neg_loglikelihood):
            self.current_neg_loglikelihood = neg_loglikelihood
            return neg_loglikelihood
        else:
            return self.current_neg_loglikelihood*10.

    """
    def check_bounds(self, theta):
        print(type(theta))
        for ii in range(0, self.ndim):

            print(theta[ii])
            #if not (self.bounds[ii, 0] < theta[ii] < self.bounds[ii, 1]):
            #    return False
    """


import math
import os
import sys

import matplotlib
import pyvista

sys.path.append("src")

from subt_proc_gen.param_classes import TunnelPtClGenParams
from EasyConfig import EasyConfig
from subt_proc_gen.display_functions import (
    plot_graph,
    plot_splines,
    plot_mesh,
    plot_tunnel_ptcls,
    plot_intersection_ptcls,
)
from subt_proc_gen.mesh_generation import (
    TunnelNetworkMeshGenerator,
    TunnelNetworkPtClGenParams,
    TunnelNetworkMeshGenParams,
)

matplotlib.use("Qt5Agg")

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure

from PyQt5.QtGui import QPixmap, QPainter, QPen, QIcon
from PyQt5.QtWidgets import (
    QMenuBar,
    QVBoxLayout,
    QWidget,
    QPushButton,
    QFrame,
    QTabWidget,
    QSplitter,
    QLabel,
    QFileDialog,
    QToolBar,
    QInputDialog,
    QMenu,
    QSlider,
    QScrollArea,
    QProgressDialog,
)
from pyvista import QtInteractor
from pyvistaqt import QtInteractor
from subt_proc_gen.tunnel import *
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import Qt, QRect, QPoint, QRunnable, QThreadPool, QPointF
import logging as log

log.basicConfig(level=log.DEBUG)

class MplCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)

class Point(QPoint):
    def __init__(self, pose=None, index=0):
        super().__init__()
        if pose is not None:
            self.setX(pose.x())
            self.setY(pose.y())
            self.index = index
            self.zpos = 0

    def z(self):
        return self.zpos

    def setZ(self, val):
        self.zpos = val

    def nppose(self):
        return np.array([self.x(), self.y(), self.z()])

    def serialize(self, dictionary):
        dictionary["index"] = self.index
        dictionary["x"] = self.x()
        dictionary["y"] = self.y()
        dictionary["z"] = self.z()

    def deserialize(self, dictionary):
        self.index = dictionary["index"]
        self.setX(dictionary["x"])
        self.setY(dictionary["y"])
        self.setZ(dictionary["z"])

class Sketch(QLabel):
    def __init__(self):
        super().__init__()
        pix = QPixmap(200, 200)
        pix.fill(Qt.white)
        self.color_index = 0
        self.colors = [
            Qt.red,
            Qt.green,
            Qt.blue,
            Qt.darkYellow,
            Qt.darkMagenta,
            Qt.black,
            Qt.yellow,
            Qt.gray,
            Qt.cyan,
        ]
        self.setPixmap(pix)
        self.setScaledContents(True)
        self.base = None
        self.p1 = None
        self.p2 = None
        self.points = []
        self.lines = []
        self.trees = []
        self.scale = 0.1
        self.current_tree_index = None
        self.selected = None
        self.params = {}

    def load(self, filename):
        self.points.clear()
        self.current_tree_index = 0
        self.trees.clear()
        try:
            f = open(filename, "r")
            data = yaml.safe_load(f)
            f.close()

            if len(data["points"]) > 0:
                for p in data["points"]:
                    q = Point()
                    q.deserialize(p)
                    self.points.append(q)
            print("Loaded {} points".format(len(self.points)))

            for color, tree in enumerate(data["trees"]):
                tree_nodes = []
                for node_id in tree["nodes"]:
                    tree_nodes.append(self.points[node_id])
                self.trees.append(
                    {"nodes": tree_nodes, "color": color, "config": tree["config"]}
                )
            self.color_index = len(self.trees) - 1
            self.update()
            return True
        except:
            return False

    def save(self, filename):
        filename = "default.yaml" if filename is None else filename

        dictionary = {"points": [], "trees": [], "config": []}

        for p in self.points:
            data = {}
            p.serialize(data)
            dictionary["points"].append(data)

        for tree in self.trees:
            dictionary["trees"].append(
                {
                    "nodes": [node.index for node in tree.get("nodes")],
                    "config": tree.get("config"),
                }
            )

        with open(filename, "w") as f:
            yaml.dump(dictionary, f)

    def update_defaults(self, **kwargs):
        self.params = kwargs
        self.update()

    def current_tree(self):
        return self.trees[self.current_tree_index]

    def delete_last(self):
        nodes = self.current_tree().get("nodes")
        if len(nodes) > 1:
            point = nodes.pop(-1)
            found = False
            for tree in self.trees:
                found = found or (point in tree.get("nodes"))
            if not found:
                self.points.remove(point)
                for i, node in enumerate(self.points):
                    node.index = i

        if len(nodes) > 0:
            self.p1 = nodes[-1]
        else:
            self.current_tree_index = 0
            self.p1 = None
            self.p2 = None

        self.update()

    def setScale(self, scale):
        self.scale = scale

    def clear_points(self):
        self.points.clear()
        self.trees.clear()
        self.current_tree_index = None
        self.p1 = None
        self.p2 = None
        self.color_index = 0
        self.update()

    def contextMenuEvent(self, ev: QtGui.QContextMenuEvent) -> None:
        for p in self.points:
            r = QRect(p.x() - 10, p.y() - 10, 20, 20)
            if r.contains(ev.pos().x(), ev.pos().y()):
                selected_tree = None
                for tree in self.trees:
                    nodes, tunnel_config = tree.get("nodes"), tree.get("config")
                    if p in nodes:
                        selected_tree = tree
                        break

                qm = QMenu()

                set_z, cont = qm.addAction("Set Z"), None
                change_config, cont = qm.addAction("Change Tunnel Config"), None
                if p == selected_tree.get("nodes")[-1]:
                    cont = qm.addAction("Continue here")

                res = qm.exec(ev.globalPos())

                if res == cont:
                    self.p1 = p
                    self.current_tree_index = self.trees.index(selected_tree)
                    self.color_index = selected_tree.get("color")
                    return

                elif res == set_z:
                    text, ok = QInputDialog.getText(
                        self,
                        "Set Z coordinate of node " + str(p.index),
                        "Value",
                        text=str(p.z()),
                    )

                    if ok and text.replace(".", "").replace("-", "").isnumeric():
                        p.setZ(float(text))
                        self.update()

                elif res == change_config:
                    dialog = self.Config()
                    dialog.set(
                        "roughness", selected_tree.get("config").get("roughness", 0)
                    )
                    dialog.set("radius", selected_tree.get("config").get("radius", 0))
                    if dialog.edit():
                        selected_tree.get("config")["roughness"] = dialog.get(
                            "roughness"
                        )
                        selected_tree.get("config")["radius"] = dialog.get("radius")

    def mouseDoubleClickEvent(self, ev: QtGui.QMouseEvent) -> None:
        super().mouseDoubleClickEvent(ev)
        for p in self.points:
            r = QRect(p.x() - 10, p.y() - 10, 20, 20)
            if r.contains(ev.pos().x(), ev.pos().y()):
                text, ok = QInputDialog.getText(
                    self,
                    "Set Z coordinate of node " + str(p.index),
                    "Value",
                    text=str(p.z()),
                )
                if ok and text.replace(".", "").replace("-", "").isnumeric():
                    p.setZ(float(text))
                    self.update()
                break

    class Config(EasyConfig):
        def __init__(self):
            super().__init__()
            self.root().addSlider(
                "roughness", pretty="Roughness", val=0, min=0, max=10, den=10
            )
            self.root().addSlider(
                "radius", pretty="Radius", val=3, min=10, max=100, den=10
            )

    def getPoints(self, scale):
        self.p1 = None
        self.p2 = None
        self.update()

        if len(self.points) == 0:
            return

        nodes = []
        for p in self.points:
            nodes.append(Node(p.nppose() * scale))

        x, y, z = nodes[0].x, nodes[0].y, nodes[0].z
        for n in nodes:
            n.set_pose(-x + n.x, y - n.y, -z + n.z)

        trees_list = list()

        for tree in self.trees:
            tree_nodes = list()
            for p in tree.get("nodes"):
                tree_nodes.append(nodes[p.index])
            trees_list.append(
                {"tree_nodes": tree_nodes, "tree_config": tree.get("config")}
            )
        return trees_list
        # return nodes, node_trees

    def mousePressEvent(self, ev: QtGui.QMouseEvent) -> None:
        super().mousePressEvent(ev)
        if ev.modifiers() & Qt.ControlModifier:
            for p in self.points:
                r = QRect(p.x() - 10, p.y() - 10, 20, 20)
                if r.contains(ev.pos().x(), ev.pos().y()):
                    self.selected = p

        elif ev.modifiers() & Qt.ShiftModifier:
            for p in self.points:
                r = QRect(p.x() - 10, p.y() - 10, 20, 20)
                if r.contains(ev.pos().x(), ev.pos().y()):
                    self.color_index += 1
                    self.trees.append(
                        {
                            "nodes": [p],
                            "color": self.color_index,
                            "config": self.params.copy(),
                        }
                    )
                    self.current_tree_index = len(self.trees) - 1
                    self.p1 = p

        elif self.p1 is None and len(self.trees) == 0:
            self.base = ev.pos()
            self.p1 = Point(ev.pos(), 0)
            self.trees.append(
                {
                    "nodes": [self.p1],
                    "color": self.color_index,
                    "config": self.params.copy(),
                }
            )
            self.points.append(self.p1)
            self.current_tree_index = 0

    def mouseMoveEvent(self, ev: QtGui.QMouseEvent) -> None:
        super().mouseMoveEvent(ev)
        if self.selected:
            self.selected.setX(ev.pos().x())
            self.selected.setY(ev.pos().y())
            self.update()
        elif self.p1 is not None:
            self.p2 = ev.pos()
            self.update()

    def mouseReleaseEvent(self, ev: QtGui.QMouseEvent) -> None:
        super().mouseReleaseEvent(ev)
        if self.selected:
            self.selected = None
        elif self.p1 and self.p2:
            found = None
            for p in self.points:
                r = QRect(p.x() - 10, p.y() - 10, 20, 20)
                if r.contains(ev.pos().x(), ev.pos().y()):
                    p.setX(self.p2.x())
                    p.setY(self.p2.y())
                    found = p
                    break
            if found:
                self.current_tree().get("nodes").append(found)
                self.p1 = found
            else:
                self.p1 = Point(self.p2, len(self.points))
                self.current_tree().get("nodes").append(self.p1)
                self.points.append(self.p1)
            self.p2 = None
            self.update()

    def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
        super().paintEvent(a0)
        painter = QPainter(self)

        for tree in self.trees:
            nodes, color = tree.get("nodes"), tree.get("color")
            for i, p in enumerate(nodes):
                painter.setPen(Qt.black)
                if p.z() != 0:
                    painter.drawText(
                        QPoint(p.x() + 10, p.y() + 10),
                        str(p.index) + " z:" + str(p.z()),
                    )
                else:
                    painter.drawText(QPoint(p.x() + 10, p.y() + 10), str(p.index))

                painter.setPen(self.colors[color])
                painter.drawEllipse(p, 10, 10)
                if i > 0:
                    painter.drawLine(p, nodes[i - 1])
                    p1, p2 = p, nodes[i - 1]
                    dist = math.sqrt(
                        math.pow(p1.x() - p2.x(), 2) + math.pow(p1.y() - p2.y(), 2)
                    )
                    painter.setPen(Qt.black)
                    painter.drawText(
                        QPointF((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2),
                        "{:.1f}".format(float(dist) * self.params.get("scale", 1)),
                    )

        if self.p1 and self.p2:
            painter.setPen(QPen(self.colors[self.color_index]))
            painter.drawLine(self.p1, self.p2)
            dist = math.sqrt(
                math.pow(self.p1.x() - self.p2.x(), 2)
                + math.pow(self.p1.y() - self.p2.y(), 2)
            )
            painter.setPen(Qt.black)
            painter.drawText(
                self.p2, "{:.1f}".format(float(dist) * self.params.get("scale", 1))
            )

        if self.p1:
            painter.setPen(QPen(self.colors[self.color_index]))
            painter.drawEllipse(self.p1, 15, 15)

        if len(self.points) > 0:
            painter.setPen(QPen(Qt.red))
            painter.drawLine(
                self.rect().x(),
                self.points[0].y(),
                self.rect().width() + self.rect().x(),
                self.points[0].y(),
            )
            painter.setPen(QPen(Qt.green))
            painter.drawLine(
                self.points[0].x(),
                self.rect().y(),
                self.points[0].x(),
                self.rect().height() + self.rect().y(),
            )

    def get_trees(self):
        return self.trees

class MainWindow(QtWidgets.QMainWindow):
    model_config = '<?xml version="1.0"?>\n\
<model>\n\
  <name>$name$</name>\n\
  <version>1.0</version>\n \
  <sdf version="1.6">model.sdf</sdf>\n\
  <description>\n\
  </description>\n\
</model>'

    model_sdf = '<?xml version="1.0"?>\n\
<sdf version="1.6">\n\
  <model name="$name$">\n\
    <static>true</static>\n\
    <link name="link">\n\
      <pose>0 0 0 0 0 0</pose>\n\
      <collision name="collision">\n\
        <geometry>\n\
          <mesh>\n\
            <uri>./mesh.obj</uri>\n\
          </mesh>\n\
        </geometry>\n\
      </collision>\n\
      <visual name="visual">\n\
        <geometry>\n\
          <mesh>\n\
            <uri>./mesh.obj</uri>\n\
          </mesh>\n\
        </geometry>\n\
      </visual>\n\
    </link>\n\
  </model>\n\
</sdf>'

    def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        self.lay.setStretchFactor(0, 1)
        self.lay.setStretchFactor(1, 10)
        # self.sc.figure.set_figwidth(self.geometry().width())
        # self.sc.figure.set_figheight(self.geometry().height())

    def update_defaults(self):
        self.sketch.update_defaults(
            radius=self.radius_slider.value(),
            roughness=self.slider.value() / 10,
            floor=self.floor_slider.value(),
            scale=self.scale_slider.value() / 10,
        )

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.pd = None
        self.mesh_generator = None
        self.config = {}
        menu = QMenuBar()
        self.setMenuBar(menu)

        m1 = menu.addMenu("File")
        m1.addAction("Load", self.load_yaml)
        m1.addAction("New", self.new_yaml)
        m1.addAction("Save as ", self.save_yaml)

        m2 = menu.addMenu("Edit")
        m2.addAction("Config", self.edit)

        self.lay = QSplitter()
        self.lay.setStretchFactor(0, 1)
        self.lay.setStretchFactor(1, 10)

        self.sketch = Sketch()

        cb = QPushButton("Clear")
        cb.clicked.connect(self.sketch.clear_points)

        self.frame2 = QFrame()
        self.plotter2 = QtInteractor(self.frame2)

        vlayout = QVBoxLayout()

        render_tb = QToolBar()
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setMinimum(1)
        self.slider.setMaximum(100)
        self.slider.setTickInterval(100)

        self.radius_slider = QSlider(Qt.Horizontal)
        self.radius_slider.setValue(4)
        self.radius_slider.setMinimum(1)
        self.radius_slider.setMaximum(8)
        self.radius_slider.setTickInterval(1)

        self.floor_slider = QSlider(Qt.Horizontal)
        self.floor_slider.setMinimum(-2)
        self.floor_slider.setMaximum(1)
        self.floor_slider.setTickInterval(1)
        self.floor_slider.setValue(-1)

        # self.slider.setSingleStep(100)
        self.slider.valueChanged.connect(self.slider_changed)
        self.radius_slider.valueChanged.connect(self.radius_slider_changed)
        self.floor_slider.valueChanged.connect(self.floor_slider_changed)

        vlayout.addWidget(render_tb)

        vvlayout = QVBoxLayout()
        vvlayout.addWidget(self.plotter2.interactor)
        self.frame2.setLayout(vvlayout)

        self.tab = QTabWidget()

        tb = QToolBar()
        helper = QWidget()
        vbox = QVBoxLayout(helper)

        sa = QScrollArea()
        sa.setWidget(self.sketch)
        self.sketch.setMinimumWidth(int(1920 * 1.5))
        self.sketch.setMinimumHeight(int(1080 * 1.5))

        vbox.addWidget(tb)
        vbox.addWidget(sa)

        tb.addAction("Save", lambda: self.sketch.save(self.config.get("last"))).setIcon(
            QIcon.fromTheme("document-save")
        )
        tb.addAction("Clear", self.sketch.clear_points).setIcon(
            QIcon.fromTheme("edit-clear")
        )
        tb.addSeparator()
        tb.addAction("Delete last", self.sketch.delete_last).setIcon(
            QIcon.fromTheme("edit-undo")
        )
        tb.addSeparator()
        tb.addAction("Go", lambda: self.thread_run(self.do_create_pctl)).setIcon(
            QIcon.fromTheme("media-playback-start")
        )
        tb.addSeparator()

        self.scale_label = QLabel("Scale: 1 ")
        self.scale_label.setMinimumWidth(70)
        tb.addWidget(self.scale_label)
        self.scale_slider = QSlider()
        self.scale_slider.setMinimum(1)
        self.scale_slider.setMaximum(20)
        self.scale_slider.setValue(10)
        self.scale_slider.setOrientation(Qt.Horizontal)
        self.scale_slider.setMaximumWidth(200)
        self.scale_slider.valueChanged.connect(self.scale_slider_changed)
        tb.addWidget(self.scale_slider)

        tb.addSeparator()

        self.slider_label = QLabel("0.001")
        tb.addWidget(QLabel("Roughness: "))
        tb.addWidget(self.slider_label)
        tb.addWidget(self.slider)

        tb.addSeparator()

        self.radius_label = QLabel("4")
        tb.addWidget(QLabel("Radius: "))
        tb.addWidget(self.radius_label)
        tb.addWidget(self.radius_slider)

        tb.addSeparator()

        self.floor_label = QLabel("1")
        tb.addWidget(QLabel("Floor: "))
        tb.addWidget(self.floor_label)
        tb.addWidget(self.floor_slider)

        self.tab.addTab(helper, "Sketch")

        helper = QWidget()
        vbox = QVBoxLayout(helper)

        tb = QToolBar()
        tb.addAction("Render", lambda: self.thread_run(self.do_render_mesh)).setIcon(
            QIcon.fromTheme("media-playback-start")
        )
        tb.addAction("Save", self.save_mesh).setIcon(QIcon.fromTheme("document-save"))
        vbox.addWidget(tb)
        vbox.addWidget(self.frame2)

        self.tab.addTab(helper, "Mesh")

        self.setCentralWidget(self.tab)
        self.update_defaults()

        self.load_config()

        last = self.config.get("last")
        if last is not None and os.path.exists(last):
            self.sketch.load(last)
            self.setWindowTitle(last)

        self.show()

    def slider_changed(self):
        self.slider_label.setText(str(self.slider.value() / 1000) + " ")
        self.update_defaults()

    def radius_slider_changed(self):
        self.radius_label.setText(str(self.radius_slider.value()) + " ")
        self.update_defaults()

    def floor_slider_changed(self):
        self.floor_label.setText(str(self.floor_slider.value()) + " ")
        self.update_defaults()

    def scale_slider_changed(self):
        self.scale_label.setText(
            "Ratio: {:.1f} ".format(self.scale_slider.value() / 10)
        )
        self.update_defaults()

    def load_config(self):
        try:
            with open("config.yaml", "r") as f:
                self.config = yaml.full_load(f)
        except:
            pass

    def save_config(self):
        with open("config.yaml", "w") as f:
            yaml.dump(self.config, f)

    def save_yaml(self):
        dest, _ = QFileDialog.getSaveFileName(
            self, "Save PTG Document", self.config.get("last"), "PTG Files (*.ptg)"
        )
        if dest and dest != "":
            if not dest.endswith(".ptg"):
                dest = dest + ".ptg"
            self.setWindowTitle(self.config.get("last"))
            self.sketch.save(dest)
            self.config["last"] = dest
            self.save_config()

    def new_yaml(self):
        dest, _ = QFileDialog.getSaveFileName(
            self, "Save PTG Document", "./tunnel.ptg", "PTG Files (*.ptg)"
        )
        if dest and dest != "":
            if not dest.endswith(".ptg"):
                dest = dest + ".ptg"
            self.sketch.clear_points()
            self.config.set("last", dest)
            self.setWindowTitle(self.config.get("last"))
            self.sketch.save(dest)

    def load_yaml(self):
        file, _ = QFileDialog.getOpenFileName(
            self, "Open PTG file", "", "PTG Files (*.ptg)"
        )
        if file is not None and file != "":
            self.config.set("last", file)
            self.setWindowTitle(self.config.get("last"))
            self.sketch.load(file)
            self.config.save("gst.yaml")

    def edit(self):
        self.config.edit()
        self.config.save("gst.yaml")

    def show_mesh(self):
        mesh = pyvista.read(self.model_path + "mesh.obj")
        mesh = mesh.clip("x", invert=False, origin=(2, 0, 0))

        self.plotter2.remove_all_lights()
        pyvista.global_theme.color = "red"
        self.plotter2.clear()
        self.plotter2.enable_shadows()
        self.plotter2.set_background(color="g")
        self.plotter2.add_mesh(mesh, show_edges=True)

    def do_render_mesh(self):
        self.mesh_generator.compute_mesh()
        self.mesh_generator.compute_floors()
        plot_mesh(self.plotter2, self.mesh_generator)
        self.pd.hide()

    def do_create_pctl(self):
        # mesh = mesh.clip("x", invert=False, origin=(2, 0, 0))

        trees = self.sketch.getPoints(self.scale_slider.value() / 10)
        if trees is None:
            self.pd.hide()
            return

        self.plotter2.remove_all_lights()
        pyvista.global_theme.color = "red"
        self.plotter2.clear()
        self.plotter2.enable_shadows()
        self.plotter2.set_background(color="grey")

        tunnel_network_params = TunnelNetworkParams.from_defaults()
        tunnel_network_params.min_distance_between_intersections = 30
        tunnel_network_params.collision_distance = 15
        tunnel_network = TunnelNetwork(params=tunnel_network_params, initial_node=False)

        tunnels_config = {}
        for tree in trees:
            tunnel = Tunnel()
            for node in tree.get("tree_nodes"):
                tunnel.append_node(node)
            tunnel_network.add_tunnel(tunnel)
            tunnels_config[tunnel] = tree.get("tree_config")

        plot_graph(self.plotter2, tunnel_network)
        plot_splines(self.plotter2, tunnel_network, color="r")

        np.random.seed(0)

        ptcl_gen_params = TunnelNetworkPtClGenParams.from_defaults()

        for k, v in tunnels_config.items():
            tunnel_ptcl_gen_params = TunnelPtClGenParams.from_defaults()
            tunnel_ptcl_gen_params.noise_multiplier = v.get("roughness", 0)
            tunnel_ptcl_gen_params.radius = v.get("radius", 1)
            ptcl_gen_params.pre_set_tunnel_params[k] = tunnel_ptcl_gen_params

        mesh_gen_params = TunnelNetworkMeshGenParams.from_defaults()
        mesh_gen_params.fta_distance = 1

        self.mesh_generator = TunnelNetworkMeshGenerator(
            tunnel_network,
            ptcl_gen_params=ptcl_gen_params,
            meshing_params=mesh_gen_params,
        )

        self.mesh_generator.compute_ptcl()
        plot_tunnel_ptcls(self.plotter2, self.mesh_generator, size=0.25, color="b")
        plot_intersection_ptcls(
            self.plotter2, self.mesh_generator, size=0.25, color="r"
        )

        # self.mesh_generator.compute_mesh()
        # self.mesh_generator.compute_floors()
        # plot_mesh(self.plotter2, self.mesh_generator)

        self.tab.setTabEnabled(1, True)
        self.tab.setCurrentIndex(1)
        self.pd.hide()

    def save_mesh(self):
        if self.mesh_generator is None:
            return

        name, kind = QFileDialog.getSaveFileName(
            self, "Save Mesh", "", "OBJ Files (*.obj)"
        )

        if name is not None and name != "":
            if not name.endswith(".obj"):
                name = name + ".obj"
            self.mesh_generator.save_mesh(name)

    def thread_run(self, func):
        self.plotter2.clear()

        class Runn(QRunnable):
            def __init__(self, callback):
                super().__init__()
                self.callback = callback

            def run(self) -> None:
                self.callback()

        self.tab.setCurrentIndex(2)
        self.pd = QProgressDialog(self)
        self.pd.setMaximum(0)
        self.pd.setCancelButton(None)
        self.pd.setLabelText("Rendering")
        self.pd.setModal(True)
        self.pd.show()

        run = Runn(func)
        QThreadPool.globalInstance().start(run)

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        self.sketch.save("kakka2.yaml")

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    app.exec_()


# https://projecteuler.net/problem=56

maxSum = 0
for a in range(0, 100):
    for b in range(0, 100):
            # Convert pow(a,b) to a string, create a list of the int conversion of each character and sum it
        digitSum = sum([int(c) for c in str(pow(a,b))])
        maxSum = digitSum if digitSum > maxSum else maxSum

print(maxSum)


import subprocess
import sys

testcase = sys.argv[1]
output = sys.argv[2]

comp = True

f = open(output)
outstr = f.read().strip().split()
f.close()

try:
    compiling = subprocess.check_output("gcc /app/golden_ticket.c -o /app/golden_ticket", shell=True)
except:
    comp = False
    print("fail")

if comp:
    try:
        cmd = subprocess.check_output(f"cat {testcase} | /app/golden_ticket", shell=True).decode().strip().split()
        if cmd==outstr:
            print("pass")
        else:
            print("fail")
    except:
        print("fail")


def divide(x,y,m,n):
    global a
    if m==n:
        return a[m][n]
    else:
        return divide(0,0,m/2,n/2)
        return divide

a=[[1, 2, 3, 4, 5],[2 ,4 ,6 ,1, 7],[1, 3, 4, 5, 9] ]
m=3
n=5
print(divide(0,0))

AN 1 SEM 1/Programarea algoritmilor/divide et impera/pbinfo.py


class UF:
    def __init__(self, n):
        self.count = n
        self.id = [x for x in range(n)]
        self.size = [1 for _ in range(n)]

    def find(self, p):
        while p != self.id[p]:
            p = self.id[p]
        return p

    def connected(self, p, q):
        return self.find(p) == self.find(q)

    def union(self, p, q):
        p = self.find(p)
        q = self.find(q)

        if not self.connected(p, q):
            if self.size[p] < self.size[q]:
                self.id[p] = q
                self.size[q] += self.size[p]
            else:
                self.id[q] = p
                self.size[p] += self.size[q]
            self.count -= 1

    def __repr__(self):
        res = ''
        for i in range(len(self.id)):
            res += str(self.id[i]) + ' '
        return res[:-1]

uf = UF(5)
print(uf)
uf.union(1, 2)
uf.union(3, 4)
print(uf)
print(uf.count)


# -*- coding: utf-8 -*-
# @Time    : 2023/7/3 8:43 下午
# @Author  : 顾安
# @File    : 5.事件循环的创建.py
# @Software: PyCharm

"""
python3.7以上版本中不需要我们自己手动创建事件循环
    在代码底层自动帮助我们创建

使用python3.6的语法创建一个事件循环
"""

import asyncio

async def work_1():
    for _ in range(5):
        print('协程任务 - 1')
        await asyncio.sleep(1)

async def work_2():
    for _ in range(5):
        print('协程任务 - 2')
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()  # 创建一个事件循环

# 当前列表中存储的是协程对象
coroutines = [
    work_1(),
    work_2()
]

done, pending = loop.run_until_complete(asyncio.wait(coroutines))

for item in done:
    print(type(item))

"""
1.事件循环如何创建 - get_event_loop
2.如何去运行事件循环 - run_until_complete
"""

5.事件循环的创建.py


from world.magic.spell_factory import SpellFactory

class SpellHandler():

    def __init__(self, caller, spell_name, target_list):
        self.caller = caller
        self.spell_name = spell_name.strip()
        self.target_list = target_list or self.caller

    def init_spell(self):
        spell_name = self.spell_name.lower()
        if spell_name is None:
            spell_name == ''
        spell = SpellFactory.get_spell_instc(self.caller, spell_name, self.target_list)
        if spell.has_enough_mana():
            spell.action()
        else:
            self.caller.msg("You don't have enough mana to do that")
            self.caller.msg("The current mana level is " +
                            str(self.caller.db.mana) +
                            " the cost to cast is " + str(spell.mana_cost))


import re

from bs4 import BeautifulSoup
from decimal import Decimal

from requests import TooManyRedirects

from storescraper.product import Product
from storescraper.store_with_url_extensions import StoreWithUrlExtensions
from storescraper.utils import session_with_proxy, html_to_markdown, \
    remove_words
from storescraper.categories import NOTEBOOK, ALL_IN_ONE, TABLET, \
    EXTERNAL_STORAGE_DRIVE, SOLID_STATE_DRIVE, MEMORY_CARD, \
    USB_FLASH_DRIVE, PROCESSOR, COMPUTER_CASE, POWER_SUPPLY, MOTHERBOARD, \
    RAM, VIDEO_CARD, MOUSE, PRINTER, HEADPHONES, STEREO_SYSTEM, UPS, MONITOR, \
    KEYBOARD_MOUSE_COMBO, KEYBOARD, GAMING_CHAIR, WEARABLE, \
    STORAGE_DRIVE

class Cintegral(StoreWithUrlExtensions):
    url_extensions = [
        ['109', NOTEBOOK],
        ['110', ALL_IN_ONE],
        ['176', TABLET],
        ['157', PRINTER],
        ['156', PRINTER],
        ['129', PRINTER],
        ['152', PRINTER],
        ['181', STORAGE_DRIVE],
        ['182', EXTERNAL_STORAGE_DRIVE],
        ['183', SOLID_STATE_DRIVE],
        ['184', MEMORY_CARD],
        ['185', USB_FLASH_DRIVE],
        ['116', POWER_SUPPLY],
        ['115', COMPUTER_CASE],
        ['118', RAM],
        ['117', MOTHERBOARD],
        ['114', PROCESSOR],
        ['119', VIDEO_CARD],
        ['96', MONITOR],
        ['122', KEYBOARD_MOUSE_COMBO],
        ['123', MOUSE],
        ['121', KEYBOARD],
        ['161', NOTEBOOK],
        ['163', WEARABLE],
        ['162', TABLET],
        ['164', KEYBOARD],
        ['139', HEADPHONES],
        ['140', STEREO_SYSTEM],
        ['153', GAMING_CHAIR],
        ['86', WEARABLE],
        ['168', VIDEO_CARD],
        ['160', MONITOR],
        ['159', NOTEBOOK],
        ['172', SOLID_STATE_DRIVE],
        ['171', POWER_SUPPLY],
        ['167', MOUSE],
        ['170', MOTHERBOARD],
        ['169', PROCESSOR],
        ['166', GAMING_CHAIR],
        ['178', RAM],
        ['106', NOTEBOOK],
        ['141', UPS],
    ]

    @classmethod
    def discover_urls_for_url_extension(cls, url_extension, extra_args=None):
        product_urls = []
        session = session_with_proxy(extra_args)
        session.headers['Content-Type'] = 'application/x-www-form-urlencoded'
        page = 1

        while True:
            if page >= 20:
                raise Exception('Page overflow: ' + url_extension)

            payload = ('action=jet_smart_filters&provider=jet-engine/default&'
                       'query[_tax_query_product_cat][]={}&'
                       'settings[lisitng_id]=645&referrer[uri]=/'
                       '?jsf=jet-engine&pagenum={}').format(
                url_extension, page)
            print(payload)

            res = session.post('https://cintegral.cl/wp-admin/admin-ajax.php',
                               payload)
            json_data = res.json()
            soup = BeautifulSoup(json_data['content'], 'html.parser')
            product_tags = soup.findAll('div', 'jet-listing-grid__item')

            if not product_tags:
                break

            for product_tag in product_tags:
                product_url = product_tag.find(
                    'a', 'jet-listing-dynamic-image__link')['href']
                product_urls.append(product_url)

            page += 1

        return product_urls

    @classmethod
    def products_for_url(cls, url, category=None, extra_args=None):
        print(url)
        session = session_with_proxy(extra_args)
        try:
            res = session.get(url)
        except TooManyRedirects:
            return []
        soup = BeautifulSoup(res.text, 'html.parser')

        name = soup.find('h1', 'product_title').text.strip()
        new_key = soup.find('link', {'rel': 'shortlink'})['href'].split(
            '?p=')[-1]
        old_key = re.match(r'https://cintegral.cl/producto/(\d+)',
                           url).groups()[0]

        stock_label_tag = soup.find('span', text='Stock Web:')
        stock_tag = stock_label_tag.next.next
        stock_match = re.search(r'(\d+)', stock_tag.text.strip())
        if not stock_match:
            return []
        stock = int(stock_match.groups()[0])

        prices_tag = soup.find('div', 'elementor-element-9386c30')

        normal_price_label_tag = prices_tag.find(
            'div', text='Pago con Tarjeta')
        if normal_price_label_tag:
            normal_price = Decimal(
                remove_words(normal_price_label_tag.next.next.text))

            offer_price_label_tag = prices_tag.find(
                'div', text='Pago transferencia')
            offer_price = Decimal(remove_words(
                offer_price_label_tag.next.next.text))
        else:
            price_label_tag = prices_tag.find('div', text='Todo Medio de Pago')
            price = Decimal(
                remove_words(price_label_tag.next.next.text))
            normal_price = offer_price = price

        mpn_label_tag = prices_tag.find('span', text='Part Number:')
        if mpn_label_tag:
            part_number = mpn_label_tag.next.next.strip()
        else:
            part_number = None

        description = html_to_markdown(str(
            soup.find('div', 'woocommerce-Tabs-panel--description')))

        picture_urls = [soup.find('meta', {'property': 'og:image'})['content']]

        if 'REACONDICIONADO' in name.upper():
            condition = 'https://schema.org/RefurbishedCondition'
        else:
            condition = 'https://schema.org/NewCondition'

        p = Product(
            name,
            cls.__name__,
            category,
            url,
            url,
            new_key,
            stock,
            normal_price,
            offer_price,
            'CLP',
            sku=old_key,
            part_number=part_number,
            description=description,
            picture_urls=picture_urls,
            condition=condition
        )

        return [p]


""" PagerMaid module to handle sticker collection. """

from PIL import Image, ImageDraw, ImageFilter
from os.path import exists
from os import remove
from requests import get
from random import randint
from telethon.tl.functions.users import GetFullUserRequest
from telethon.tl.types import MessageEntityMentionName
from telethon.errors.rpcerrorlist import ChatSendStickersForbiddenError
from struct import error as StructError
from pagermaid import version
from pagermaid.listener import listener
from pagermaid.utils import alias_command

def crop_max_square(pil_img):
    return crop_center(pil_img, min(pil_img.size), min(pil_img.size))

def crop_center(pil_img, crop_width, crop_height):
    img_width, img_height = pil_img.size
    return pil_img.crop(((img_width - crop_width) // 2,
                         (img_height - crop_height) // 2,
                         (img_width + crop_width) // 2,
                         (img_height + crop_height) // 2))

def mask_circle_transparent(pil_img, blur_radius, offset=0):
    offset = blur_radius * 2 + offset
    mask = Image.new("L", pil_img.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.ellipse((offset, offset, pil_img.size[0] - offset, pil_img.size[1] - offset), fill=255)
    mask = mask.filter(ImageFilter.GaussianBlur(blur_radius))

    result = pil_img.copy()
    result.putalpha(mask)
    return result

@listener(is_plugin=True, outgoing=True, command=alias_command("diu"),
          description="生成一张 扔头像 图片，（可选：当第二个参数存在时，旋转用户头像 180°）",
          parameters="<username/uid> [随意内容]")
async def throwit(context):
    if len(context.parameter) > 2:
        await context.edit("出错了呜呜呜 ~ 无效的参数。")
        return
    diu_round = False
    await context.edit("正在生成 扔头像 图片中 . . .")
    if context.reply_to_msg_id:
        reply_message = await context.get_reply_message()
        if reply_message:
            user_id = reply_message.from_id
            target_user = await context.client(GetFullUserRequest(user_id))
            if len(context.parameter) == 1:
                diu_round = True
        else:
            await context.edit('出错了呜呜呜 ~ 无法获取所回复的用户。')
            return
    else:
        if len(context.parameter) == 1 or len(context.parameter) == 2:
            user = context.parameter[0]
            if user.isnumeric():
                user = int(user)
        else:
            user_object = await context.client.get_me()
            user = user_object.id
        if context.message.entities is not None:
            if isinstance(context.message.entities[0], MessageEntityMentionName):
                return await context.client(GetFullUserRequest(context.message.entities[0].user_id))
        try:
            user_object = await context.client.get_entity(user)
            target_user = await context.client(GetFullUserRequest(user_object.id))
        except (TypeError, ValueError, OverflowError, StructError) as exception:
            if str(exception).startswith("Cannot find any entity corresponding to"):
                await context.edit("出错了呜呜呜 ~ 指定的用户不存在。")
                return
            if str(exception).startswith("No user has"):
                await context.edit("出错了呜呜呜 ~ 指定的道纹不存在。")
                return
            if str(exception).startswith("Could not find the input entity for") or isinstance(exception, StructError):
                await context.edit("出错了呜呜呜 ~ 无法通过此 UserID 找到对应的用户。")
                return
            if isinstance(exception, OverflowError):
                await context.edit("出错了呜呜呜 ~ 指定的 UserID 已超出长度限制，您确定输对了？")
                return
            raise exception
    photo = await context.client.download_profile_photo(
        target_user.user.id,
        "plugins/throwit/" + str(target_user.user.id) + ".jpg",
        download_big=True
    )
    reply_to = context.message.reply_to_msg_id
    if exists("plugins/throwit/" + str(target_user.user.id) + ".jpg"):
        if not exists('plugins/throwit/1.png'):
            r = get('https://gitlab.com/Xtao-Labs/PagerMaid_Plugins/-/raw/master/throwit/1.png')
            with open("plugins/throwit/1.png", "wb") as code:
                code.write(r.content)
        if not exists('plugins/throwit/2.png'):
            r = get('https://gitlab.com/Xtao-Labs/PagerMaid_Plugins/-/raw/master/throwit/2.png')
            with open("plugins/throwit/2.png", "wb") as code:
                code.write(r.content)
        if not exists('plugins/throwit/3.png'):
            r = get('https://gitlab.com/Xtao-Labs/PagerMaid_Plugins/-/raw/master/throwit/3.png')
            with open("plugins/throwit/3.png", "wb") as code:
                code.write(r.content)
        # 随机数生成
        randint_r = randint(1, 3)
        # 将头像转为圆形
        markImg = Image.open("plugins/throwit/" + str(target_user.user.id) + ".jpg")
        if randint_r == 1:
            thumb_width = 136
        elif randint_r == 2:
            thumb_width = 122
        elif randint_r == 3:
            thumb_width = 180
        im_square = crop_max_square(markImg).resize((thumb_width, thumb_width), Image.LANCZOS)
        im_thumb = mask_circle_transparent(im_square, 0)
        im_thumb.save("plugins/throwit/" + str(target_user.user.id) + ".png")
        # 将头像复制到模板上
        if randint_r == 1:
            background = Image.open("plugins/throwit/2.png")
        elif randint_r == 2:
            background = Image.open("plugins/throwit/1.png")
        elif randint_r == 3:
            background = Image.open("plugins/throwit/3.png")
        foreground = Image.open("plugins/throwit/" + str(target_user.user.id) + ".png")
        if len(context.parameter) == 2:
            diu_round = True
        if diu_round:
            foreground = foreground.rotate(180)  # 对图片进行旋转
        if randint_r == 1:
            background.paste(foreground, (19, 181), foreground)
        elif randint_r == 2:
            background.paste(foreground, (368, 16), foreground)
        elif randint_r == 3:
            background.paste(foreground, (331, 281), foreground)
        background.save('plugins/throwit/throwout.webp')
        target_file = await context.client.upload_file('plugins/throwit/throwout.webp')
        try:
            remove("plugins/throwit/" + str(target_user.user.id) + ".jpg")
            remove("plugins/throwit/" + str(target_user.user.id) + ".png")
            remove("plugins/throwit/throwout.webp")
            remove(photo)
        except:
            pass
    else:
        await context.edit("此用户未设置头像或头像对您不可见。")
        return
    if reply_to:
        try:
            await context.client.send_file(
                context.chat_id,
                target_file,
                link_preview=False,
                force_document=False,
                reply_to=reply_to
            )
            await context.delete()
            try:
                remove(photo)
            except:
                pass
            return
        except TypeError:
            await context.edit("此用户未设置头像或头像对您不可见。")
        except ChatSendStickersForbiddenError:
            await context.edit("此群组无法发送贴纸。")
    else:
        try:
            await context.client.send_file(
                context.chat_id,
                target_file,
                link_preview=False,
                force_document=False
            )
            await context.delete()
            try:
                remove(photo)
            except:
                pass
            return
        except TypeError:
            await context.edit("此用户未设置头像或头像对您不可见。")
        except ChatSendStickersForbiddenError:
            await context.edit("此群组无法发送贴纸。")