import logging

import time
import multiprocessing
from requests_futures.sessions import FuturesSession
from utils_ak.networking.proxy import cast_requests_proxies
from utils_ak.callback_timer import CallbackTimer

logger = logging.getLogger(__name__)

class NoProxyAvailableException(Exception):
    pass

class AvailabilityProxyGuard:
    def __init__(
        self,
        proxy_config,
        check_proxy_availability=True,
        check_proxy_url=None,
        check_proxy_params=None,
        timeout=10,
        proxy_lives=3,
    ):
        # {proxy: max_usages_at_once}
        self.proxy_config = dict(proxy_config)

        # {proxy: available}
        self.counter = dict(proxy_config)
        self.max_proxy_lives = proxy_lives
        self.proxy_lives = {proxy: self.max_proxy_lives for proxy in proxy_config}

        # test proxies
        for proxy in self.proxy_config:
            if not self._is_proxy_valid(proxy):
                raise Exception(f"Proxy {proxy} is not valid")

        self.lock = multiprocessing.Lock()
        self.available_proxies = set(self.proxy_config.keys())

        self.timer = CallbackTimer(self.upd_availability, interval=300)
        self.check_proxy_availability = check_proxy_availability
        self.check_proxy_url = check_proxy_url
        self.check_proxy_params = check_proxy_params
        self.timeout = timeout

    def update_proxy_lives(self, proxy, success):
        if success:
            self.proxy_lives[proxy] = self.max_proxy_lives
        else:
            self.proxy_lives[proxy] -= 1

    @staticmethod
    def _is_proxy_valid(proxy):
        try:
            cast_requests_proxies(proxy)
        except Exception:
            return False
        else:
            return True

    @property
    def available_counter(self):
        return {
            proxy: available
            for proxy, available in self.counter.items()
            if proxy in self.available_proxies
        }

    @property
    def proxies(self):
        return list(self.counter.keys())

    @property
    def non_available_proxies(self):
        return set(self.proxies) - set(self.available_proxies)

    def on_acquire_proxy_callback(self, proxy):
        pass

    def acquire_proxy(self, timeout=None, sleep_timeout=0.01):
        started = time.time()

        while True:
            self.lock.acquire(True)

            self.timer.run_if_possible()

            if any(
                available > 0 for proxy, available in self.available_counter.items()
            ):
                # found some available proxy. Note: lock is still acquired
                break

            # no available proxy
            self.lock.release()

            if timeout and time.time() - started > timeout:
                raise NoProxyAvailableException("No proxy available at the moment")

            time.sleep(sleep_timeout)

        proxy = max(self.available_counter.items(), key=lambda x: x[1])[0]
        logger.debug(f"Acquiring proxy {proxy}")
        self.counter[proxy] -= 1
        self.on_acquire_proxy_callback(proxy)
        self.lock.release()
        return proxy

    def release_proxy(self, proxy, success=True):
        logger.debug(f"Releasing proxy {proxy}")
        with self.lock:
            self.counter[proxy] += 1
            self.update_proxy_lives(proxy, success)

            if (
                not success
                and self.proxy_lives[proxy] <= 0
                and proxy in self.available_proxies
            ):
                logger.debug(f"Proxy {proxy} is not available")
                self.available_proxies.remove(proxy)

    def upd_availability(self, failed_only=True):
        logger.debug(f"Start updating proxy availability. failed_only: {failed_only}")

        if not self.check_proxy_availability:
            return True

        if not self.check_proxy_url:
            raise Exception("Availability can be checked only with specified url")

        proxies = self.proxies if not failed_only else self.non_available_proxies

        if not proxies:
            logger.debug("No proxies to update")
            return

        session = FuturesSession(max_workers=300)

        responses = []
        for proxy in proxies:
            response = session.get(
                self.check_proxy_url,
                params=self.check_proxy_params,
                proxies=cast_requests_proxies(proxy),
                timeout=self.timeout,
            )
            responses.append((proxy, response))

        for proxy, response in responses:
            success = self._is_availability_response_ok(response)
            self.update_proxy_lives(proxy, success)

            if success:
                # succeed
                if proxy not in self.available_proxies:
                    logger.debug(f"Proxy {proxy} is available")
                    self.available_proxies.add(proxy)
            else:
                # fail
                if proxy in self.available_proxies:
                    logger.debug(f"Proxy {proxy} is not available")
                    self.available_proxies.remove(proxy)

        logger.debug("Stop updating proxy availability")

    @staticmethod
    def _is_availability_response_ok(response):
        try:
            res = response.result()
            assert res.status_code == 200
        except Exception:
            return False
        else:
            return True

if __name__ == "__main__":
    from utils_ak.log import configure_stream_logging

    configure_stream_logging(level=logging.DEBUG)
    import random

    proxy_guard = AvailabilityProxyGuard(
        {None: 5},
        check_proxy_url="https://api.binance.com/api/v1/depth",
        check_proxy_params={"symbol": "ETHBTC", "limit": 100},
    )
    proxy_guard.upd_availability(failed_only=False)

    for i in range(10):
        proxy_ = proxy_guard.acquire_proxy(timeout=None)

        print(proxy_, proxy_guard.counter)
        if random.randint(0, 2) == 0:
            proxy_guard.release_proxy(proxy_)


