"""
Scrape Los Angeles Metro ridership data
"""
import datetime
import os
from urllib.parse import quote_plus

import bs4
import pandas as pd
import requests
import sqlalchemy

# The URL for the ridership form
RIDERSHIP_URL = "http://isotp.metro.net/MetroRidership/IndexSys.aspx"

# Parameters needed to validate the request
ASPX_PARAMETERS = ["__VIEWSTATE", "__EVENTVALIDATION"]

# The S3 bucket into which to load data.
S3_BUCKET = "s3://tmf-ita-data"

def get_form_data():
    """
    Make an inital fetch of the form so we can scrape the options
    as well as the parameters needed to validate our requests.
    """
    # Fetch the page and parse it
    r = requests.get(RIDERSHIP_URL)
    r.raise_for_status()
    soup = bs4.BeautifulSoup(r.text, features="html.parser")

    # Get validation info
    aspx_data = {
        param: soup.find(attrs={"id": param}).attrs.get("value", "")
        for param in ASPX_PARAMETERS
    }

    # Get all of the metro lines
    line_options = soup.find(attrs={"id": "ContentPlaceHolder1_lbLines"}).select(
        "option"
    )
    lines = [
        option.attrs["value"]
        for option in line_options
        if option.attrs["value"] != "All"
    ]

    # Get the available years
    year_options = soup.find(attrs={"id": "ContentPlaceHolder1_ddlYear"}).select(
        "option"
    )
    years = [option.attrs["value"] for option in year_options]
    return lines, years, aspx_data

def submit_form(year, period, line, aspx_data):
    """
    Submit a form to the Metro ridership site requesting data for a line.

    Parameters
    ----------
    year: int
        The year for which to fetch the data.
    period: str or int
        The time period in which to fetch the data. Typically you will want
        an integer month, though other values like quarters ("Q1") may work.
    line: str or int
        The Metro line number
    aspx_data: dict
        The metadata needed for forming a correct form submission.

    Returns
    -------
    An HTML string of the resposnse.
    """
    form_data = {
        "ctl00$ContentPlaceHolder1$rbFYCY": "CY",
        "ctl00$ContentPlaceHolder1$ddlYear": str(year),
        "ctl00$ContentPlaceHolder1$ddlPeriod": str(period),
        "ctl00$ContentPlaceHolder1$btnSubmit": "Submit",
        "ctl00$ContentPlaceHolder1$lbLines": str(line),
        **aspx_data,
    }
    r = requests.post(RIDERSHIP_URL, data=form_data)
    r.raise_for_status()
    if r.text.find("Data not available yet") != -1:
        raise ValueError(f"Data not available for {year}, {period}, {line}")

    return r.text

def parse_response(html):
    """
    Parse an HTML response from the ridership form into a dataframe.

    Parameters
    ----------
    html: str
        The HTML webpage from the ridership site.

    Returns
    -------
    A dataframe from the parsed HTML table.
    """
    tables = pd.read_html(
        html,
        flavor="bs4",
        attrs={"id": "ContentPlaceHolder1_ASPxRoundPanel2_gvRidership"},
    )
    if len(tables) == 0:
        raise ValueError("No table found")
    df = tables[0]
    # Filter out the "Total" row
    df = df[df["Day Type"] != "Total"]
    return df

def get_ridership_data(year, period, line, aspx_data):
    """
    Get ridership for a given year, time period, and line.

    Parameters
    ----------
    year: int
        The year for which to fetch the data.
    period: str or int
        The time period in which to fetch the data. Typically you will want
        an integer month, though other values like quarters ("Q1") may work.
    line: str or int
        The Metro line number
    aspx_data: dict
        The metadata needed for forming a correct form submission.

    Returns
    -------
    A dataframe with ridership data for the line/period/year.
    """
    html = submit_form(year, period, line, aspx_data)
    df = parse_response(html)

    df = df.assign(year=year, month=period, line=line)
    return df

def get_all_ridership_data(verbosity=0):
    """
    Fetch all ridership data from the web form.
    """
    lines, years, aspx_data = get_form_data()
    months = [str(i) for i in range(1, 13)]
    ridership = pd.DataFrame()
    # Get the current timestamp so we don't try to fetch from the future.
    now = pd.Timestamp.now()

    for year in years:
        # Don't try to fetch from years in the future.
        if int(year) > now.year:
            continue
        if verbosity > 0:
            print(f"Fetching data for {year}")
        for month in months:
            # Don't try to fetch from months in the future
            if int(year) == now.year and int(month) >= now.month:
                continue
            if verbosity > 1:
                print(f"Fetching data for month {month}")
            for line in lines:
                try:
                    df = get_ridership_data(year, month, line, aspx_data)
                    ridership = ridership.append(df)
                    if verbosity > 2:
                        print(f"Fetched data for line {line}")
                except Exception as e:
                    if verbosity > 2:
                        print(f"Failed to get data for line {line}")
                        print(e)
    return ridership

if __name__ == "__main__":
    """
    The entrypoint for the job.
    """
    # Load the data
    today = datetime.date.today()
    name = "metro-ridership-{}.parquet".format(today)
    ridership = get_all_ridership_data(2)

    # Load into the data warehouse
    if os.environ.get("DEV"):
        POSTGRES_URI = os.environ.get("POSTGRES_URI")
    else:
        POSTGRES_URI = (
            f"postgres://"
            f"{quote_plus(os.environ['POSTGRES_CREDENTIAL_USERNAME'])}:"
            f"{quote_plus(os.environ['POSTGRES_CREDENTIAL_PASSWORD'])}@"
            f"{os.environ['POSTGRES_HOST']}:{os.environ['POSTGRES_PORT']}"
            f"/{os.environ['POSTGRES_DATABASE']}"
        )
    engine = sqlalchemy.create_engine(POSTGRES_URI)
    ridership.to_sql(
        "metro_ridership",
        engine,
        schema="transportation",
        if_exists="replace",
        index=False,
        method="multi",
    )

    # Load to s3
    if not os.environ.get("DEV"):
        ridership.to_parquet(f"{S3_BUCKET}/{name}")


import validators
import os
from http.client import BAD_GATEWAY, INTERNAL_SERVER_ERROR

def getQueryParameters(params):
    '''

    Parameters
    -----------
    params: MultiDict
        request's query parameters

    Returns
    ------------
    url: str
        url to be shortened
    provider: str
        specified provider to prefer if possible

    Raises
    ------------
    ValueError
        if input parameters are not valid

    '''
    if params.get('url'):
        url = params.get('url')
    else:
        raise ValueError("Url Not Found")
    if params.get('provider'):
        provider = params.get('provider')
        if provider not in ['bitly', 'tinyurl']:
            raise ValueError("Invalid Provider")
    else:
        provider = 'bitly'
    if validators.url(url.strip()):
        return url, provider
    else:
        raise ValueError("Invalid Url")

def getEnvVars(**kwargs):
    '''

    Parameters
    -------------
    key-value pairs
    keys: will be used for drawing variables from return dict
    values: name of the enviornment variable

    Returns
    --------------
    envVars: dict

    Example
    -------------
    Get environment variable with name exampleEnvVarName and value 'test'

    assert getEnvVars(exampleKey='exampleEnvVarName')['exampleKey'] == 'test'
    True

    '''
    try:
        envVars = {key: os.environ[val] for key, val in
                   zip(kwargs.keys(), kwargs.values())}
    except KeyError:
        print("Enviroment variables not found.")
        # here should return internal server error
        raise KeyError("Enviroment variables not found.")

    return envVars

def error_response_creator(status_codes: dict):
    '''
    return error response based on third party api response codes.
    ready to adapt in case of adding new third party apis.
    '''
    for status_code in status_codes.values():
        if 399 < status_code < 500:             # at least one with error
            return "Internal Server Error", INTERNAL_SERVER_ERROR
    return "Bad Gateway", BAD_GATEWAY


import pyro
from cuqi.samples import Samples
from cuqi.distribution import Posterior, JointDistribution
from cuqipy_pytorch.distribution import StackedJointDistribution
import torch as xp
import numpy as np

class NUTS:

    def __init__(self, target, MCMC_kwargs=None, NUTS_kwargs=None):

        if MCMC_kwargs is None:
            MCMC_kwargs = {}
        if NUTS_kwargs is None:
            NUTS_kwargs = {}

        if isinstance(target, StackedJointDistribution):
            self.joint = JointDistribution(*target._densities)
            self.target = target
        elif isinstance(target, JointDistribution):
            self.joint = target
            self.target = StackedJointDistribution(*target._densities)
        elif isinstance(target, Posterior):
            self.joint = JointDistribution(target.likelihood, target.prior)
            self.target = StackedJointDistribution(*self.joint._densities)

        self.kernel = pyro.infer.NUTS(potential_fn=self.potential_fn, **NUTS_kwargs)

        self.MCMC_kwargs = MCMC_kwargs

    def potential_fn(self, params):
        return -self.target.logd(params["x"])

    def sample(self, N, Nb=200):

        # NUTS kernel
        kernel = self.kernel

        # Add defaults to MCMC kwargs
        MCMC_kwargs = self.MCMC_kwargs
        MCMC_kwargs["kernel"] = kernel
        MCMC_kwargs["num_samples"] = N
        MCMC_kwargs["warmup_steps"] = Nb
        MCMC_kwargs["num_chains"] = 1
        if "initial_params" not in MCMC_kwargs:
            MCMC_kwargs["initial_params"] = {"x":xp.ones(self.target.dim)}

        # Sampler
        sampler = pyro.infer.MCMC(**MCMC_kwargs)

        # Run sampler
        sampler.run()

        # Get samples
        samples_pyro = sampler.get_samples()

        # Split samples
        split_indices = np.cumsum(self.joint.dim)
        split_samples = np.split(samples_pyro["x"].numpy().T, split_indices[:-1])

        # Acc to dict
        samples = {}
        par_names = self.joint.get_parameter_names()
        for i, par_name in enumerate(par_names):
            samples[par_name] = Samples(split_samples[i], self.target.get_density(par_name).geometry)

        #if len(samples) == 1:
        #    return samples[par_names[0]]
        return samples


