import abc
import optparse
import random
import numpy as np
from typing import cast
from scipy import signal
from scipy import fft
from scipy import interpolate
from matplotlib import colormaps
from math import ceil
from pytui import StyledWindow, Plot, Text
from radio import Radio, RtlRadio, PlutoRadio

# returns a matplotlib color map as rgb tuples
def get_colormap(name: str) -> list[tuple[int, int, int]]:
    colors = [colormaps[name](x) for x in range(0, 256)]
    return [(int(r*255), int(g*255), int(b*255)) for (r, g, b, a) in colors]

# returns a gradient between two colors as rgb tuples
def color_gradient(
    start: tuple[int, int, int],
    end: tuple[int, int, int],
    n: int
) -> list[tuple[int, int, int]]:
    gradient = [start]
    for t in range(1, n):
        gradient.append(cast(tuple[int, int, int], tuple([
          int(start[j] + (float(t)/(n-1))*(end[j]-start[j]))
          for j in range(3)
        ])))
    return gradient

def get_matrix_colormap() -> list[tuple[int, int, int]]:
    black = (0, 0, 0)
    vampire = (0x0d, 0x02, 0x08)
    dark_green = (0x00, 0x3b, 0x00)
    islamic_green = (0x00, 0x8f, 0x11)
    malachite = (0x00, 0xff, 0x41)
    return (
        color_gradient(black, vampire, 96)
        + color_gradient(vampire, dark_green, 32)
        + color_gradient(dark_green, islamic_green, 64)
        + color_gradient(islamic_green, malachite, 64)
    )

Styles: dict[str, dict] = {
    # colors from
    # https://marketplace.visualstudio.com/items?itemName=enkia.tokyo-night
    'tokyonight': {
        'waterfall-glyph': lambda: '█',
        'colormap': get_colormap('viridis'),
        'header': {'bg': 0x1a1b26, 'fg': 0xa9b1d6},
        # 'plot': {'bg': 0x24283b, 'fg': 0xf7768e},   # red
        'plot': {'bg': 0x24283b, 'fg': 0x7aa2f7},   # blue
        'plot-label': {'bg': 0x24283b, 'fg': 0x565f89}
    },

    # https://matplotlib.org/matplotblog/posts/matplotlib-cyberpunk-style/
    'cyberpunk': {
        'waterfall-glyph': lambda: '█',
        'colormap': get_colormap('viridis'),
        'header': {'bg': 0x2A3459, 'fg': 0x08F7FE},
        # 'plot': {'bg': 0x2A3459, 'fg': 0x08F7FE},
        'plot': {'bg': 0x2A3459, 'fg': 0xFE53BB},
        'plot-label': {'bg': 0x2A3459, 'fg': 0x08F7FE}
    },

    # https://www.schemecolor.com/matrix-code-green.php
    'matrix': {
        'waterfall-glyph': lambda: random.choice(
            'ｦｱｲｳｴｵｶｷｸｹｺｻｼｽｾｿﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜﾝ'
        ),
        'colormap': get_matrix_colormap(),
        'header': {'bg': 0x0d0208, 'fg': 0x008f11},
        'plot': {'bg': 0x0d0208, 'fg': 0x00ff41},
        'plot-label': {'bg': 0x0d0208, 'fg': 0x008f11}
    },

    # https://www.nordtheme.com/docs/colors-and-palettes
    'nord': {
        'waterfall-glyph': lambda: '█',
        'colormap': get_colormap('cividis'),
        'header': {'bg': 0xd8dee9, 'fg': 0x81a1c1},
        'plot': {'bg': 0xeceff4, 'fg': 0x2e3440},
        'plot-label': {'bg': 0xd8dee9, 'fg': 0x81a1c1}
    },

}

def format_freq(f: float) -> str:
    if f >= 1e9:
        (f, s) = (f/1e6, 'Ghz')
    else:
        (f, s) = (f/1e3, 'Mhz')

    return f'{(f/1000):.4f}'.rstrip('0').rstrip('.') + ' ' + s

def make_frequency_labels(width: int, start: float, end: float) -> str:
    # *2 to account for flipping at midpoint
    maxWidth = 2*len('|999.9999 Mhz ')
    n = ceil(width/maxWidth)
    # ensure odd number of ticks to get one in the middle
    n = n-1 if n % 2 == 0 else n

    ticks = np.linspace(0, width, n)
    values = np.linspace(start, end, len(ticks))
    labels = ''.ljust(width)

    for i in range(0, n):
        hz = format_freq(values[i])
        if i < n / 2:
            (hz, x) = ('|'+hz, int(ticks[i]))
        else:
            (hz, x) = (hz+'|', int(ticks[i]) - len(hz+'|'))
        labels = labels[:x] + hz + labels[x + len(hz):]

    return labels

