""" A thin wrapper for using the dronekit library.

The main motivation behind putting this into its own class is that ability
to unit test this with the dronekit sitl and to make our main logic somewhat
easier to decouple from the dronekit library if the time ever comes.
"""
import logging
import time
import dronekit
from gps import get_distance
from helper import location_global_relative_to_gps_reading

class Controller:
    """This class acts as a wrapper for dronekit and controls the vehicle."""
    def __init__(self, connection_string, baud=None, com=None):
        """Open a connection to the vehicle.

        Args:
            connection_string (str): Location of the drone.
            baud (int): Baudrate of serial connection (if applicable).
        """
        self.logger = logging.getLogger(__name__)
        self.connection_string = connection_string
        self.vehicle = None
        self.__com = com
        if baud:
            self.logger.debug('Attempting connection to %s at baud %s',
                              connection_string, baud)
            if self.__com:
                self.__com.send(u"Attempting connection to {} at baud {}".format(
                                connection_string, baud))
            self.vehicle = dronekit.connect(self.connection_string,
                                            wait_ready=True, baud=baud)
        else:
            self.logger.debug('Attempting connection to %s',
                              connection_string)
            if self.__com:
                self.__com.send(u"Attempting connection to {}".format(
                                connection_string))
            self.vehicle = dronekit.connect(self.connection_string,
                                            wait_ready=True)
        self.logger.debug('Connected.')
        if self.__com:
            self.__com.send(u"Connected.")

        def _vehicle_state_callback(vehicle, attribute, value):
            """Logs vehicle state changes."""
            self.logger.debug("Attribute {}: {}".format(attribute, value))
            if self.__com:
                self.__com.send(u"Attribute {}: {}".format(attribute, value))
        self.vehicle.add_attribute_listener('armed',
                                            _vehicle_state_callback)
        self.vehicle.add_attribute_listener('mode',
                                            _vehicle_state_callback)
        self.home = None  # Set right after arming (GPS can be trusted then)

    def arm(self):
        """Sets the mode to guided and arms the copter for flight."""
        while not self.vehicle.is_armable:
            self.logger.debug('Waiting for vehicle to initialise...')
            if self.__com:
                self.__com.send(u"Waiting for vehicle to initialise...")
            time.sleep(5)
        # Arm the copter
        self.vehicle.mode = dronekit.VehicleMode("GUIDED")
        while not self.vehicle.armed:
            self.logger.debug('Trying to arm...')
            if self.__com:
                self.__com.send(u"Trying to arm...")
            self.vehicle.armed = True
            time.sleep(1)
        self.home = self.vehicle.location.global_relative_frame

    def takeoff(self, target_altitude):
        """Takes off the copter (must be armed first) to the target altitude.
        This function blocks until the height has been reached or takeoff
        has been cancelled by the user.
        """
        self.logger.debug("Attempting simple takeoff to {} m...".format(target_altitude))
        if self.__com:
            self.__com.send(u"Attempting simple takeoff to {} m...".format(target_altitude))
        self.vehicle.simple_takeoff(target_altitude)
        start_takeoff_time = time.time()

        # Wait till target altitude reached
        while True:
            time.sleep(3)
            time_since_takeoff = time.time() - start_takeoff_time
            self.log_flight_info()
            self.check_geofence(10, target_altitude + 10)
            if self.vehicle.location.global_relative_frame.alt >= target_altitude * 0.95:
                self.logger.debug("Reached target altitude")
                if self.__com:
                    self.__com.send(u"Reached target altitude")
                break
            elif time_since_takeoff > 30:
                self.logger.debug("Time limit reached for takeoff. Takeoff finished")
                if self.__com:
                    self.__com.send(u"Time limit reach for takeoff. Takeoff finished")
                break
            elif self.vehicle.mode.name != "GUIDED":
                self.logger.debug("No longer guided. Autopilot did not reach target altitude.")
                if self.__com:
                    self.__com.send(u"No longer guided. Autopilot did not reach target altitude.")
                # User took over control or geofence triggered
                break
        self.home.alt = target_altitude  # This way home isn't 0 meters high when calling goto
        return

    def log_flight_info(self, destination=None):
        """Logs some info from the vehicle."""
        current_location = self.vehicle.location.global_relative_frame
        self.logger.debug("{}".format(current_location))
        self.logger.debug("Velocity: {}".format(self.vehicle.velocity))
        self.logger.debug("Groundspeed: {}".format(self.vehicle.groundspeed))
        self.logger.debug("Airspeed: {}".format(self.vehicle.airspeed))
        if destination:
            current_reading = location_global_relative_to_gps_reading(current_location)
            destination_reading = location_global_relative_to_gps_reading(destination)
            distance = get_distance(destination_reading, current_reading)
            self.logger.debug("Distance from destination: {}".format(distance))

    def check_geofence(self, max_distance, max_altitude):
        """Ensures the vehicle stays within our geofence (basically a cyclinder
        around the takeoff location)."""
        current = location_global_relative_to_gps_reading(
                    self.vehicle.location.global_relative_frame)
        home = location_global_relative_to_gps_reading(self.home)
        distance = get_distance(home, current)
        if distance > max_distance:
            self.logger.critical("Exceeded distance limit")
            self.logger.critical("Max Distance: {}".format(max_distance))
            self.logger.critical("Current Distance: {}".format(distance))
            if self.vehicle.mode.name == "GUIDED":
                self.logger.critical("LANDING...")
                if self.__com:
                    self.__com.send(u"GEOFENCE DISTANCE EXCEEDED. LANDING...")
                self.land()
        elif current.altitude > max_altitude:
            self.logger.critical("Exceeded altitude limit")
            self.logger.critical("Max Altitude: {}".format(max_altitude))
            self.logger.critical("Current Altitude: {}".format(current.altitude))
            if self.vehicle.mode.name == "GUIDED":
                self.logger.critical("LANDING...")
                if self.__com:
                    self.__com.send(u"GEOFENCE ALTITUDE EXCEEDED. LANDING...")
                self.land()

    def goto(self, point):
        """Tells the drone to goto to a point (doesn't block, user responsible
        for verifying point is reached).

        point: expected to be a LocationGlobalRelative.
        """
        self.logger.debug("Going to destination: {}".format(point))
        self.vehicle.simple_goto(point)

    def land(self):
        """Lands the drone and blocks until landed."""
        self.logger.debug("Landing...")
        self.vehicle.mode = dronekit.VehicleMode("LAND")
        while True:
            time.sleep(3)
            self.log_flight_info()
            self.logger.debug("{}".format(self.vehicle.location.global_relative_frame))
            if self.vehicle.location.global_relative_frame.alt < 1:
                self.logger.debug("Reached Ground")
                break
            if self.vehicle.armed is False:
                self.logger.debug("Reached Ground (assuming since no longer armed)")
                break


import os
import asyncio
from pathlib import Path

from jina import __resources_path__
from jina.parsers import set_pea_parser
from jina.peapods.runtimes.jinad import JinadRuntime

import pytest

cur_dir = os.path.dirname(os.path.abspath(__file__))

@pytest.mark.parametrize(
    'upload_files, uses, py_modules',
    [
        ('executor', 'MyExecutor', 'my_executor.py'),
        (os.path.join(cur_dir, 'executor'), 'MyExecutor', 'my_executor.py'),
        ('executor', 'config.yml', ''),
        (os.path.join(cur_dir, 'executor'), 'config.yml', ''),
    ],
)
def test_mask_args_py_module(upload_files, uses, py_modules, monkeypatch):
    monkeypatch.setattr(JinadRuntime, 'async_setup', lambda *args: asyncio.sleep(0.1))
    args = set_pea_parser().parse_args(
        [
            '--uses',
            uses,
            '--py-modules',
            py_modules,
            '--upload-files',
            upload_files,
            '--log-config',
            os.path.join(__resources_path__, 'logging.quiet.yml'),
        ]
    )
    runtime = JinadRuntime(args=args)
    assert runtime.filepaths == [Path(os.path.join(cur_dir, 'executor'))]
    newargs = runtime._mask_args()
    assert newargs.uses == uses
    assert newargs.py_modules == [py_modules]
    assert newargs.disable_remote == True
    assert newargs.upload_files == []
    assert newargs.log_config == ''
    assert newargs.noblock_on_start == False


# **************************************************************************
# *
# * Authors:     Javier Vargas and Adrian Quintana (jvargas@cnb.csic.es aquintana@cnb.csic.es)
# *
# * Unidad de  Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307  USA
# *
# *  All comments concerning this program package may be sent to the
# *  e-mail address 'jmdelarosa@cnb.csic.es'
# *
# **************************************************************************

import pyworkflow.protocol.params as params
import pyworkflow.em as em
from pyworkflow.em.packages.xmipp3.convert import getImageLocation

ALIGN_MASK_CIRCULAR = 0
ALIGN_MASK_BINARY_FILE = 1

ALIGN_ALGORITHM_EXHAUSTIVE = 0
ALIGN_ALGORITHM_LOCAL = 1
ALIGN_ALGORITHM_EXHAUSTIVE_LOCAL = 2
ALIGN_ALGORITHM_FAST_FOURIER = 3