fruits = ["apple","orange","banana"]                            #fruit list
num_char = ["zero","one","two","three","four","five","six","seven","eight","nine"]  #numbers in characters
length = len(fruits)                                            #length of fruit
user_input = None                                               #user input is None in initial
limit_quantity = [9,9,9]                                        #limit of sales
count_friuits = [0,0,0]                                         #count of fruits sold
option = "y"                                                    #whether user want to continue

def customerinput():                                            #function to get input from user
    global user_input                                           #global variable to use it in other funtions
    user_input = input("WHAT DO YOU WANT : ")
    for index_fruit in range(0,length):                         #for loop to run the values
        if (count_friuits[index_fruit]  >= 9):                  #if count of a fruit is greater than or equal to break the loop
            break
        if((fruits[index_fruit]) in user_input):                #to check if the user_input contains the fruit
            for index_num in range(0,10):                       #for loop to run all numbers in characters
                if(num_char[index_num] in user_input):          #if the numbers in characters in user_input add the value to the count_fruits
                    count_friuits[index_fruit] += index_num
            if(count_friuits[index_fruit] == 0):                #if the count is not given in the user_input ask user for count
                count_friuits[index_fruit] += int(input("ENTER COUNT OF "+fruits[index_fruit]+": "))

while (option == "y"):                                          #whetjer the user want to continue
    for index in range(0,length):                               #to check the stock of fruits
        if (limit_quantity[index] <= count_friuits[index]):
            print(fruits[index]+" IS OUT OF STOCK")
    customerinput()                                             #calling the customerinput() funtion
    option = input("CONTINUE (y/n) : ")                         #user input to continue or to end
for index in range(0,length):
    print(fruits[index]+" SOLD IS : ",count_friuits[index])
"""
---------- OUTPUT:1 ----------
WHAT DO YOU WANT : one apple
CONTINUE (y/n) : y
WHAT DO YOU WANT : orange
ENTER COUNT OF orange: 5
CONTINUE (y/n) : y
WHAT DO YOU WANT : three banana
CONTINUE (y/n) : n
apple SOLD IS :  1
orange SOLD IS :  5
banana SOLD IS :  3
---------- OUTPUT:2 ----------
WHAT DO YOU WANT : three orange
CONTINUE (y/n) : y
WHAT DO YOU WANT : banana
ENTER COUNT OF banana: 9
CONTINUE (y/n) : y
banana IS OUT OF STOCK
WHAT DO YOU WANT : apple
ENTER COUNT OF apple: 9
CONTINUE (y/n) : y
apple IS OUT OF STOCK
banana IS OUT OF STOCK
WHAT DO YOU WANT : two apple
CONTINUE (y/n) : n
apple SOLD IS :  9
orange SOLD IS :  3
banana SOLD IS :  9
"""


############################################################
# -*- coding: utf-8 -*-
#
#       #   #  #   #   #    #
#      ##  ##  #  ##  #    #
#     # # # #  # # # #    #  #
#    #  ##  #  ##  ##    ######
#   #   #   #  #   #       #
#
# Python-based Tool for interaction with the 10micron mounts
# GUI with PyQT5 for python
#
# written in python3, (c) 2019-2023 by mworion
# Licence APL2.0
#
###########################################################
# standard libraries
import socket

# external packages
import wakeonlan

# local import
from mountcontrol.mount import checkFormatMAC

class SettMount(object):
    """
    """

    def __init__(self):
        self.ui.mountOn.clicked.connect(self.mountBoot)
        self.ui.mountOff.clicked.connect(self.mountShutdown)
        self.ui.mountHost.editingFinished.connect(self.mountHost)
        self.ui.port3492.clicked.connect(self.mountHost)
        self.ui.port3490.clicked.connect(self.mountHost)
        self.ui.mountMAC.editingFinished.connect(self.mountMAC)
        self.ui.bootRackComp.clicked.connect(self.bootRackComp)
        self.ui.waitTimeMount.valueChanged.connect(self.setWaitTime)
        self.ui.waitTimeMountFlip.valueChanged.connect(self.setWaitTimeFlip)
        self.ui.clockSync.stateChanged.connect(self.toggleClockSync)
        self.ui.copyFromTelescopeDriver.clicked.connect(self.updateTelescopeParametersToGui)
        self.app.mountOn.connect(self.mountBoot)
        self.app.mountOff.connect(self.mountShutdown)
        self.app.mount.signals.settingDone.connect(self.setMountMAC)
        self.app.mount.signals.firmwareDone.connect(self.updateFwGui)
        self.app.update3s.connect(self.updateTelescopeParametersToGuiCyclic)
        self.app.update30s.connect(self.syncClock)

    def initConfig(self):
        """
        :return:
        """
        config = self.app.config['mainW']
        self.ui.mountHost.setText(config.get('mountHost', ''))
        self.ui.port3492.setChecked(config.get('port3492', True))
        self.mountHost()
        self.ui.mountMAC.setText(config.get('mountMAC', ''))
        self.mountMAC()
        self.ui.mountWolAddress.setText(config.get('mountWolAddress',
                                                   '255.255.255.255'))
        self.ui.mountWolPort.setText(config.get('mountWolPort', '9'))
        self.ui.rackCompMAC.setText(config.get('rackCompMAC', ''))
        self.ui.waitTimeMount.setValue(config.get('waitTime', 0))
        self.ui.waitTimeMountFlip.setValue(config.get('waitTimeFlip', 0))
        self.ui.automaticTelescope.setChecked(config.get('automaticTelescope', False))
        self.ui.automaticWOL.setChecked(config.get('automaticWOL', False))
        self.ui.syncTimeNone.setChecked(config.get('syncTimeNone', True))
        self.ui.syncTimeCont.setChecked(config.get('syncTimeCont', False))
        self.ui.syncTimeNotTrack.setChecked(config.get('syncTimeNotTrack', False))
        self.ui.clockSync.setChecked(config.get('clockSync', False))
        self.toggleClockSync()

        if self.ui.automaticWOL.isChecked():
            self.mountBoot()
        return True

    def storeConfig(self):
        """
        :return:
        """
        config = self.app.config['mainW']
        config['mountHost'] = self.ui.mountHost.text()
        config['mountMAC'] = self.ui.mountMAC.text()
        config['mountWolAddress'] = self.ui.mountWolAddress.text()
        config['mountWolPort'] = self.ui.mountWolPort.text()
        config['rackCompMAC'] = self.ui.rackCompMAC.text()
        config['waitTime'] = self.ui.waitTimeMount.value()
        config['waitTimeFlip'] = self.ui.waitTimeMountFlip.value()
        config['port3492'] = self.ui.port3492.isChecked()
        config['automaticTelescope'] = self.ui.automaticTelescope.isChecked()
        config['automaticWOL'] = self.ui.automaticWOL.isChecked()
        config['syncTimeNone'] = self.ui.syncTimeNone.isChecked()
        config['syncTimeCont'] = self.ui.syncTimeCont.isChecked()
        config['syncTimeNotTrack'] = self.ui.syncTimeNotTrack.isChecked()
        config['clockSync'] = self.ui.clockSync.isChecked()
        return True

    def mountBoot(self):
        """
        :return:
        """
        bAddress = self.ui.mountWolAddress.text().strip()
        bPort = self.ui.mountWolPort.text().strip()
        bPort = (int(bPort) if bPort else 0)
        suc = self.app.mount.bootMount(bAddress=bAddress, bPort=bPort)
        if suc:
            self.msg.emit(0, 'Mount', 'Command',
                          'Sent boot command to mount')
        else:
            self.msg.emit(2, 'Mount', 'Command', 'Mount cannot be booted')
        return suc

    def mountShutdown(self):
        """
        :return:
        """
        suc = self.app.mount.shutdown()
        if suc:
            self.msg.emit(0, 'Mount', 'Command', 'Shutting mount down')
        else:
            self.msg.emit(2, 'Mount', 'Command', 'Mount cannot be shutdown')
        return suc

    def bootRackComp(self):
        """
        :return:
        """
        MAC = self.ui.rackCompMAC.text()
        MAC = checkFormatMAC(MAC)
        if MAC is not None:
            wakeonlan.send_magic_packet(MAC)
            self.msg.emit(0, 'Rack', 'Command',
                          'Sent boot command to rack computer')
            return True
        else:
            self.msg.emit(2, 'Rack', 'Command',
                          'Rack computer cannot be booted')
            return False

    def mountHost(self):
        """
        :return: true for test purpose
        """
        if self.ui.port3492.isChecked():
            port = 3492
        else:
            port = 3490

        host = self.ui.mountHost.text()
        if not host:
            return False
        try:
            socket.gethostbyname(host)
        except Exception as e:
            self.msg.emit(2, 'Mount', 'Setting error', f'{e}')
            return False

        self.app.mount.host = (host, port)
        self.app.hostChanged.emit()
        return True

    def mountMAC(self):
        """
        :return: true for test purpose
        """
        self.app.mount.MAC = self.ui.mountMAC.text()
        return True

    def setMountMAC(self, sett=None):
        """
        :param sett:
        :return: true for test purpose
        """
        if sett is None:
            return False
        if sett.addressLanMAC is None:
            return False
        if not sett.addressLanMAC:
            return False

        self.app.mount.MAC = sett.addressLanMAC
        self.ui.mountMAC.setText(self.app.mount.MAC)
        return True

    def setWaitTime(self):
        """
        :return: true for test purpose
        """
        self.app.mount.waitTime = self.ui.waitTimeMount.value()
        return True

    def setWaitTimeFlip(self):
        """
        :return: true for test purpose
        """
        self.app.mount.waitTimeFlip = self.ui.waitTimeMountFlip.value()
        return True

    def updateFwGui(self, fw):
        """
        :return:    True if ok for testing
        """
        self.guiSetText(self.ui.product, 's', fw.product)
        self.guiSetText(self.ui.vString, 's', fw.vString)
        self.guiSetText(self.ui.fwdate, 's', fw.date)
        self.guiSetText(self.ui.fwtime, 's', fw.time)
        self.guiSetText(self.ui.hardware, 's', fw.hardware)
        return True

    def toggleClockSync(self):
        """
        :return:
        """
        enableSync = self.ui.clockSync.isChecked()
        self.ui.syncTimeNone.setEnabled(enableSync)
        self.ui.syncTimeCont.setEnabled(enableSync)
        self.ui.syncTimeNotTrack.setEnabled(enableSync)
        self.ui.clockOffset.setEnabled(enableSync)
        self.ui.clockOffsetMS.setEnabled(enableSync)
        if enableSync:
            self.app.mount.startClockTimer()
        else:
            self.app.mount.stopClockTimer()
        return True

    def syncClock(self):
        """
        :return:
        """
        noSync = self.ui.syncTimeNone.isChecked()
        if noSync:
            return False
        if not self.deviceStat['mount']:
            return False

        doSyncNotTrack = self.ui.syncTimeNotTrack.isChecked()
        mountTracks = self.app.mount.obsSite.status in [0, 10]
        if doSyncNotTrack and mountTracks:
            return False

        delta = self.app.mount.obsSite.timeDiff * 1000
        if abs(delta) < 10:
            return False

        if delta > 999:
            delta = 999
        if delta < -999:
            delta = -999

        delta = int(delta)
        suc = self.app.mount.obsSite.adjustClock(delta)
        if not suc:
            self.msg.emit(2, 'System', 'Clock',
                          'Cannot adjust mount clock')
            return False

        self.msg.emit(0, 'System', 'Clock',
                      f'Correction: [{-delta} ms]')
        return True

    def updateTelescopeParametersToGui(self):
        """
        updateTelescopeParametersToGui takes the information gathered from the
        driver and programs them into gui for later use.

        :return: true for test purpose
        """

        value = self.app.telescope.data.get(
            'TELESCOPE_INFO.TELESCOPE_FOCAL_LENGTH', 0)
        if value is not None:
            value = float(value)
            self.ui.focalLength.setValue(value)

        value = self.app.telescope.data.get('TELESCOPE_INFO.TELESCOPE_APERTURE',
                                            0)
        if value is not None:
            value = float(value)
            self.ui.aperture.setValue(value)

        return True

    def updateTelescopeParametersToGuiCyclic(self):
        """
        :return:
        """
        if not self.ui.automaticTelescope.isChecked():
            return False
        self.updateTelescopeParametersToGui()
        return True