import re
from collections import defaultdict

from lib import *
problem = old_aoc.Problem("2021/05: Hydrothermal Venture")
problem.preprocessor = ppr.lsv

@problem.solver()
def solve(inp):
    linepoints1 = defaultdict(int)
    linepoints2 = defaultdict(int)

    for v in inp:
        m = re.match("(\d+),(\d+) -> (\d+),(\d+)", v)
        x1, y1, x2, y2 = map(int, m.groups())

        if x1 < x2:
            xrange = range(x1, x2 + 1)
        elif x1 > x2:
            xrange = range(x1, x2-1, -1)
        if y1 < y2:
            yrange = range(y1, y2 + 1)
        elif y1 > y2:
            yrange = range(y1, y2-1, -1)

        if x1 == x2:
            for y in yrange:
                linepoints1[(x1, y)] += 1
                linepoints2[(x1, y)] += 1
        elif y1 == y2:
            for x in xrange:
                linepoints1[(x, y1)] += 1
                linepoints2[(x, y1)] += 1
        else:
            for x, y in zip(xrange, yrange) :
                linepoints2[(x, y)] += 1

    p1 = len([i for i in linepoints1 if linepoints1[i] > 1])
    p2 = len([i for i in linepoints2 if linepoints2[i] > 1])

    return (p1, p2)

SAMPLE_INP = ("""
0,9 -> 5,9
8,0 -> 0,8
9,4 -> 3,4
2,2 -> 2,1
7,0 -> 7,4
6,4 -> 2,0
0,9 -> 2,9
3,4 -> 1,4
0,0 -> 8,8
5,5 -> 8,2
""")

if __name__ == "__main__":
    problem.solve(SAMPLE_INP, 5, 12)


"""

BlackHoleAggregate.py

Author: Jordan Mirocha
Affiliation: UCLA
Created on: Sat Mar 17 13:38:58 PDT 2018

Description:

"""

import numpy as np
from scipy.integrate import ode
from .Halo import HaloPopulation
from ..util.Math import interp1d
from ..physics.Constants import G, g_per_msun, m_p, sigma_T, c, rhodot_cgs, \
    rho_cgs, s_per_myr, t_edd