class XmippProtAlignVolume(em.ProtAlignVolume):
    """
    Aligns a set of volumes using cross correlation
    or a Fast Fourier method.

    *Note:* Fast Fourier requires compilation of Xmipp with --cltomo flag
     """
    _label = 'align volume'

    def __init__(self, **args):
        em.ProtAlignVolume.__init__(self, **args)
        self.stepsExecutionMode = em.STEPS_PARALLEL

    #--------------------------- DEFINE param functions --------------------------------------------
    def _defineParams(self, form):
        form.addSection(label='Volume parameters')
        form.addParam('inputReference', params.PointerParam, pointerClass='Volume',
                      label="Reference volume", important=True,
                      help='Reference volume to be used for the alignment.')
        form.addParam('inputVolumes', params.MultiPointerParam, pointerClass='SetOfVolumes,Volume',
                      label="Input volume(s)", important=True,
                      help='Select one or more volumes (Volume or SetOfVolumes)\n'
                           'to be aligned against the reference volume.')

        group1 = form.addGroup('Mask')
        group1.addParam('applyMask', params.BooleanParam, default=False,
                      label='Apply mask?',
                      help='Apply a 3D Binary mask to the volumes')
        group1.addParam('maskType', params.EnumParam, choices=['circular','binary file'], default=ALIGN_MASK_CIRCULAR,
                      label='Mask type', display=params.EnumParam.DISPLAY_COMBO, condition='applyMask',
                      help='Select the type of mask you want to apply')
        group1.addParam('maskRadius', params.IntParam, default=-1, condition='applyMask and maskType==%d' % ALIGN_MASK_CIRCULAR,
                      label='Mask radius',
                      help='Insert the radius for the mask')
        group1.addParam('maskFile', params.PointerParam, condition='applyMask and maskType==%d' % ALIGN_MASK_BINARY_FILE,
                      pointerClass='VolumeMask', label='Mask file',
                      help='Select the volume mask object')

        form.addSection(label='Search strategy')
        form.addParam('alignmentAlgorithm', params.EnumParam, default=ALIGN_ALGORITHM_EXHAUSTIVE,
                      choices=['exhaustive',
                               'local',
                               'exhaustive + local',
                               'fast fourier'],
                      label='Alignment algorithm', display=params.EnumParam.DISPLAY_COMBO,
                      help='Exhaustive searches all possible combinations within a search space.'
                            'Local searches around a given position.'
                            'Be aware that the Fast Fourier algorithm requires a special compilation'
                            'of Xmipp (--cltomo flag). It performs the same job as the  '
                            'exhaustive method but much faster.')

        anglesCond = 'alignmentAlgorithm!=%d' % ALIGN_ALGORITHM_LOCAL

        group = form.addGroup('Angles range', condition=anglesCond, expertLevel=params.LEVEL_ADVANCED)

        line = group.addLine('Rotational angle (deg)')
        line.addParam('minRotationalAngle', params.FloatParam, default=0, label='Min')
        line.addParam('maxRotationalAngle', params.FloatParam, default=360, label='Max')
        line.addParam('stepRotationalAngle', params.FloatParam, default=5, label='Step')

        line = group.addLine('Tilt angle (deg)', expertLevel=params.LEVEL_ADVANCED)
        line.addParam('minTiltAngle', params.FloatParam, default=0, label='Min')
        line.addParam('maxTiltAngle', params.FloatParam, default=180, label='Max')
        line.addParam('stepTiltAngle', params.FloatParam, default=5, label='Step')

        line = group.addLine('Inplane angle (deg)', expertLevel=params.LEVEL_ADVANCED)
        line.addParam('minInplaneAngle', params.FloatParam, default=0, label='Min')
        line.addParam('maxInplaneAngle', params.FloatParam, default=360, label='Max')
        line.addParam('stepInplaneAngle', params.FloatParam, default=5, label='Step')

        group = form.addGroup('Shifts range', condition=anglesCond, expertLevel=params.LEVEL_ADVANCED)
        line = group.addLine('Shift X (px)')
        line.addParam('minimumShiftX', params.FloatParam, default=0, label='Min')
        line.addParam('maximumShiftX', params.FloatParam, default=0, label='Max')
        line.addParam('stepShiftX', params.FloatParam, default=1, label='Step')

        line = group.addLine('Shift Y (px)', expertLevel=params.LEVEL_ADVANCED)
        line.addParam('minimumShiftY', params.FloatParam, default=0, label='Min')
        line.addParam('maximumShiftY', params.FloatParam, default=0, label='Max')
        line.addParam('stepShiftY', params.FloatParam, default=1, label='Step')

        line = group.addLine('Shift Z (px)', expertLevel=params.LEVEL_ADVANCED)
        line.addParam('minimumShiftZ', params.FloatParam, default=0, label='Min')
        line.addParam('maximumShiftZ', params.FloatParam, default=0, label='Max')
        line.addParam('stepShiftZ', params.FloatParam, default=1, label='Step')

        line = form.addLine('Scale ', expertLevel=params.LEVEL_ADVANCED, condition=anglesCond)
        line.addParam('minimumScale', params.FloatParam, default=1, label='Min')
        line.addParam('maximumScale', params.FloatParam, default=1, label='Max')
        line.addParam('stepScale', params.FloatParam, default=0.005, label='Step')

        group = form.addGroup('Initial values',
                              condition='alignmentAlgorithm==%d' % ALIGN_ALGORITHM_LOCAL,
                              expertLevel=params.LEVEL_ADVANCED)
        line = group.addLine('Initial angles')
        line.addParam('initialRotAngle', params.FloatParam, default=0, label='Rot')
        line.addParam('initialTiltAngle', params.FloatParam, default=0, label='Tilt')
        line.addParam('initialInplaneAngle', params.FloatParam, default=0, label='Psi')

        line = group.addLine('Initial shifts ', expertLevel=params.LEVEL_ADVANCED)
        line.addParam('initialShiftX', params.FloatParam, default=0, label='X')
        line.addParam('initialShiftY', params.FloatParam, default=0, label='Y')
        line.addParam('initialShiftZ', params.FloatParam, default=0, label='Z')

        group.addParam('initialScale', params.FloatParam, default=1, expertLevel=params.LEVEL_ADVANCED,
                      label='Initial scale')

        form.addParallelSection(threads=8, mpi=1)

    #--------------------------- INSERT steps functions --------------------------------------------
    def _insertAllSteps(self):
        # Iterate through all input volumes and align them
        # againt the reference volume
        refFn = getImageLocation(self.inputReference.get())
        maskArgs = self._getMaskArgs()
        alignArgs = self._getAlignArgs()
        alignSteps = []

        for vol in self._iterInputVolumes():
            volFn = getImageLocation(vol)
            stepId = self._insertFunctionStep('alignVolumeStep', refFn, volFn, vol.outputName,
                                              maskArgs, alignArgs, prerequisites=[])
            alignSteps.append(stepId)

        self._insertFunctionStep('createOutputStep', prerequisites=alignSteps)

    #--------------------------- STEPS functions --------------------------------------------
    def alignVolumeStep(self, refFn, inVolFn, outVolFn, maskArgs, alignArgs):

        args = "--i1 %s --i2 %s --apply %s" % (refFn, inVolFn, outVolFn)
        args += maskArgs
        args += alignArgs

        self.runJob("xmipp_volume_align", args)

        if self.alignmentAlgorithm == ALIGN_ALGORITHM_EXHAUSTIVE_LOCAL:
            args = "--i1 %s --i2 %s --apply --local" % (refFn, outVolFn)
            self.runJob("xmipp_volume_align", args)

    def createOutputStep(self):
        vols = []
        for vol in self._iterInputVolumes():
            outVol = em.Volume()
            outVol.setLocation(vol.outputName)
            outVol.setObjLabel(vol.getObjLabel())
            outVol.setObjComment(vol.getObjComment())
            vols.append(outVol)

        if len(vols) > 1:
            volSet = self._createSetOfVolumes()
            volSet.setSamplingRate(self.inputReference.get().getSamplingRate())
            for vol in vols:
                volSet.append(vol)
            outputArgs = {'outputVolumes': volSet}
        else:
            vols[0].setSamplingRate(self.inputReference.get().getSamplingRate())
            outputArgs = {'outputVolume': vols[0]}

        self._defineOutputs(**outputArgs)
        for pointer in self.inputVolumes:
            self._defineSourceRelation(pointer, outputArgs.values()[0])

    #--------------------------- INFO functions --------------------------------------------

    def _validate(self):
        errors = []
        for pointer in self.inputVolumes:
            if pointer.pointsNone():
                errors.append('Invalid input, pointer: %s' % pointer.getObjValue())
                errors.append('              extended: %s' % pointer.getExtended())
        return errors

    def _summary(self):
        summary = []
        nVols = self._getNumberOfInputs()

        if nVols > 0:
            summary.append("Volumes to align: *%d* " % nVols)
        else:
            summary.append("No volumes selected.")
        summary.append("Alignment method: %s" % self.getEnumText('alignmentAlgorithm'))

        return summary

    def _methods(self):
        nVols = self._getNumberOfInputs()

        if nVols > 0:
            methods = 'We aligned %d volumes against a reference volume using ' % nVols
            #TODO: Check a more descriptive way to add the reference and
            # all aligned volumes to the methods (such as obj.getNameId())
            # also to show the number of volumes from each set in the input.
            # This approach implies to consistently include also the outputs
            # ids to be tracked in all the workflow's methods.
            if self.alignmentAlgorithm == ALIGN_ALGORITHM_FAST_FOURIER:
                methods += ' the Fast Fourier alignment described in [Chen2013].'

            elif self.alignmentAlgorithm == ALIGN_ALGORITHM_LOCAL:
                methods += ' a local search of the alignment parameters.'
            elif self.alignmentAlgorithm == ALIGN_ALGORITHM_EXHAUSTIVE:
                methods += ' an exhaustive search.'
            elif self.alignmentAlgorithm == ALIGN_ALGORITHM_EXHAUSTIVE_LOCAL:
                methods += ' an exhaustive search followed by a local search.'
        else:
            methods = 'No methods available yet.'

        return [methods]

    def _citations(self):
        if self.alignmentAlgorithm == ALIGN_ALGORITHM_FAST_FOURIER:
            return ['Chen2013']

    #--------------------------- UTILS functions --------------------------------------------
    def _iterInputVolumes(self):
        """ Iterate over all the input volumes. """
        for pointer in self.inputVolumes:
            item = pointer.get()
            if item is None:
                break
            itemId = item.getObjId()
            if isinstance(item, em.Volume):
                item.outputName = self._getExtraPath('output_vol%06d.vol' % itemId)
                yield item
            elif isinstance(item, em.SetOfVolumes):
                for vol in item:
                    vol.outputName = self._getExtraPath('output_vol%06d_%03d.vol' % (itemId, vol.getObjId()))
                    yield vol

    def _getNumberOfInputs(self):
        """ Return the total number of input volumes. """
        nVols = 0
        for _ in self._iterInputVolumes():
            nVols += 1

        return nVols

    def _getMaskArgs(self):
        maskArgs = ''
        if self.applyMask:
            if self.maskType == ALIGN_MASK_CIRCULAR:
                maskArgs+=" --mask circular -%d" % self.maskRadius
            else:
                maskArgs+=" --mask binary_file %s" % self.volMask
        return maskArgs

    def _getAlignArgs(self):
        alignArgs = ''

        if self.alignmentAlgorithm == ALIGN_ALGORITHM_FAST_FOURIER:
            alignArgs += " --frm"

        elif self.alignmentAlgorithm == ALIGN_ALGORITHM_LOCAL:
            alignArgs += " --local --rot %f %f 1 --tilt %f %f 1 --psi %f %f 1 -x %f %f 1 -y %f %f 1 -z %f %f 1 --scale %f %f 0.005" %\
               (self.initialRotAngle, self.initialRotAngle,
                self.initialTiltAngle, self.initialTiltAngle,
                self.initialInplaneAngle, self.initialInplaneAngle,
                self.initialShiftX, self.initialShiftX,
                self.initialShiftY, self.initialShiftY,
                self.initialShiftZ,self.initialShiftZ,
                self.initialScale, self.initialScale)
        else: # Exhaustive or Exhaustive+Local
            alignArgs += " --rot %f %f %f --tilt %f %f %f --psi %f %f %f -x %f %f %f -y %f %f %f -z %f %f %f --scale %f %f %f" %\
               (self.minRotationalAngle, self.maxRotationalAngle, self.stepRotationalAngle,
                self.minTiltAngle, self.maxTiltAngle, self.stepTiltAngle,
                self.minInplaneAngle, self.maxInplaneAngle, self.stepInplaneAngle,
                self.minimumShiftX, self.maximumShiftX, self.stepShiftX,
                self.minimumShiftY, self.maximumShiftY, self.stepShiftY,
                self.minimumShiftZ, self.maximumShiftZ, self.stepShiftZ,
                self.minimumScale, self.maximumScale, self.stepScale)

        return alignArgs