from math import factorial
from strah import digit_sum
import time

print(digit_sum(145, factorial))
s = 0
for i in range(3, 10 ** 8):
    if i == digit_sum(i, factorial):
        s += i
        print(i)
print(s)
print(time.process_time())


#!/usr/bin/env python
"""
Draw the waterfilling solution using TiKz.

The genLatexCode returns latex code that can draw the provided solution by
the waterfilling algorithm, while the drawWF creates a file with this
code.
"""

import numpy as np

from pyphysim.comm import waterfilling

def genLatexCode(vtChannels, waterLevel, noiseVar=1.0, channelLength=0.8):
    """Generates latex code to draw (using Tikz) the waterfilling
    representation.

    Parameters
    ----------
    vtChannels : np.ndarray
        Channel gains of the parallel AWGN channels. This is a 1D numpy array.
    waterLevel : float
        Water level.
    noiseVar : float
        The noise variance.
    channelLength : float
        Length (in cm) of the representation of each channel in the X axis.

    Returns
    -------
    newTexCode : str
        LaTex code to draw the waterfilling solution.
    """

    # Draw Parameters
    maxYcoord = 3  # Maximum coordinate for the Y axis. Note that the axis

    # itself will expand two millimeters

    # ----- Auxiliary function definition ---------------------------------
    def pointsToString(points):
        """
        Auxiliary function

        Parameters
        ----------
        points : np.ndarray

        Returns
        -------
        str
            String representation of the points.
        """
        pointsString = ""
        for index in range(0, numChannels):
            pointsString += ("{num}/{value},".format(num=index,
                                                     value=points[index]))

        # The last element must not have a comma at the end
        # index = numChannels-1
        # pointsString += (
        #     "{num}/{value}".format(num=index,value=vtInvChannels[index]))

        # Remove the last ',' character
        return pointsString.rstrip(',')

    # ----- End of auxiliary function -------------------------------------

    # Code
    vtInvChannels = float(noiseVar) / np.squeeze(vtChannels)
    numChannels = vtChannels.size
    xMax = numChannels * channelLength + 0.2
    yMax = (np.concatenate((vtInvChannels, np.array([waterLevel])))).max()

    texCode = """
    \\documentclass[a4]{{report}}

    \\usepackage[english]{{babel}}
    \\usepackage[utf8]{{inputenc}} % Use this if the file is encoded with utf-8
    \\usepackage{{times}}
    \\usepackage[T1]{{fontenc}}
    \\usepackage{{amsmath,amssymb}} % Part of AMS-LaTeX
    % One of the good things of the amsmath package is the math environments matrix, pmatrix, bmatrix, Bmatrix, vmatrix and Vmatrix
    \\usepackage{{graphicx}}
    \\usepackage{{tikz}} % Create graphics in Latex
    \\usepackage{{cancel}} % teste $\\cancel{{x}}$ e voce vera o que ele faz. Outro melhor ainda e $\\cancelto{{x}}{{0}}$.

    \\everymath{{\\displaystyle}}
    \\begin{{document}}

    \\pgfdeclarelayer{{background}}
    \\pgfdeclarelayer{{foreground}}
    \\pgfsetlayers{{background,main,foreground}}

    \\begin{{tikzpicture}}[every node/.style={{scale=0.8}}]
      %% Desenha eixos
      \\coordinate (origem) at (0,0);
      \\def\\YMax{{ {YMax} }}
      \\def\\XMax{{ {XMax} }}

      \\draw[-latex,shorten <=-3mm] (origem) -- (0,\\YMax) node[left]{{$\\frac{{N_0}}{{|H_n|^2}}$}};
      \\draw[-latex,shorten <=-3mm,shorten >=-1mm] (origem) -- (\\XMax,0) node[below] {{Channel}};

      %% Desenha nivel de agual
      \\def\\waterLevelCoord{{ {WaterLevelCoord} }}
      \\def\\waterLevelLabel{{ {WaterLevelLabel:.4f} }}
      \\begin{{pgfonlayer}}{{background}}
        \\fill[gray!30!white] (origem) rectangle (\\XMax,\\waterLevelCoord);
      \\end{{pgfonlayer}}
      \\begin{{pgfonlayer}}{{foreground}}
        \\draw[dashed] (0,\\waterLevelCoord) node[left] {{ \\waterLevelLabel }} -- ++(\\XMax,0);
      \\end{{pgfonlayer}}

      %% Desenha os canais
      \\def\\channelLength{{8mm}}
      \\draw[fill=white] (0,0)
      \\foreach \\ind/\\value in {{ {Points} }}
      {{
                                              % Store coordinates P0,P1,...
        -| (\\ind*\\channelLength,\\value) coordinate (P\\ind)
      }}
       -- ++(\\channelLength,0) -- ++(0,-{LastPoint});

       %% Draw the Power arrows
       % \\draw[latex-] (P0) ++(\\channelLength/2,1mm) -- ++(30:0.6cm) node[right] {{$P_1^*$}};
       % \\draw[latex-latex] (P1) ++(\\channelLength/2,0) -- node[right] {{$P_2^*$}} ++(0,\\waterLevelCoord-0.6*\\YMax);
       % \\draw[latex-latex] (P2) ++(\\channelLength/2,0) -- node[right] {{$P_3^*$}} ++(0,\\waterLevelCoord-0.2*\\YMax);

    \\end{{tikzpicture}}

    \\end{{document}}
    """

    pointsString = pointsToString(maxYcoord * (vtInvChannels / yMax))
    newTexCode = texCode.format(
        XMax=xMax,
        YMax=maxYcoord + 0.2,  # yMax,
        WaterLevelCoord=maxYcoord * (waterLevel / yMax),
        WaterLevelLabel=waterLevel,
        Points=pointsString,
        LastPoint=(maxYcoord * (vtInvChannels[-1] / yMax)))

    return newTexCode