class BlackHoleAggregate(HaloPopulation):
    def __init__(self, **kwargs):
        """
        Initializes a GalaxyPopulation object (duh).
        """

        # This is basically just initializing an instance of the cosmology
        # class. Also creates the parameter file attribute ``pf``.
        HaloPopulation.__init__(self, **kwargs)

    @property
    def _frd(self):
        if not hasattr(self, '_frd_'):
            pass

        return self._frd_

    @_frd.setter
    def _frd(self, value):
        self._frd_ = value

    def _frd_func(self, z):
        # This is a cheat so that the FRD spline isn't constructed
        # until CALLED. Used only for linking.
        return self.FRD(z)

    def FRD(self, z):
        """
        Compute BH formation rate density.

        Units = cgs

        A bit odd to have this in mass units (would rather #/time/vol) but
        for the fcoll model one doesn't need to invoke a BH mass, hence
        the difference between the linked FRD model and the fcoll model below.

        """

        on = self.on(z)
        if not np.any(on):
            return z * on

        # SFRD given by some function
        if self.is_link_sfrd:
            # _frd is in # / cm^3 / s, so we convert to g / cm^3 / s
            return self._frd(z) * on * self.pf['pop_mass'] * g_per_msun \
                * self.pf['pop_bh_seed_eff']

        # Otherwise, use dfcolldt model (all we know right now).
        bhfrd = self.pf['pop_bh_seed_eff'] * self.cosm.rho_b_z0 * self.dfcolldt(z)

        return bhfrd

    @property
    def Ledd_1Msun(self):
        # Multiply by BH mass density to get luminosity in erg/s
        return self.pf['pop_eta'] * 4.0 * np.pi * G * g_per_msun * m_p \
            * c / sigma_T

    def _BHGRD(self, z, rho_bh):
        """
        rho_bh in Msun / cMpc^3 / yr.
        """

        # Convert to Msun / cMpc^3
        new = self.FRD(z) * rhodot_cgs

        # Currently in Msun / cMpc^3 / sec
        old = self.pf['pop_fduty'] \
            * rho_bh[0] * 4.0 * np.pi * G * m_p \
                / sigma_T / c / self.pf['pop_eta']

        # In Msun / cMpc^3 / dz
        return -np.array([new + old]) * self.cosm.dtdz(z)

    @property
    def _BHMD(self):
        if not hasattr(self, '_BHMD_'):

            z0 = min(self.halos.tab_z.max(), self.zform)
            zf = max(float(self.halos.tab_z.min()), self.pf['final_redshift'])
            zf = max(zf, self.zdead)

            if self.pf['sam_dz'] is not None:
                dz = self.pf['sam_dz'] * np.ones_like(self.halos.tab_z)
                zfreq = int(round(self.pf['sam_dz'] / np.diff(self.halos.tab_z)[0], 0))
            else:
                dz = np.diff(self.halos.tab_z)
                zfreq = 1

            # Initialize solver
            solver = ode(self._BHGRD).set_integrator('lsoda', nsteps=1e4,
                atol=self.pf['sam_atol'], rtol=self.pf['sam_rtol'],
                with_jacobian=False)

            in_range = np.logical_and(self.halos.tab_z >= zf,
                self.halos.tab_z <= z0)
            zarr = self.halos.tab_z[in_range][::zfreq]
            Nz = zarr.size

            # y in units of Msun / cMpc^3
            #Mh0 = #self.halos.Mmin(z0)
            #if self.is_link_sfrd:
            #    rho_bh_0 = 1e-10
            #else:
            #    rho_bh_0 = self.halos.fcoll_2d(z0, 5.) * self.pf['pop_bh_seed_eff'] \
            #        * self.cosm.rho_b_z0 * rho_cgs

            solver.set_initial_value(np.array([0.0]), z0)

            zflip = zarr[-1::-1]

            rho_bh = []
            redshifts = []
            for i in range(Nz):

                if i == Nz - 1:
                    break

                redshifts.append(zflip[i])
                rho_bh.append(solver.y[0])

                z = redshifts[-1]

                solver.integrate(solver.t-dz[i])

            z = np.array(redshifts)[-1::-1]

            # Convert back to cgs (internal units)
            rho_bh = np.array(rho_bh)[-1::-1] / rho_cgs

            self._z = z
            self._rhobh = rho_bh

            tmp = interp1d(z, rho_bh,
                kind=self.pf['pop_interp_sfrd'],
                bounds_error=False, fill_value=0.0)

            self._BHMD_ = lambda z: tmp(z)

        return self._BHMD_

    def BHMD(self, z):
        """
        Compute the BH mass density.
        """

        return self._BHMD(z)

    def ARD(self, z):
        """
        Compute the BH accretion rate density.
        """

        tacc = self.pf['pop_eta'] * t_edd / self.pf['pop_fduty']
        return self.BHMD(z) / tacc

    def Emissivity(self, z, E=None, Emin=None, Emax=None):
        """
        Compute the emissivity of this population as a function of redshift
        and rest-frame photon energy [eV].

        ..note:: If `E` is not supplied, this is a luminosity density in the
            (Emin, Emax) band.

        Parameters
        ----------
        z : int, float

        Returns
        -------
        Emissivity in units of erg / s / c-cm**3 [/ eV]

        """

        on = self.on(z)
        if not np.any(on):
            return z * on

        if self.pf['pop_sed_model'] and (Emin is not None) and (Emax is not None):
            if (Emin > self.pf['pop_Emax']):
                return 0.0
            if (Emax < self.pf['pop_Emin']):
                return 0.0

        # This assumes we're interested in the (EminNorm, EmaxNorm) band
        rhoL = on * self.Ledd_1Msun * self.BHMD(z) / g_per_msun

        ## Convert from reference band to arbitrary band
        rhoL *= self._convert_band(Emin, Emax)
        #if (Emax is None) or (Emin is None):
        #    pass
        #elif Emax > 13.6 and Emin < self.pf['pop_Emin_xray']:
        #    rhoL *= self.pf['pop_fesc']
        #elif Emax <= 13.6:
        #    rhoL *= self.pf['pop_fesc_LW']

        if E is not None:
            return rhoL * self.src.Spectrum(E)
        else:
            return rhoL

    def NumberEmissivity(self, z, E=None, Emin=None, Emax=None):
        return self.Emissivity(z, E=E, Emin=Emin, Emax=Emax) / (E * erg_per_ev)

    def LuminosityDensity(self, z, Emin=None, Emax=None):
        """
        Return the luminosity density in the (Emin, Emax) band.

        Parameters
        ----------
        z : int, flot
            Redshift of interest.

        Returns
        -------
        Luminosity density in erg / s / c-cm**3.

        """

        return self.Emissivity(z, Emin=Emin, Emax=Emax)

    def PhotonLuminosityDensity(self, z, Emin=None, Emax=None):
        """
        Return the photon luminosity density in the (Emin, Emax) band.

        Parameters
        ----------
        z : int, flot
            Redshift of interest.

        Returns
        -------
        Photon luminosity density in photons / s / c-cm**3.

        """

        rhoL = self.LuminosityDensity(z, Emin, Emax)
        eV_per_phot = self._get_energy_per_photon(Emin, Emax)

        return rhoL / (eV_per_phot * erg_per_ev)


import json
import random
import socket
import struct
import time

from kazoo.client import KazooClient

from utils import log

zk_root = '/demo'

G = {'servers': []}