class XmippProtAlignVolumeForWeb(XmippProtAlignVolume):
    """ Aligns a set of volumes using cross correlation.
    Based on Xmipp protocol for aligning volumes, but
    the parameters are restricted for ease of use.
    """
    _label = 'align volume web'

    def _defineParams(self, form):
        XmippProtAlignVolume._defineParams(self, form)

        maskGroup = form.getParam('Mask')
        maskGroup.config(condition='False')

        # Set as default the fast fourier align method
        # this requires that the Xmipp is compiled with
        # the corresponding flag
        form.getParam('alignmentAlgorithm').config(default=ALIGN_ALGORITHM_FAST_FOURIER)


#!/usr/bin/env python
'''
类似于cp命令   cp a b
'''
import sys

def pycp(src,dest):
    with open(src,'rb') as f1:
        with open(dest, 'a+b') as f2:
            while True:
                data = f1.read(4)
                if not data:
                    break
                f2.write(data)

s = sys.argv[1]
d = sys.argv[2]
pycp(s,d)


from populus.migrations import (
    Migration,
    DeployContract,
)
from populus.migrations.writer import (
    write_migration,
)
from populus.migrations.migration import (
    get_migration_classes_for_execution,
)

def test_chain_fixture(project_dir, write_project_file, request, MATH):
    write_project_file('contracts/Math.sol', MATH['source'])
    write_project_file('migrations/__init__.py')

    project = request.getfuncargvalue('project')

    chain = request.getfuncargvalue('chain')
    assert chain.web3.isConnected


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

import streamlit as st
import pandas as pd
from OOPapproach import *
from SongRecommendation import *
import base64
from nltk.sentiment.vader import  SentimentIntensityAnalyzer

def artistsearch():

    userinput = st.text_input("Enter an artist you like ")
    userinput = userinput.lower()
    st.text("your artist is: "+userinput)

    song_df_normalised = pd.read_csv("datasets/song_df_normalised.csv")

    try:
        artist = song_df_normalised[song_df_normalised['track_artist'].str.contains(userinput)]['track_artist'].tolist()[0]

    except IndexError:
        st.error("No result :(")

    else:
        artist_list = song_df_normalised[song_df_normalised['track_artist'].str.contains(userinput)]['track_artist'].tolist()

        artist_list = list(set(artist_list))
        option = st.selectbox("Confirm artist", artist_list)
        x = artist_list.index(option)
        artist_name = artist_list[x]

        st.text("Top songs for "+artist_name+" are:")

        artist_song_df = song_df_normalised[song_df_normalised['track_artist'] == artist_name]
        artist_song_df = artist_song_df.sort_values('track_popularity',ascending=False)
        artist_song_list = artist_song_df['track_name'].to_list()

        n = len(artist_song_list)
        if n>10:
            n=5
        for i in range(n):
            c = i + 1
            st.text(str(c)+" : "+artist_song_list[i])
            x = song_df_normalised[(song_df_normalised['track_name'] == artist_song_list[i]) & (song_df_normalised['track_artist'] == artist_name)]['links'].tolist()[0]
            components.iframe(src="https://w.soundcloud.com/player/?url="+x+"&color=%23ff5500")

        artist_song_list.clear()

        #recommend = st.button("go further ")
        #if recommend:
        #    songrecommender()

def main():
    artistsearch()

if __name__  == '__main__':
    main()


from PyQt4 import QtGui
import AW.UI.ui_ls as ui_ls

#####################################################################
# Log Snapshot Application Window
#####################################################################
class MainForm(QtGui.QDialog, ui_ls.Ui_Dialog):
    #######################################################
    # ctor
    #######################################################
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)
        self.setupUi(self)

        self.snapshotDict = {}

        # Controls

        self.controlsListModel = QtGui.QStandardItemModel()
        self.lvControls.setModel(self.controlsListModel)
        self.lvControls.selectionModel().selectionChanged.connect(self.controlSelected)
        self.lvControls.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)

        # before
        self.listBefore = []

        # after
        self.listAfter = []

        # Sensors
        self.sensorsListModel = QtGui.QStandardItemModel()
        self.lvSensors.setModel(self.sensorsListModel)
        self.lvSensors.selectionModel().selectionChanged.connect(self.sensorSelected)
        self.lvSensors.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)

        self.sensorsValuesListModel = QtGui.QStandardItemModel()
        self.lvSensorsValues.setModel(self.sensorsValuesListModel)
        self.lvSensorsValues.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)

        self.accept()

    #######################################################
    # Fill before and after when control selected
    #######################################################
    def controlSelected(self):
        if(self.lvControls.selectedIndexes() != []):
            row = self.lvControls.selectedIndexes()[0].row()

            beforeTxt = ""
            for item in self.listBefore[row]:
                beforeTxt = "{0}{1}".format(beforeTxt,item)

            afterTxt = ""
            for item in self.listAfter[row]:
                afterTxt = "{0}{1}".format(afterTxt,item)

            self.teBefore.setPlainText(beforeTxt)
            self.teAfter.setPlainText(afterTxt)

        else:
            self.teBefore.setPlainText("")
            self.teAfter.setPlainText("")

    #######################################################
    # Draw graph when sensor selected
    #######################################################
    def sensorSelected(self):
        self.canvasSensor.figure.clear()

        if(self.lvSensors.selectedIndexes() != []):
            row = self.lvSensors.selectedIndexes()[0].row()
            data = []
            try:
                for val in self.snapshotDict["Sensorshld"]["Sensors"][row]["Values"]:
                    data.append(float(val))
            except:
                data = [0,1,2]

            ax = self.canvasSensor.figure.add_subplot(111)
            self.canvasSensor.figure.suptitle(self.snapshotDict["Sensorshld"]["Sensors"][row]["Header"], weight = "bold", fontsize=14)
            ax.set_xlabel("Seconds", fontsize=14)
            ax.set_ylabel(self.snapshotDict["Sensorshld"]["Sensors"][row]["Unit"], fontsize=14)
        else:
            data = [1, 2, 3, 4, 5, 10, 3, 2]
            ax = self.canvasSensor.figure.add_subplot(111)
            self.canvasSensor.figure.suptitle("ERROR")
            ax.set_xlabel("X Label")
            ax.set_ylabel("Y Label")

        ax.plot(data, "*-")
        self.canvasSensor.draw()

    #######################################################
    # Fills UI
    #######################################################
    def fillUI(self, snapshotDict):
        self.snapshotDict = snapshotDict

        # Fill Controls
        for file in self.snapshotDict["Files"]:
            item = QtGui.QStandardItem(file["Filename"])
            self.controlsListModel.appendRow(item)

            # add all controls for this file to self.listBefore and After
            listB = []
            listA = []
            for control in file["Controls"]:
                listB.append("Control: {0}, Value: {1}\n".format(control["Control"], control["Before"]))
                listA.append("Control: {0}, Value: {1}\n".format(control["Control"], control["After"]))
            self.listBefore.append(listB)
            self.listAfter.append(listA)

            # add value of specific control to self.listBefore and After
            for control in file["Controls"]:
                item = QtGui.QStandardItem(control["Control"])
                self.controlsListModel.appendRow(item)
                self.listBefore.append("{0}\n".format(control["Before"]))
                self.listAfter.append("{0}\n".format(control["After"]))

        # Fill Sensors
        for sensor in self.snapshotDict["Sensorshld"]["Sensors"]:
            item = QtGui.QStandardItem(sensor["Header"])
            self.sensorsListModel.appendRow(item)

            item = QtGui.QStandardItem("{0:<7} {1}".format(sensor["Values"][0], sensor["Unit"]))
            self.sensorsValuesListModel.appendRow(item)

        if self.exec_() == QtGui.QDialog.Accepted:
            pass


#!/usr/bin/python
from collections import deque
from numpy import random
import simpy
import device
from device import Device
from shared_folders import SharedFolder
from matplotlib import pyplot
import numpy

SIM_TIME = 10000000

#******************************************************************************
# Create the synthetic content synchronization network
#******************************************************************************
def generate_network(num_dv, devices, shared_folders):

    # shared folders per device - negative_binomial (s, mu)
    DV_DG = [0.470, 1.119]

    # device per shared folder - negative_binomial (s, mu)
    SF_DG = [0.231, 0.537]

    # derive the expected number of shared folders using the negative_binomials

    # this piece is just converting the parameterization of the
    # negative_binomials from (s, mu) to "p". Then, we use the rate between
    # the means to estimate the expected number of shared folders
    # from the given number of devices

    dv_s = DV_DG[0]
    dv_m = DV_DG[1]
    dv_p = dv_s / (dv_s + dv_m)
    nd = 1 + (dv_s * (1.0 - dv_p) / dv_p)

    sf_s = SF_DG[0]
    sf_m = SF_DG[1]
    sf_p = sf_s / (sf_s + sf_m)
    dn = 1 + (sf_s * (1.0 - sf_p) / sf_p)

    # the number of shared folders is finally derived
    num_sf = int(num_dv * nd / dn)

    # sample the number of devices per shared folder (shared folder degree)
    sf_dgr = [x + 1 for x in random.negative_binomial(sf_s, sf_p, num_sf)]

    # sample the number of shared folders per device (device degree)
    dv_dgr = [x + 1 for x in random.negative_binomial(dv_s, dv_p, num_dv)]

    # create the population of edges leaving shared folders
    l = [i for i, j in enumerate(sf_dgr) for k in range(min(j, num_dv))]
    random.shuffle(l)
    sf_pop = deque(l)

    # create empty shared folders
    for sf_id in range(num_sf):
        shared_folders[sf_id] = SharedFolder(sf_id)

    # first we pick a random shared folder for each device
    for dv_id in range(num_dv):
        devices[dv_id] = Device(dv_id)

        sf_id = sf_pop.pop()
        devices[dv_id].add_shared_folder(shared_folders[sf_id])
        shared_folders[sf_id].add_device(devices[dv_id])

    # then we complement the shared folder degree

    # we skip devices with degree 1 in a first pass, since they just got 1 sf
    r = 1

    # we might have less edges leaving devices than necessary
    while sf_pop:
        # create the population of edges leaving devices
        l = [i for i, j in enumerate(dv_dgr) for k in range(min(j - r, num_sf))]
        random.shuffle(l)
        dv_pop = deque(l)

        # if we need to recreate the population, we use devices w/ degree 1 too
        r = 0

        while sf_pop and dv_pop:
            dv = dv_pop.pop()
            sf = sf_pop.pop()

            # we are lazy and simply skip the unfortunate repetitions
            if not shared_folders[sf] in devices[dv].my_shared_folders:
                devices[dv].add_shared_folder(shared_folders[sf])
                shared_folders[sf].add_device(devices[dv])
            else:
                sf_pop.append(sf)

#******************************************************************************
# implements the simulation
#******************************************************************************
if __name__ == '__main__':
    #global u_used_v
    #global d_used_v
    # number of devices in the simulation
    NUM_DEV = 50

    # collection of devices
    devices = {}

    # collection of shared folders
    shared_folders = {}

   # u_used_v.append(0)
   # d_used_v.append(0)
    # create the content sharing network
    env = simpy.Environment()
    generate_network(NUM_DEV, devices, shared_folders)

    #for fold in shared_folders:
        #print (fold,shared_folders[fold].getStDevices())

    # DEBUG: dumping the network
    for dev_id in devices:
        #print (str(devices[dev_id]))
        devices[dev_id].setEnv(env)
        env.process(devices[dev_id].deviceP())

    env.run(until=SIM_TIME)

    fig,(down,up) = pyplot.subplots(2,1)
    x = numpy.linspace(0,len(device.getDUsedV()),len(device.getDUsedV()),endpoint=True)
    down.bar(x,device.getDUsedV())
    down.set_ylabel("D used band")
    x = numpy.linspace(0,len(device.getUUsedV()),len(device.getUUsedV()),endpoint=True)
    up.bar(x,device.getUUsedV())
    up.set_ylabel("UP used band")

    pyplot.show()