def drawWF(vtChannels, waterLevel, noiseVar=1.0, channelLength=0.8):
    """Creates a file with the latex code to draw (using Tikz) the
    waterfilling representation.

    Parameters
    ----------
    vtChannels : np.ndarray
        Channel gains of the parallel AWGN channels. This is a 1D numpy array.
    waterLevel : float
        Water level.
    noiseVar : float
        Noise variance.
    channelLength : float
        Length (in cm) of the representation of each channel in the X axis.
    """
    texCode = genLatexCode(vtChannels, waterLevel, noiseVar, channelLength)
    fId = open("texCode.tex", 'w')
    fId.write(texCode)
    fId.close()

# This method is only for testing purposes and is does not need to be
# exposed to the outside of this module.
def _test_drawwf():
    import os

    print("Inicio")

    vtChannels = np.array([9.32904521e-13, 2.63321084e-13, 5.06505202e-14])
    noiseVar = 2.5119e-14
    Pt = 0.2512
    (vtOptP, mu) = waterfilling.doWF(vtChannels, Pt, noiseVar)
    # print (vtOptP, mu)

    drawWF(vtChannels, mu, noiseVar)
    os.system("pdflatex texCode.tex > /dev/null")
    os.system("rm texCode.log texCode.aux texCode.tex")

# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
if __name__ == '__main__':  # pragma: no cover
    _test_drawwf()

if __name__ == '__main__1':  # pragma: no cover
    # vtChannels = np.abs(randn_c(4,1))
    vtChannels = np.array([0.49702888, 0.59012981, 0.43485267, 0.6692608])
    Power = 4
    noise_var = 0.1
    Es = 1

    (vtOptP, mu) = waterfilling.doWF(vtChannels, Power, noise_var)

    print("vtOptP")
    print(vtOptP)
    print("mu")
    print(mu)

    print(sum(vtOptP))

    # drawWF(vtChannels, mu, noise_var)


import cv2
import numpy as np
import dlib
import matplotlib
matplotlib.use('TKAgg')
import matplotlib.pyplot as plt
import time
import dlib
import argparse
import os

from expression_prototypes import get_expression_prototypes, get_matching_expression_prototypes
from profiling import PerformanceTimer
from transforms import dlib_rect_to_bb, landmarks_to_points, verts_to_indices, landmark_indices_to_triangles, apply_transform
from processing import get_scaled_rgb_frame, get_face_bb_landmarks, triangulate_landmarks, get_transforms, get_face_coordinates_system, landmarks_to_image_space
from visualisation import view_landmarks, debug_fill_triangles
from transfer import transfer_expression, transfer_face, transfer_poly
from utils import *

parser = argparse.ArgumentParser(description='Facial re-enactment prototype from source to target clip')
parser.add_argument("--source", metavar="/path/to/source.mp4", help="path to source video clip")
parser.add_argument("--target", metavar="/path/to/target.mp4", help="path to target video clip")
parser.add_argument("--output", required=False, metavar="output.mp4", help="output file path, optional")
parser.add_argument("--debugtriangles", required=False, action='store_true', help="specify this to see tracking triangles")
parser.add_argument("--blank", required=False, action='store_true', help="include this to make the resulting face on top of a blank canvas, for easier inspection")
parser.add_argument("--slow", required=False, action='store_true', help="include this to see the face reconstruction in a slow rate for debugging purposes")
parser.add_argument("--srcscale", type=float, required=False, metavar=1, help="Specify scaling of source frames ( use smaller values to improve performance )", default=0.25)
parser.add_argument("--trgscale", type=float, required=False, metavar=1, help="Specify scaling of target frames ( use smaller values to improve performance )", default=0.25)
parser.add_argument("--use3D", required=False, action='store_true', help="Specify to use 3D transfer method instead of 2D")

args = parser.parse_args()

assert args.source, "Argument --source must be provided"
assert args.target, "Argument --target must be provided"

DEBUG_TRIANGLES = args.debugtriangles
generated_colors = False
generated_triangulation = False
colors = []

profiler = PerformanceTimer()

sourceName = args.source
targetName = args.target
outputName = args.output

predictor_data = 'shape_predictor_68_face_landmarks.dat'

source = cv2.VideoCapture(sourceName)
target = cv2.VideoCapture(targetName)
output = None

sourceSuccess = True
targetSuccess = True
frameTime = 1/24

face_detector = dlib.get_frontal_face_detector()
landmark_predictor = dlib.shape_predictor(predictor_data)

fig = plt.figure()

#some offline processing before rendering

#source frame
srcWindow = fig.add_subplot(161)
#target frame
trgWindow = fig.add_subplot(162)
#target prototype
protoWindow = fig.add_subplot(163)
#transformed prototype
transformedProtoWindow = fig.add_subplot(164)

#transformed target frame
transformedTargetWindow = fig.add_subplot(165)
#final result frame
protoToTargetWindow = fig.add_subplot(166)

#get landmark faces in source video using some sort of disimilarity measure

#average sum euclidean distance?
#some others - compare performance?

#performance measure - self re-enacntment contour comparison makes most sense

srcScalingFactor = args.srcscale
trgScalingFactor = args.trgscale

sourceSuccess, sourceFrame = get_scaled_rgb_frame(source, srcScalingFactor)
targetSuccess, targetFrame = get_scaled_rgb_frame(target, trgScalingFactor)
im_h,im_w = sourceFrame.shape[:2]
trg_h, trg_w = targetFrame.shape[:2]

srcPlot = srcWindow.imshow(sourceFrame)
trgPlot = trgWindow.imshow(targetFrame)
transformedTargetPlot = transformedTargetWindow.imshow(targetFrame)
protoPlot = protoWindow.imshow(targetFrame)
transformedProtoPlot = transformedProtoWindow.imshow(targetFrame)
finalPlot = protoToTargetWindow.imshow(targetFrame)

plt.ion()
plt.show()

target_prototype_matching_faces = []

source_prototype_faces, source_frame_prototype_index = get_expression_prototypes(source, srcScalingFactor, profiler)

#go through target video and identify key face frames that  matched source video prototypes
#use similarity measure to also point which reference face should be matched durring time measures

target_prototype_faces_frames_landmarks = get_matching_expression_prototypes(target, trgScalingFactor, source_prototype_faces, profiler)

frameCount = 0
srcLandmarkTrianglesIndices = []

#go

#reopen clips to reset capture
source = cv2.VideoCapture(sourceName)
target = cv2.VideoCapture(targetName)
sourceFPS = source.get(cv2.CAP_PROP_FPS)

base_output_folder = 'debug\\{}'.format(outputName)
if not os.path.exists(base_output_folder):
    os.makedirs(base_output_folder, exist_ok=True)

base_output_path = base_output_folder+'\\{}.jpeg'

while targetSuccess and sourceSuccess:
    use3D = args.use3D
    print("Processing frame {} ...".format(frameCount))
    frameCount = frameCount + 1

    profiler.tick("Process Frame")
    #get frames
    sourceSuccess, sourceFrame = get_scaled_rgb_frame(source, srcScalingFactor)
    targetSuccess, targetFrame = get_scaled_rgb_frame(target, trgScalingFactor)
    if not sourceSuccess or not targetSuccess:
        break

    try:
        target_prototype,target_prototype_landmarks = target_prototype_faces_frames_landmarks[source_frame_prototype_index[frameCount-1]]
    except:
        target_prototype,target_prototype_landmarks = target_prototype_faces_frames_landmarks[source_frame_prototype_index[len(source_frame_prototype_index)-1]]

    srcPlot.set_data(sourceFrame)
    trgPlot.set_data(targetFrame)
    protoPlot.set_data(target_prototype)

    sourceToTarget, newTargetLandmarks, triangle_landmark_indices, source_frame_landmarks, target_landmarks = transfer_expression(sourceFrame, targetFrame, trgWindow, srcWindow, profiler, use3D)

    sourceToProto, newProtoLandmarks, _ , _, _ = transfer_expression(sourceFrame, target_prototype, protoWindow, srcWindow, profiler, use3D)

    #sourceToProto, newProtoLandmarks, _ , _= transfer_expression(sourceFrame, targetFrame, protoWindow, srcWindow, profiler)
    if(sourceToTarget is None or sourceToProto is None):
        continue

    transformedTargetPlot.set_data(sourceToTarget)
    transformedProtoPlot.set_data(sourceToProto)
    protoToSource = transfer_poly(sourceToTarget, sourceToProto, newTargetLandmarks, newProtoLandmarks)
    #protoToSource = transfer_poly(sourceToProto,sourceToTarget, newProtoLandmarks, newTargetLandmarks)

    cloneMask = np.zeros(protoToSource.shape, protoToSource.dtype)
    cloneContour = cv2.convexHull(np.int32(target_landmarks))
    cloneMask = cv2.fillConvexPoly(cloneMask, cloneContour, (255,255,255))
    cloneMask = cv2.erode(cloneMask, np.ones((5,5)))
    #finalFrame = cv2.seamlessClone(protoToSource, np.copy(targetFrame), cloneMask ,(int(trg_w/2),int(trg_h/2)),cv2.NORMAL_CLONE)
    target_face_center, _, _, _, target_local_landmarks  = get_face_coordinates_system(target_landmarks);
    finalFrame = cv2.seamlessClone(protoToSource, np.copy(targetFrame), cloneMask ,(int(target_face_center[0]),int(target_face_center[1]-10)),cv2.NORMAL_CLONE)

   # finalFrame = protoToSource;
    #protoToSource = transfer_face(sourceToProto, sourceToTarget, newProtoLandmarks, newTargetLandmarks, triangle_landmark_indices)
    #protoToSource = transfer_face(sourceFrame,  source_frame_landmarks ,sourceToProto, sourceToTarget, triangle_landmark_indices)
    if args.slow:
        plt.pause(frameTime)

    finalPlot.set_data(finalFrame)

    src_out_path = base_output_path.format('{}_src'.format(frameCount))
    cv2.imwrite(src_out_path, cv2.cvtColor(sourceFrame, cv2.COLOR_RGB2BGR))
    trg_out_path = base_output_path.format('{}_trg'.format(frameCount))
    cv2.imwrite(trg_out_path, cv2.cvtColor(targetFrame, cv2.COLOR_RGB2BGR))
    transformed_target_out_path = base_output_path.format('{}_src2trg'.format(frameCount))
    cv2.imwrite(transformed_target_out_path, cv2.cvtColor(sourceToTarget, cv2.COLOR_RGB2BGR))
    proto_out_path = base_output_path.format('{}_proto'.format(frameCount))
    cv2.imwrite(proto_out_path, cv2.cvtColor(target_prototype, cv2.COLOR_RGB2BGR))
    transformed_proto_out_path = base_output_path.format('{}_src2proto'.format(frameCount))
    cv2.imwrite(transformed_proto_out_path, cv2.cvtColor(sourceToProto, cv2.COLOR_RGB2BGR))
    final_out_path = base_output_path.format('{}_result'.format(frameCount))
    cv2.imwrite(final_out_path, cv2.cvtColor(finalFrame, cv2.COLOR_RGB2BGR))

    if args.output and output is None:
        output = cv2.VideoWriter(args.output, cv2.VideoWriter_fourcc('m', 'j', 'p', 'g'), sourceFPS, (finalFrame.shape[1], finalFrame.shape[0]))
    if output:
        output.write(np.uint8(cv2.cvtColor(finalFrame, cv2.COLOR_RGB2BGR)))
    print("Done one full frame process")
    profiler.tock()

    plt.pause(frameTime)
    for p in reversed(srcWindow.patches):
        p.remove()
    for p in reversed(trgWindow.patches):
        p.remove()
    for p in reversed(protoWindow.patches):
        p.remove()
    for p in reversed(transformedProtoWindow.patches):
        p.remove()