class RemoteServer:

    def __init__(self, addr):
        self.addr = addr
        self._socket = None

    @property
    def socket(self):
        if not self._socket:
            self.connect()
        return self._socket

    def rpc(self, func, params):
        sock = self.socket
        message = json.dumps({'func': func, 'params': params}).encode('utf-8')
        length_prefix = struct.pack('I', len(message))
        sock.sendall(length_prefix)
        sock.sendall(message)
        log(sock, sock.fileno(), 'sended')
        length_prefix = sock.recv(4)
        length, = struct.unpack('I', length_prefix)
        resp = json.loads(sock.recv(length).decode('utf-8'))
        return resp['status'], resp['result']

    def connect(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        host, port = self.addr.split(':')
        sock.connect((host, int(port)))
        self._socket = sock

    def reconnect(self):
        self.close()
        self.connect()

    def close(self):
        if self._socket:
            self._socket.close()
            self._socket = None

    def __getattr__(self, func_name):
        def _(params):
            return self.rpc(func_name, params)

        setattr(self, func_name, _)
        return _

def get_servers():
    zk = KazooClient(hosts='127.0.0.1:2181')
    zk.start()
    current_addrs = set()

    def watch_servers(_):
        new_addrs = set()

        for child in zk.get_children(zk_root, watch=watch_servers):
            node = zk.get(zk_root + '/' + child)
            addr = json.loads(node[0])
            new_addrs.add('%s:%d' % (addr['host'], addr['port']))
        added_addrs = new_addrs - current_addrs
        removed_addrs = current_addrs - new_addrs
        removed_servers = []
        for server in G['servers']:
            if server.addr == removed_addrs:
                removed_servers.append(server)

        for server in removed_servers:
            G['servers'].remove(server)
            current_addrs.remove(server.addr)
            log(f'Remove server {server.addr}')

        for addr in added_addrs:
            current_addrs.add(addr)
            G['servers'].append(RemoteServer(addr))
            log(f'Add server {server.addr}')

    for child in zk.get_children(zk_root, watch=watch_servers):
        node = zk.get(zk_root + '/' + child)
        addr = json.loads(node[0])
        log(addr)
        current_addrs.add('%s:%d' % (addr['host'], addr['port']))
    G['servers'] = [RemoteServer(s) for s in current_addrs]
    return G['servers']

def random_server() -> RemoteServer:
    if not G['servers']:
        get_servers()
    if not G['servers']:
        return

    return random.choice(G['servers'])

if __name__ == '__main__':
    for i in range(100):
        server = random_server()
        if not server:
            break
        time.sleep(0.5)
        try:
            status, result = server.foo('request %d' % i)
            print(server.addr, status, result)
        except Exception as e:
            server.close()
            print(e)
        server = random_server()
        if not server:
            break
        time.sleep(0.5)
        try:
            status, result = server.pi(i)
            print(server.addr, status, result)
        except Exception as e:
            server.close()
            print(e)


"generator that yields Entries"

import fileinput

from toolz import partition_all

from parse import settings

def entries_from_path(path):
    "generator that yields Entries either from Path or from StdIn"
    return partition_all(settings.lines_per_entry, _lines_from_path(path))

def _lines_from_path(path):
    "generator that yields Lines either from Path or from StdIn"
    for line in fileinput.input(path):
        yield str(line).rstrip('\n')


import argparse
import requests
from bs4 import BeautifulSoup

if __name__ == '__main__':
  parser = argparse.ArgumentParser(description='Invidious Channel Video Crawler')
  parser.add_argument('-c', '--channel-path', dest='channel', type=str, help='The channel path from where to be crawled.', required=True)
  parser.add_argument('-r', '--indious-url', dest='url', type=str, help='Output folder.', required=True)
  args = parser.parse_args()

  url = args.url + args.channel
  while True:
    html = requests.get(url).text
    soup = BeautifulSoup(html, 'html.parser')
    for a in soup.find_all('a'):
      if a["href"].startswith("/watch?v") and len(a.find_all("p")) == 2:
        a["href"] = args.url + a["href"]
        a.find("img")["src"] = args.url + a.find("img")["src"]
        print(f"- [ ] [{a.find_all('p')[1].text} -- {a.find_all('p')[0].text}]({a['href']})")
    if len(list(filter(lambda a: a["href"].startswith(args.channel + "?page=") and "Next page" in a.text, soup.find_all('a')))) == 0:
      break
    else:
      url = args.url + list(filter(lambda a: a["href"].startswith(args.channel + "?page=") and "Next page" in a.text, soup.find_all('a')))[0]["href"]


import tikzplotlib
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
from matplotlib.collections import LineCollection
import matplotlib.animation as animation
from tqdm import tqdm

import generate
import torch
import numpy as np
import os

np.set_printoptions(formatter={'float': lambda x: "{0:0.3f}".format(x)})
# live is 0
live_or_animate= True

def generate_rotated_hexagon(theta, hexagon_segments):
    rotation_matrix = generate.generate_rotation(theta)
    # [segments, points, [x,y]]
    new_segments = torch.einsum("ab,cdb->cda", rotation_matrix, hexagon_segments)
    return new_segments

max_radius = 30

fig = plt.figure()
if not live_or_animate:
    plt.subplots_adjust(bottom=plt.rcParams["figure.subplot.bottom"] + 0.1)
ax = fig.add_subplot(1, 1, 1)
# ax = plt.gca()
ax.set_aspect("equal")
max_dist = max_radius*1.1+1
ax.set_xlim(-max_dist, max_dist)
ax.set_ylim(-max_dist, max_dist)

# [num_segments, 2 points, 2 coords]
hexagon_segments = generate.generate_hexagon(max_radius, theta=0)
hexagon_segments[...,1]=hexagon_segments[...,1]*1.01

collection_a = LineCollection(
    generate_rotated_hexagon(
        torch.as_tensor(0, dtype=torch.double, device=generate.device),
        hexagon_segments,
    ).cpu(),
    colors=["black"],
    zorder=0,
)
collection_b = LineCollection(
    generate_rotated_hexagon(
        torch.as_tensor(0, dtype=torch.double, device=generate.device),
        hexagon_segments,
    ).cpu(),
    colors=["black"],
    zorder=0,
)
text = ax.text(-max_dist, max_dist, np.float(0))

ax.add_collection(collection_a)
ax.add_collection(collection_b)

def update(val):
    angle = torch.as_tensor(np.deg2rad(val), dtype=torch.double, device=generate.device)
    collection_a.set_segments(generate_rotated_hexagon(angle/2, hexagon_segments).cpu())
    collection_b.set_segments(generate_rotated_hexagon(-angle/2, hexagon_segments).cpu())
    text.set_text(val)

    if not live_or_animate:
        fig.canvas.draw_idle()
    else:
        return [collection_a, collection_b, text]

if not live_or_animate:
    axcolor = "lightgoldenrodyellow"
    angle_ax = plt.axes(
        [
            plt.rcParams["figure.subplot.left"],
            plt.rcParams["figure.subplot.bottom"],
            plt.rcParams["figure.subplot.right"] - plt.rcParams["figure.subplot.left"],
            0.03,
        ],
        facecolor=axcolor,
    )
    angle_slider = Slider(angle_ax, "Angle", 0, 360, valinit=0, valstep=1)

    angle_slider.on_changed(update)
else:
    Writer = animation.writers['ffmpeg']
    writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)
    ani = animation.FuncAnimation(fig, update, tqdm(np.linspace(0,360,num=360*10)), interval=1, blit=True)