import math

def main():
    year = eval(input("Insert the year: "))

    C = year//100
    epact = (8 + (C//4) - C + ((8*C + 13)//25)+11*(year%19))%30

    print("Epact is", epact)

main()


import pygame
import random
import time
import sys
import os
import math
import numpy as np

# center window
os.environ['SDL_VIDEO_CENTERED'] = '1'
np.seterr(all='ignore')

# window dimensions
W_WIDTH = 300
W_HEIGHT = 300

DIAGONAL = np.sqrt(W_WIDTH**2 + W_HEIGHT**2)

# movement directions constants
UP = 10
DOWN = 11
LEFT = 12
RIGHT = 13

# ai specific movement directions
STRAIGHT = 0
MOVE_LEFT = 1
MOVE_RIGHT = 2

class Snake:
    def __init__(self):
        self.position = [100, 50]
        self.body = [[100, 50], [90, 50], [80, 50]]
        self.direction = RIGHT

    def change_dir_human(self, dire):
        if dire == RIGHT and not self.direction == LEFT:
            self.direction = dire
        elif dire == LEFT and not self.direction == RIGHT:
            self.direction = dire
        elif dire == UP and not self.direction == DOWN:
            self.direction = dire
        elif dire == DOWN and not self.direction == UP:
            self.direction = dire
        else:
            return

    # mapping nn outputs with the game logic
    def change_dir_ai(self, dire):
        if self.direction == RIGHT:
            if dire == MOVE_LEFT:
                self.direction = UP
            elif dire == MOVE_RIGHT:
                self.direction = DOWN
        elif self.direction == LEFT:
            if dire == MOVE_LEFT:
                self.direction = DOWN
            elif dire == MOVE_RIGHT:
                self.direction = UP
        elif self.direction == UP:
            if dire == MOVE_LEFT:
                self.direction = LEFT
            elif dire == MOVE_RIGHT:
                self.direction = RIGHT
        else:
            if dire == MOVE_LEFT:
                self.direction = RIGHT
            elif dire == MOVE_RIGHT:
                self.direction = LEFT

    def move(self, food_pos):
        if self.direction == RIGHT:
            self.position[0] += 10
        elif self.direction == LEFT:
            self.position[0] -= 10
        elif self.direction == UP:
            self.position[1] -= 10
        else:
            self.position[1] += 10

        # move
        self.body.insert(0, list(self.position))

        if self.position == food_pos:
            return True
        else:
            # remove extra block from movement if food wasn't eaten
            self.body.pop()
            return False

    # check for wall/tail collisions
    def check_collision(self):
        if self.position[0] > W_WIDTH - 10 or self.position[0] < 10:
            return True
        elif self.position[1] > W_HEIGHT - 10 or self.position[1] < 10:
            return True

        for bp in self.body[1:]:
            if self.position == bp:
                return True

        return False

    # same as above, except it uses passed position instead of the class attribute
    def check_collision_arg(self, n_pos):
        if n_pos[0] > W_WIDTH - 10 or n_pos[0] < 10:
            return 1.0
        elif n_pos[1] > W_HEIGHT - 10 or n_pos[1] < 10:
            return 1.0

        for bp in self.body[1:]:
            if n_pos == bp:
                return 1.0

        return 0.0

# class used for spawning food at the random position
class FoodSpawner:
    def __init__(self):
        self.w_edge = (W_WIDTH - 10) / 10
        self.h_edge = (W_HEIGHT - 10) / 10
        self.gen_rand_pos()
        self.on_screen = True

    def gen_rand_pos(self):
        self.position = [random.randrange(1, self.w_edge) * 10, random.randrange(1, self.h_edge) * 10]

    def spawn_food(self):
        if not self.on_screen:
            self.gen_rand_pos()
            self.on_screen = True

        return self.position

class Game:
    def __init__(self, init_pygame=True):
        if init_pygame:
            self.window = pygame.display.set_mode([W_WIDTH, W_HEIGHT])
            pygame.display.set_caption('Snake')
            self.fps = pygame.time.Clock()
        self.snake = Snake()
        self.score = len(self.snake.body)
        self.food_spawner = FoodSpawner()

    def check_events_human_gameplay(self, events):
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    self.snake.change_dir_human(UP)
                elif event.key == pygame.K_DOWN:
                    self.snake.change_dir_human(DOWN)
                elif event.key == pygame.K_LEFT:
                    self.snake.change_dir_human(LEFT)
                else:
                    self.snake.change_dir_human(RIGHT)

    def check_events_ai_gameplay(self, events):
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

    def reset_defaults(self):
        self.snake = Snake()
        self.food_spawner = FoodSpawner()

    # pygame draw loop
    def game_loop(self, nn=None, delay=0):
        self.score = 0
        # main game loop
        while True:
            events = pygame.event.get()
            food = self.food_spawner.spawn_food()
            print(self.get_nn_inputs(food))

            if nn == None:
                self.check_events_human_gameplay(events)
            else:
                # exit event only
                self.check_events_ai_gameplay(events)
                # get direction by feeding snake info into the nn inputs
                direction = nn.play([self.get_nn_inputs(food)])
                self.snake.change_dir_ai(direction)

            if self.snake.move(food):
                self.score += 1
                self.food_spawner.on_screen = False

            # fill window and draw border
            self.window.fill(pygame.Color(200, 191, 131))
            pygame.draw.rect(self.window, pygame.Color(222, 210, 151), \
                pygame.Rect(0, 0, W_WIDTH, W_HEIGHT), 12)

            # draw snake
            for pos in self.snake.body:
                pygame.draw.rect(self.window, pygame.Color(0, 255, 0), \
                    pygame.Rect(pos[0], pos[1], 10, 10))

            # draw food
            pygame.draw.rect(self.window, pygame.Color(255, 0, 0), \
                pygame.Rect(food[0], food[1], 10, 10))

            # check for collisions and end the game if collision happend
            if self.snake.check_collision():
                pygame.quit()
                return self.score

            pygame.display.flip()
            self.fps.tick(24)

            time.sleep(delay)

############################################ Neural Network train functions ##########################################

    def get_nn_inputs_DEPRECATED(self, food):
        # obstacle left - 0 or 1
        # obstacle right - 0 or 1
        # obstacle up - 0 or 1
        # obstacle down - 0 or 1
        # normalised angle between food and snakes direction

        # is there an obstacle to the up, down, left, or right
        obs_u = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] - 10])
        obs_d = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] + 10])
        obs_l = self.snake.check_collision_arg([self.snake.position[0] - 10, self.snake.position[1]])
        obs_r = self.snake.check_collision_arg([self.snake.position[0] + 10, self.snake.position[1]])

        # calculating angle between the snake and food direction vectors
        snake_vec = self.get_snake_direction_vector()
        food_vec = self.get_food_direction_vector(food)
        angle = self.get_angle1(snake_vec, food_vec)

        food_dist = self.get_food_distance(food)

        return np.array([obs_u, obs_d, obs_l, obs_r, angle, food_dist])

    def get_nn_inputs(self, food):
        # obstacle ahead - (0, 1)
        # obstacle left - (0, 1)
        # obstacle right - (0, 1)
        obs_a = None
        obs_l = None
        obs_r = None
        if self.snake.direction == UP:
            obs_a = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] - 10])
            obs_l = self.snake.check_collision_arg([self.snake.position[0] - 10, self.snake.position[1]])
            obs_r = self.snake.check_collision_arg([self.snake.position[0] + 10, self.snake.position[1]])
        elif self.snake.direction == DOWN:
            obs_a = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] + 10])
            obs_l = self.snake.check_collision_arg([self.snake.position[0] + 10, self.snake.position[1]])
            obs_r = self.snake.check_collision_arg([self.snake.position[0] - 10, self.snake.position[1]])
        elif self.snake.direction == RIGHT:
            obs_a = self.snake.check_collision_arg([self.snake.position[0] + 10, self.snake.position[1]])
            obs_l = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] - 10])
            obs_r = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] + 10])
        else:
            obs_a = self.snake.check_collision_arg([self.snake.position[0] - 10, self.snake.position[1]])
            obs_l = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] + 10])
            obs_r = self.snake.check_collision_arg([self.snake.position[0], self.snake.position[1] - 10])

        # calculating angle between snake and food direction vectors
        snake_vec = self.get_snake_direction_vector()
        food_vec = self.get_food_direction_vector(food)
        angle = self.get_angle2(snake_vec, food_vec)

        # calculating the distance between food and snakes head
        # food_dist = self.get_food_distance(food)

        return np.array([obs_a, obs_l, obs_r, angle])

    # [0, 180]
    def get_angle1(self, a, b):
        a = self.normalize_vector(a)
        b = self.normalize_vector(b)
        c = np.dot(a, b) / np.linalg.norm(a) / np.linalg.norm(b)
        return np.arccos(np.clip(c, -1.0, 1.0)) / math.pi

    # https://math.stackexchange.com/questions/878785/how-to-find-an-angle-in-range0-360-between-2-vectors
    # Just like the dot product is proportional to the cosine of the angle,
    # the determinant is proprortional to its sine. And if you know the cosine and the sine,
    # then you can compute the angle. Many programming languages provide a function atan2 for this purpose.
    def get_angle2(self, a, b):
        a = self.normalize_vector(a)
        b = self.normalize_vector(b)
        return math.atan2(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]) / math.pi

    def normalize_vector(self, vector):
        return vector / np.linalg.norm(vector)

    def get_snake_direction_vector(self):
        return np.array(self.snake.body[0]) - np.array(self.snake.body[1])

    def get_food_direction_vector(self, food):
        return np.array(food) - np.array(self.snake.body[0])

    def get_food_distance(self, food):
        raw = np.sqrt((self.snake.position[0] - food[0])**2 + \
                (self.snake.position[1] - food[1])**2)

        return raw / DIAGONAL

    # Train 2 - punish the snake for not moving towards food
    def game_loop_train(self, nn, starting_score=50):
        self.reset_defaults()
        nn.fitness = starting_score # avoid negative and zeros when generating wheel

        # main game loop
        while True:
            # spawn food at the random location (if not spawned already)
            food = self.food_spawner.spawn_food()
            old_distance = self.get_food_distance(food)

            # feed snake info into the neural network
            direction = nn.play([self.get_nn_inputs(food)])
            self.snake.change_dir_ai(direction)

            # move the snake and add pts if food is eaten
            if self.snake.move(food):
                nn.fitness += 50
                self.food_spawner.on_screen = False
            else:
                # check if snake moved towards/away from the food
                new_distance = self.get_food_distance(food)
                if new_distance < old_distance:
                    nn.fitness += 1
                else:
                    nn.fitness -= 2.5

            # check if the score reached zero or bellow
            if nn.fitness <= 0:
                nn.fitness = starting_score / 2
                return
            # check for collisions and end the game if collision happend
            elif self.snake.check_collision():
                return