print('Transfer complete')
output.release()
source.release()
target.release()


import os
import sys
import datetime
import github
import collections

DEBUG = False

past_days_30 = datetime.datetime.now() + datetime.timedelta(-30)
past_days_60 = datetime.datetime.now() + datetime.timedelta(-60)

def debug(message):
    if DEBUG:
        print("%s %s" % (datetime.datetime.now(), message))

org_members_cache = set()

def is_in_org(api_org, author):

    if len(org_members_cache) == 0:
        for member in api_org.get_members():
            org_members_cache.add(member.login)

    return author.login in org_members_cache

class Contributor(object):
    def __init__(self):
        self.stats = []
        self.user = None

    def extend(self, stats):
        self.stats.extend(stats)

    def _stats_this_month(self):
        return filter(lambda week: week.w >= past_days_30, self.stats)

    def _stats_last_month(self):
        return filter(lambda week: past_days_30 >= week.w >= past_days_60, self.stats)

    @staticmethod
    def _score(stats):
        result = 0
        for stat in stats:
            commits, additions, deletions = stat.c, stat.a, stat.d
            # Somewhat arbitrarily, value commits at 10 "points" a piece. Code is worth 1 point for
            # 10 lines, capped at 100 points for deletions, 100 for additions each week.
            result += 10 * commits + min(100, int(additions/10)) + min(100, int(deletions/10))
        return int(result)

    def score_this_month(self):
        debug("Computing this-month score for %s" % self.user)
        stats = self._stats_this_month()
        return Contributor._score(stats)

    def score_last_month(self):
        debug("Computing last-month score for %s" % self.user)
        stats = self._stats_last_month()
        return Contributor._score(stats)

class ScoreSummary(object):
    def __init__(self, contributors, scores):
        self.contributors = contributors
        self.scores = scores

    def __str__(self):
        result = []

        for contributor_id in self.scores.keys():
            score_this_month, score_last_month = self.scores[contributor_id]
            result.append((self.contributors[contributor_id].user.name,
                           self.contributors[contributor_id].user.login,
                           self.contributors[contributor_id].user.avatar_url,
                           score_this_month, score_last_month))

        return '\n'.join([','.join(str(y) for y in x) for x in sorted(result, reverse=True,
                                                                      key=lambda t: t[3])])

def main(github_organization, github_token):
    print("Generating your report.")
    print("This might take a while depending on the number of repos in your organization.")
    print("Please wait...")

    api_client = github.Github(github_token)
    api_org = api_client.get_organization(github_organization)
    repos = api_org.get_repos()

    contributors = collections.defaultdict(Contributor)

    for repo in repos:
        debug("Inspecting repository %s" % repo)

        # Only inspect private repos and repos that have been pushed to in the last 60 days.
        if repo.private and repo.pushed_at > past_days_60:
            stats_contributors = repo.get_stats_contributors()

            if stats_contributors is not None:
                for stats_contributor in stats_contributors:
                    debug("Logging stats for contributor %s" % stats_contributor.author)

                    if not is_in_org(api_org, stats_contributor.author):
                        continue

                    contributors[stats_contributor.author.id].user = stats_contributor.author
                    contributors[stats_contributor.author.id].stats.extend(stats_contributor.weeks)

    scores = {}
    for contributor in sorted(contributors.keys()):
        this_month = contributors[contributor].score_this_month()
        last_month = contributors[contributor].score_last_month()

        if this_month != 0 or last_month != 0:
            scores[contributor] = (this_month, last_month)

    score_summary = str(ScoreSummary(contributors, scores))
    print()
    print("User Name,User ID,User Avatar URL,Score This Month,Score Last Month")
    print(score_summary)

def usage():
    print("Usage: python3 %s <organization_name>" % sys.argv[0])
    sys.exit(1)

if __name__ == '__main__':
    if 'GITHUB_TOKEN' not in os.environ:
        usage()
    if len(sys.argv) != 2:
        usage()
    main(sys.argv[1], os.environ['GITHUB_TOKEN'])


from tkinter import *

# Configuración de la raiz
root = Tk()
# Titulo
root.title('Hola Mundo')
# Icono
root.iconbitmap('@hola.xbm')
root.resizable(True, True) # Ancho, Alto > True habilita False bloquea. Puede usarse 1 para True y 0 para False

# Configuración de un marco
frame = Frame(root, width=480, height=320)
frame.pack()

# Crear label
label = Label(frame, text='¡Hola Mundo!')
#label.place(x=100, y=100)
label.place(x=0, y=0)

# Comenzar el bucle de la aplicación
root.mainloop()

Fase 4 - Temas avanzados/Tema 13 - Interfaces graficas con tkinter/label_in_frame.py


# 进程池:池⼦⾥⾯放的进程，进程池会根据任务执⾏情况⾃动创建进程，⽽且尽量少创建进程，合理利⽤进
# 程池中的进程完成多任务
import multiprocessing
import time
# 拷⻉任务
def work():
     print("复制中...", multiprocessing.current_process().pid)
     # 获取当前进程的守护状态
     # 提示：使⽤进程池创建的进程是守护主进程的状态，默认⾃⼰通过Process创建的进程是不是守住主
    #进程的状态
     # print(multiprocessing.current_process().daemon)
     time.sleep(0.5)
if __name__ == '__main__':
     # 创建进程池
     # 3:进程池中进程的最⼤个数
     pool = multiprocessing.Pool(3)
     # 模拟⼤批量的任务，让进程池去执⾏
     for i in range(5):
         # 循环让进程池执⾏对应的work任务
         # 同步执⾏任务，⼀个任务执⾏完成以后另外⼀个任务才能执⾏
         # pool.apply(work)
         # 异步执⾏，任务执⾏不会等待，多个任务⼀起执⾏
         pool.apply_async(work)
     # 关闭进程池，意思告诉主进程以后不会有新的任务添加进来
     pool.close()
     # 主进程等待进程池执⾏完成以后程序再退出
     pool.join()


import sys
import os
from tkinter import *
import threading
import time
from h5_listener import h5_listener
from receipt_printer import receipt_printer
import fasteners
import selenium.webdriver as webdriver
from selenium.common.exceptions import NoSuchElementException

# 数据读写锁
data_lock = threading.Lock()

# 线程
threads = []

# 读取配置文件
def readConfig():
    if not os.path.exists('./config.ini'):
        sys.exit(0)  # 结束程序
    config = {}
    # 读取config文件，获取模板的每个输入框的对应方式
    with open('./config.ini', encoding='utf-8') as f:
        lines = f.readlines()
        for line in lines:
            # print(line)
            if line[0] == "#":
                continue
            if '=' in line:
                data = line.strip().split('=')
                config[data[0]] = data[1]
    print(config)
    return config

# 启动子线程
def start_threads():
    with data_lock:
        shared_data['running'] = True
        shared_data['frequency'] = frequency
    global threads
    threads = []
    threads.append(threading.Thread(target=h5_listener, args=(shared_data, data_lock)))
    threads.append(threading.Thread(target=receipt_printer, args=(shared_data, data_lock)))

    for thread in threads:
        thread.start()

# 暂停子线程
def stop_threads():
    with data_lock:
        shared_data['running'] = False
        shared_data['frequency'] = 0.01