ani.save('MoireLapseDilated1percent.mp4', writer=writer)

# plt.show()


import logging
import boto3
from botocore.exceptions import ClientError

def list_bucket(region=None):
    # list bucket
    try:
        if region is None:
            s3 = boto3.client('s3')
            response = s3.list_buckets()

            for bucket in response['Buckets']:
                print(f'  {bucket["Name"]}')
        else:
            print("can't retrieve buckets..")
    except ClientError as e:
        logging.error(e)
        return False
    return True

if __name__ == "__main__":
    print ("Hello,world")
    list_bucket()
    #list_bucket("ap-northeast-2")


import wx

class CustomDropTarget( wx.PyDropTarget ):

    def __init__( self, formatNames, parent=None ):
        wx.PyDropTarget.__init__( self )

        self.app = wx.GetApp()
        self.parent = parent

        # Specify the type of data we will accept
        self.doc = wx.DataObjectComposite()
        self.formats = {}
        for formatName in formatNames:
            do = wx.CustomDataObject( formatName )
            self.formats[formatName] = do
            self.doc.Add( do )
        self.SetDataObject( self.doc )

    def OnDragOver( self, x, y, d ):

        # Return x.DragNone if the validation fails
        if not self.app.dDropMgr.ValidateDropItem( x, y, self.parent ):
            return wx.DragNone
        else:
            return d

    def OnData( self, x, y, d ):

        # Copy the data from the drag source to our data object
        if self.GetData():

            # Call the method on the string taken from the data object
            format = self.doc.GetReceivedFormat().GetId()
            do = self.formats[format]
            self.app.dDropMgr.OnDropItem( do.GetData(), self.parent, x, y )

        return d


"""Version.version_of renamed to Version.task

Revision ID: 5355b569237b
Revises: 6297277da38
Create Date: 2013-06-10 11:47:28.984222

"""

# revision identifiers, used by Alembic.
revision = '5355b569237b'
down_revision = '6297277da38'

from alembic import op
import sqlalchemy as sa

def upgrade():
    try:
        op.alter_column('Versions', 'version_of_id', new_column_name='task_id')
    except sa.exc.OperationalError:
        # SQLite3
        # just create the new column
        # and copy data
        op.add_column(
            'Versions',
            'task_id',
            sa.Column(sa.Integer, sa.ForeignKey("Tasks.id"), nullable=False)
        )
        # copy data from Links.path to Links_Temp.full_path
        op.execute(
            'INSERT INTO "Versions".task_id '
            'SELECT "Versions".version_of_id '
            'FROM "Versions"'
        )

def downgrade():
    try:
        op.alter_column('Versions', 'task_id', new_column_name='version_of_id')
    except sa.exc.OperationalError:
        # SQLite3
        # just create the new column
        # and copy data
        op.add_column(
            'Versions',
            'version_of_id',
            sa.Column(sa.Integer, sa.ForeignKey("Tasks.id"), nullable=False)
        )
        op.execute(
            'INSERT INTO "Versions".version_of_id '
            'SELECT "Versions".task_id '
            'FROM "Versions"'
        )


import PySimpleGUI as sg
from src.windows import menu
from src.handlers import dato_1 as dato1
from src.handlers import dato_2 as dato2
def start():
	"""ejecucion de la ventana del menú"""
	window=loop()
	window.close()