# debug
if __name__ == '__main__':
    g = Game()
    g.game_loop(delay=0.1)


import allure
from Source.Framework.BasePage import BasePage
from Source.Test.Python.DNVGL.PageObjects.DNVLoginPage import DNVLoginPage

""" Path to the objects """
login_button_xpath = "//*[@id=\"dnvgl\"]/header/section/a"

class DNVHomePage(BasePage):
    """Page Object of DNV Home Page"""

    @allure.step
    def initiate(self, url):
        """ Initiate page object """
        self.driver.get(url)

    @allure.step
    def click_login_button(self):
        """ click on login button and return next page """
        element = self.driver.find_element_by_xpath(login_button_xpath)
        element.click()
        login_page = DNVLoginPage(self.driver)
        login_page.wait_until_loaded()
        return login_page


# 1.暴力，求出str1的所有子序列，并判断是否在str2中O(n)，从后往前推，找到就返回长度
# 2.DP 自底向上 看成由两个str组成的一个二维数组
# a.重复性(反向思维) 看最后一个字符是否相等
# ① 相等 problems[i,j] = sub[i-1,j-1] + 1
# ② 不等 problems[i,j] = max(sub[i-1,j],sub[i,j-1],sub[i-1,j-1]) # 最后一项可省略，求解sub[i-1,j]时会再求解一次
# b.DP array f[i,j]
# c.DP方程 f[i,j] = f[i-1,j-1]+1 if i==j else max(f[i-1,j],f[i,j-1])
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m,n = len(text1),len(text2)
        if m*n == 0:
            return 0
        # dp = [[0 for j in range(n)] for i in range(m)]
        # # 初始化 二维 自底向上
        # if text1[0] in text2:
        #     for j in range(text2.index(text1[0]),n):
        #         dp[0][j] = 1
        # if text2[0] in text1:
        #     for i in range(text1.index(text2[0]),m):
        #         dp[i][0] = 1

        # for i in range(1,m):
        #     for j in range(1,n):
        #         dp[i][j] = dp[i-1][j-1]+1 if text1[i] == text2[j] else max(dp[i-1][j],dp[i][j-1])
        # print(dp)
        # return dp[m-1][n-1]

        # 滚动数组思想
        dp = [0]*n
        if text1[0] in text2:
            for j in range(text2.index(text1[0]),n):
                dp[j] = 1
        change = n
        if text2[0] in text1:
            change = text1.index(text2[0])
        print(dp)
        for i in range(1,m):
            # prev 记录dp(i-1,j-1)
            prev = dp[0]
            for j in range(n):
                if j == 0:
                    if i >= change:
                        dp[j] = 1
                else:
                    # curr 记录当前要改变的值，并在值改变之后将未改变的值赋值给prev，相当于保存了(i-1,j-1)处的值
                    curr = dp[j]
                    if text1[i] == text2[j]:
                        dp[j] = prev+1
                    else:
                        dp[j] = max(dp[j],dp[j-1])
                    prev = curr
            print(dp)
        return dp[n-1]

5 动态规划 1143. 最长公共子序列.py


# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

from collections import deque
class Codec:
    def serialize(self, root):
        """Encodes a tree to a single string.

        :type root: TreeNode
        :rtype: str
        """
        if root == None: return 'X,'
        leftserilized = self.serialize(root.left)
        rightserilized = self.serialize(root.right)
        return str(root.val) + ',' + leftserilized + rightserilized

    def deserialize(self, data):
        """Decodes your encoded data to tree.

        :type data: str
        :rtype: TreeNode
        """
        data = data.split(',')
        root = self.buildTree(data)
        return root

    def buildTree(self,data):
        if not data: return None
        val = data.pop(0)
        if val == 'X': return None
        node = TreeNode(val)
        node.left = self.buildTree(data)
        node.right = self.buildTree(data)
        return node

class Solution:
    def recoverFromPreorder(self, S: str) -> TreeNode:
        path = list()
        i = 0
        while i < len(S):
            # 统计当前level
            level = 0
            while S[i] == '-':
                level += 1
                i += 1

            # 字符转化
            val = 0
            while i < len(S) and S[i].isdigit():
                val = val*10 + ord(S[i])-ord('0')
                i += 1

            # 构建节点
            node = TreeNode(val)
            if level == len(path):
                if path:
                    path[-1].left = node
            else:
                path = path[:level]
                path[-1].right = TreeNode(val)
            path.append(node)

        return path[0]

if __name__ == "__main__":
    s = Solution()
    c = Codec()
    print(c.serialize(s.recoverFromPreorder("1-2--3--4-5--6--7")))


import asyncio
import logging
import threading

from hyperapp.common.module import Module

log = logging.getLogger(__name__)

class ThisModule(Module):

    def __init__(self, module_name, services, config):
        super().__init__(module_name, services, config)
        self._stop_event = services.async_stop_event
        self._test_stop_event = threading.Event()
        services.test_init_event = threading.Event()
        services.test_stop_event = self._test_stop_event

    async def async_init(self, services):
        log.info("Test async init close: started.")
        services.test_init_event.set()

    async def async_stop(self):
        log.info("Test async init close: got stop event.")
        self._test_stop_event.set()


# Combines two files by reference number.

start_file = "start.txt"
x_file = "x.txt"
out_file = "combref.txt"

start_dict = {}
with open(start_file) as file:
    for line in file:
        try:
            (ref, start) = line.split()
            start_dict[ref] = start
        except:
            next(file)

with open(x_file) as file:
    for line in file:
        try:
            (ref, per, seq) = line.split()
            start = start_dict[ref]
            print(start + " " + per, file=open(out_file, "a"))
        except:
            next(file)


from subprocess import Popen

from unittest import mock
import os
from threading import Thread

import socket
import time
import tempfile

import mlflow
from mlflow.server import BACKEND_STORE_URI_ENV_VAR, ARTIFACT_ROOT_ENV_VAR
from mlflow.utils.file_utils import path_to_local_file_uri, local_file_uri_to_path
from tests.helper_functions import LOCALHOST, get_safe_port

def _await_server_up_or_die(port, timeout=60):
    """Waits until the local flask server is listening on the given port."""
    print("Awaiting server to be up on %s:%s" % (LOCALHOST, port))
    start_time = time.time()
    connected = False
    while not connected and time.time() - start_time < timeout:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(2)
        result = sock.connect_ex((LOCALHOST, port))
        if result == 0:
            connected = True
        else:
            print("Server not yet up, waiting...")
            time.sleep(0.5)
    if not connected:
        raise Exception("Failed to connect on %s:%s after %s seconds" % (LOCALHOST, port, timeout))
    print("Server is up on %s:%s!" % (LOCALHOST, port))

# NB: We explicitly wait and timeout on server shutdown in order to ensure that pytest output
# reveals the cause in the event of a test hang due to the subprocess not exiting.
def _await_server_down_or_die(process, timeout=60):
    """Waits until the local flask server process is terminated."""
    print("Awaiting termination of server process...")
    start_time = time.time()

    def wait():
        process.wait()

    Thread(target=wait).start()
    while process.returncode is None and time.time() - start_time < timeout:
        time.sleep(0.5)
    if process.returncode is None:
        raise Exception("Server failed to shutdown after %s seconds" % timeout)

def _init_server(backend_uri, root_artifact_uri):
    """
    Launch a new REST server using the tracking store specified by backend_uri and root artifact
    directory specified by root_artifact_uri.
    :returns A tuple (url, process) containing the string URL of the server and a handle to the
             server process (a multiprocessing.Process object).
    """
    mlflow.set_tracking_uri(None)
    server_port = get_safe_port()
    env = {
        BACKEND_STORE_URI_ENV_VAR: backend_uri,
        ARTIFACT_ROOT_ENV_VAR: path_to_local_file_uri(
            tempfile.mkdtemp(dir=local_file_uri_to_path(root_artifact_uri))
        ),
    }
    with mock.patch.dict(os.environ, env):
        cmd = [
            "python",
            "-c",
            'from mlflow.server import app; app.run("{hostname}", {port})'.format(
                hostname=LOCALHOST, port=server_port
            ),
        ]
        process = Popen(cmd)

    _await_server_up_or_die(server_port)
    url = "http://{hostname}:{port}".format(hostname=LOCALHOST, port=server_port)
    print("Launching tracking server against backend URI %s. Server URL: %s" % (backend_uri, url))
    return url, process


# coding: utf-8
from flask import render_template, Blueprint, redirect, request, url_for, flash, g
from ..forms import SigninForm, SignupForm
from ..utils.account import signin_user, signout_user
from ..utils.permissions import VisitorPermission, UserPermission
from ..models import db, User
from ..forms import SettingsForm

bp = Blueprint('user', __name__)

@bp.route('/people/<int:uid>')
def profile(uid):
    user = User.query.get_or_404(uid)
    return render_template('user/profile.html', user=user)

@bp.route('/people/<int:uid>/votes')
def votes(uid):
    user = User.query.get_or_404(uid)
    return render_template('user/votes.html', user=user)

@bp.route('/people/<int:uid>/likes')
def likes(uid):
    user = User.query.get_or_404(uid)
    return render_template('user/likes.html', user=user)

@bp.route('/my/settings', methods=['GET', 'POST'])
@UserPermission()
def settings():
    """个人设置"""
    form = SettingsForm(obj=g.user)
    if form.validate_on_submit():
        form.populate_obj(g.user)
        db.session.add(g.user)
        db.session.commit()
        flash('设置已保存')
        return redirect(url_for('.settings'))
    return render_template('user/settings.html', form=form)


import numpy as np
import theano
from layers import LSTMLayer,DropoutLayer
import theano.tensor as T
from theano import shared
from helper.utils import init_weight,init_bias,get_err_fn,count_params
from helper.optimizer import RMSprop

dtype = T.config.floatX