# 更新GUI
def update_gui(status_var, url_var, current_code_var, print_status_var, previous_code_var):
    status_var.set('Status: Running' if shared_data['running'] else 'Status: Stopped')
    url_var.set('Current Url: ' + shared_data['url'])
    current_code_var.set('Current Take Code: ' + shared_data['current_code'])
    print_status_var.set('Print Status: Printing' if shared_data['print_flag'] else 'Print Status: Printed')
    previous_code_var.set('Previous Take Code: ' + shared_data['previous_code'])
    root.after(1000, update_gui, status_var, url_var, current_code_var, print_status_var, previous_code_var)  # 每秒更新一次

# 当窗口关闭时
def on_close():

    try:
        root.destroy()  # 销毁窗口

        # 关闭浏览器driver
        with data_lock:
            driver = shared_data['driver']

        driver.quit()

        stop_threads()  # 停止所有线程

        # 等待所有子线程完成
        for thread in threads:
            thread.join()

        # pid_lock.release()  # 释放锁
        sys.exit(0)  # 结束程序

    except Exception as e:
            pass

# def restart():

#     with data_lock:
#         if shared_data['restart_flag']:
#             previous_driver = shared_data['driver']
#             # 关闭浏览器
#             try:
#                 # 尝试关闭
#                 previous_driver.quit()
#             except WebDriverException:
#                 print("Browser has been closed")
#             # 创建一个Chrome浏览器实例
#             new_driver = webdriver.Chrome()
#             shared_data['driver'] = new_driver
#             # 打开一个网页
#             new_driver.get(h5_url)
#             # 以全屏模式打开Chrome浏览器
#             new_driver.fullscreen_window()
#         else:
#             shared_data['restart_flag'] = True

# 读取配置文件

config = readConfig()

h5_url = ''
frequency = 2
zoom = 1.3
restart_flag = False

# 读取监听url
if config['url'] == '':
    sys.exit(0)  # 结束程序
else:
    h5_url = config['url']
    print(config['url'])

if config['time'] != '':
    frequency = config['time']

if config['zoom'] != '':
    try:
        zoom =config['zoom']
    except Exception:
        pass

# 创建一个Chrome浏览器实例
chrome_options = webdriver.ChromeOptions()

argument_str = "--force-device-scale-factor=" + str(zoom)
chrome_options.add_argument(argument_str)

driver = webdriver.Chrome(options=chrome_options)
# 打开一个网页
driver.get(h5_url)
# 以全屏模式打开Chrome浏览器
driver.fullscreen_window()

# 全局共享变量
shared_data = {
    'driver': driver,
    'url': h5_url,
    'zoom': zoom,
    'current_code': '',
    'previous_code': '',
    'print_flag': False,
    'running' : True,
    'frequency' : frequency,
    'restart_flag' : restart_flag,
    'receipt' : {},
    'new_code_event': threading.Event()
}

# 限制同时只能运行一个程序，禁止多开
# 利用文件锁技术，事先选定一个文件作为锁，运行第一个进程时锁住此文件
# 再次运行程序时检测文件此是否被锁定，若被锁定就说明已有一个程序正在运行
# pid_lock = fasteners.InterProcessLock('./H5Printer.lock')
# gotten = pid_lock.acquire(blocking=False)
# if not gotten:
#     print("Another instance of this application currently running.")
#     sys.exit(1)

# GUI
root = Tk()
root.geometry('700x350')  # 设置窗口的宽为300，高为200
root.minsize(350, 250)  # 设置窗口的最小宽度为300，最小高度为200
root.title('H5 Printer')  # 设置窗口的标题
root.protocol("WM_DELETE_WINDOW", on_close)  # 当窗口关闭时调用on_close函数

# 设置文本
status_var = StringVar()
url_var = StringVar()
current_code_var = StringVar()
previous_code_var = StringVar()
print_status_var = StringVar()

Button(root,
       text="Stop/Start",
       command=lambda: start_threads() if not shared_data['running'] else stop_threads(),
       bg="lightblue",
       fg="orange",
       padx=10,
       pady=10,
       font=("Arial", 20, "bold")
       ).pack()
Label(root,
      textvariable=status_var,
      font=("Arial", 20, "bold"),
      fg="red",
      ).pack()
Label(root,
      textvariable=url_var,
      font=("Arial", 15)
      ).pack()
Label(root,
      textvariable=current_code_var,
      font=("Arial", 15, "bold")
      ).pack()
Label(root,
      textvariable=print_status_var,
      font=("Arial", 15)
      ).pack()
Label(root,
      textvariable=previous_code_var,
      font=("Arial", 15)
      ).pack()
# Button(root,
#        text="Restart H5",
#        command=restart(),
#        bg="lightblue",
#        fg="orange",
#        padx=10,
#        pady=10,
#        font=("Arial", 15, "bold")
#        ).pack()

update_gui(status_var, url_var, current_code_var, print_status_var, previous_code_var)

# 自动开始监听
start_threads()

# 最小化窗口
root.iconify()

root.mainloop()


import pickle
import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from keras.utils import to_categorical
from torch.functional import Tensor
import torch.nn.functional as F

from flask import Flask, render_template,request
app = Flask(__name__)

class Model(nn.Module):
        def __init__(self, input_dim):
            super(Model, self).__init__()
            self.layer1 = nn.Linear(input_dim,50)
            self.layer2 = nn.Linear(50, 20)
            self.layer3 = nn.Linear(20, 3)

        def forward(self, x):
            x = F.relu(self.layer1(x))
            x = F.relu(self.layer2(x))
            x = F.softmax(self.layer3(x)) # To check with the loss function
            return x
'''
features, labels = load_iris(return_X_y=True)
features_train,features_test, labels_train, labels_test = train_test_split(features, labels, random_state=42, shuffle=True)

Training
model = Model(features_train.shape[1])
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
loss_fn = nn.CrossEntropyLoss()
epochs = 100
x_train, y_train = Variable(torch.from_numpy(features_train)).float(), Variable(torch.from_numpy(labels_train)).long()
for epoch in range(1, epochs+1):
    # print ("Epoch #",epoch)
    y_pred = model(x_train)
    loss = loss_fn(y_pred, y_train)
    # print_(loss.item())

    # Zero gradients
    optimizer.zero_grad()
    loss.backward() # Gradients
    optimizer.step() # Update

predictions
x_test = Variable(torch.from_numpy(features_test)).float()
pred = model(x_test)
pred = pred.detach().numpy()

saving the model
torch.save(model, "swap.pkl")
'''
@app.route('/',methods=['GET', 'POST'])
def index():
    if request.get_json() is not None:
        content=request.get_json(silent=True)
        sepal_length =content['sepal_length']
        sepal_width =content['sepal_width']
        petal_length =content['petal_length']
        petal_width =content['petal_width']

    elif request.method=='POST':
        sepal_length=float(request.form['sl'])
        sepal_width=float(request.form['sw'])
        petal_length=float(request.form['pl'])
        petal_width=float(request.form['pw'])

    else:
        return render_template('index.html')

    saved_model = torch.load("swap.pkl")
    row=Tensor([sepal_length,sepal_width,petal_length,petal_width])
    n=np.argmax(saved_model(row).detach().numpy(), axis=0)
    columns=['Setosa','Versicolour','Virginica']
    return {"class":columns[n]}
if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8000, debug=True)


from service.powerstrip import PowerStrip
from service.brewtimer import BrewTimer
from service.brewconfig import BrewConfig

class HeatService:

    bt = None
    DEFAULT_TIME = 10.0

    def temp_actor(self, pid_output):
        """
        switches the lan powerstrip on pid_output, if greater 0 switch PLUG_1 ON else switch OFF
        :param pid_output: PID calculated output value
        """

        status = PowerStrip().fetch_status()
        if pid_output > 0.0 and status.get(PowerStrip.PLUG_1) == PowerStrip.OFF:
            actor = HeatService.DEFAULT_TIME * (pid_output / BrewConfig.MAX)
            print("powerstrip on ", pid_output, "for", actor, "sec.")
            if self.alive():
                pass
            else:
                self.start(actor)
        if pid_output <= 0.0 and status.get(PowerStrip.PLUG_1) == PowerStrip.ON:
            if self.alive():
                self.stop()
                print("stopped timer")
            else:
                self.switch(PowerStrip.OFF)

    def start(self, duration):
        if duration == HeatService.DEFAULT_TIME:
            self.bt = BrewTimer(duration, self.alive)
        else:
            self.bt = BrewTimer(duration, self.switch)
        self.switch(PowerStrip.ON)
        self.bt.start()

    def stop(self):
        self.bt.cancel()
        self.switch(PowerStrip.OFF)

    def switch(self, state=0):
        status = PowerStrip().switch(PowerStrip.PLUG_1, state)
        return status

    def alive(self):
        if self.bt:
            return self.bt.alive()
        return False

    def remaining(self):
        if self.bt:
            return self.bt.remaining()
        return False


from unittest import skip

from django.urls import reverse
from playwright.sync_api import sync_playwright, expect

from bookmarks.e2e.helpers import LinkdingE2ETestCase

class BookmarkItemE2ETestCase(LinkdingE2ETestCase):
    @skip("Fails in CI, needs investigation")
    def test_toggle_notes_should_show_hide_notes(self):
        bookmark = self.setup_bookmark(notes='Test notes')

        with sync_playwright() as p:
            page = self.open(reverse('bookmarks:index'), p)

            notes = self.locate_bookmark(bookmark.title).locator('.notes')
            expect(notes).to_be_hidden()

            toggle_notes = page.locator('li button.toggle-notes')
            toggle_notes.click()
            expect(notes).to_be_visible()

            toggle_notes.click()
            expect(notes).to_be_hidden()