def loop():
	"""loop de la ventana"""
	window=menu.build()
	while True:
		event,values=window.read()
		if event in ("Salir","-exit-"):
			break
		if event=="-dato1-":
			window.hide()
			dato1.start()
			sg.Popup("Se obtuvieron las 15 provincias con más casos de infecciones respiratorias <<resultado en archivo 'provincias'>>",no_titlebar=True)
			window.un_hide()
		if event=="-dato2-":
			window.hide()
			dato2.start()
			sg.Popup("Se obtuvieron las 20 marcas que más utilizan nafta <<resultado en archivo 'Marcas'>>",no_titlebar=True)
			window.un_hide()
	return window


from cgi import test
from lib2to3.pgen2 import token
import requests
import json

from flask import Flask
app = Flask(__name__)
toquen='4bd8dda5-9f21-66f4-e929-49c4bb76c4dd'

@app.route('/')
def hello_world():
    return 'Hello, World!'

@app.route('/pregunta_uno/<numero>', methods=['GET'])
def pregunta_uno(numero):
    secuencia=''
    cantidad=0
    for i in range(1,int(numero)+1):
        secuencia+=str(i)
        cantidad= len(secuencia)
    res="{ numero: "+str(numero)+ ", secuencia: "+ str(secuencia)+ ", cantidad: "+ str(cantidad)+"}"
    return res


from PyQt5.QtWidgets import QMainWindow
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import *
from MainOperations import AnaIslemler
from OtherClasses import InfoWindow

class Run(QMainWindow):
    def __init__(self):
        super().__init__()

        loadUi("..\GUIPages\welcome.ui", self)

        self.pushButton.clicked.connect(self.open_Info)
        self.InfoWindow = InfoWindow()

        self.pushButton_2.clicked.connect(self.open_AnaIslemler)
        self.AnaIslemler= AnaIslemler()

    def open_AnaIslemler(self):
        self.AnaIslemler.show()
        self.close()

    def open_Info(self):
        self.InfoWindow.show()

app = QApplication([])
window = Run()
window.show()
app.exec_()


from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://web.whatsapp.com/')
name = input('Enter the name of user or group:')
msg = input('Enter your message:')
count = int(input('Enter the count:'))
input('Enter anything affter scanning QR code')
user = driver.find_element_by_xpath('//span[@title = "{}"]'.format(name))
user.click()
msg_box = driver.find_element_by_xpath('//*[@id="main"]/footer/div[1]/div[2]/div/div[2]')
for i in range(count):
    print(i)
    msg_box.send_keys(msg)
    driver.find_element_by_xpath('//*[@id="main"]/footer/div[1]/div[3]/button').click()

print("Success")


"""empty message

Revision ID: 28ab9a07f1d6
Revises: 2ba2f91a5bcf
Create Date: 2017-02-24 02:37:13.402761

"""

# revision identifiers, used by Alembic.
revision = '28ab9a07f1d6'
down_revision = '2ba2f91a5bcf'

from alembic import op
import sqlalchemy as sa