def make_db_labels(width: int, height: int, mindb: float, maxdb: float) -> str:
    scale = [' '.ljust(width)]*height
    labels = np.linspace(maxdb, mindb, height//2)
    for i, label in enumerate(labels):
        scale[i*2] = str(round(label)).rjust(width)
    return "\n".join(scale)

def get_psd(
    sample: list[np.complex64],
    window: str = 'hann',
    nperseg: int = None,
    fs: int = None
) -> list[float]:
    if nperseg is None or nperseg == len(sample):
        _, power = signal.periodogram(
            sample,
            window=window,
            return_onesided=False
        )
    else:
        _, power = signal.welch(
            sample,
            window=window,
            return_onesided=False,
            nperseg=nperseg,
            fs=fs
        )
    return fft.fftshift(power)

def to_db(values: list[float]) -> list[float]:
    return list(10.0 * np.log10(values))

def zero_adjust(values: list[float], offset: float) -> list[float]:
    return [x - offset for x in values]

def to_dbfs(values: list[float], offset: float) -> list[float]:
    return zero_adjust(to_db(values), offset)

# fits a list of one size to another by lerping the values
def fit_values(values: list[float], length: int) -> list[float]:
    if len(values) == length:
        return values
    # create function to interpolate from 0-length to values
    x = np.arange(0, len(values))
    f = interpolate.interp1d(np.arange(0, len(values)), values, kind='nearest')
    # linearly subdivide x into length sample
    sx = np.linspace(x[0], x[-1], length)
    # scale sample into new length
    return f(sx)

class Visualizer(abc.ABC):
    def __init__(
        self,
        radio: Radio,
        style: dict = Styles['tokyonight']
    ) -> None:
        self.radio = radio
        self.windows: list[StyledWindow] = []
        self.style = style

    @abc.abstractmethod
    def layout(self, container: StyledWindow) -> None:
        pass

    @abc.abstractmethod
    def update_sample(self, sample: list[np.complex64]) -> None:
        pass

    @abc.abstractmethod
    def update_radio(self, radio: Radio) -> None:
        pass

    def draw(self) -> None:
        for window in self.windows:
            window.draw()

class FFTVisualizer(Visualizer):
    def __init__(
        self,
        radio: Radio,
        mindbfs: int = 0,
        maxdbfs: int = 50,
        nperseg: int = 1024,
        window: str = 'hann',
        zoff: float = -1.0,
        style: dict = Styles['tokyonight']
    ) -> None:
        super().__init__(radio, style)
        self.mindbfs = mindbfs
        self.maxdbfs = maxdbfs
        self.nperseg = nperseg
        self.window = window
        self.zoff = zoff

    def get_dbfs(self, sample: list[np.complex64]) -> list[float]:
        return to_dbfs(get_psd(
            sample,
            window=self.window,
            nperseg=self.nperseg,
            fs=self.radio.rx_bw()
        ), self.zoff)

class Seek(FFTVisualizer):
    def __init__(
        self,
        radio: Radio,
        fstart: float,
        fstop: float,
        mindbfs: int = 0,
        maxdbfs: int = 50,
        nperseg: int = 1024,
        window: str = 'hann',
        zoff: float = -1.0,
        style: dict = Styles['tokyonight']
    ) -> None:
        super().__init__(radio, mindbfs, maxdbfs, nperseg, window, zoff, style)
        self.fstart = fstart
        self.fstop = fstop
        self.signals: dict[int, float] = {}

    def find_signals(
        self,
        sample: list[np.complex64]
    ) -> list[tuple[int, float]]:
        dbfs = self.get_dbfs(sample)
        return [(i, x) for i, x in enumerate(dbfs) if x >= self.mindbfs]

    def have_signal(self, sample: list[np.complex64]) -> bool:
        return len(self.find_signals(sample)) > 0

    def layout(self, container: StyledWindow) -> None:
        dbwidth = max(len(str(self.mindbfs)), len(str(self.maxdbfs)))

        (self.header, body) = container.hsplit(1)
        (self.yaxis, body) = body.vsplit(dbwidth)
        (self.plot, self.xaxis) = body.hsplit(None, 1)

        self.windows = [self.header, self.plot, self.xaxis, self.yaxis]

        self.header.update_style(self.style['header'])
        self.plot.update_style(self.style['plot'])
        self.xaxis.update_style(self.style['plot-label'])
        self.yaxis.update_style(self.style['plot-label'])

        self.update_header()
        self.update_yaxis()
        self.update_xaxis()

    def update_header(self) -> None:
        f = self.radio.rx_freq()
        peak = 'None'
        if self.signals:
            peakf = max(self.signals, key=lambda k: self.signals[k])
            peakdb = round(self.signals[peakf])
            peak = f'{peakf:8} ({peakdb})'

        self.header.update_content(
            f'now:{f:8} | '
            f'peak:{peak}'
        )

    def update_xaxis(self) -> None:
        self.xaxis.update_content(make_frequency_labels(
            self.xaxis.width, self.fstart, self.fstop
        ))

    def update_yaxis(self) -> None:
        self.yaxis.update_content(make_db_labels(
            self.yaxis.width,
            self.yaxis.height-1,  # account for xaxis labels
            self.mindbfs,
            self.maxdbfs
        ))

    def update_plot(self) -> None:
        plot = Plot(
            self.plot.width,
            self.plot.height,
            self.fstart,
            self.mindbfs,
            self.fstop,
            self.maxdbfs
        )

        for freq, dbfs in self.signals.items():
            plot.point(freq, dbfs)

        self.plot.update_content(plot.draw())

    def update_sample(self, sample: list[np.complex64]) -> None:
        signals = self.find_signals(sample)
        update = False

        for foff, dbfs in signals:
            freq = self.radio.rx_freq()+(foff-self.radio.rx_bw()//2)

            if freq not in self.signals or self.signals[freq] < dbfs:
                update = True
                self.signals[freq] = dbfs
                if dbfs > self.maxdbfs:
                    self.maxdbfs = round(dbfs)

        if update:
            self.update_yaxis()
            self.update_plot()

    def update_radio(self, radio: Radio) -> None:
        self.radio = radio
        self.update_header()

class PSD(FFTVisualizer):
    def layout(self, container: StyledWindow) -> None:
        dbwidth = max(len(str(self.mindbfs)), len(str(self.maxdbfs)))
        (self.yaxis, body) = container.vsplit(dbwidth)
        (self.plot, self.xaxis) = body.hsplit(None, 1)

        self.windows = [self.plot, self.xaxis, self.yaxis]

        self.plot.update_style(self.style['plot'])
        self.xaxis.update_style(self.style['plot-label'])
        self.yaxis.update_style(self.style['plot-label'])

        self.update_yaxis()
        self.update_xaxis()

    def update_xaxis(self) -> None:
        f = self.radio.rx_freq()
        r = self.radio.rx_bw()
        self.xaxis.update_content(make_frequency_labels(
            self.xaxis.width, f-r/2, f+r/2
        ))

    def update_yaxis(self) -> None:
        self.yaxis.update_content(make_db_labels(
            self.yaxis.width,
            self.yaxis.height-1,  # account for xaxis labels
            self.mindbfs,
            self.maxdbfs
        ))

    def update_plot(self, values: list[float]) -> None:
        plot = Plot(
            self.plot.width,
            self.plot.height,
            0,
            self.mindbfs,
            len(values),
            self.maxdbfs
        )

        (x1, y1) = (0, values[0])
        for x in range(1, len(values)):
            y = values[x]
            plot.line(x1, y1, x, y)
            (x1, y1) = (x, y)

        self.plot.update_content(plot.draw())

    def update_sample(self, sample: list[np.complex64]) -> None:
        self.update_plot(self.get_dbfs(sample))

    def update_radio(self, radio: Radio) -> None:
        self.radio = radio
        self.update_xaxis()

class Waterfall(FFTVisualizer):
    def layout(self, container: StyledWindow) -> None:
        (self.waterfall, self.xaxis) = container.hsplit(None, 1)
        self.windows = [self.waterfall, self.xaxis]

        self.xaxis.update_style(self.style['plot-label'])
        self.update_xaxis()

    def update_xaxis(self) -> None:
        f = self.radio.rx_freq()
        r = self.radio.rx_bw()
        self.xaxis.update_content(make_frequency_labels(
            self.xaxis.width, f-r/2, f+r/2
        ))

    def update_sample(self, sample: list[np.complex64]) -> None:
        def norm(x: float) -> int:
            x = min(max(x, self.mindbfs), self.maxdbfs)
            return int((x-self.mindbfs)/(self.maxdbfs-self.mindbfs) * 255)

        dbfs = self.get_dbfs(sample)

        # lerp to waterfall width and normalize values to 0-255
        values = [norm(x) for x in fit_values(dbfs, self.waterfall.width)]

        # map to rgb value in style colormap
        colors = [self.style['colormap'][x] for x in values]

        # map to styled glyph
        chars = [
            Text(self.style['waterfall-glyph']()).style({
                'bg': self.style['plot']['bg'],
                'fg': x
            })
            for x in colors
        ]

        self.waterfall.append_line(''.join(chars))

    def update_radio(self, radio: Radio) -> None:
        self.radio = radio
        self.update_xaxis()

class Constellation(Visualizer):
    def __init__(
        self,
        radio: Radio,
        iqrange: int = 1,
        style: dict = Styles['tokyonight']
    ) -> None:
        super().__init__(radio, style)
        self.iqrange = iqrange

    def layout(self, container: StyledWindow) -> None:
        self.plot = container
        self.plot.update_style(self.style['plot'])
        self.windows = [self.plot]

    def update_sample(self, sample: list[np.complex64]) -> None:
        r = self.iqrange
        plot = Plot(self.plot.width, self.plot.height, -r, -r, r, r)
        # axis
        plot.line(-r, 0, r, 0)
        plot.line(0, r, 0, -r)
        # iq points
        for point in zip(np.real(sample), np.imag(sample)):
            plot.point(point[0], point[1])
        self.plot.update_content(plot.draw())

    def update_radio(self, radio: Radio) -> None:
        pass

def parse_frange(radio: Radio, options: optparse.Values) -> tuple[int, int]:
    minf = radio.min_freq()
    maxf = radio.max_freq()

    if options.frange is None:
        return (minf, maxf)
    else:
        (fstart, fstop) = options.frange.split(':')
        fstart = minf if fstart == '' else min(maxf, max(minf, int(fstart)))
        fstop = maxf if fstop == '' else min(maxf, max(minf, int(fstop)))
        if fstart > fstop:
            raise optparse.OptionValueError('start frequency higher than stop')
        options.frange = (fstart, fstop)
    return options.frange

def config_visualizer(
    name: str,
    radio: Radio,
    options: optparse.Values
) -> Visualizer:
    (fftsize, nperseg) = (options.fftsize, options.nperseg)
    # default to non-segmented periodogram for RtlRadio
    dnperseg = fftsize if isinstance(radio, RtlRadio) else fftsize//4
    nperseg = dnperseg if nperseg is None else min(fftsize, nperseg)

    if name == 'psd':
        return PSD(
            radio,
            mindbfs=options.mindbfs,
            maxdbfs=options.maxdbfs,
            nperseg=nperseg,
            window=options.window,
            zoff=-1.0,
            style=Styles[options.style]
        )
    elif name == 'waterfall':
        return Waterfall(
            radio,
            mindbfs=options.mindbfs,
            maxdbfs=options.maxdbfs,
            nperseg=nperseg,
            window=options.window,
            zoff=-1.0,
            style=Styles[options.style]
        )
    elif name == 'seek':
        (fstart, fstop) = parse_frange(radio, options)

        return Seek(
            radio,
            fstart=fstart,
            fstop=fstop,
            mindbfs=options.mindbfs,
            nperseg=nperseg,
            window=options.window,
            zoff=-1.0,
            style=Styles[options.style]
        )
    elif name == 'constellation':
        iqrange = 16384 if isinstance(radio, PlutoRadio) else 1
        return Constellation(radio, iqrange, Styles[options.style])
    else:
        raise optparse.OptionValueError(f'unknown visualizer {name}.')


from Tkinter import *

def callback():
	popup_window = Toplevel()
	label = Label(popup_window,text = "window label")
	label.grid(row = 0)

root = Tk()

button = Button(root,text = "Popup",command = callback)
button.grid(row = 0)

root.mainloop()


# coding: utf-8
# @Time   : 2018/10/4 9:29
# @Author : Milo
# @Email  : 1612562704@qq.com

'''

给定两个以字符串形式表示的非负整数 num1 和 num2，返回 num1 和 num2 的乘积，它们的乘积也表示为字符串形式。

说明：

1.num1 和 num2 的长度小于110。
2.num1 和 num2 只包含数字 0-9。
3.num1 和 num2 均不以零开头，除非是数字 0 本身。
4.不能使用任何标准库的大数类型（比如 BigInteger）或直接将输入转换为整数来处理。
'''

class Solution:
    def multiply(self, num1, num2):
        res = [0 for i in range(len(num1+num2))]
        num1 = num1[::-1]
        num2 = num2[::-1]
        print(res)
        for i in range(len(num2)):
            for j in range(len(num1)):
                res[i+j] += int(num2[i]) * int(num1[j])
        print(res)
        result = []
        for i in range(len(res)):
            digit = res[i] % 10
            carry = res[i] // 10
            if i < len(res) - 1:
                res[i+1] += carry
            result.append(str(digit))
        result.reverse()
        while result[0] == "0" and len(result)>1:
            del result[0]
        print(result)
        return "".join(result)

a = Solution()
print(a.multiply("0","123400"))
print(999*123400)


from datetime import datetime, timedelta

import shippo
from tests.helper import create_mock_international_transaction, ShippoTestCase, DUMMY_PICKUP, shippo_vcr

class PickupTests(ShippoTestCase):
    request_client = shippo.http_client.RequestsClient

    @shippo_vcr.use_cassette(cassette_library_dir="tests/fixtures/pickup")
    def test_create(self):
        transaction, carrier_account = create_mock_international_transaction()
        PICKUP = DUMMY_PICKUP
        PICKUP["carrier_account"] = carrier_account
        PICKUP["transactions"] = [transaction.object_id]
        pickupTimeStart = datetime.now() + timedelta(hours=1)
        pickupTimeEnd = pickupTimeStart + timedelta(days=1)
        PICKUP["pickupTimeStart"] = pickupTimeStart.isoformat() + "Z"
        PICKUP["pickupTimeEnd"] = pickupTimeEnd.isoformat() + "Z"
        try:
            pickup = shippo.Pickup.create(**PICKUP)
        except shippo.error.InvalidRequestError:
            self.skipTest("Invalid request error")
        else:
            self.assertEqual(pickup.status, "SUCCESS")


#!/usr/bin/env python3
"""Discord app."""
import asyncio
import curses
import os
import subprocess

import discord
import requests

import theme as thm
import ui as UI

class Client(discord.Client):
    """Wrapper around discord.Client class."""

    def __init__(self, callback, theme):
        super(Client, self).__init__()
        self.callback = callback
        self.theme = theme
        self.ui = None

    def set_ui(self, ui):
        """UI setter."""
        self.ui = ui

    def chan(self, message):
        """Return the wrapper.Channel object of a message."""
        if self.ui is None:
            return None
        if message.channel.is_private:
            server = self.ui.servers[0]
        else:
            server = self.ui.servers.get(message.server.id)
        if server is None:
            return None
        return server[message.channel.id]

    async def on_message(self, message):
        """Add message to channel and handle mentions."""
        # Download avatar to cache
        asyncio.get_event_loop().run_in_executor(None, download_avatar, message.author)

        chan = self.chan(message)
        if chan is None:
            return
        print(message.author.name, message.content, file=open('log', 'a'))
        chan.add_message(message)
        if chan == self.ui.channel:
            self.ui.pad.redraw()
        else:
            mentioned = False
            # Direct mentions
            if any([member for member in message.mentions if member.id == self.user.id]):
                mentioned = True
            # Role mentions
            if message.server is not None:
                roles = message.server.get_member(self.user.id).roles
                if any([r in roles for r in message.role_mentions]):
                    mentioned = True
            # @everyone / @here mentions
            if '@everyone' in message.content or '@here' in message.content:
                mentioned = True
            # Direct messages
            if message.channel.is_private:
                mentioned = True
            if mentioned and message.author.id != self.user.id:
                chan.mentions += 1
                # Desktop notifications (Linux only)
                subprocess.Popen(['notify-send',
                                  '-i', '/tmp/%s.png' % message.author.avatar,
                                  message.author.name, message.clean_content])
            # If we're currently focusing the server in which the message happened
            if self.ui.server is not None and ((message.server is None and self.ui.server.id == 0) or
                                               (message.server is not None and message.server.id == self.ui.server.id)):
                self.ui.chan.redraw()
            self.ui.serv.redraw()
            chan.unread = True
        self.ui.draw()
        self.ui.refresh()

    async def on_message_delete(self, message):
        """Delete message from channel."""
        chan = self.chan(message)
        if chan is None:
            return
        chan.delete_message(message)
        if chan == self.ui.channel:
            self.ui.pad.redraw()
            self.ui.draw()
            self.ui.refresh()

    async def on_message_edit(self, before, after):
        """Edit message in channel."""
        chan = self.chan(before)
        if chan is None:
            return
        chan.edit_message(before, after)
        if chan == self.ui.channel:
            self.ui.pad.redraw()
            self.ui.draw()
            self.ui.refresh()

    async def on_ready(self):
        """Discord client initialization, main function wrapper."""
        window = None
        try:
            window = curses.initscr()
            curses.noecho()         # Don't echo input
            curses.raw()            # Catch Ctrl+S, Ctrl+Z and such
            window.keypad(True)     # Catch Ctrl+Down as one key
            curses.start_color()    # Custom colors
            await self.callback(window, thm.Theme(self.theme), self)
        finally:
            if window is not None:
                window.keypad(False)
                curses.echo()
                curses.nocbreak()
                curses.endwin()
            await self.logout()

def download_avatar(user):
    """Download a user's avatar to /tmp/ if not already done."""
    filename = '/tmp/%s.png' % user.avatar
    if os.path.exists(filename):
        return
    url = user.avatar_url or user.default_avatar_url
    url = url.replace('.webp', '.png')
    file = requests.get(url)
    open(filename, 'wb').write(file.content)

def getch(window):
    """Return the key pressed."""
    key = -1
    while key == -1:
        try:
            key = window.getch()
        except KeyboardInterrupt:
            key = 3
    return key

async def main(window, theme, client):
    """Main function."""
    curses.use_default_colors()
    curses.curs_set(0)

    theme.refresh_layout(window)

    key = -1

    win = UI.UI(window, theme, client)
    await win.update()
    client.set_ui(win)

    while key != 17:  # Ctrl+Q
        if key != -1:
            win.press(key)
        await win.do()  # Queue
        win.draw()
        win.refresh()
        # Blocking for a key press, but letting discord.py run
        key = await asyncio.get_event_loop().run_in_executor(None, getch, window)

def _run():
    token = open('token').read().strip()
    client = Client(main, 'theme.toml')
    try:
        client.run(token, bot=False)
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    # Set environment variable
    if os.environ.get('TERM') != 'xterm-256color':
        print('Setting $TERM to `xterm-256color`')
        os.environ['TERM'] = 'xterm-256color'
    # Set terminal title
    print('\33]0;DiscordZ\a', end='')
    _run()


from flask import Flask, render_template, request
from flask_restful import Resource, Api, reqparse
import pandas as pd
import requests as req
import random
import string

app = Flask(__name__)
api = Api(app)

@app.route('/login', methods=['GET', 'POST'])
def login_required():
    if request.method == 'POST':
        tokens = pd.read_csv('users.csv')
        alphabets = string.ascii_letters
        numbers = string.digits
        pasw = alphabets + numbers

        token = ''
        for _ in range(15):
            token += random.choice(pasw)

        data = pd.DataFrame({
            'token': token
        }, index=[1])
        tokens = tokens.append(data, ignore_index=True)
        tokens.to_csv('users.csv', index=False)
        print(token)
        return render_template('login.html', token=token)

    return render_template('login.html')

@app.route('/home', methods=['GET', 'POST'])
def home():
    api_url = 'https://172.31.39.248:8000/users'
    if request.method == 'POST':
        if request.form.get('Activate') == 'Activate':
            token = request.form.get('token')
            country = request.form.get('vpn')
            print(country)
            operation = 'enable'
            params = {
                'token': token,
                'country': country,
                'operation': operation
            }
            response = req.put(url=api_url, json=params)
            print(response.status_code)

        if request.form.get('Deactivate') == 'Deactivate':
            token = request.form.get('token')
            country = request.form.get('vpn')
            operation = 'disable'
            params = {
                'token': token,
                'country': country,
                'operation': operation
            }
            response = req.put(url=api_url, json=params)
            print(response.status_code)
        return render_template('home.html')

    if request.method == 'GET':
        return render_template('home.html')

class Users(Resource):

    @staticmethod
    def get():
        parser = reqparse.RequestParser()
        parser.add_argument('token', required=True)
        args = parser.parse_args()
        data = pd.read_csv('users.csv')
        if args['token'] in list(data['token']):
            return data[data['token'] == args['token']].to_dict('records'), 200

        else:
            return {
                       'message': 'Token is Invalid.'
                   }, 404

    @staticmethod
    def post():
        parser = reqparse.RequestParser()
        parser.add_argument('token', required=True)
        parser.add_argument('country', required=True)
        parser.add_argument('operation', required=True)
        args = parser.parse_args()

        data = pd.read_csv('users.csv')

        for token in list(data['token']):
            if args['token'] in token:
                return {
                           'message': f"'{args['token']}' already exists."
                       }, 409
        else:
            new_data = pd.DataFrame({
                'token': [args['token']],
                'country': [args['country']],
                'operation': [args['operation']],
            })
            data = data.append(new_data, ignore_index=True)
            data.to_csv('users.csv', index=False)
            return 200

    @staticmethod
    def put():
        parser = reqparse.RequestParser()
        parser.add_argument('token', required=True)
        parser.add_argument('country', required=True)
        parser.add_argument('operation', required=True)
        args = parser.parse_args()

        data = pd.read_csv('users.csv')

        if args['token'] in list(data['token']):
            data.loc[data['token'] == args['token'], 'country'] = args['country']
            data.loc[data['token'] == args['token'], 'operation'] = args['operation']

            # save back to CSV
            data.to_csv('users.csv', index=False)
            return 200

        else:
            return {
                       'message': f"'{args['token']}' not found."
                   }, 404

    @staticmethod
    def delete():
        parser = reqparse.RequestParser()
        parser.add_argument('token', required=True)
        args = parser.parse_args()

        data = pd.read_csv('users.csv')

        for token in list(data['token']):
            if args['token'] in token:
                data = data[data['token'] != args['token']]

                data.to_csv('users.csv', index=False)
                return 200

        else:
            return {
                       'message': f"'{args['token']}' not found."
                   }, 404

api.add_resource(Users, '/users')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)


#For fast I/O
import sys
input = lambda: sys.stdin.readline().strip()

for Homu in range(int(input())):
    n,l = [int(i) for i in input().split()]
    a = [int(i) for i in input().split()]

    s = ['B' for i in range(l)]

    for ind in a:
        i_1 = min(ind-1, l-ind)
        i_2 = max(ind-1, l-ind)

        if s[i_1] != 'A':
            s[i_1] = 'A'
        else:
            s[i_2] = 'A'

    s = ''.join(s)
    print(s)


import customtkinter as ctk

class CountEntry(ctk.CTkEntry):
    def __init__(self, parent, **kwargs):
        super().__init__(
            parent,
            placeholder_text="Count",
            width=250,
            height=30,
            border_width=2,
            corner_radius=10,
            font=("Jetbrains Mono", 14, "bold"),
            **kwargs,
        )


# -*- coding: utf-8 -*-
"""
Created on Wed Nov 13 06:51:26 2019

@author: Nate P
"""

import requests
from bs4 import BeautifulSoup as bs
import re

url = 'https://www.azlyrics.com/r/rollingstones.html'
rs_request = requests.get(url).text
rs_soup = bs(rs_request, 'lxml')

""" rs albums found in 'div', class = 'album'. Will need to clean albums, and drop those that are 'compilations' """

""" Use regular expression to extract Album name, Year. Album name is in Quotes, Year is in parenthesis """

re_album_name = re.compile('".+"') #Matches everything within quotes (or album names), INCLUDING quote. This will extract album name.

re_album_year = re.compile('\([0-9]+\)') ### Matches everything within paranthesis, INCLUDING paranthesis. This will extract year. UPDATE: only matches numbers!!!

""" Use pattern objects (re_album_name, re_album_year) to match strings
    Use for loop and 'if album in text' to filter out compilation albums.

"""
"""
List comprehension to scrape album names, need to clean further. Scraped, uncleaned data. in format of 'album: "The Rolling Stones" (1964)'
"""
albums_scraped = [album.text for album in rs_soup.findAll('div','album') if 'album' in album.text]

"""
Extract album name, album year
"""

album_names = [re_album_name.search(album).group(0).replace('"','') for album in albums_scraped]

album_years = [re_album_year.search(album).group(0).replace('(','').replace(')','') for album in albums_scraped]


import numpy as np
import pandas as pd
import graphing
from m1b_gradient_descent import gradient_descent
from matplotlib import pyplot as plt
import plotly.express as px

aval_dogs = pd.read_csv('05 Refine and test machine learning models/dog-training.csv', delimiter='\t')

#training model
model = gradient_descent(aval_dogs.month_old_when_trained, aval_dogs.mean_rescues_per_year, learning_rate=5E-4, number_of_iterations=8000)
graphing.scatter_2D(aval_dogs, "month_old_when_trained", "mean_rescues_per_year", trendline=model.predict, show=True)

#normalize model before train
aval_dogs['std_age_when_trained'] = (aval_dogs.month_old_when_trained - aval_dogs.month_old_when_trained.mean()) / np.std(aval_dogs.month_old_when_trained)

#fig = px.box(aval_dogs,y=["month_old_when_trained", "standardized_age_when_trained"])
#fig.write_html('fig.html', auto_open=True)
model_norm = gradient_descent(aval_dogs.std_age_when_trained, aval_dogs.mean_rescues_per_year, learning_rate=5E-4, number_of_iterations=8000)
graphing.scatter_2D(aval_dogs, 'std_age_when_trained', "mean_rescues_per_year", trendline=model_norm.predict, show=True)

#comparing costs of training normalized and not model
costNone = model.cost_history
costNorm = model_norm.cost_history

df1 = pd.DataFrame({'cost': costNone, 'Model':'None'})
df2 = pd.DataFrame({'cost': costNorm, 'Model':'Normalized'})
df1['number_of_ite'] = df1.index + 1
df2['number_of_ite'] = df2.index + 1
df = pd.concat([df1,df2])
print(df.head())
graphing.scatter_2D(df, label_x='number_of_ite', label_y='cost',show=True)

05 Refine and test machine learning models/training_normalized_data.py


from flask import Flask, render_template, request
from scraper import scrape
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True

@app.route('/', methods=['GET', 'POST'])
def home():
	if request.method == 'POST':
		barcode = request.form['barcode']
		scrape(barcode)

	return render_template('header.html')

if __name__ == '__main__':
    app.run()


def canSum(target, numbers, memo={}):
    if(target in memo):
        return memo[target]

    if(target == 0):
        return True

    if(target < 0):
        return False

    for num in numbers:
        remainder = target - num
        if(canSum(remainder, numbers) == True):
            memo[target] = True
            return True

    memo[target] = False
    return False

print(canSum(7, [2, 3]))
print(canSum(7, [5, 3, 4, 7]))
print(canSum(7, [2, 4]))
print(canSum(8, [2, 3, 5]))
print(canSum(300, [7, 14]))


from typing import List, Optional

from sqlalchemy import insert, select, update

from src.database.connection_sql import ConnectionSQLDatabase
from src.models.sql.filter import FilterModelSQL
from src.utils.conflog import logger

class FilterSQLRepository:
    def __init__(self) -> None:
        self.session = ConnectionSQLDatabase().get_session()

    def insert_filter(self, value: list) -> FilterModelSQL:
        stmt = insert(FilterModelSQL).values(value).returning(FilterModelSQL)
        result = self.session.scalars(stmt)
        self.session.commit()
        logger.info("All filters successfully saved.")
        return result.first()

    def add_filter(self, value: dict) -> FilterModelSQL:
        model = FilterModelSQL(**value)
        self.session.add(model)
        self.session.commit()
        self.session.refresh(model)
        logger.info("Filter successfully saved.")
        return model

    def update_filter(
        self, filter_id: str, value: dict
    ) -> Optional[FilterModelSQL]:
        stmt = (
            update(FilterModelSQL)
            .where(FilterModelSQL.id == filter_id)
            .values(value)
            .returning(FilterModelSQL)
        )
        result = self.session.scalars(stmt)
        self.session.commit()
        logger.info("Filter updated successfully.")
        return result.first()

    def toggle_filter(
        self, filter_id: str, action: bool
    ) -> Optional[FilterModelSQL]:
        stmt = (
            update(FilterModelSQL)
            .where(FilterModelSQL.id == filter_id)
            .values({FilterModelSQL.is_active: action})
            .returning(FilterModelSQL)
        )
        result = self.session.scalars(stmt)
        self.session.commit()
        logger.info("Filter status updated successfully.")
        return result.first()

    def select_by_id(
        self, filter_id: str, is_active: bool | None = None
    ) -> Optional[FilterModelSQL]:
        stmt = select(FilterModelSQL).where(FilterModelSQL.id == filter_id)
        if is_active:
            stmt = stmt.where(FilterModelSQL.is_active == is_active)
        return self.session.scalars(stmt).first()

    def select_all(
        self, is_active: bool | None = None
    ) -> List[FilterModelSQL]:
        stmt = select(FilterModelSQL)
        if is_active:
            stmt = stmt.where(FilterModelSQL.is_active == is_active)
        return self.session.scalars(stmt).all()


from Bio import SeqIO
import glob

db = 'uniprotkb'

for original_file in glob.glob('../Data/{}/*.mafft.afa'.format(db))[:]:
    print(original_file)
    records = list(SeqIO.parse(original_file, 'fasta'))

    wt_record = records[0]

    only_seqs = []
    with open(original_file.replace('.mafft.afa', '.mafft.processed.afa'), 'w') as outfile:
        valid_indices = [i for i,j in enumerate(list(str(wt_record.seq))) if j not in ['.', '-']]
        for record in records:
            seq_list = [j for i,j in enumerate(list(str(record.seq))) if i in valid_indices]
            seq_str = ''.join(seq_list)
            seq_str = seq_str.upper()
            seq_str = seq_str.replace('.', '-').replace('X', '-')
            if seq_str not in only_seqs:
                only_seqs.append(seq_str)
                outfile.write('>{}\n{}\n'.format(record.id, seq_str))

    with open(original_file.replace('.mafft.afa', '.mafft.processed.flat'), 'w') as outfile:
        for seq in only_seqs:
            outfile.write('{}\n'.format(seq))


import requests
import sys

api_response = requests.get("https://api.coindesk.com/v1/bpi/currentprice.json")
dump = api_response.json()

#Check if sys args in not less than 2 and handle errors
if len(sys.argv) != 2:
    sys.exit("Missing command-line argument")
elif (sys.argv[1]).isalpha():
    sys.exit("Command-line argument is not a number")
else:
    #Get keys of current bitcoin rate from coindesk
    arg = float(sys.argv[1])
    results = dump["bpi"]["USD"]["rate"]
    final = results.replace(",", "")
    amount = float((sys.argv[1])) * float(final)
    print(f"${amount:,.4f}")


from modules.paths import PathManager
from modules.dataframe import DataframeManager
from modules.workbook import WorkbookManager
from modules.logics import get_cleared_channel
import pandas as pd
import numpy as np

def main() -> None:

    file_path = PathManager.open_file_dialog_solo()

    if not file_path:
        print('Файл не выбран.')
        return None

    df = DataframeManager.import_dataframe(file_path)
    df.dropna(axis='columns', how='all', inplace=True)

    # Избавляет от NaN в первых трех строках
    df.iloc[0] = df.iloc[0].apply(lambda x: '' if x == 'Consolidated' else x)
    df.iloc[1] = df.iloc[1].apply(lambda x: '' if x is np.NAN else x)
    df.iloc[2] = df.iloc[2].apply(lambda x: '' if x is np.NAN else x)

    # Конкатенирует строки в заголовок
    header = [str(i + j).strip() for i, j in zip(df.iloc[0], (df.iloc[1] + ' ' + df.iloc[2]))]
    df.columns = header

    # Удаляет лишние строки и сбрасываем индексацию
    df.drop([0, 1, 2, 3], inplace=True)
    df.reset_index(drop=True, inplace=True)

    # Список столбцов с типом данных float64
    substrings = ('desktop', 'tv', 'mobile', 'id', 'длительность')

    for column in df.columns:
        if is_substring(substrings, column):
            df[column] = df[column].apply(lambda x: str(x).replace(',', '.').strip()).astype('float64')

    # Приводит дату в формате dd/mm/yy к dd.mm.yy
    df['Дата'] = df['Дата'].apply(lambda x: x.replace('/', '.'))

    # Импорт дат (CSV UTF-8)
    date = pd.read_csv('addons/dates.csv',encoding='utf-8', sep=';')
    date.dropna(axis='columns', how='all', inplace=True)

    # LEFT JOIN
    df = df.merge(date, how='left', on='Дата')

    # Определяет временные столбцы
    df['Время начала (0-24)'] = df['Ролик время начала'].apply(get_correct_time)
    df['Час начала'] = df['Время начала (0-24)'].apply(lambda x: int(x[:2]))
    df['День / Ночь'] = np.where((df['Час начала'] >= 2) & (df['Час начала'] <= 4), 'Ночь', 'День')
    df['Временной интервал'] = df['Время начала (0-24)'].apply(get_time_interval)

    # Импорт телеканалов (CSV UTF-8)
    ad = pd.read_csv('addons/ad_channels.csv',encoding='utf-8', sep=';')
    ad.dropna(axis='columns', how='all', inplace=True)

    # Определяет тип телеканала
    df['Тип канала'] = df['Телекомпания'].apply(lambda x: get_channel_type(x, ad))

    # Импортируем файл для установки границ Prime (CSV UTF-8)
    off_prime = pd.read_csv('addons/off_prime.csv', encoding='utf-8', sep=';')

    # Удаляем пустые столбцы
    off_prime.dropna(axis='columns', how='all', inplace=True)

    df = df.merge(off_prime, how='left', on=['Тип канала', 'День тип'])

    # Платформа оригинала
    df['Платформа оригинала'] = df['Телекомпания'].apply(lambda x: 'ТВ' if 'СЕТЕВОЕ' in x else 'Интернет')

    # Удаляем из каналов скобки
    df['Телекомпания'] = df['Телекомпания'].apply(get_cleared_channel)

    # Премиальное / Средний
    df['Позиционирование'] = df['Ролик позиционирование'].apply(lambda x: 'Средний' if x == 'Средний' else 'Премиальное')

    # Импортируем файл для определения баинговой аудитории (CSV UTF-8)
    auditory = pd.read_csv('addons/auditory.csv', encoding='utf-8', sep=';')

    # Удаляем пустые столбцы
    auditory.dropna(axis='columns', how='all', inplace=True)

    # Соединяем по первичному ключу (LEFT JOIN)
    df = df.merge(auditory, how='left', on='Телекомпания')

    # Импорт файл для определения телеканала и его номера
    channels = pd.read_csv('addons/channels.csv', encoding='utf-8', sep=';')
    # Удаляем пустые столбцы
    channels.dropna(axis='columns', how='all', inplace=True)

    # Соединяем по первичному ключу (LEFT JOIN)
    df = df.merge(channels, how='left', on=['Ролик распространение', 'Телекомпания'])

    # Проставляем прайм
    df['от'] = np.where(pd.to_timedelta(df['Время начала (0-24)']) > pd.to_timedelta(df['Off от']), 1, 0)
    df['до'] = np.where(pd.to_timedelta(df['Время начала (0-24)']) <= pd.to_timedelta(df['Off до']), 1, 0)
    df['от_до'] = df['от'] * df['до']
    df['Prime'] = np.where(df['от_до'] == 1, 'OFF', 'PT')

    # Удаляем временные столбцы
    del df['от']
    del df['до']
    del df['от_до']

    # Мэтчим строки Интернет и ТВ
    df_group = df[[column for column in df.columns if is_rating(column) or column == 'Ролик ID выхода оригинала']]
    df_group = df_group.groupby('Ролик ID выхода оригинала').sum()

    df = df[[column for column in df.columns if not is_rating(column)]]
    df = df[df['Платформа оригинала'] == 'ТВ']
    del df['Платформа оригинала']

    df = df.merge(df_group, how='left', on='Ролик ID выхода оригинала')

    # Sales TVR TV
    tv = df[[column for column in df.columns if 'TV BA' in column]]
    tv.columns = [column.replace('TV ', '') for column in tv.columns]

    tv.insert(0, 'Баинговая аудитория', df['Баинговая аудитория'])
    df['Sales TVR TV'] = tv.apply(lambda x: x[x['Баинговая аудитория']], axis=1)

    # Sales TVR Desktop
    desktop = df[[column for column in df.columns if 'Desktop BA' in column]]
    desktop.columns = [column.replace('Desktop ', '') for column in desktop.columns]

    desktop.insert(0, 'Баинговая аудитория', df['Баинговая аудитория'])
    df['Sales TVR Desktop'] = desktop.apply(lambda x: x[x['Баинговая аудитория']], axis=1)

    # Sales TVR Mobile
    mobile = df[[column for column in df.columns if 'Mobile BA' in column]]
    mobile.columns = [column.replace('Mobile ', '') for column in mobile.columns]

    mobile.insert(0, 'Баинговая аудитория', df['Баинговая аудитория'])
    df['Sales TVR Mobile'] = mobile.apply(lambda x: x[x['Баинговая аудитория']], axis=1)

    # Sales Std. TVR
    df['Sales Std. TVR TV'] = (df['Sales TVR TV'] * df['Ролик ожидаемая длительность']) / 20
    df['Sales Std. TVR Desktop'] = (df['Sales TVR Desktop'] * df['Ролик ожидаемая длительность']) / 20
    df['Sales Std. TVR Mobile'] = (df['Sales TVR Mobile'] * df['Ролик ожидаемая длительность']) / 20

    # Big Sales TVR
    df['Big Sales TVR'] = df['Sales TVR TV'] + df['Sales TVR Desktop'] + df['Sales TVR Mobile']
    df['Big Sales Std. TVR'] = df['Sales Std. TVR TV'] + df['Sales Std. TVR Desktop'] + df['Sales Std. TVR Mobile']

    # Убираем лишние столбцы
    df = df[[i for i in df.columns if 'BA' not in i]]

    # Определяем целевые аудитории
    targets = set([i.replace('TV ', '') for i in df.columns if (('TV' in i) and ('TVR' not in i))])

    # TVR + Std. TVR + Big TVR
    for target in targets:
        df[f'TVR {target} TV'] = df[f'TV {target}']
        df[f'TVR {target} Desktop'] = df[f'Desktop {target}']
        df[f'TVR {target} Mobile'] = df[f'Mobile {target}']

        del df[f'TV {target}']
        del df[f'Desktop {target}']
        del df[f'Mobile {target}']

        df[f'Std. TVR {target} TV'] = (
            df[f'TVR {target} TV'] * df['Ролик ожидаемая длительность']) / 20
        df[f'Std. TVR {target} Desktop'] = (
            df[f'TVR {target} Desktop'] * df['Ролик ожидаемая длительность']) / 20
        df[f'Std. TVR {target} Mobile'] = (
            df[f'TVR {target} Mobile'] * df['Ролик ожидаемая длительность']) / 20

        df[f'Big TVR {target}'] = df[f'TVR {target} TV'] + \
            df[f'TVR {target} Desktop'] + df[f'TVR {target} Mobile']
        df[f'Big Std. TVR {target}'] = df[f'Std. TVR {target} TV'] + \
            df[f'Std. TVR {target} Desktop'] + df[f'Std. TVR {target} Mobile']

    # Импорт файла для округления (CSV UTF-8)
    round = pd.read_csv('addons/round.csv', encoding='utf-8', sep=';')
    # Удаляем пустые столбцы
    round.dropna(axis='columns', how='all', inplace=True)

    df = df.merge(round, how='left', on=['Год', 'Ролик распространение', 'Телекомпания'])

    # Добавляем округление
    df['Округление'] = df['Округление'].apply(lambda x: x.replace(',', '.').strip()).astype('float64')
    df['GRP_округл'] = np.max(df[['Big Sales TVR', 'Округление']], axis=1)
    df['GRP20_округл'] = (df['GRP_округл'] * df['Ролик ожидаемая длительность']) / 20
    df['GRP20/min'] = np.where(df['Ролик тип'] == 'Ролик', df['GRP20_округл'], df['Ролик ожидаемая длительность'] / 60)

    df = df.round(4)

    # Экспорт датафрейма в openpyxl
    wb = WorkbookManager.create_workbook()
    ws = WorkbookManager.create_sheet(wb, 'Выгрузка')

    DataframeManager.export_dataframe_to_sheet(df, ws)

    # Форматирование Excel книги
    WorkbookManager.format_sheet(ws)

    # Сохраняем Excel книгу
    file_path_to_save = PathManager.save_file_dialog()

    if file_path_to_save:
        WorkbookManager.save_workbook(wb, file_path_to_save)
        print(f'Файл успешно сохранен: {file_path_to_save}')
    else:
        print('Файл не сохранен.')

def is_substring(substrings: tuple, string: str) -> bool:
    '''Возвращает True, если столбец необходимо преобразовать в 'float64', иначе False'''
    return any(substring in string.lower() for substring in substrings)

def get_time_interval(time: str) -> str:
    '''Возвращает интервал времени'''
    hours = int(time[:2])

    intervals = {
        (6, 8): '06:00:00 - 09:00:00',
        (9, 12): '09:00:00 - 13:00:00',
        (13, 15): '13:00:00 - 16:00:00',
        (16, 18): '16:00:00 - 19:00:00',
        (19, 21): '19:00:00 - 22:00:00',
        (22, 23): '22:00:00 - 00:00:00',
        (0, 5): '00:00:00 - 06:00:00'
    }

    for interval, result in intervals.items():
        if interval[0] <= hours <= interval[1]:
            return result

def get_correct_time(time: str) -> str:
    '''Formats 29:00:00 hour format to 24:00:00'''
    hours, minutes, seconds = map(int, time.split(':'))

    hours %= 24

    return f'{hours:02}:{minutes:02}:{seconds:02}'

def get_channel_type(telecompany: str, df: pd.DataFrame) -> str:
    '''Возвращает тип телеканала'''
    telecompany_name = telecompany.replace('(СЕТЕВОЕ ВЕЩАНИЕ)', '').strip()
    if telecompany_name in df['Union'].to_list():
        return 'ЕРК'
    elif telecompany_name in df['Digital'].to_list():
        return 'ЦРК'
    else:
        return 'Нац'

def is_rating(column: str) -> bool:
    '''Возвращает True если это столбец с рейтингом, иначе False'''
    return any(device in column for device in ['TV', 'Mobile', 'Desktop'])

if __name__ == '__main__':
    main()


# This part for library
from bs4 import BeautifulSoup
import requests
import re
import csv
from itertools import zip_longest
from selenium import webdriver
import urllib.request
import base64
import itertools
from automobilewebscrapper.models import Marque, VoitureNeuf, VendeurPro, VoitureOccasion, Concessionnaires

print("Hello !!")
# This part for declaration variable
tagsMarqueVoituresNeuf = []
tagAltNewCar = []
tagSrcNewCar = []
tagsVoiNeufLink=[]

#Variable for get information of new cars
tagsVoiNeufModelSpan=[]
tagsVoiNeufModelH2=[]
tagsVoiNeufModelImg = []
tagsVoiNeufModelPrice = []
tagsVoiNeufModelSpanFinalList = []
tagsVoiNeufModelH2FinalList = []

#Variables for the occasion cars
linkPages = []
linkPageWithoutFooter = []
allYearOfCarOcc = []
allRoadOfCarOcc = []
allEnergiesOfCarOcc = []
allVitesssOfCarOcc = []
nameCarOcc = []
localiteCarOcc = []
descrCarOcc = []
priceCarOcc = []
imgCarOcc = []

nameMarque = []
nameMarqueFinal = []
imgCarOccFinal = []
descrCarOccFinal = []

#Variables for Vendor pro
nameVendeurList = []
imagesVendeurList = []
addressVendeurList = []
phoneVendeurList = []
faxVendeurList = []
addressVendeurListNew = []
phoneVendeurListNew = []
faxVendeurListNew = []

# Store the given url in an attribute named URL
URL = "https://www.automobile.tn/fr"
#[:21] it mean give me from 0 position to 21 position
WebSite = URL[:25]
# To make a request to a web page with specific URl
result = requests.get(URL)

#Parse the result using the HTML mode
doc = BeautifulSoup(result.text, "html.parser")

#To automate the work we will look for all the links to find the links to access the computers and the phones
#We use the find_all to get a list of links and next we will make some filters to get the correct informations
#We notice in the inspection mode(On browser) what we are looking for have a common class dropdown-item
#So we will search in all the file with filtering by class
tags = doc.find_all('a',{"class":"dropdown-item"})

#The result of find_all given us all the tags of .....
#So for takes only the content of those tags we make this scripts
#1. Loop on the tags (The tags in the list)
for tag in tags:
    #2. We append only the content of those tags on a new list named tagsMarqueVoituresNeuf and etc...
    if(tag['href'] in "/fr/neuf"):
        tagsMarqueVoituresNeuf.append(tag['href'])

URLFORVoiNeuf = WebSite + tagsMarqueVoituresNeuf[0]
# To make a request to a web page for get all the new cars
resultVoiNeuf = requests.get(URLFORVoiNeuf)

#Parse the result using the HTML mode
docVoiNeuf = BeautifulSoup(resultVoiNeuf.text, "html.parser")

#To automate the work we will look for all the links to find the links to access the computers and the phones
#We use the find_all to get a list of links and next we will make some filters to get the correct informations
#We notice in the inspection mode(On browser) what we are looking for have a common class dropdown-item
#So we will search in all the file with filtering by class
tagsVoiNeuf= docVoiNeuf.find_all('img',alt=True)

#The result of find_all given us all the tags of .....
#So for takes only the content of those tags we make this scripts
#1. Loop on the tags (The tags in the list)
for tag in tagsVoiNeuf:
    #2. We append only the content of those tags on a new list named tagAltNewCar and etc...
    tagAltNewCar.append(tag['alt'])
    tagSrcNewCar.append(tag['src'])

#If we have some empty element with this instruction you will get an list without any element
tagAltNewCar = list(filter((None), tagAltNewCar))
# print(tagAltNewCar)

tagSrcNewCar = list(filter((None), tagSrcNewCar))
#There is in the list first and the element an URL not have any meaning so we deleted
tagSrcNewCar = tagSrcNewCar[1:len(tagSrcNewCar)-1]
# print(tagSrcNewCar)

#Function to convert an image from url web site to an image base64 after that we will stock it in the database
def get_as_base64(url):
    return base64.b64encode(requests.get(url).content)

'''This par for a new cars'''
# To access on each marque automatically we do this instructions
# We find in the inspection part that each last year URL(https://www.automobile.tn/fr/neuf) concatenate with model of cars
# But in our list we have this model with espace so we replace the space between all the string with dash
# Next we just concatenate the URL + / + model name and we get it
for i in range(len(tagAltNewCar)):
    tagsVoiNeufLink.append(URLFORVoiNeuf + "/" +tagAltNewCar[i].replace(' ','-'))

# print(tagsVoiNeufLink)
####################### Get Information From the new cars #######################
####################### Marque Part #######################
#This function to get all the information from each marque is existing from the website
def getInformationForVoiNeuf(URLWebSite):
    resultVoiNeufModel = requests.get(URLWebSite)

    #Parse the result using the HTML mode
    docVoiNeufModel1 = BeautifulSoup(resultVoiNeufModel.text, "html.parser")

    tagsVoiNeufModel = docVoiNeufModel1.find_all('div',{"class":"versions-item"})

    for tVM in tagsVoiNeufModel:
        for span in tVM.find_all('span',{"class":"tag stock-limite"}):
            tagsVoiNeufModelSpan.append(span.find_all(text=True))

        for h2 in tVM.find_all('h2'):
            tagsVoiNeufModelH2.append(h2.find_all(text=True))

        for img in tVM.find_all('img', {"class":"img-fluid"}):
            tagsVoiNeufModelImg.append(img['src'])

        for spanPrix in tVM.find_all('div',{"class":"price"}):
            for spanPrixDetal in spanPrix.find_all('span'):
                if(spanPrixDetal.find_all(text=True)[0] !="DT"):
                    tagsVoiNeufModelPrice.append(spanPrixDetal.find_all(text=True)[0])

print('Hello2')

####################### Get Information From concessionaires #######################
####################### Concessionaires Part #######################

resultConcessionaires = requests.get(URLFORVoiNeuf+"/concessionnaires")

#Parse the result using the HTML mode
docConcessionaires = BeautifulSoup(resultConcessionaires.text, "html.parser")

tagsConcessionaires = docConcessionaires.find_all('div',{"class":"infos-wrapper"})

tagsConcessionairesH2 = []
tagsConcessionairesH2List = []
tagsConcessionairesBTel = []

for tC in tagsConcessionaires:
    for tCh2 in tC.find_all('h2',{"style":"font-weight: bold; font-size: 15px;"}):
        tagsConcessionairesH2.append(tCh2.find_all(text=True))

    for tCb2 in tC.find_all("b", text="Tél. : "):
        tagsConcessionairesBTel.append(tCb2.next_sibling.strip())

print('Hello3')

for tag in tags:
    if("recherche" in tag['href']):
        URLVoiOccRech = URL + tag['href'][3:]
# print(URLVoiOccRech)

resultConAncVoit = requests.get(URLVoiOccRech)

#Parse the result using the HTML mode
docConAncVoit = BeautifulSoup(resultConAncVoit.text, "html.parser")

tagsConAncVoit = docConAncVoit.find_all('a')

nameAllConAncVoit = []
linkAllConAncVoit = []
for tCAV in tagsConAncVoit:
    # print(tCAV['href'])
    if("/fr/occasion?" in tCAV['href']):
        nameAllConAncVoit.append(tCAV['href'][25:].replace('-',' '))
        linkAllConAncVoit.append(URL + tCAV['href'][3:])

def getAllPagesOfCarsOcc(linkPagesFinal):
    #You will define en function right here for the if statement and else to
    linkPagesFinal = list(set(linkPages))

    return (linkPagesFinal)

def getInformationFromCArsOcc(linkPagesFinal):

    for lPF in linkPagesFinal:
        resultVoiOccModel = requests.get(lPF)

        #Parse the result using the HTML mode
        docVoiOccModel1 = BeautifulSoup(resultVoiOccModel.text, "html.parser")

        for liYear in docVoiOccModel1.find_all('li',{"class":"year"}):
            for spanYear in liYear.find_all('span',{"class":"value"}):
                if("https://" not in spanYear.find_all(text=True)[0]):
                    allYearOfCarOcc.append(spanYear.find_all(text=True)[0])

        for liRoad in docVoiOccModel1.find_all('li',{"class":"road"}):
            for spanRoad in liRoad.find_all('span',{"class":"value"}):
                if("https://" not in spanRoad.find_all(text=True)[0]):
                    allRoadOfCarOcc.append(spanRoad.find_all(text=True)[0])

        for liEnergy in docVoiOccModel1.find_all('li',{"class":"fuel"}):
            for spanEnergy in liEnergy.find_all('span',{"class":"value"}):
                if("https://" not in spanEnergy.find_all(text=True)[0]):
                    allEnergiesOfCarOcc.append(spanEnergy.find_all(text=True)[0])

        for liVitesse in docVoiOccModel1.find_all('li',{"class":"boite"}):
            for spanVitesse in liVitesse.find_all('span',{"class":"value"}):
                if("https://" not in spanVitesse.find_all(text=True)[0]):
                    allVitesssOfCarOcc.append(spanVitesse.find_all(text=True)[0])

        for liMap in docVoiOccModel1.find_all('li',{"class":"map"}):
            for spanMap in liMap.find_all('span',{"class":"value"}):
                if("https://" not in spanMap.find_all(text=True)[0]):
                    localiteCarOcc.append(spanMap.find_all(text=True)[0])

        for divNameCar in docVoiOccModel1.find_all('div',{"class":"thumb-caption"}):
            for h2NameCar in divNameCar.find_all('h2'):
                for spanNameCar in h2NameCar.find_all('span'):
                    nameCarOcc.append(spanNameCar.find_all(text=True)[0])

        for adescCarOcc in docVoiOccModel1.find_all('a',{"class":"details-container"}):
            for pdescCarOcc in adescCarOcc.find_all('p'):
                descrCarOcc.append(pdescCarOcc.find_all(text=True)[0].replace('\n                ',''))

        for divCarPrice in docVoiOccModel1.find_all('div',{"class":"price"}):
            if(divCarPrice.find_all(text=True)[0] !="\n"):
                priceCarOcc.append(divCarPrice.find_all(text=True)[0].replace('\n                    ',''))

        for imgOfCarOcc in docVoiOccModel1.find_all('div',{"class":"details-wrapper"}):
            for images in imgOfCarOcc.find_all('img'):
                imgCarOcc.append(images['src'])

    for nCO in nameCarOcc:
        nameMarque.append(nCO.split(" ",1)[0])

############ Function for all linkAllConAncVoit
tCAVFPFinale = []
for lACAV in linkAllConAncVoit:
    resultConAncVoitFooterPage = requests.get(lACAV)

    #Parse the result using the HTML mode
    docConAncVoitFooterPage = BeautifulSoup(resultConAncVoitFooterPage.text, "html.parser")

    tagsConAncVoitFooterPage = docConAncVoitFooterPage.find_all('a',{"class": "page-link"})

    if(tagsConAncVoitFooterPage):
        for tCAVFP in tagsConAncVoitFooterPage:
            tCAVFPFinale.append(URL + tCAVFP['href'][3:])
        tCAVFPFinale2 = list(set(tCAVFPFinale))

    else:
        linkPageWithoutFooter.append(lACAV)

getInformationFromCArsOcc(tCAVFPFinale2)
getInformationFromCArsOcc(linkPageWithoutFooter)

imgCarOccFinal = list(set(imgCarOcc))
nameMarqueFinal = list(set(nameMarque))

for dCO in descrCarOcc:
    enoced = dCO.encode("UTF-8")
    decoded = enoced.decode("UTF-8")
    descrCarOccFinal.append(decoded.replace('\n',' '))

nameMarqueInList = []
marques2 = Marque.objects.values('nomMarque')
print(marques2)
for mq2 in marques2:
    print(mq2['nomMarque'])
    nameMarqueInList.append(mq2['nomMarque'])
print(nameMarqueInList)

nameCarOccAndMarqueCar = []
for i1 in nameCarOcc:
    for j1 in nameMarqueInList:
        if(j1 in i1):
            nameCarOccAndMarqueCar.append(j1)

print(nameCarOccAndMarqueCar)
print(len(nameCarOccAndMarqueCar))
print(len(nameCarOcc))

priceCarOcc2 =[]
for pco in priceCarOcc:
    priceCarOcc2.append(pco.replace(' ',''))

allRoadOfCarOcc2 =[]
for pco2 in allRoadOfCarOcc:
    allRoadOfCarOcc2.append(pco2.replace(' ',''))

nameMarqueInListDB = []
nameCarInListDB = []
resultDB = []

marques3 = Marque.objects.values('nomMarque')
print(marques3)
for mq3 in marques3:
    print(mq3['nomMarque'])
    nameMarqueInListDB.append(mq3['nomMarque'])
print(nameMarqueInListDB)

for i in nameCarOcc:
    for j in nameMarqueInListDB:
        if(j in i):
            resultDB.append(j)
            break

print('Hello4')

for tag in tags:
    if("vendeurs-pro" in tag['href']):
        URLVoiOccVendPro = URL + tag['href'][3:]
print(URLVoiOccVendPro)

resultConAncVoitVendPro = requests.get(URLVoiOccVendPro)

#Parse the result using the HTML mode
docConAncVoitVendPro = BeautifulSoup(resultConAncVoitVendPro.text, "html.parser")

tagsConAncVoitVendPro = docConAncVoitVendPro.find_all('div',{"class":"infos-wrapper"})

for tCAVVP in tagsConAncVoitVendPro:
    for tCAVVPI in tCAVVP.find_all('img'):
        nameVendeurList.append(tCAVVPI['alt'])
        imagesVendeurList.append(URL[:len(URL)-2] + tCAVVPI['src'])

    for tCAVVPA in tCAVVP.find_all('div', {"class":"address"}):
        addressVendeurList.append(tCAVVPA.find_all(text=True))

    for tCAVVPP in tCAVVP.find_all('div', {"class":"phone"}):
        phoneVendeurList.append(tCAVVPP.find_all(text=True))

    for tCAVVPF in tCAVVP.find_all('div', {"class":"fax"}):
        for tCAVVPFB in tCAVVPF.find_all('b',text='Fax. : '):
            faxVendeurList.append(tCAVVPFB.next_sibling)

for aVL in addressVendeurList:
    addressVendeurListNew.append(aVL[0].replace('\n                                                    ',''))

for pVL in phoneVendeurList:
    phoneVendeurListNew.append(pVL[2].replace('                                            ',''))

for fVL in faxVendeurList:
    faxVendeurListNew.append(fVL.replace('                                            ',''))

print('Hello5')


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

# Calendarios
from datetime import timedelta

# import exceptions to use in Python constraints
from odoo import models, fields, api, exceptions

# Modelos (tablas y atributos)

class Course(models.Model):
    _name = 'openacademy.course'

    name = fields.Char(string="Title", required=True)
    description = fields.Text()

    # Relaciones entre tablas
    responsible_id = fields.Many2one('res.users',
                                     ondelete='set null', string="Responsable", index=True)
    session_ids = fields.One2many(
        'openacademy.session', 'course_id', string="Sessions")

    # SQL contrsints
    #     CHECK that the course description and the course title are different

    _sql_constraints = [
        ('name_description_check',
         'CHECK(name != description)',
         "The title of the course should not be the description"),
        # Make the Course’s name UNIQUE
        ('name_unique',
         'UNIQUE(name)',
         "The course title must be unique"),
    ]

class Session(models.Model):
    _name = 'openacademy.session'

    name = fields.Char(required=True)
    start_date = fields.Date(default=fields.Date.today)  # Default

    duration = fields.Float(digits=(6, 2), help="Duration in days")
    seats = fields.Integer(string="Number of seats")

    active = fields.Boolean(default=True)

    # complex domains. Modify the Session model’s domain
    instructor_id = fields.Many2one('res.partner', string="Instructor",
                                    domain=['|', ('instructor', '=', True),
                                            ('category_id.name', 'ilike', "Teacher")])

    course_id = fields.Many2one(
        'openacademy.course', ondelete='cascade', string="Course", required=True)

    # Using the relational field many2many, modify the Session model to relate every session to
    # a set of attendees.
    # Attendees will be represented by partner records, so we will
    # relate to the built-in model res.partner. Adapt the views accordingly.
    attendee_ids = fields.Many2many('res.partner', string="Attendees")

    # Computed fields. Add the percentage of taken seats to the Session model
    taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')

    # Calendar
    end_date = fields.Date(string="End Date", store=True,
                           compute='_get_end_date', inverse='_set_end_date')

    # hours = fields.Float(string="Duration in hours",
    #                      compute='_get_hours', inverse='_set_hours')

    attendees_count = fields.Integer(
        string="Attendees count", compute='_get_attendees_count', store=True)

    @api.depends('seats', 'attendee_ids')
    def _taken_seats(self):
        for r in self:
            if not r.seats:
                r.taken_seats = 0.0
            else:
                r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats

    # onchange. Add an explicit onchange to warn about invalid values,
    # like a negative number of seats, or more participants than seats.

    @api.onchange('seats', 'attendee_ids')
    def _verify_valid_seats(self):
        if self.seats < 0:
            return {
                'warning': {
                    'title': "Incorrect 'seats' value",
                    'message': "The number of available seats may not be negative",
                },
            }
        if self.seats < len(self.attendee_ids):
            return {
                'warning': {
                    'title': "Too many attendees",
                    'message': "Increase seats or remove excess attendees",
                },
            }

    # Calendar

    @api.depends('start_date', 'duration')
    def _get_end_date(self):
        for r in self:
            if not (r.start_date and r.duration):
                r.end_date = r.start_date
                continue

            # Add duration to start_date, but: Monday + 5 days = Saturday, so
            # subtract one second to get on Friday instead
            start = fields.Datetime.from_string(r.start_date)
            duration = timedelta(days=r.duration, seconds=-1)
            r.end_date = start + duration

    def _set_end_date(self):
        for r in self:
            if not (r.start_date and r.end_date):
                continue

            # Compute the difference between dates, but: Friday - Monday = 4 days,
            # so add one day to get 5 days instead
            start_date = fields.Datetime.from_string(r.start_date)
            end_date = fields.Datetime.from_string(r.end_date)
            r.duration = (end_date - start_date).days + 1

    # Graph

    @api.depends('attendee_ids')
    def _get_attendees_count(self):
        for r in self:
            r.attendees_count = len(r.attendee_ids)

    # Model constraints
    # Add Python constraints
    # # Add a constraint that checks that the instructor is not present in the attendees of his/her own session

    @api.constrains('instructor_id', 'attendee_ids')
    def _check_instructor_not_in_attendees(self):
        for r in self:
            if r.instructor_id and r.instructor_id in r.attendee_ids:
                raise exceptions.ValidationError(
                    "A session's instructor can't be an attendee")

class Partner(models.Model):
    _inherit = 'res.partner'

    # Add a new column to the res.partner model, by default partners are not
    # instructors
    instructor = fields.Boolean("Instructor", default=False)

    session_ids = fields.Many2many('openacademy.session',
                                   string="Attended Sessions", readonly=True)


# Plot the summary statistics (values stored in this class).
def plotSummaryStats(self, output=None, totalVisits=True):
    """
    Plot the normalized metric values as a function of opsim run.

    output: str, opt
        Name of figure to save to disk. If this is left as None the figure
        is not saved.
    totalVisits: bool
        If True the total number of visits is included in the metrics plotted.
        When comparing runs a very different lengths it is recommended to
        set this flag to False.
    """
    ylabel = '(run - ' + self.baselineRun + ')/' + self.baselineRun
    dataframe = self.noramlizeStatsdf
    magcols = [col for col in dataframe.columns if 'M5' in col]
    HAcols = [col for col in dataframe.columns if 'HA' in col]
    propMocols = [col for col in dataframe.columns if 'Prop. Mo.' in col]
    seeingcols = [col for col in dataframe.columns if 'seeing' in col]
    parallaxCols = [col for col in dataframe.columns if 'Parallax' in col]
    if totalVisits is True:
        othercols = ['Mean Slew Time', 'Median Slew Time', 'Median NVists Per Night',
                     'Median Open Shutter Fraction', 'Nights with Observations',
                     'Total Eff Time', 'Total Visits']
    else:
        othercols = ['Mean Slew Time', 'Median Slew Time',
                     'Median NVists Per Night',
                     'Median Open Shutter Fraction']
    colsets = [othercols, magcols, HAcols, propMocols, parallaxCols, seeingcols]
    fig, axs = plt.subplots(len(colsets), 1, figsize=(8, 33))
    fig.subplots_adjust(hspace=.4)
    axs = axs.ravel()
    for i, c in enumerate(colsets):
        x = np.arange(len(dataframe))
        for metric in dataframe[c].columns:
            axs[i].plot(x, dataframe[metric], marker='.', ms=10, label=metric)
        axs[i].grid(True)
        axs[i].set_ylabel(ylabel)
        lgd = axs[i].legend(loc=(1.02, 0.2), ncol=1)
        plt.setp(axs[i].xaxis.get_majorticklabels(), rotation=90)
        plt.setp(axs[i], xticks=x, xticklabels=[x.strip('') for x in dataframe.index.values])
    if output:
        plt.savefig(output, bbox_extra_artists=(lgd,), bbox_inches='tight')


import pygame, os, turtle, sys, time

pygame.init() #Iniciamos pygame
tiempo = time.time()

def collide_DOWN(jugador): #Funcion para detectar colisiones con los bordes inferiores
    choque = False
    for i in range (1, largo_jugador):
        pixeles_fondo = pygame.Surface.get_at(fondo, (jugador.x + i, jugador.y + 20))
        if pixeles_fondo == (0, 0, 0, 255):
            choque = True
    return choque

def collide_UP(jugador): #Funcion para detectar colisiones con los bordes superiores
    choque = False
    for i in range (1, largo_jugador):
        pixeles_fondo = pygame.Surface.get_at(fondo, (jugador.x + i, jugador.y))
        if pixeles_fondo == (0, 0, 0, 255):
            choque = True
    return choque

def collide_RIGHT(jugador): #Funcion para detectar colisiones con los bordes derechos
    choque = False
    for i in range (1, largo_jugador):
        pixeles_fondo = pygame.Surface.get_at(fondo, (jugador.x + 20, jugador.y + i))
        if pixeles_fondo == (0, 0, 0, 255):
            choque = True
    return choque

def collide_LEFT(jugador): #Funcion para detectar colisiones con los bordes izquierdos
    choque = False
    for i in range (1, largo_jugador):
        pixeles_fondo = pygame.Surface.get_at(fondo, (jugador.x, jugador.y + i))
        if pixeles_fondo == (0, 0, 0, 255):
            choque = True
    return choque

def WIN_GAME(jugador): #Funcion para el juego ganado
    global tiempo_final
    if jugador.y > alto - alto_jugador - 4:
        run = False
        print(tiempo_final)
        WIN_IMAGE()

def LOSE_GAME(jugador): #Funcion para el juego perdido
    global tiempo_final
    run = False
    print(tiempo_final)
    LOSE_IMAGE()

def tiempo_transcurrido(): #Funcion para el tiempo transcurrido
    global tiempo
    tiempo_actual = time.time() #Tiempo actual
    tiempo_transcurrido = tiempo_actual - tiempo #Calculamos el tiempo transcurrido
    return tiempo_transcurrido

def movimiento_jugador(keys_pressed, jugador): #Funcion para el movimiento del jugador
    global CONT_PASOS
    if keys_pressed[pygame.K_a] or keys_pressed[pygame.K_LEFT]: #SI SE APRETA A O FLECHA IZQUIERDA SE MUEVE 1 PIXELES HACÍA LA IZQUIERDA
        if collide_LEFT(jugador) == False:
            jugador.x -= vel
            CONT_PASOS += 1
    if keys_pressed[pygame.K_d] or keys_pressed[pygame.K_RIGHT]: #SI SE APRETA D O FLECHA DERECHA SE MUEVE 1 PIXELES HACÍA LA DERECHA
        if collide_RIGHT(jugador) == False:
            jugador.x += vel
            CONT_PASOS += 1
    if keys_pressed[pygame.K_w] or keys_pressed[pygame.K_UP]: #SI SE APRETA W O FLECHA SUPERIOR SE MUEVE 1 PIXELES HACÍA ARRIBA
        if collide_UP(jugador) == False:
            jugador.y -= vel
            CONT_PASOS += 1
    if keys_pressed[pygame.K_s] or keys_pressed[pygame.K_DOWN]: #SI SE APRETA S O FLECHA INFERIOR SE MUEVE 1 PIXELES HACÍA ABAJO
        if collide_DOWN(jugador) == False:
            jugador.y += vel
            CONT_PASOS += 1

def WIN_IMAGE(): #Funcion para la imagen de ganado
    pygame.init()
    ven = pygame.display.set_mode((800,600))
    pygame.display.set_caption("Juego terminado")
    Fuente = pygame.font.SysFont("Arial", 80)
    while True:
        ven.fill((blanco))  #color de fondo
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                pygame.quit()
                sys.exit()
            texto=Fuente.render("¡YOU WIN!",0,(azul))
            ven.blit(texto,(230,230))
            pygame.display.update()

def LOSE_IMAGE(): #Funcion para la imagen de perdida
    pygame.init()
    ven = pygame.display.set_mode((800,600))
    pygame.display.set_caption("Juego terminado")
    Fuente = pygame.font.SysFont("Arial", 80)
    while True:
        ven.fill((blanco))
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                pygame.quit()
                sys.exit()
            texto=Fuente.render("¡YOU LOSE!",0,(rojo))
            ven.blit(texto,(230,230))
            pygame.display.update()

def mov_imagenes(jugador): #Funcion para las imagenes en el juego
    global tiempo_final
    ventana.fill(blanco)
    ventana.blit(fondo, (0, 0))
    ventana.blit(imagen_jugador, (jugador.x, jugador.y))
    PASOS = pasos_fuente.render("Pasos: " + str(CONT_PASOS), 1, rojo)
    TIEMPO = tiempo_fuente.render("Tiempo: " + str((int(tiempo_final))), 1, rojo)
    ventana.blit(PASOS, (ancho - PASOS.get_width() - 10, 590))
    ventana.blit(TIEMPO, (10, 590))
    pygame.display.update()

def main(): #Funcion principal del juego
    global tiempo_final
    jugador = pygame.Rect(ancho/2, alto/2, largo_jugador, alto_jugador) #Creacion del jugador
    clock = pygame.time.Clock()
    run = True
    #PROGRAMA MAIN
    while run == True: #Ciclo principal del juego

        clock.tick(FPS) #Se limitan los fotogramas a "FPS"
        for event in pygame.event.get():
            if event.type == pygame.QUIT: #Se terminara el bucle si se cierra la ventana.

                run = False
        keys_pressed = pygame.key.get_pressed() #Se obtienen las teclas presionadas
        tiempo_final = tiempo_transcurrido()
        movimiento_jugador(keys_pressed, jugador) #Se llama a la funcion para el movimiento del jugador
        mov_imagenes(jugador) #Se llama a la funcion para las imagenes en el juego
        WIN_GAME(jugador) #Se llama a la funcion para ver si gana
        if tiempo_final > tiempo_limite:
            LOSE_GAME(jugador) #Se llama a la funcion de que perdió

#COLORES
blanco = (255, 255, 255)
negro = (0, 0, 0)
rojo = (255, 0, 0)
azul = (0, 0, 255)

#CONSTANTES
vel = 1 #Velocidad del jugador
FPS = 60 #Fotogramas por segundo que tendra el programa
ancho, alto = 800, 600 #Dimensiones de la ventana del juego
tiempo_limite = 50 #Tiempo limite para ganar

#CONTADOR
CONT_PASOS = 0 #Contador de pasos

#LETRA PASOS
pasos_fuente = pygame.font.SysFont('comicsans', 40) #Fuente para los pasos
tiempo_fuente = pygame.font.SysFont('comicsans', 40) #Fuente para el tiempo

#PANTALLA
ventana = pygame.display.set_mode((ancho, alto+50)) #Creacion de la ventana del juego
pygame.display.set_caption("Laberinto del fauno") #NOMBRE DEL JUEGO

fondo = pygame.image.load("laberinto.svg") #Cargamos la imagen que representara al jugador
fondo = pygame.transform.rotate(pygame.transform.scale(fondo, (ancho, alto)), 180) # Rotamos y escalamos la imagen

largo_jugador, alto_jugador = 20, 20 #Dimensiones del jugador
imagen_jugador = pygame.transform.scale(pygame.image.load("circ_rojo.png"), (largo_jugador, alto_jugador)) #Cargamos la imagen del jugador y la escalamos

main()


#
# @lc app=leetcode.cn id=88 lang=python3
#
# [88] 合并两个有序数组
#

# @lc code=start
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        利用三个指针，分别指向两个数组的末尾，以及当前插入数字的位置。
        从后往前比较两个数组的元素，每次将较大的放到nums1的末尾。
        时间复杂度为O(m+n)，空间复杂度为O(1)
        """
        i, j = m-1, n-1
        end = m + n -1
        while i >= 0 and j >= 0:
            if nums1[i] < nums2[j]:
                nums1[end] = nums2[j]
                end -= 1
                j -= 1
            else:
                nums1[end] = nums1[i]
                end -= 1
                i -= 1
        if j >= 0:
            nums1[:j+1] = nums2[:j+1]
# @lc code=end

88.合并两个有序数组.py


import argparse

from collections import namedtuple
from datetime import datetime

# from typing import NamedTuple

DATETIME_SUPPORTED_FORMATS = ["%d-%m-%Y", "%Y-%m-%d"]

# We could do sth like this to add typing to our src/dst/date attributes
# class Request(NamedTuple):
#     src: str
#     dst: str
#     date: datetime

class Request(namedtuple("request", "src dst date")):
    @staticmethod
    def date_type(date_string):
        for fmt in DATETIME_SUPPORTED_FORMATS:
            try:
                return datetime.strptime(date_string, fmt)
            except ValueError:
                pass

        msg = f"date {date_string} doesn't match formats {DATETIME_SUPPORTED_FORMATS}"
        raise NotImplementedError(msg)

    @classmethod
    def from_cli(cls):
        parser = argparse.ArgumentParser()

        parser.add_argument("src", nargs="?")
        parser.add_argument("dst", nargs="?")
        parser.add_argument("date", nargs="?", type=cls.date_type)

        args = parser.parse_args()

        return cls(args.src, args.dst, args.date)


import pika
import numpy as np
from src.lib.generators import Meter, Photovoltaic
from src.lib.metermessage import MeterMessage

import threading
import time

class ThreadTimer(object):
    # Timer for simulation. Uses a Mutex as it should be shared if simulating multiple households
    def __init__(self, init_time=0, duration=3600):
        self.mutex = threading.Lock()
        self.duration = duration
        self.init_time = init_time
        self.time = init_time

    def end(self):
        with self.mutex:
            return self.duration + self.init_time <= self.time

    def increment_time(self, interval=1):
        with self.mutex:
            self.time += interval

    def get_time(self):
        self.mutex
        with self.mutex:
            return self.time

class BrokerConfigs(object):
    # Configurations for RabbitMQ Channel
    def __init__(self, queue='default', host='localhost', routing_key='default', exchange='', credentials=pika.PlainCredentials('guest', 'guest')):
        self.credentials = credentials
        self.queue = str(queue)
        self.host = str(host)
        self.routing_key = str(routing_key)
        self.exchange = str(exchange)

class ThreadHousehold(object):
    # Thread simulating Household, Starts when start_event is set, stops when stop_event is set
    def __init__(self, start_event, stop_event, timer: ThreadTimer=None, meter=Meter(), brokerconfigs=BrokerConfigs()):
        self.start_event = start_event
        self.stop_event = stop_event
        self.meter = meter

        self.timer = timer

        self.config = brokerconfigs
        self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=self.config.host, credentials=self.config.credentials))
        self.channel = self.connection.channel()
        self.channel.queue_declare(queue=self.config.queue)

        thread = threading.Thread(target=self._run)
        thread.start()

    def _publish(self, message=''):
        self.channel.basic_publish(exchange=self.config.exchange, routing_key=self.config.routing_key, body=message)

    def _run(self):
        while not self.start_event.is_set():
            time.sleep(0.01)

        print('Household thread Started')

        t_last = 0

        while not self.stop_event.is_set():
            if self.timer is not None:
                t = self.timer.get_time()
            else:
                t = int(time.time())
                # Only send message if 2 seconds has passed
            if t_last + 2 <= t:
                m = MeterMessage(origin=self.meter.id, time=t, consumption=self.meter.get_consumption(t))
                self._publish(message=str(m.to_json()))
                t_last = t
            if self.timer is not None:
                self.timer.increment_time(2)

            time.sleep(0.01)

        print('Household thread Finished')

        self.connection.close()

class ThreadPvGenerator(object):
    # Thread simulating Generator, Starts when start_event is set, stops when stop_event is set
    def __init__(self, start_event, stop_event, photovoltaic=Photovoltaic(), brokerconfigs=BrokerConfigs(), logfile=None):
        self.start_event = start_event
        self.stop_event = stop_event

        if logfile is not None:
            self.logfile = open(logfile, 'w')

            self.logfile.write(f"{'Time':>12} [s] | {'Meter Name':^10}{'Consumption':^17} [W] |{'PV Name':^10}{'Generation':^20} [kW] |{'Netto':^20} [kW]\n")
        else:
            self.logfile = None

        self.photovoltaic = photovoltaic

        self.config = brokerconfigs
        self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=self.config.host, credentials=self.config.credentials))
        self.channel = self.connection.channel()
        self.channel.queue_declare(queue=self.config.queue)

        thread = threading.Thread(target=self._run)
        thread.setDaemon(True)
        thread.start()

    def _run(self):
        while not self.start_event.is_set():
            time.sleep(0.01)

        print("PV Thread Start")

        self.channel.basic_consume(queue=self.config.queue, on_message_callback=self._on_request, auto_ack=True)
        while not self.stop_event.is_set():
            self.connection.process_data_events()
            time.sleep(0.1)
        self.connection.close()
        print("PV thread finished")

    def _on_request(self, ch, method, properties, body):
        # self.queue[properties.correlation_id] = body
        m = MeterMessage.from_json(body)
        self.logger(message=m)

    def logger(self, message: MeterMessage = ''):
        generation = self.photovoltaic.get_power(message.time)
        str = "{:>12} [s] | {:^10} consumed {:<07} [W] | {:^10} generated {:<08} [kW] | Netto: {:<012} [kW]\n"\
            .format(message.time, message.origin, np.round(message.consumption, 2), self.photovoltaic.id,\
                np.round(generation/1000.0, 6), np.round((generation - message.consumption)/1000, 6))
        if self.logfile is not None:
            self.logfile.write(str)
            return
        print(str)

    def __del__(self):
        self.stop_event.set()
        print("closing thread")
        if self.logfile is not None:
            self.logfile.close()

if __name__ == '__main__':
    exit(0)


#!/usr/bin/env python3
import csv
import sys
import re
import os
import glob
from typing import Dict, List, Tuple

from wisselwerking.history import Enrollment, EnrollmentCollection, read_history, rename_dept
from wisselwerking.settings import \
    capacity_file, \
    output_file, \
    ASSIGNED_CHOICE, \
    CAPACITY_CHOICE, \
    CAPACITY_VALUE, \
    TEAM, \
    MAIL_COLUMN, \
    ENROLLMENT_FIRSTNAME, \
    ENROLLMENT_LASTNAME, \
    ENROLLMENT_MAIL, \
    ENROLLMENT_DEPT, \
    ENROLLMENT_CHOICES, \
    RANDOM_CHOICE, \
    NONE_CHOICE, \
    NO_ASSIGNMENT

filename = sys.argv[1]
previous_years_dir = sys.argv[2]

#
# Start assigning!
#

enrollments: List[Dict[str, str]] = []
capacities = {}
counter = {}

assignments: List[Tuple[Dict[str, str], str]] = []

def format_name(enrollment, include_lastname=False):
    first_name = str.join(' ',
                          (part.capitalize() for part in enrollment[ENROLLMENT_FIRSTNAME].strip().split(' ')))
    if include_lastname:
        parts = []
        for part in enrollment[ENROLLMENT_LASTNAME].strip().split(' '):
            if part.lower() in ['van', 'von', 'de', 'der', 'den', 'die']:
                parts.append(part.lower())
            else:
                parts.append(part.capitalize())
        return first_name + ' ' + str.join(' ', parts)

    return first_name

def mail_template(assigned, enrollment):
    name = format_name(enrollment)
    first_choice = enrollment[ENROLLMENT_CHOICES[0]].strip()
    second_choice = enrollment[ENROLLMENT_CHOICES[1]].strip()
    third_choice = enrollment[ENROLLMENT_CHOICES[2]].strip()
    if assigned == first_choice or first_choice == RANDOM_CHOICE:
        # first choice
        content = f"""Je bent geplaatst voor de Wisselwerking {assigned}. We hebben je gegevens doorgegeven aan de contactpersoon van deze Wisselwerking. Deze zal contact met opnemen om verdere afspraken te maken over je deelname.

Heel veel plezier bij je wisselwerking!"""
    elif assigned == second_choice or assigned == third_choice or \
            RANDOM_CHOICE in [second_choice, third_choice]:
        # second, third choice
        if assigned == third_choice:
            ordinal = "derde"
        elif assigned == second_choice:
            ordinal = "tweede"
        else:
            # random!
            ordinal = "vrije"

        content = f"""Helaas was bij jouw eerste keuze voor de Wisselwerking bij {first_choice} geen plek meer. Je bent nu geplaatst bij je {ordinal} keuze: {assigned}.

We hebben je gegevens doorgegeven aan de contactpersoon van deze Wisselwerking. Deze zal contact met opnemen om verdere afspraken te maken over je deelname.

Heel veel plezier bij je wisselwerking!"""
    else:
        # nothing
        content = f"Je hebt je aangemeld voor de Wisselwerking {first_choice}. Helaas waren deze en eventuele verdere keuzes vol."

    return f"""
Beste {name},

{content}

Hartelijke groet,

Team Wisselwerking Geesteswetenschappen
{TEAM}
""".strip()

def get_capacity(choice) -> int:
    if choice == RANDOM_CHOICE:
        return 999
    try:
        capacity = capacities[choice]
        if capacity is None:
            raise KeyError
        return capacity
    except KeyError:
        while True:
            value = input(f"Capacity for {choice}? ")
            try:
                parsed = int(value)
                capacities[choice] = parsed
                return parsed
            except ValueError:
                print("NOPE")
                pass

def save_capacities():
    with open(capacity_file, mode="w", encoding="utf-8-sig") as csv_file:
        fieldnames = [CAPACITY_CHOICE, CAPACITY_VALUE]
        writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=';')

        writer.writeheader()
        for (choice, value) in capacities.items():
            writer.writerow({
                CAPACITY_CHOICE: choice,
                CAPACITY_VALUE: value
            })

if os.path.exists(capacity_file):
    with open(capacity_file, mode="r", encoding="utf-8-sig") as csv_file:
        csv_reader = csv.DictReader(csv_file, delimiter=';')

        for row in csv_reader:
            try:
                capacity = int(row[CAPACITY_VALUE])
            except ValueError:
                capacity = None
            except TypeError:
                capacity = None
            capacities[row[CAPACITY_CHOICE]] = capacity

with open(filename, mode="r", encoding='iso8859-15') as csv_file:
    csv_reader = csv.DictReader(csv_file, delimiter=';')
    form_fieldnames = csv_reader.fieldnames
    line_count = 0

    for row in csv_reader:
        # The top row is the last entry
        enrollments.insert(0, row)
        line_count += 1

history = read_history(previous_years_dir)

# Make sure all possible choices are known
for enrollment in enrollments:
    for choice in map(lambda key: enrollment[key], ENROLLMENT_CHOICES):
        if not choice or choice.strip() in NONE_CHOICE:
            continue
        else:
            counter[choice.strip()] = 0

def assign_choice(enrollment: Dict[str, str], choice: str):
    try:
        counter[choice] += 1
    except KeyError:
        counter[choice] = 1
    assignments.append((enrollment, choice))
    unassigned.remove(enrollment)

    if choice in choices and counter[choice] >= get_capacity(choice):
        choices.remove(choice)

def show_historic_counts():
    print("""
    TOEWIJZINGEN VAN VORIGE WISSELWERKINGEN:
    """)
    historic_counts = {}
    for item in history.list_assigned():
        try:
            historic_counts[item] += 1
        except KeyError:
            historic_counts[item] = 1

    for item in sorted(historic_counts):
        print(f"{str(historic_counts[item]).rjust(3)} {item}")

def show_counts(show_unassigned=True):
    print("""
    AANTAL AANMELDINGEN:
    """)

    choices = sorted(set(capacities.keys()).union(counter.keys()))
    maxlength = sorted(len(choice) for choice in choices)[-1]
    sum = 0
    empty = []

    for choice in choices:
        count = counter.get(choice, 0)
        if count == 0:
            if choice != RANDOM_CHOICE:
                empty.append(choice)
        else:
            print(f"{str(count).rjust(3)} {choice}")
            sum += count

    print("=" * (maxlength + 4))
    print(f"{str(sum).rjust(3)} TOTAAL")

    if empty:
        print("""
    WISSELWERKINGEN ZONDER TOEWIJZINGEN:
    """)
        for choice in empty:
            print(choice)

    if show_unassigned and unassigned:
        print(f"""
    {len(unassigned)} WISSELWERKERS ZONDER TOEWIJZINGEN:
    """)
        for enrollment in unassigned:
            print(enrollment[ENROLLMENT_MAIL])

choices = list(sorted(set(capacities.keys()).union(counter.keys())))
for item, capacity in capacities.items():
    # possible to close a department
    if capacity == 0:
        choices.remove(item)
unassigned = list(enrollments)

priority = []
# Walk through the choices in iterations
# Give priority on order of choice and within that on order of enrollment
for key in ENROLLMENT_CHOICES:
    for enrollment in enrollments:
        choice = enrollment[key]
        if choice and choice not in NONE_CHOICE:
            priority.append((enrollment, choice.strip()))

try:
    while unassigned and choices:
        done = True
        for choice in list(choices):
            for enrollment, enrollment_choice in priority:
                if enrollment in unassigned and enrollment_choice == choice:
                    assign_choice(enrollment, choice)
                    done = False
                    break
        if done:
            break
except KeyboardInterrupt:
    # still store the updated capacities
    save_capacities()
    raise

# assign the random members
choices.remove(RANDOM_CHOICE)

def reassign_random(assignments: List[Tuple[Dict[str, str], str]], history: EnrollmentCollection):
    first = True
    for enrollment in list(enrollment for (enrollment, choice) in assignments if choice == RANDOM_CHOICE):
        unassigned.append(enrollment)
        email = enrollment[ENROLLMENT_MAIL]
        if first:
            print("\n\n===TUSSENSTAND===\n\n")
            show_historic_counts()
            show_counts(False)
            first = False
        previous = list(history.by_email(email))
        depts = set((rename_dept(row[ENROLLMENT_DEPT])) + map(lambda x: x.from_dept, previous))
        print(f"\n\n{email} ({'; '.join(depts)}) moet verrast worden")
        if previous:
            print("Deed eerder de volgende wisselwerkingen: " +
                  ", ".join(x.assigned_dept for x in previous ))
        else:
            print("Wisselwerking-newbie!")

        while True:
            choice = input("Wijs een andere wisselwerking toe: ")
            if (0 if choice not in counter else counter[choice]) < get_capacity(choice):
                for item in assignments:
                    check_enrolment, _ = item
                    if check_enrolment == enrollment:
                        assignments.remove(item)
                        break
                assign_choice(enrollment, choice)
                counter[RANDOM_CHOICE] -= 1
                break
            else:
                print("Zit al vol!")

reassign_random(assignments, history)

save_capacities()

show_counts()

# Store the assignments
with open(output_file, mode="w", encoding="utf-8-sig") as csv_file:
    fieldnames = [ASSIGNED_CHOICE, ENROLLMENT_MAIL, MAIL_COLUMN] + \
        [field for field in form_fieldnames if field != MAIL_COLUMN]
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=';')

    writer.writeheader()
    for (row, assigned) in assignments:
        writer.writerow({
            ASSIGNED_CHOICE: assigned,
            "mail": mail_template(assigned, row),
            **row
        })

# Store the assignments per choice - to mail the organizers
output_prepath = str.join('.', output_file.split('.')[:-1])

def output_text_file(choice: str, escape=True):
    return output_prepath + '.' + (choice if not escape else re.sub(r'[\*\(\) \-\.\&]+', '-', choice)) + '.txt'

existing_files = glob.glob(output_text_file('*', False))

for choice in sorted(counter):
    if choice == RANDOM_CHOICE:
        continue
    count = counter[choice]
    target = output_text_file(choice)
    try:
        existing_files.remove(target)
    except ValueError:
        pass
    with open(target, mode="w", encoding="utf-8-sig") as txt_file:
        choice_assignments = []
        for (row, assigned) in assignments:
            if assigned == choice:
                choice_assignments.append(
                    f"{format_name(row, True)} <{row[ENROLLMENT_MAIL]}> ({rename_dept(row[ENROLLMENT_DEPT])})\n")

        if count > 0:
            txt_file.writelines([f"""Beste organisator,

Leuk dat je je hebt opgegeven om een wisselwerking te organiseren! Voor de wisselwerking {choice} hebben de volgende {count} person(en) zich aangemeld:

"""] +
                                choice_assignments +
                                [f"""
Zou je zo snel mogelijk contact willen opnemen met deze mensen om afspraken te maken over de wisselwerking?

Heel veel plezier bij de wisselwerking!

Hartelijke groet,

Team Wisselwerking Geesteswetenschappen
{TEAM}
"""])
        else:
            txt_file.writelines([f"""Beste organisator,

Helaas heeft dit jaar niemand zich aangemeld voor de Wisselwerking {choice}.

Dank dat je een Wisselwerking wilde organiseren. We hopen dat je volgend jaar weer meedoet!

Hartelijke groet,

Team Wisselwerking Geesteswetenschappen
{TEAM}
"""])

# Clear existing files, which are no longer assigned
for existing_file in existing_files:
    os.remove(existing_file)

print("DONE! Plaats toewijzingen.csv op de O-schijf")


from flask import request, jsonify
from models import (
    Movie,
    Actor,
    MovieActor
)

def create_movie():
    data_json = request.get_json()
    title = data_json.get('title')
    genre = data_json.get('genre')
    if title is None:
        return 'valid title is required', 400
    if genre is None:
        return 'valid genre is required', 400
    m = Movie.get_or_create(
        title=title,
        genre=genre
    )
    actor_names = data_json.get('actors')
    if actor_names is not None:
        for actor_name in actor_names:
            a = Actor.get_or_create(actor_name)
            MovieActor.get_or_create(
                actor_uuid=a.uuid,
                movie_uuid=m.uuid
            )
    return jsonify(m.serialize_to_dict()), 200

def get_movies():
    genre_filter = request.args.get('genre')
    actor_filter = request.args.get('actor')

    movies = Movie.select()
    # performance improvement can be made by having slightly uglier code
    if actor_filter is not None:
        movies = movies.join(MovieActor).join(Actor).where(
            Actor.name == actor_filter
        )
    if genre_filter is not None:
        movies = movies.where(
            Movie.genre == genre_filter
        )
    return jsonify([movie.serialize_to_dict() for movie in movies])


"""
Rellenamos una lista con el nombre de cinco alumnos,
rellenar otra lista con la nota final de esos cinco alumnos,
con array asociativo
"""
"""
nombres = []
notas = []

for i in range(4):
    nombres.append(input("Inserta el nombre del alumno: ").lower())
    notas.append(float(input("Ingresa la nota del alumno: ")))
for i in range(4):
    print("El alumno ",nombres[i],"tiene una nota de ",notas[i])
"""
"""
Con diccionario, solicitar las ventas mensuales del ultimo trimestre.
"""
diccionario = {'Octubre':0,'Noviembre':0,'Diciembre':0}
for i in diccionario:
    ventas = float(input("Ingresa las ventas mensuales del mes de "+i+": "))
    diccionario[i] = ventas

print(diccionario)

mes = input("Qué mes quieres ver?: ")
if mes in diccionario:
    print(diccionario[mes])
else:
    print("No esta en el diccionario")

#lista los elementos del diccionario
print(diccionario.items())

#elimina una posicion concreta
del diccionario['Octubre']
print (diccionario)
#vacia el diccionario
diccionario.clear()
print(diccionario)
#rellenar diccionario en tiempo de ejecucion
dato = input("Ingrese dato: ")
valor = float(input("Ingrese el valor del dato: "))
diccionario[dato] = valor
print(diccionario)
#eliminar el diccionario
del diccionario