import sys
# general + data loading
import pandas as pd
from sqlalchemy import create_engine

# pre-processing
from nltk import pos_tag
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
import re

# machine learning
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.multioutput import MultiOutputClassifier
#from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

# storage
import pickle

# Load custom functions from the model folder
import sys, os
sys.path.insert(1, os.path.join(os.path.dirname(os.path.realpath(__file__))))
import glove
import ml_helper as utils

def load_data(database_filepath):
  '''Loads the relevant data for the model training.'''
  # download glove data
  if not glove.download('twitter'):
    print("ERROR: Download of GloVe Data failed. Please download and extract manually to the ./models directory from http://nlp.stanford.edu/data/wordvecs/glove.twitter.27B.zip")
  # laad remaining data
  engine = create_engine('sqlite:///{}'.format(database_filepath))
  df = pd.read_sql_table('texts', engine)
  X = df[['message', 'original', 'genre']]
  Y = df.iloc[:, 4:]
  return X['message'], Y, Y.columns

def build_model():
  '''Creates the pipeline with pre-processing and classifier.'''
  pipeline = Pipeline([
    ('features', FeatureUnion([
      ('term_emb', Pipeline([
        ('vectorize', CountVectorizer(tokenizer=utils.tokenize_clean, max_df=0.5)),
        ('tfidf', TfidfTransformer(use_idf=False)),
      ])),
      ('glove', Pipeline([
        ('glove_emb', glove.GloVeTransformer('twitter', 25, 'centroid', tokenizer=utils.tokenize_clean, max_feat=5))
      ]))
    ])),
    ('cls', MultiOutputClassifier(LogisticRegression(max_iter=50, C=2.0), n_jobs=-1) )
  ])
  return pipeline

def evaluate_model(model, X_test, Y_test, category_names):
  '''Evaluate the model.'''
  utils.score_and_doc(model, "deploy_final", X_test, Y_test, extended=True)

def save_model(model, model_filepath):
  '''Store the model as serialized data.'''
  pickle.dump(model, open(model_filepath, 'wb'))

def main():
    if len(sys.argv) == 3:
        database_filepath, model_filepath = sys.argv[1:]
        print('Loading data...\n    DATABASE: {}'.format(database_filepath))
        X, Y, category_names = load_data(database_filepath)
        X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

        print('Building model...')
        model = build_model()

        print('Training model...')
        model.fit(X_train, Y_train)

        print('Evaluating model...')
        evaluate_model(model, X_test, Y_test, category_names)

        print('Saving model...\n    MODEL: {}'.format(model_filepath))
        save_model(model, model_filepath)

        print('Trained model saved!')

    else:
        print('Please provide the filepath of the disaster messages database '\
              'as the first argument and the filepath of the pickle file to '\
              'save the model to as the second argument. \n\nExample: python '\
              'train_classifier.py ../data/DisasterResponse.db classifier.pkl')

if __name__ == '__main__':
    main()


#
# @lc app=leetcode.cn id=513 lang=python3
#
# [513] 找树左下角的值
#
# https://leetcode-cn.com/problems/find-bottom-left-tree-value/description/
#
# algorithms
# Medium (72.65%)
# Likes:    169
# Dislikes: 0
# Total Accepted:    36K
# Total Submissions: 49.5K
# Testcase Example:  '[2,1,3]'
#
# 给定一个二叉树，在树的最后一行找到最左边的值。
#
# 示例 1:
#
#
# 输入:
#
#    2
#   / \
#  1   3
#
# 输出:
# 1
#
#
#
#
# 示例 2:
#
#
# 输入:
#
#        1
#       / \
#      2   3
#     /   / \
#    4   5   6
#       /
#      7
#
# 输出:
# 7
#
#
#
#
# 注意: 您可以假设树（即给定的根节点）不为 NULL。
#
#

# @lc code=start
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

# BFS,先放右边的节点
# DFS因为要加level的判断，所以反而没有BFS巧妙
# T:O(N) S:O(WIDHT)
class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        queue = collections.deque([root])
        while queue:
            node = queue.popleft()
            # 先右后左
            if node.right:
                queue.append(node.right)
            if node. left:
                queue.append(node.left)
        return node.val
# @lc code=end

513.找树左下角的值.py


import random
import pandas
import sys
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
import csv
import statistics as stat

#config file containing location of graph and discount function csv files
config_file = open("./data_files/email.config").readlines()
#config_file = open("./data_files/redditunif-negxsquared.config").readlines()
#config_file = open("./data_files/astrolaptop-negxsquared.config").readlines()

def ProbFunc(nodeType,c):
	#return 2*c-c*c

	if nodeType==1:
		return c*c
	elif nodeType==2:
		return c
	else:
		return (2-c)*c

#Set default values for filepaths and running variables
data_csv=""
func_csv=""
output_dir=""

#Note that we do not currently use start, end, DStep, or batches

data_counter=1
for line in config_file:
	if str(line)[0] =="#":
		next
	else:
		if data_counter==1:
			data_csv=line[:-1]
		elif data_counter==2:
			func_csv=line[:-1]
		elif data_counter==3:
			output_dir=line[:-1]
		data_counter+=1

#Graph Creation
temp=pandas.read_csv(data_csv,sep=",",header=None)

numV = int(temp[0][0].split()[0])
numE = int(temp[0][0].split()[1])

adj={}
radj={}
P={}
rP={}

for lines in temp[0]:
	line=lines.split()
	if len(line)<3:
		continue
	u=int(line[0])
	v=int(line[1])
	deg=int(line[2])
	#edge probabilites are calculated using the degree
	pp=1.0/deg

	if u in adj.keys():
		adj[u].append((u,v))
		P[u,v]=pp
	else:
		adj[u]=[(u,v)]
		P[u,v]=pp

	if v in radj.keys():
		radj[v].append((u,v))
		rP[v,u]=pp
	else:
		radj[v]=[(u,v)]
		rP[v,u]=pp

#radj is used for the alpha_ji's
#add empty lists to for nodes that don't have directed edges
for i in list(range(0,numV)):
	if i not in adj.keys():
		adj[i]=[]
	if i not in radj.keys():
		radj[i] = []
print("Graph has been built")

#Discount adoption function assigner
temp=pandas.read_csv(func_csv,sep=",",header=None)

Type={}

for lines in temp[0]:
	line=lines.split()
	if int(line[1])==4: #carryover from previous code. Not sure this is needed
		line[1]=3
	Type[int(line[0])]=int(line[1])

LPSolver = SolverFactory("gurobi")

budgetlist = [10,20,30,40,50]
#budgetlist=[10]

base_dir = output_dir + "/Alpha=1"
#base_dir = "C:/Users/Jeremy Berg/OneDrive - Naval Postgraduate School/01- Student/99 Thesis/Code/CIM-master-Robust/Results/Alpha=1"
seeded_nodes={}
seeded_discounts={}
inf_list={}
obj_vals={}

for budget in budgetlist:
	seeded_nodes[budget]=[]
	seeded_discounts[budget]=[]
	budget_file = open(base_dir + f"/B={budget}.txt")
	found=False
	for line in budget_file:
		splitline = line.split(sep='\t')
		if found:
			seeded_nodes[budget].append(int(splitline[0]))
			seeded_discounts[budget].append(float(splitline[1]))
		if splitline[0]=="CD":
			found=True

discounts={}
for budget in budgetlist:
	for i in list(range(0,numV)):
		if i in seeded_nodes[budget]:
			discounts[budget,i]=seeded_discounts[budget][seeded_nodes[budget].index(i)]
		else:
			discounts[budget,i]=0
#creates a full discount list from imported values
#turn dictionary into 2 dimensional key

for budget in budgetlist:
	print(f"============= Current Budget: {budget} =============")
	if budget == budgetlist[0]:
		pimodel = pyo.ConcreteModel()
		pimodel.pi = pyo.Var(pyo.Set(initialize=list(range(0,numV))),domain=pyo.NonNegativeReals, bounds=(0,1))

		pimodel.con1=pyo.ConstraintList()
		for i,j in list(P.keys()):
			pimodel.con1.add(expr=pimodel.pi[i] - pimodel.pi[j] <= 1 - P[i,j])

		pimodel.con2=pyo.ConstraintList()
		for i in list(range(0,numV)):
			pimodel.con2.add(expr= -pimodel.pi[i]<= -ProbFunc(Type[i],discounts[budget,i]))

		pimodel.obj=pyo.Objective(expr=sum(pimodel.pi[i] for i in list(range(0,numV))), sense=pyo.minimize)
		LPSolver.solve(pimodel,tee=False)
		fullpi=pyo.value(pimodel.obj)
	else:
		for i in list(range(0,numV)):
			pimodel.con2[i+1].set_value(expr= -pimodel.pi[i]<= -ProbFunc(Type[i],discounts[budget,i]))
		LPSolver.solve(pimodel, tee=False)
		fullpi=pyo.value(pimodel.obj)

	print(f"Budget {budget} full pi: {fullpi}")


from beartype.typing import (
    Callable,
    Union,
)