class lstm_3layer_joints2:
   def __init__(self,rng, params,cost_function='mse',optimizer = RMSprop):
       batch_size=params['batch_size']
       sequence_length=params["seq_length"]

       lr=params['lr']
       self.n_in = 48
       self.n_lstm = params['n_hidden']
       self.n_out = params['n_output']

       X = T.tensor3() # batch of sequence of vector
       Y = T.tensor3() # batch of sequence of vector
       is_train = T.iscalar('is_train') # pseudo boolean for switching between training and prediction

       self.W_hy = init_weight((self.n_lstm, self.n_out), rng=rng,name='W_hy', sample= 'glorot')
       self.b_y = init_bias(self.n_out,rng=rng, sample='zero')

       self.numOfLayers=3 #important for training!!!!
       layer1=LSTMLayer(rng,0,self.n_in,self.n_lstm)
       layer2=LSTMLayer(rng,1,self.n_lstm,self.n_lstm)
       layer3=LSTMLayer(rng,2,self.n_lstm,self.n_lstm)

       self.params = layer1.params+layer2.params+layer3.params
       self.params.append(self.W_hy)
       self.params.append(self.b_y)

       def step_lstm(x_t,mask1,mask2,h_tm1_1,c_tm1_1,h_tm1_2,c_tm1_2,h_tm1_3,c_tm1_3):
           [h_t_1,c_t_1,y_t_1]=layer1.run(x_t,h_tm1_1,c_tm1_1)
           dl1=DropoutLayer(rng,input=y_t_1,prob=0.5,is_train=is_train,mask=mask1)
           [h_t_2,c_t_2,y_t_2]=layer2.run(dl1.output,h_tm1_2,c_tm1_2)
           dl2=DropoutLayer(rng,input=y_t_2,prob=0.5,is_train=is_train,mask=mask2)
           [h_t_3,c_t_3,y_t_3]=layer3.run(dl2.output,h_tm1_3,c_tm1_3)
           y = T.dot(y_t_3, self.W_hy) + self.b_y
           return [h_t_1,c_t_1,h_t_2,c_t_2,h_t_3,c_t_3,y]

       h0_1 = T.matrix(name="h0_1",dtype=dtype) # initial hidden state
       c0_1 = T.matrix(name="c0_1",dtype=dtype) # initial hidden state
       h0_2 = T.matrix(name="h0_2",dtype=dtype) # initial hidden state
       c0_2 = T.matrix(name="c0_2",dtype=dtype) # initial hidden state
       h0_3 = T.matrix(name="h0_3",dtype=dtype) # initial hidden state
       c0_3 = T.matrix(name="c0_3",dtype=dtype) # initial hidden state

       mask_shape=(sequence_length,batch_size,self.n_lstm)
       p_1=0.5
       mask1= rng.binomial(size=mask_shape, p=p_1, dtype=X.dtype)
       mask2= rng.binomial(size=mask_shape, p=p_1, dtype=X.dtype)

       noise= rng.normal(size=(batch_size,sequence_length,self.n_in), std=0.008, avg=0.0,dtype=theano.config.floatX)
       X_train=noise+X
       X_tilde= T.switch(T.neq(is_train, 0), X_train, X)

       [h_t_1,c_t_1,h_t_2,c_t_2,h_t_3,c_t_3,y_vals], _ = theano.scan(fn=step_lstm,
                                         sequences=[X_tilde.dimshuffle(1,0,2),mask1,mask2],
                                         outputs_info=[h0_1, c0_1,h0_2, c0_2, h0_3, c0_3, None])

       self.output = y_vals.dimshuffle(1,0,2)
       cost=get_err_fn(self,cost_function,Y)

       L2_reg=0.0001
       L2_sqr = theano.shared(0.)
       for param in self.params:
           L2_sqr += (T.sum(param[0] ** 2)+T.sum(param[1] ** 2))

       cost += L2_reg*L2_sqr

       _optimizer = optimizer(
            cost,
            self.params,
            lr=lr
        )

       self.train = theano.function(inputs=[X,Y,is_train,h0_1, c0_1,h0_2, c0_2, h0_3, c0_3],outputs=[cost,h_t_1[-1],c_t_1[-1],h_t_2[-1],c_t_2[-1],h_t_3[-1],c_t_3[-1]],updates=_optimizer.getUpdates(),allow_input_downcast=True)
       self.predictions = theano.function(inputs = [X,is_train,h0_1, c0_1,h0_2, c0_2, h0_3, c0_3], outputs = [self.output,h_t_1[-1],c_t_1[-1],h_t_2[-1],c_t_2[-1],h_t_3[-1],c_t_3[-1]],allow_input_downcast=True)
       self.n_param=count_params(self.params)


#!/usr/bin/python

import RPi.GPIO as GPIO
import serial
import time

ser = serial.Serial('/dev/ttyS0',115200)
ser.flushInput()

power_key = 6
rec_buff = ''
APN = 'CMNET'
ServerIP = '118.190.93.84'
Port = '2317'
Message = 'Waveshare'

def power_on(power_key):
	print('SIM7600X is starting:')
	GPIO.setmode(GPIO.BCM)
	GPIO.setwarnings(False)
	GPIO.setup(power_key,GPIO.OUT)
	time.sleep(0.1)
	GPIO.output(power_key,GPIO.HIGH)
	time.sleep(2)
	GPIO.output(power_key,GPIO.LOW)
	time.sleep(20)
	ser.flushInput()
	print('SIM7600X is ready')

def power_down(power_key):
	print('SIM7600X is loging off:')
	GPIO.output(power_key,GPIO.HIGH)
	time.sleep(3)
	GPIO.output(power_key,GPIO.LOW)
	time.sleep(18)
	print('Good bye')

def send_at(command,back,timeout):
	rec_buff = ''
	ser.write((command+'\r\n').encode())
	time.sleep(timeout)
	if ser.inWaiting():
		time.sleep(0.1 )
		rec_buff = ser.read(ser.inWaiting())
	if rec_buff != '':
		if back not in rec_buff.decode():
			print(command + ' ERROR')
			print(command + ' back:\t' + rec_buff.decode())
			return 0
		else:
			print(rec_buff.decode())
			return 1
	else:
		print(command + ' no responce')

try:
	power_on(power_key)
	send_at('AT+CSQ','OK',1)
	send_at('AT+CREG?','+CREG: 0,1',1)
	send_at('AT+CPSI?','OK',1)
	send_at('AT+CGREG?','+CGREG: 0,1',0.5)
	send_at('AT+CGSOCKCONT=1,\"IP\",\"'+APN+'\"','OK',1)
	send_at('AT+CSOCKSETPN=1', 'OK', 1)
	send_at('AT+CIPMODE=0', 'OK', 1)
	send_at('AT+NETOPEN', '+NETOPEN: 0',5)
	send_at('AT+IPADDR', '+IPADDR:', 1)
	send_at('AT+CIPOPEN=0,\"TCP\",\"'+ServerIP+'\",'+Port,'+CIPOPEN: 0,0', 5)
	send_at('AT+CIPSEND=0,', '>', 2)#If not sure the message number,write the command like this: AT+CIPSEND=0, (end with 1A(hex))
	ser.write(Message.encode())
	if 1 == send_at(b'\x1a'.decode(),'OK',5):
		print('send message successfully!')
	send_at('AT+CIPCLOSE=0','+CIPCLOSE: 0,0',15)
	send_at('AT+NETCLOSE', '+NETCLOSE: 0', 1)
	power_down(power_key)
except:
	if ser != None:
		ser.close()
		GPIO.cleanup()

if ser != None:
		ser.close()
		GPIO.cleanup()


from .models import AircraftOperator
from .models import AircraftType
from .models import Mission
from .models import MissionPersonnel
from collections import defaultdict
from django import forms
from django.contrib.auth.models import User
import re

class MissionForm(forms.ModelForm):
    type = forms.ChoiceField(choices=Mission.TYPE_CHOICES, initial=None)
    aircraft_operator = forms.ModelChoiceField(queryset=AircraftOperator.objects.all(), empty_label=None)
    aircraft_type = forms.ModelChoiceField(queryset=AircraftType.objects.all(), empty_label=None)

    added_by = forms.ModelChoiceField(queryset=User.objects.all(), required=False)
    updated_by = forms.ModelChoiceField(queryset=User.objects.all(), required=False)

    class Meta:
        model = Mission
        fields = (
            'short_description',
            'synopsis',
            'location',
            'start_date',
            'start_time',
            'end_date',
            'end_time',
            'mission_no',
            'PEP_task_no',
            'PEP_ASE_no',
            'type',
            'subject_condition',
            'terrain_assessment',
            'objective_hazards',
            'subjective_hazards',
            'mission_strategy',
            'communications',
            'equipment',
            'pilot_briefing',
            'evolution_count',
            'aircraft_operator',
            'aircraft_type',
            'pilot',
            'callsign',
        )
        widgets = {
            'synopsis': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'subject_condition': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'terrain_assessment': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'objective_hazards': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'subjective_hazards': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'mission_strategy': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'communications': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'equipment': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),
            'pilot_briefing': forms.Textarea(attrs={'rows': 3, 'placeholder': 'Not provided'}),

            'short_description': forms.TextInput(attrs={'placeholder': 'Not provided'}),
            'location': forms.TextInput(attrs={'placeholder': 'Not provided'}),
            'start_date': forms.DateInput(attrs={'placeholder': 'Not provided'}, format='%m/%d/%Y'),
            'start_time': forms.TimeInput(attrs={'placeholder': 'Not provided'}),
            'end_date': forms.DateInput(attrs={'placeholder': 'Not provided'}, format='%m/%d/%Y'),
            'end_time': forms.TimeInput(attrs={'placeholder': 'Not provided'}),
            'mission_no': forms.TextInput(attrs={'placeholder': 'Not provided'}),
            'PEP_task_no': forms.TextInput(attrs={'placeholder': 'Not provided'}),
            'PEP_ASE_no': forms.TextInput(attrs={'placeholder': 'Not provided'}),
            'pilot': forms.TextInput(attrs={'placeholder': 'Not provided'}),
            'callsign': forms.TextInput(attrs={'placeholder': 'Not provided'}),
        }

    def save(self, *args, **kwargs):
        instance = super(MissionForm, self).save(*args, **kwargs)

        personnel = defaultdict(dict)
        pattern = re.compile(r'personnel-(\d+)-([a-zA-Z_-]+)')
        for key, value in self.data.items():
            if pattern.match(key):
                personnel_forloop_counter, personnel_attr = pattern.match(key).groups()
                personnel[personnel_forloop_counter][personnel_attr] = value

        submission_personnel_ids = [int(person.get('id')) for person in personnel.values() if person.get('id')]
        existing_personnel_ids = MissionPersonnel.objects.filter(mission=instance).values_list('id', flat=True)

        personnel_ids_to_delete = set(existing_personnel_ids) - set(submission_personnel_ids)
        MissionPersonnel.objects.filter(mission=instance, id__in=personnel_ids_to_delete).delete()

        for person in personnel.values():
            if not person['id']:
                person['id'] = None

            obj, created = MissionPersonnel.objects.update_or_create(mission=instance, id=person.get('id'), defaults={'name': person.get('name'), 'role_id': person.get('role'), 'evolutions': person.get('evolutions')})

        return instance


#!/usr/bin/python3
#Retain the last n items using deque

__doc__ = '''
practice deque data structures
'''

from collections import deque

def search(lines, pattern, history=5):
    prevlines = deque(maxlen=history)
    for line in lines:
        if pattern in line:
            yield line, prevlines
        prevlines.append(line)

def main():
    with open('deque_ex.input', 'rt') as f:
        for line, prevlines in search(f, 'python', 6):
            for pline in prevlines:
                print('*{}'.format(pline))
            print('*Result: {}'.format(line))
            print('*'*30)

if __name__ == "__main__":
    main()


""" Configuration """

import os
from ConfigParser import RawConfigParser
import multiprocessing

kConfigurationPath = os.path.join(os.environ['HOME'], '.rigor.ini')

__defaults__ = dict(
		max_workers = multiprocessing.cpu_count(),
		copy_local = 'yes',
		ssl = 'yes',
		min_database_connections = 0,
		max_database_connections = 10,
		adapter = 'psycopg2',
		metadata_file = 'metadata.json',
		timestamp_format = '%Y-%m-%dT%H:%M:%SZ'
	)
config = RawConfigParser(__defaults__) # pylint: disable=C0103
config.read(kConfigurationPath)