def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.create_table('messages',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=40), nullable=True),
    sa.Column('content', sa.Text(), nullable=True),
    sa.Column('token', sa.String(length=40), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    ### end Alembic commands ###

def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('messages')
    ### end Alembic commands ###


import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer

filepath = 'data/Suicide_Detection.csv'

df = pd.read_csv(filepath, header=0)
print(df.iloc[0])

sentences = df['text'].values

ex = sentences.shape[0]
y = np.zeros((ex))
y[df['class'] == 'suicide'] = 1

sentences = sentences[:5000]
y = y[:5000]

sentences_train, sentences_test, y_train, y_test = train_test_split(
    sentences, y, test_size=0.25, random_state=1000)

vectorizer = CountVectorizer()
vectorizer.fit(sentences_train)
X_train = vectorizer.transform(sentences_train)
X_test  = vectorizer.transform(sentences_test)

from keras.models import Sequential
from keras import layers

from keras.backend import clear_session
clear_session()

input_dim = X_train.shape[1]  # Number of features

model = Sequential()
model.add(layers.Dense(10, input_dim=input_dim, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc'])
model.summary()

history = model.fit(X_train, y_train, epochs=10, verbose=False, validation_data=(X_test, y_test), batch_size=100)

loss, accuracy = model.evaluate(X_train, y_train, verbose=False)
print("Training Accuracy: {:.4f}".format(accuracy))
loss, accuracy = model.evaluate(X_test, y_test, verbose=False)
print("Testing Accuracy:  {:.4f}".format(accuracy))

import matplotlib.pyplot as plt
plt.style.use('ggplot')

def plot_history(history):
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    x = range(1, len(acc) + 1)

    plt.figure(figsize=(12, 5))
    plt.subplot(1, 2, 1)
    plt.plot(x, acc, 'b', label='Training acc')
    plt.plot(x, val_acc, 'r', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.subplot(1, 2, 2)
    plt.plot(x, loss, 'b', label='Training loss')
    plt.plot(x, val_loss, 'r', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()

    plt.savefig('test.pdf')

plot_history(history)


import torch
from torch import nn
from torch.nn import functional as F
from modules.decompose import fft_frequency_decompose, fft_frequency_recompose
from modules.linear import LinearOutputStack
from modules.psychoacoustic import PsychoacousticFeature
from modules.reverb import NeuralReverb
from train.optim import optimizer
from util import device, playable
from util.readmedocs import readme
import zounds
import numpy as np

from util.weight_init import make_initializer

samplerate = zounds.SR22050()

n_samples = 2 ** 15

# [32768, 16384, 8192, 4096, 2048, 1024]
band_sizes = [2 ** (15 - i) for i in range(6)]
base_keep = 8
atoms_counts = {
    1024: base_keep * 8,
    2048: base_keep * 8,
    4096: base_keep * 16,
    8192: base_keep * 16,
    16384: base_keep * 16,
    32768: base_keep * 16
}

kernel_sizes = {
    1024: 512,
    2048: 512,
    4096: 512,
    8192: 512,
    16384: 512,
    32768: 512
}

band_1 = zounds.FrequencyBand(1, samplerate.nyquist)
band_2 = zounds.FrequencyBand(samplerate.nyquist / 2, samplerate.nyquist)

scale_1 = zounds.LinearScale(band_1, 128)
scale_2 = zounds.LinearScale(band_2, 128)

fb_1 = zounds.learn.FilterBank(
    samplerate, 128, scale_1, 0.1, normalize_filters=True, a_weighting=False).to(device)
fb_2 = zounds.learn.FilterBank(
    samplerate, 128, scale_2, 0.1, normalize_filters=True, a_weighting=False).to(device)

n_rooms = 8

init_weights = make_initializer(0.1)

class DilatedBlock(nn.Module):
    def __init__(self, channels, dilation):
        super().__init__()
        self.dilated = nn.Conv1d(channels, channels, 3, padding=dilation, dilation=dilation)
        self.conv = nn.Conv1d(channels, channels, 1, 1, 0)

    def forward(self, x):
        orig = x
        x = self.dilated(x)
        x = self.conv(x)
        x = x + orig
        x = F.leaky_relu(x, 0.2)
        return x

class AtomCollection(nn.Module):
    def __init__(
            self,
            n_atoms,
            kernel_size,
            atoms_to_keep,
            atoms_to_apply=None):

        super().__init__()

        # self.net = nn.Sequential(
        #     nn.Conv1d(n_atoms, 32, 1, 1, 0),
        #     nn.Dropout(0.5),
        #     DilatedBlock(32, 1),
        #     nn.Dropout(0.5),
        #     DilatedBlock(32, 3),
        #     nn.Dropout(0.5),
        #     nn.Conv1d(32, n_atoms, 1, 1, 0)
        # )

        self.n_atoms = n_atoms
        self.kernel_size = kernel_size
        self.atoms_to_keep = atoms_to_keep
        self.atoms_to_apply = atoms_to_apply or n_atoms

        self.atoms = nn.Parameter(
            torch.zeros(n_atoms, 1, self.kernel_size).uniform_(-0.01, 0.01))

        self.apply(init_weights)

    def clip_atom_norms(self):
        self.atoms.data[:] = self.unit_norm_atoms()

    def unit_norm_atoms(self):
        indices = torch.randperm(self.n_atoms)[:self.atoms_to_apply]

        atoms = self.atoms[indices]
        norms = torch.norm(atoms, dim=-1, keepdim=True)
        atoms = atoms / (norms + 1e-12)
        return atoms

    def orthogonal_loss(self):
        x = self.unit_norm_atoms().view(self.n_atoms, self.kernel_size)
        sim = x @ x.T
        return sim.mean()

    def clip_atom_norms(self):
        pass

    def forward(self, x):

        batch_size = x.shape[0]

        # give atoms unit norm
        atoms = self.unit_norm_atoms()

        full = feature_map = x = F.conv1d(
            x, atoms, bias=None, stride=1, padding=self.kernel_size // 2)

        # logits = torch.softmax(feature_map, dim=1)
        # logits = logits.reshape(batch_size, -1)

        shape = feature_map.shape

        feature_map = feature_map.reshape(batch_size, -1)

        values, indices = torch.topk(
            feature_map, k=self.atoms_to_keep, dim=-1)

        values = feature_map.gather(-1, indices)

        new_feature_map = torch.zeros_like(feature_map)
        new_feature_map.scatter_(-1, indices, values)

        feature_map = new_feature_map.reshape(shape)

        x = F.conv_transpose1d(
            feature_map, atoms, bias=None, stride=1, padding=self.kernel_size // 2)

        return feature_map, x, full

class MultiBandSparseModel(nn.Module):
    def __init__(self):
        super().__init__()
        # [32768, 16384, 8192, 4096, 2048, 1024]

        n_atoms = 512

        self.bands = nn.ModuleDict({
            str(bs): AtomCollection(
                n_atoms=n_atoms,
                kernel_size=kernel_sizes[bs],
                atoms_to_keep=atoms_counts[bs]) for bs in band_sizes
        })

        rooms = np.random.uniform(-1, 1, (n_rooms, n_samples))

        lin = np.linspace(1, 0, num=n_samples)
        pow = np.array([1, 3, 5, 7, 9, 11, 13, 15])

        rooms = rooms * (lin[None, :] ** pow[:, None])

        self.verb = NeuralReverb(n_samples, n_rooms, impulses=rooms)
        self.to_rooms = LinearOutputStack(
            128, 2, out_channels=n_rooms, in_channels=n_atoms * len(band_sizes))
        self.to_mix = LinearOutputStack(
            128, 2, out_channels=1, in_channels=n_atoms * len(band_sizes))

    def clip_atom_norms(self):
        for size, band in self.bands.items():
            band.clip_atom_norms()

    def orthogonal_loss(self):
        loss = 0
        for band in self.bands.values():
            loss = loss + band.orthogonal_loss()
        return loss

    def forward(self, x):

        # bands = fft_frequency_decompose(x, band_sizes[-1])

        bands = x

        # n_samples = x.shape[-1]

        feature_maps = {}
        recon = {}
        full_maps = []
        sparse = []

        # TODO: Use global avg pooling on full (not sparse)
        # feature maps to choose reverb parameters
        for size, band in bands.items():
            fm, x, full = self.bands[str(size)].forward(band)
            sparse.append(full.sum(dim=1))
            full_maps.append(full.mean(dim=-1))
            recon[size] = x
            feature_maps[size] = fm

        # full_features = torch.cat(full_maps, dim=-1)
        # rooms = torch.softmax(self.to_rooms(full_features), dim=-1)
        # mix = torch.sigmoid(self.to_mix(full_features)).view(-1, 1, 1)

        # signal = fft_frequency_recompose(recon, n_samples)
        signal = recon

        # wet = self.verb.forward(signal, rooms)
        # signal = (signal * mix) + (wet * (1 - mix))

        return feature_maps, signal, sparse

model = MultiBandSparseModel().to(device)
optim = optimizer(model, lr=1e-3)

def perceptual_feature(x):
    # final_bands = {}
    # bands = fft_frequency_decompose(x, band_sizes[-1])
    bands = x

    # for k, v in bands.items():
    #     filt = fb_1 if k == band_sizes[0] else fb_2
    #     z = filt.forward(v, normalize=False)
    #     z = z.unfold(-1, 128, 64)
    #     z = torch.abs(torch.fft.rfft(z, dim=-1, norm='ortho'))
    #     final_bands[k] = z
    # return final_bands
    return bands

def perceptual_loss(fake, real):
    fake_bands = perceptual_feature(fake)
    real_bands = perceptual_feature(real)
    loss = 0
    for k, v in fake_bands.items():
        loss = loss + F.mse_loss(v, real_bands[k])
    return loss

def train_model(batch):
    optim.zero_grad()

    batch = fft_frequency_decompose(batch, band_sizes[-1])

    feature_maps, signal, sparse = model.forward(batch)

    # ortho_loss = model.orthogonal_loss() * 100
    loss = perceptual_loss(signal, batch) #+ ortho_loss
    loss.backward()
    optim.step()
    with torch.no_grad():
        model.clip_atom_norms()

    signal = fft_frequency_recompose(signal, n_samples)

    return loss, signal, feature_maps

@readme
class MultiBandMatchingPursuitExperiment(object):
    def __init__(self, stream):
        super().__init__()
        self.stream = stream

        self.signal = None
        self.feature_maps = None
        self.r = None
        self.model = model

    def listen(self):
        return playable(self.signal, samplerate)

    def fake_spec(self):
        return np.log(1e-4 + np.abs(zounds.spectral.stft(self.listen())))

    def real(self):
        return playable(self.r, samplerate)

    def feature_map(self, n):
        return self.feature_maps[n].data.cpu().numpy()[0]

    def run(self):
        for i, item in enumerate(self.stream):
            item = item.view(-1, 1, n_samples)
            # item = zounds.mu_law(item)
            # item = torch.from_numpy(item).float().to(device)

            self.r = item

            loss, self.signal, self.feature_maps = train_model(item)

            if i % 10 == 0:
                print(loss.item())


import tempfile
from pathlib import Path
from typing import List
from jinja2 import Environment, FileSystemLoader
from examples.ssmt.ssmt_with_custom_packages.NewInfectionsAnalyzer import NewInfectionsAnalyzer
from idmtools.core.platform_factory import Platform
from idmtools.analysis.platform_anaylsis import PlatformAnalysis

def write_wrapper_script(list_of_packages: List[str]):
    env = Environment(loader=FileSystemLoader(Path(__file__).parent))
    template = env.get_template('package_script.sh.jinja2')
    f = tempfile.NamedTemporaryFile(suffix='.sh', mode='wb', delete=False)
    f.write(template.render(dict(packages=list_of_packages)).replace("\r", "").encode('utf-8'))
    f.flush()
    return f.name

if __name__ == "__main__":
    platform = Platform('Calculon')
    analysis = PlatformAnalysis(
        platform=platform, experiment_ids=["d66a72ee-74a9-ed11-aa02-b88303911bc1"],
        analyzers=[NewInfectionsAnalyzer], #analyzers_args=[{'name': 'plot new infections'}],
        analysis_name="Example to use extra packages",
        wrapper_shell_script=write_wrapper_script(['kaleido', 'plotly']),
        # You can pass any additional arguments needed to AnalyzerManager through the extra_args parameter
        extra_args=dict(max_workers=8)
    )

    analysis.analyze(check_status=True)
    wi = analysis.get_work_item()
    print(wi)