# ....................{ HINTS                              }....................
BeartypeValidatorTester = Callable[[object], bool]
'''
PEP-compliant type hint matching a **beartype validator tester** (i.e.,
caller-defined callable accepting a single arbitrary object and returning
either ``True`` if that object satisfies an arbitrary constraint *or* ``False``
otherwise).

Beartype validator testers are suitable for subscripting functional beartype
validator factories (e.g., :attr:`beartype.vale.Is`).
'''

BeartypeValidatorRepresenter = Union[str, Callable[[], str]]
'''
PEP-compliant type hint matching a **beartype validator representer** (i.e.,
either a string *or* caller-defined callable accepting no arguments returning a
machine-readable representation of a beartype validator).

Technically, this representation *could* be passed by the caller rather than
this callable dynamically generating that representation. Pragmatically,
generating this representation is sufficiently slow for numerous types of
validators that deferring their generation until required by a call to the
:meth:`__repr__` dunder method externally called by a call to the :func:`repr`
builtin` on this validator is effectively mandatory. Validators whose
representations are particularly slow to generate include:

* The :class:`Is` class subscripted by a lambda rather than non-lambda
  function. Generating the representation of that class subscripted by a
  non-lambda function only requires introspecting the name of that function and
  is thus trivially fast. However, lambda functions have no names and are thus
  *only* distinguishable by their source code; generating the representation of
  that class subscripted by a lambda function requires parsing the source code
  of the file declaring that lambda for the exact substring of that code
  declaring that lambda.
'''


# -*- coding: utf-8 -*-
from requests import Request, Session, Timeout
import dateutil.parser
from datetime import datetime
from rest_framework.exceptions import ValidationError

from django.core.cache import cache
from django.conf import settings
from django.contrib.gis.geos import Point, Polygon
from django.utils.timezone import make_aware

from apps.bigcz.models import ResourceLink, ResourceList
from apps.bigcz.utils import RequestTimedOutError

from apps.bigcz.clients.hydroshare.models import HydroshareResource

CATALOG_NAME = 'hydroshare'
CATALOG_URL = 'https://www.hydroshare.org/hsapi/resource/'

DATE_MIN = make_aware(datetime(1776, 7, 4, 0, 0))

def parse_date(value):
    d = dateutil.parser.parse(value)
    if d.tzinfo is None or d.tzinfo.utcoffset(d) is None:
        return make_aware(d)
    else:
        return d

def parse_box(box):
    return Polygon((
        (float(box['westlimit']), float(box['northlimit'])),
        (float(box['eastlimit']), float(box['northlimit'])),
        (float(box['eastlimit']), float(box['southlimit'])),
        (float(box['westlimit']), float(box['southlimit'])),
        (float(box['westlimit']), float(box['northlimit'])),
    ))

def parse_point(point):
    return Point(float(point['east']), float(point['north']))

def parse_geom(coverages):
    geoms = []
    if coverages:
        geoms.extend([parse_box(c['value'])
                      for c in coverages
                      if c['type'] == 'box'])
        geoms.extend([parse_point(c['value'])
                      for c in coverages
                      if c['type'] == 'point'])
        if geoms:
            geom = geoms[0]
            for g in geoms[1:]:
                geom |= g

            return geom

    return None

def parse_coverage_period(coverages):
    if coverages:
        period = [c['value'] for c in coverages if c['type'] == 'period']
        if period and period[0]:
            return period[0]['start'], period[0]['end']

    return None, None

def parse_record(item):
    start, end = parse_coverage_period(item['coverages'])

    return HydroshareResource(
        id=item['resource_id'],
        title=item['resource_title'],
        description=None,
        author=item['creator'],
        links=[
            ResourceLink('details', item['resource_url'])
        ],
        created_at=parse_date(item['date_created']),
        updated_at=parse_date(item['date_last_updated']),
        geom=parse_geom(item['coverages']),
        begin_date=parse_date(start) if start else None,
        end_date=parse_date(end) if end else None)

def prepare_bbox(box):
    return {
        'west': box.xmin,
        'east': box.xmax,
        'north': box.ymin,
        'south': box.ymax,
    }

def prepare_date(value):
    return value.strftime('%Y-%m-%d')

def nullable_attrgetter(key, default):
    """To allow sorting on nullable field with default value"""
    def getter(item):
        return getattr(item, key) or default

    return getter

def search(**kwargs):
    query = kwargs.get('query')
    to_date = kwargs.get('to_date')
    from_date = kwargs.get('from_date')
    bbox = kwargs.get('bbox')
    page = kwargs.get('page')
    exclude_private = 'exclude_private' in kwargs.get('options')

    if not query:
        raise ValidationError({
            'error': 'Required argument: query'})

    params = {
        'full_text_search': query,
    }

    if bbox:
        params.update(prepare_bbox(bbox))
        params.update({
            'coverage_type': 'box'
        })
    if page:
        params.update({
            'page': page
        })

    session = Session()
    request = session.prepare_request(Request('GET',
                                              CATALOG_URL,
                                              params=params))

    key = f'bigcz_hydroshare_{hash(frozenset(params.items()))}'
    cached = cache.get(key)
    if cached:
        data = cached

    else:
        try:
            response = session.send(request,
                                    timeout=settings.BIGCZ_CLIENT_TIMEOUT)
            data = response.json()
            cache.set(key, data, timeout=1800)  # Cache for half hour
        except Timeout:
            raise RequestTimedOutError()

    if 'results' not in data:
        raise ValueError(data)

    items = data['results']
    if exclude_private:
        items = [item for item in items if item['public']]

    records = [parse_record(item) for item in items]
    # Include only those with geometries
    records = [r for r in records if r.geom]

    if from_date:
        records = [r for r in records
                   if r.end_date and r.end_date >= make_aware(from_date)]

    if to_date:
        records = [r for r in records
                   if r.begin_date and r.begin_date <= make_aware(to_date)]

    results = sorted(records,
                     key=nullable_attrgetter('end_date', DATE_MIN),
                     reverse=True)
    count = data['count']

    return ResourceList(
        api_url=request.url,
        catalog=CATALOG_NAME,
        count=count,
        results=results)


from datetime import datetime

import requests
import json
import csv

def csv_to_json(csv_path, json_path, host, port, collection):
    url = f"http://{host}:{port}/{collection}"
    jsonArray = []

    with open(csv_path, encoding='utf-8') as csv_file:
        csvReader = csv.DictReader(csv_file)

        for row in csvReader:
            if collection == 'flights':
                date_str = row['date']
                date_obj = datetime.strptime(date_str, '%d/%m/%Y').date()

                row['date'] = date_obj.strftime('%Y-%m-%d')

            elif collection == 'offers':
                date_str_start = row['start_date']
                date_str_end = row['end_date']
                date_obj_start = datetime.strptime(date_str_start, '%d/%m/%Y').date()
                date_obj_send = datetime.strptime(date_str_end, '%d/%m/%Y').date()

                row['start_date'] = date_obj_start.strftime('%Y-%m-%d')
                row['end_date'] = date_obj_send.strftime('%Y-%m-%d')

            jsonArray.append(row)
            payload = json.dumps(row)

            headers = {
                'Content-Type': 'application/json'
            }
            response = requests.request("POST", url, headers=headers, data=payload)
            print(response.text)

    with open(json_path, 'w', encoding='utf-8') as json_file:
        jsonString = json.dumps(jsonArray, indent=4, ensure_ascii=False)
        json_file.write(jsonString)

offers_csv_path = r'hoteleOfertyBaza.csv'
offers_json_path = r'offers.json'
# csv_to_json(offers_csv_path, offers_json_path, "localhost", 8085, "offers")

flights_csv_path = r'lotyOfertyBaza.csv'
flights_json_path = r'flights.json'
# csv_to_json(flights_csv_path, flights_json_path, "localhost", 8085, "flights") # 5245 cluster 8085 local


class Solution:
    #solution1: using stack
    #time: O(N), space: O(N)
    def isValid(self, s: str) -> bool:
        brackets = {"(" : ")", "{" : "}", "[" : "]"}
        openBrackets, closeBrackets = brackets.keys(), brackets.values()

        stack = []
        for char in s:
            if char in openBrackets:
                stack.append(char)
            else:
                if not stack:
                    return False
                else:
                    pop = stack.pop()
                    if brackets[pop] != char:
                        return False
        return not stack


import threading
import logging
import os
import json
import re
import time

FREQ_RE = re.compile("^(\d+)([smhd])$")
SUFFIX_TO_SEC_MULTIPLIER = {"s": 1, "m": 60, "h": 60 * 60, "d": 60 * 60 * 24}

def parse_freq(s_freq):
    m = FREQ_RE.match(s_freq)
    return int(m.group(1)) * SUFFIX_TO_SEC_MULTIPLIER[m.group(2)]

class MonitorManager(threading.Thread):
    def __init__(self, block, unix_service):
        threading.Thread.__init__(self)
        self.id = block["id"]
        self.unix_service = unix_service
        self.block = block

    def run(self):
        freq = parse_freq(self.block.get("frequency", "1m"))
        logging.info(
            "[{}] Running {} every {} seconds".format(
                self.block["id"], self.block["command"], freq
            )
        )
        logging.debug("[{}] 5 seconds for startup".format(self.block["id"]))
        time.sleep(5)
        while True:
            result = self.unix_service.run_block(self.block, (), None)
            if isinstance(result, str):
                result = result.strip()

            logging.debug("[{}] Result: {}".format(self.block["id"], result))
            self.process(result)
            time.sleep(freq)

    def process(self, data):
        self.unix_service.emit_event(self.id, data)