#
# LSST Data Management System
# Copyright 2008-2016 AURA/LSST.
#
# This product includes software developed by the
# LSST Project (http://www.lsst.org/).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the LSST License Statement and
# the GNU General Public License along with this program.  If not,
# see <http://www.lsstcorp.org/LegalNotices/>.
#
from __future__ import absolute_import, division
import contextlib

from builtins import object

import lsstDebug
from lsst.pex.config import ConfigurableField
from lsst.log import Log
import lsst.daf.base as dafBase
from .timer import logInfo

__all__ = ["Task", "TaskError"]

class TaskError(Exception):
    """!Use to report errors for which a traceback is not useful.

    Examples of such errors:
    - processCcd is asked to run detection, but not calibration, and no calexp is found.
    - coadd finds no valid images in the specified patch.
    """
    pass

class Task(object):
    """!Base class for data processing tasks

    See \ref pipeBase_introduction "pipe_base introduction" to learn what tasks are,
    and \ref pipeTasks_writeTask "how to write a task" for more information about writing tasks.
    If the second link is broken (as it will be before the documentation is cross-linked)
    then look at the main page of pipe_tasks documentation for a link.

    Useful attributes include:
    * log: an lsst.log.Log
    * config: task-specific configuration; an instance of ConfigClass (see below)
    * metadata: an lsst.daf.base.PropertyList for collecting task-specific metadata,
        e.g. data quality and performance metrics. This is data that is only meant to be
        persisted, never to be used by the task.

    Subclasses typically have a method named "run" to perform the main data processing. Details:
    * run should process the minimum reasonable amount of data, typically a single CCD.
      Iteration, if desired, is performed by a caller of the run method. This is good design and allows
      multiprocessing without the run method having to support it directly.
    * If "run" can persist or unpersist data:
        * "run" should accept a butler data reference (or a collection of data references, if appropriate,
            e.g. coaddition).
        * There should be a way to run the task without persisting data. Typically the run method returns all
            data, even if it is persisted, and the task's config method offers a flag to disable persistence.

    \deprecated Tasks other than cmdLineTask.CmdLineTask%s should \em not accept a blob such as a butler data
    reference.  How we will handle data references is still TBD, so don't make changes yet! RHL 2014-06-27

    Subclasses must also have an attribute ConfigClass that is a subclass of lsst.pex.config.Config
    which configures the task. Subclasses should also have an attribute _DefaultName:
    the default name if there is no parent task. _DefaultName is required for subclasses of
    \ref cmdLineTask.CmdLineTask "CmdLineTask" and recommended for subclasses of Task because it simplifies
    construction (e.g. for unit tests).

    Tasks intended to be run from the command line should be subclasses of \ref cmdLineTask.CmdLineTask
    "CmdLineTask", not Task.
    """

    def __init__(self, config=None, name=None, parentTask=None, log=None):
        """!Create a Task

        @param[in] config       configuration for this task (an instance of self.ConfigClass,
            which is a task-specific subclass of lsst.pex.config.Config), or None. If None:
            - If parentTask specified then defaults to parentTask.config.\<name>
            - If parentTask is None then defaults to self.ConfigClass()
        @param[in] name         brief name of task, or None; if None then defaults to self._DefaultName
        @param[in] parentTask   the parent task of this subtask, if any.
            - If None (a top-level task) then you must specify config and name is ignored.
            - If not None (a subtask) then you must specify name
        @param[in] log          log (an lsst.log.Log) whose name is used as a log name prefix,
            or None for no prefix. Ignored if parentTask specifie, in which case parentTask.log's
            name is used as a prefix.
            The task's log name is `prefix + "." + name` if a prefix exists, else `name`.
            The task's log is then a child logger of parentTask.log (if parentTask specified),
            or a child logger of the log from the argument (if log is not None).

        @throw RuntimeError if parentTask is None and config is None.
        @throw RuntimeError if parentTask is not None and name is None.
        @throw RuntimeError if name is None and _DefaultName does not exist.
        """
        self.metadata = dafBase.PropertyList()
        self._parentTask = parentTask

        if parentTask is not None:
            if name is None:
                raise RuntimeError("name is required for a subtask")
            self._name = name
            self._fullName = parentTask._computeFullName(name)
            if config is None:
                config = getattr(parentTask.config, name)
            self._taskDict = parentTask._taskDict
            loggerName = parentTask.log.getName() + '.' + name
        else:
            if name is None:
                name = getattr(self, "_DefaultName", None)
                if name is None:
                    raise RuntimeError("name is required for a task unless it has attribute _DefaultName")
                name = self._DefaultName
            self._name = name
            self._fullName = self._name
            if config is None:
                config = self.ConfigClass()
            self._taskDict = dict()
            loggerName = self._fullName
            if log is not None and log.getName():
                loggerName = log.getName() + '.' + loggerName

        self.log = Log.getLogger(loggerName)
        self.config = config
        self._display = lsstDebug.Info(self.__module__).display
        self._taskDict[self._fullName] = self

    def emptyMetadata(self):
        """!Empty (clear) the metadata for this Task and all sub-Tasks."""
        for subtask in self._taskDict.values():
            subtask.metadata = dafBase.PropertyList()

    def getSchemaCatalogs(self):
        """!Return the schemas generated by this task

        @warning Subclasses the use schemas must override this method. The default implemenation
        returns an empty dict.

        @return a dict of butler dataset type: empty catalog (an instance of the appropriate
            lsst.afw.table Catalog type) for this task

        This method may be called at any time after the Task is constructed, which means that
        all task schemas should be computed at construction time, __not__ when data is actually
        processed. This reflects the philosophy that the schema should not depend on the data.

        Returning catalogs rather than just schemas allows us to save e.g. slots for SourceCatalog as well.

        See also Task.getAllSchemaCatalogs
        """
        return {}

    def getAllSchemaCatalogs(self):
        """!Call getSchemaCatalogs() on all tasks in the hiearchy, combining the results into a single dict.

        @return a dict of butler dataset type: empty catalog (an instance of the appropriate
            lsst.afw.table Catalog type) for all tasks in the hierarchy, from the top-level task down
            through all subtasks

        This method may be called on any task in the hierarchy; it will return the same answer, regardless.

        The default implementation should always suffice. If your subtask uses schemas the override
        Task.getSchemaCatalogs, not this method.
        """
        schemaDict = self.getSchemaCatalogs()
        for subtask in self._taskDict.values():
            schemaDict.update(subtask.getSchemaCatalogs())
        return schemaDict

    def getFullMetadata(self):
        """!Get metadata for all tasks

        The returned metadata includes timing information (if \@timer.timeMethod is used)
        and any metadata set by the task. The name of each item consists of the full task name
        with "." replaced by ":", followed by "." and the name of the item, e.g.:
            topLeveltTaskName:subtaskName:subsubtaskName.itemName
        using ":" in the full task name disambiguates the rare situation that a task has a subtask
        and a metadata item with the same name.

        @return metadata: an lsst.daf.base.PropertySet containing full task name: metadata
            for the top-level task and all subtasks, sub-subtasks, etc.
        """
        fullMetadata = dafBase.PropertySet()
        for fullName, task in self.getTaskDict().items():
            fullMetadata.set(fullName.replace(".", ":"), task.metadata)
        return fullMetadata

    def getFullName(self):
        """!Return the task name as a hierarchical name including parent task names

        The full name consists of the name of the parent task and each subtask separated by periods.
        For example:
        - The full name of top-level task "top" is simply "top"
        - The full name of subtask "sub" of top-level task "top" is "top.sub"
        - The full name of subtask "sub2" of subtask "sub" of top-level task "top" is "top.sub.sub2".
        """
        return self._fullName

    def getName(self):
        """!Return the name of the task

        See getFullName to get a hierarchical name including parent task names
        """
        return self._name

    def getTaskDict(self):
        """!Return a dictionary of all tasks as a shallow copy.

        @return taskDict: a dict containing full task name: task object
            for the top-level task and all subtasks, sub-subtasks, etc.
        """
        return self._taskDict.copy()

    def makeSubtask(self, name, **keyArgs):
        """!Create a subtask as a new instance self.\<name>

        The subtask must be defined by self.config.\<name>, an instance of pex_config ConfigurableField
        or RegistryField.

        @param name         brief name of subtask
        @param **keyArgs    extra keyword arguments used to construct the task.
            The following arguments are automatically provided and cannot be overridden:
            "config" and "parentTask".
        """
        taskField = getattr(self.config, name, None)
        if taskField is None:
            raise KeyError("%s's config does not have field %r" % (self.getFullName(), name))
        subtask = taskField.apply(name=name, parentTask=self, **keyArgs)
        setattr(self, name, subtask)

    @contextlib.contextmanager
    def timer(self, name, logLevel=Log.DEBUG):
        """!Context manager to log performance data for an arbitrary block of code

        @param[in] name         name of code being timed;
            data will be logged using item name: \<name>Start\<item> and \<name>End\<item>
        @param[in] logLevel     one of the lsst.log.Log level constants

        Example of use:
        \code
        with self.timer("someCodeToTime"):
            ...code to time...
        \endcode

        See timer.logInfo for the information logged
        """
        logInfo(obj=self, prefix=name + "Start", logLevel=logLevel)
        try:
            yield
        finally:
            logInfo(obj=self, prefix=name + "End", logLevel=logLevel)

    @classmethod
    def makeField(cls, doc):
        """!Make an lsst.pex.config.ConfigurableField for this task

        Provides a convenient way to specify this task is a subtask of another task.
        Here is an example of use:
        \code
        class OtherTaskConfig(lsst.pex.config.Config)
            aSubtask = ATaskClass.makeField("a brief description of what this task does")
        \endcode

        @param[in] cls      this class
        @param[in] doc      help text for the field
        @return a lsst.pex.config.ConfigurableField for this task
        """
        return ConfigurableField(doc=doc, target=cls)

    def _computeFullName(self, name):
        """!Compute the full name of a subtask or metadata item, given its brief name

        For example: if the full name of this task is "top.sub.sub2"
        then _computeFullName("subname") returns "top.sub.sub2.subname".

        @param[in] name     brief name of subtask or metadata item
        @return the full name: the "name" argument prefixed by the full task name and a period.
        """
        return "%s.%s" % (self._fullName, name)

    def __reduce__(self):
        """Pickler"""
        return self.__class__, (self.config, self._name, self._parentTask, None)


"""This is a cog for a discord.py bot.
It will add some management commands to a bot.

Commands:
    load            load an extension / cog
    unload          unload an extension / cog
    reload          reload an extension / cog
    cogs            show currently active extensions / cogs
    error           print the traceback of the last unhandled error to chat
"""
import json
import traceback
import typing
import subprocess
import re
from io import BytesIO
from datetime import datetime, timezone
from os import path, listdir
from discord import Embed, File
from discord.ext import commands

class Management(commands.Cog, name='Management'):
    def __init__(self, client):
        self.client = client
        self.reload_config()
        self.cog_re = re.compile(r'\s*src\/cogs\/(.+)\.py\s*\|\s*\d+\s*[+-]+')

    async def cog_check(self, ctx):
        return self.client.user_is_admin(ctx.author)

    @commands.Cog.listener()
    async def on_ready(self):
        loaded = self.client.extensions
        unloaded = [x for x in self.crawl_cogs() if x not in loaded and 'extra.' not in x]
        activity = self.client.error_activity if unloaded else self.client.default_activity
        await self.client.change_presence(activity=activity)

    # ----------------------------------------------
    # Error handler
    # ----------------------------------------------
    @commands.Cog.listener()
    async def on_command_error(self, ctx, error):
        if isinstance(error, commands.CommandNotFound):
            return

        if isinstance(error, commands.CommandOnCooldown):
            await ctx.send(error)
            return

        if isinstance(error, commands.MissingRequiredArgument):
            par = str(error.param)
            missing = par.split(": ")[0]
            if ':' in par:
                missing_type = ' (' + str(par).split(": ")[1] + ')'
            else:
                missing_type = ''
            await ctx.send(
                f'Missing parameter: `{missing}{missing_type}`'
            )
            return

        if isinstance(error, commands.CheckFailure):
            await ctx.send('Sorry, you are not allowed to run this command.')
            return

        if isinstance(error, commands.BadArgument):
            # It's in an embed to prevent mentions from working
            embed = Embed(
                title='Error',
                description=str(error),
                color=0x2ECC71
            )
            await ctx.send(embed=embed)
            return

        if isinstance(error, commands.UnexpectedQuoteError):
            await ctx.send('`Unexpected quote encountered`')
            return

        # In case of an unhandled error -> Save the error so it can be accessed later
        await ctx.send(self.client.error_string)
        await self.client.log_error(error, ctx)

        print(f'Ignoring exception in command {ctx.command}:', flush=True)
        traceback.print_exception(
            type(error), error, error.__traceback__
        )
        print('-------------------------------------------------------------', flush=True)

    def reload_config(self):
        with open("../state/config.json") as conffile:
            self.client.config = json.load(conffile)

    def crawl_cogs(self, directory='cogs'):
        cogs = []
        for element in listdir(directory):
            if element in ('samples', 'utils'):
                continue
            abs_el = path.join(directory, element)
            if path.isdir(abs_el):
                cogs += self.crawl_cogs(abs_el)
            else:
                filename, ext = path.splitext(element)
                if ext == '.py':
                    dot_dir = directory.replace('\\', '.')
                    dot_dir = dot_dir.replace('/', '.')
                    cogs.append(f'{dot_dir}.' + filename)
        return cogs

    # ----------------------------------------------
    # Function to load extensions
    # ----------------------------------------------
    @commands.command(
        name='load',
        brief='Load bot extension',
        description='Load bot extension',
        hidden=True,
    )
    async def load_extension(self, ctx, extension_name):
        for cog_name in self.crawl_cogs():
            if extension_name in cog_name:
                target_extension = cog_name
                break
        try:
            self.client.load_extension(target_extension)
        except Exception as e:
            await self.client.log_error(e, ctx)
            await ctx.send(f'```py\n{type(e).__name__}: {str(e)}\n```')
            return
        await ctx.send(f'```css\nExtension [{target_extension}] loaded.```')

    # ----------------------------------------------
    # Function to unload extensions
    # ----------------------------------------------
    @commands.command(
        name='unload',
        brief='Unload bot extension',
        description='Unload bot extension',
        hidden=True,
    )
    async def unload_extension(self, ctx, extension_name):
        for cog_name in self.client.extensions:
            if extension_name in cog_name:
                target_extension = cog_name
                break
        if target_extension.lower() in 'cogs.management':
            await ctx.send(
                f"```diff\n- {target_extension} can't be unloaded" +
                f"\n+ try reload instead```"
            )
            return
        if self.client.extensions.get(target_extension) is None:
            return
        self.client.unload_extension(target_extension)
        await ctx.send(f'```css\nExtension [{target_extension}] unloaded.```')

    # ----------------------------------------------
    # Function to reload extensions
    # ----------------------------------------------
    @commands.command(
        name='reload',
        brief='Reload bot extension',
        description='Reload bot extension',
        hidden=True,
        aliases=['re']
    )
    async def reload_extension(self, ctx, extension_name):
        target_extensions = []
        if extension_name == 'all':
            target_extensions = [__name__] + \
                [x for x in self.client.extensions if not x == __name__]
        else:
            for cog_name in self.client.extensions:
                if extension_name in cog_name:
                    target_extensions = [cog_name]
                    break
        if not target_extensions:
            return
        result = []
        for ext in target_extensions:
            try:
                self.client.reload_extension(ext)
                result.append(f'Extension [{ext}] reloaded.')
            except Exception as e:
                await self.client.log_error(e, ctx)
                result.append(f'#ERROR loading [{ext}]')
                continue
        result = '\n'.join(result)
        await ctx.send(f'```css\n{result}```')

    # ----------------------------------------------
    # Function to get bot extensions
    # ----------------------------------------------
    @commands.command(
        name='cogs',
        brief='Get loaded cogs',
        description='Get loaded cogs',
        aliases=['extensions'],
        hidden=True,
    )
    async def print_cogs(self, ctx):
        loaded = self.client.extensions
        unloaded = [x for x in self.crawl_cogs() if x not in loaded]
        response = ['\n[Loaded extensions]'] + ['\n  ' + x for x in loaded]
        response += ['\n[Unloaded extensions]'] + \
            ['\n  ' + x for x in unloaded]
        await ctx.send(f'```css{"".join(response)}```')
        return True

    @commands.group(
        invoke_without_command=True,
        name='error',
        hidden=True,
        aliases=['errors']
    )
    async def error(self, ctx, n: typing.Optional[int] = None):
        """Show a concise list of stored errors"""

        if n is not None:
            await self.print_traceback(ctx, n)
            return

        NUM_ERRORS_PER_PAGE = 15

        error_log = self.client.last_errors

        if not error_log:
            await ctx.send('Error log is empty')
            return

        response = [f'```css\nNumber of stored errors: {len(error_log)}']
        for i, exc_tuple in enumerate(error_log):
            exc, date, error_source, *_ = exc_tuple
            call_info = (
                f'CMD: {error_source.invoked_with}'
                if isinstance(error_source, commands.Context) else 'outside command'
            )
            response.append(
                f'{i}: ['
                + date.isoformat().split('.')[0]
                + '] - ['
                + call_info
                + f']\nException: {exc}'
            )
            if i % NUM_ERRORS_PER_PAGE == NUM_ERRORS_PER_PAGE-1:
                response.append('```')
                await ctx.send('\n'.join(response))
                response = [f'```css']
        if len(response) > 1:
            response.append('```')
            await ctx.send('\n'.join(response))

    @error.command(
        name='clear',
        aliases=['delete'],
    )
    async def error_clear(self, ctx, n: int = None):
        """Clear error with index [n]"""
        if n is None:
            self.client.last_errors = []
            await ctx.send('Error log cleared')
        else:
            self.client.last_errors.pop(n)
            await ctx.send(f'Deleted error #{n}')
        await self.client.change_presence(
            activity=self.client.default_activity
        )

    @error.command(
        name='traceback',
        aliases=['tb'],
    )
    async def error_traceback(self, ctx, n: int = None):
        """Print the traceback of error [n] from the error log"""
        await self.print_traceback(ctx, n)

    async def print_traceback(self, ctx, n):
        error_log = self.client.last_errors

        if not error_log:
            await ctx.send('Error log is empty')
            return

        if n is None:
            await ctx.send('Please specify an error index')
            await self.client.get_command('error').invoke(ctx)
            return

        if n >= len(error_log) or n < 0:
            await ctx.send('Error index does not exist')
            return

        exc, date, error_source, orig_content = error_log[n]
        delta = (datetime.utcnow() - date).total_seconds()
        hours = int(delta // 3600)
        seconds = int(delta - (hours * 3600))
        delta_str = f'{hours} hours and {seconds} seconds ago'
        tb = ''.join(
            traceback.format_exception(type(exc), exc, exc.__traceback__)
        )
        response = [f'`Error occured {delta_str}`']
        if error_source is not None:
            guild = error_source.guild
            channel = error_source.channel
            response.append(
                f'`Server:{guild.name} | Channel: {channel.name}`' if guild else '`In DMChannel`'
            )
            response.append(
                f'`User: {error_source.author.name}#{error_source.author.discriminator}`'
            )
            if isinstance(error_source, commands.Context):
                response.append(f'`Command: {error_source.invoked_with}`')
                response.append(error_source.message.jump_url)
            else:
                response.append(f'`Command: No Command`')
                response.append(error_source.jump_url)
        response.append(f'```python\n')
        num_chars = sum(len(line) for line in response)
        for line in tb.split('\n'):
            num_chars += len(line)
            response.append(line)
            if num_chars > 1900:
                response.append('```')
                await ctx.send('\n'.join(response))
                response = ['```python\n']
                num_chars = 0
        response.append('```')
        await ctx.send('\n'.join(response))
        if error_source is not None:
            e = Embed(title='Full command that caused the error:',
                      description=orig_content)
            e.set_footer(text=error_source.author.display_name,
                         icon_url=error_source.author.avatar_url)
            await ctx.send(embed=e)

    @commands.command(
        name='servers',
        hidden=True,
    )
    async def show_servers(self, ctx):
        to_send = '\n'.join(str(guild) for guild in self.client.guilds)
        await ctx.send(
            f'**I am active in {len(self.client.guilds)} Servers**',
            file=File(
                fp=BytesIO(to_send.encode()),
                filename=f'servers_{datetime.now(tz=timezone.utc).isoformat()}.txt'
            )
        )

    # ----------------------------------------------
    # Command to pull the latest changes from github
    # ----------------------------------------------
    @commands.group(
        name='git',
        hidden=True,
    )
    async def git(self, ctx):
        """Commands to run git commands on the local repo"""
        pass

    @git.command(
        name='pull',
    )
    async def pull(self, ctx, noreload: typing.Optional[str] = None):
        """Pull the latest changes from github"""
        await ctx.trigger_typing()
        try:
            output = subprocess.check_output(
                ['git', 'pull']).decode()
            await ctx.send('```git\n' + output + '\n```')
        except Exception as e:
            return await ctx.send(str(e))

        if noreload is not None:
            return

        _cogs = [f'cogs.{i}' for i in self.cog_re.findall(output)]
        active_cogs = [i for i in _cogs if i in self.client.extensions]
        if active_cogs:
            for cog_name in active_cogs:
                await ctx.invoke(self.client.get_command('reload'), cog_name)

    # ----------------------------------------------
    # Command to reset the repo to a previous commit
    # ----------------------------------------------
    @git.command(
        name='reset',
    )
    async def reset(self, ctx, n: int):
        """Reset repo to HEAD~[n]"""
        if not n > 0:
            raise commands.BadArgument('Please specify n>0')
        await ctx.trigger_typing()
        try:
            output = subprocess.check_output(
                ['git', 'reset', '--hard', f'HEAD~{n}']).decode()
            await ctx.send('```git\n' + output + '\n```')
        except Exception as e:
            await ctx.send(str(e))

    # ----------------------------------------------
    # Command to stop the bot
    # ----------------------------------------------
    @commands.command(
        name='shutdown',
        hidden=True
    )
    async def shutdown(self, ctx):
        """Stop the bot"""
        await self.client.close()

def setup(client):
    client.add_cog(Management(client))