import gzip
import os
import logging
from functools import partial

import numpy as np
import numpy.ma as ma
from pyg2p import Loggable

from . import grib_interpolation_lib
from .latlong import LatLong
from .scipy_interpolation_lib import ScipyInterpolation, DEBUG_BILINEAR_INTERPOLATION, DEBUG_ADW_INTERPOLATION, \
                                        DEBUG_MIN_LAT, DEBUG_MIN_LON, DEBUG_MAX_LAT, DEBUG_MAX_LON

from ...exceptions import ApplicationException, NO_INTERTABLE_CREATED
import pyg2p.util.files
import pyg2p.util.numeric

class Interpolator(Loggable):
    _LOADED_INTERTABLES = {}
    _prefix = 'I'
    scipy_modes_nnear = {'nearest': 1, 'invdist': 4, 'adw': 4, 'cdd': 4, 'bilinear': 4, 'triangulation': 3, 'bilinear_delaunay': 4}
    suffixes = {'grib_nearest': 'grib_nearest', 'grib_invdist': 'grib_invdist',
                'nearest': 'scipy_nearest', 'invdist': 'scipy_invdist', 'adw': 'scipy_adw', 'cdd': 'scipy_cdd',
                'bilinear': 'scipy_bilinear', 'triangulation': 'scipy_triangulation', 'bilinear_delaunay': 'scipy_bilinear_delaunay'}
    _format_intertable = 'tbl{prognum}_{source_file}_{target_size}_{suffix}.npy.gz'.format

    def __init__(self, exec_ctx, mv_input):
        super().__init__()
        self._mv_grib = mv_input
        self.interpolate_with_grib = exec_ctx.is_with_grib_interpolation
        self._mode = exec_ctx.get('interpolation.mode')
        self._adw_broadcasting = exec_ctx.get('interpolation.adw_broadcasting')
        self._source_filename = pyg2p.util.files.filename(exec_ctx.get('input.file'))
        self._suffix = self.suffixes[self._mode]
        self._intertable_dirs = exec_ctx.get('interpolation.dirs')
        self._rotated_target_grid = exec_ctx.get('interpolation.rotated_target')
        self._target_coords = LatLong(exec_ctx.get('interpolation.latMap'), exec_ctx.get('interpolation.lonMap'))
        self.mv_out = self._target_coords.mv
        self.parallel = exec_ctx.get('interpolation.parallel')
        self.format_intertablename = partial(self._format_intertable,
                                             source_file=pyg2p.util.files.normalize_filename(self._source_filename),
                                             target_size=self._target_coords.lats.size,
                                             suffix=self._suffix)
        # values used for interpolation table computation
        self._aux_val = None
        self._aux_gid = None
        self._aux_2nd_res_gid = None
        self._aux_2nd_res_val = None

        self.create_if_missing = exec_ctx.get('interpolation.create')
        self.grib_methods = {'grib_nearest': self.grib_nearest, 'grib_invdist': self.grib_inverse_distance}
        self.intertables_config = exec_ctx.configuration.intertables  # IntertablesConfiguration object

    def interpolate(self, lats, longs, v, grid_id, geodetic_info, gid=-1, is_second_res=False):
        if self.interpolate_with_grib:
            out_v = self.interpolate_grib(v, gid, grid_id, is_second_res=is_second_res)
        else:
            # interpolating gridded data with scipy kdtree
            out_v = self.interpolate_scipy(lats, longs, v, grid_id, geodetic_info)
        return out_v

    def _intertable_filename(self, grid_id):
        intertable_id = '{}{}_{}{}'.format(self._prefix, grid_id.replace('$', '_'), self._target_coords.identifier, self._suffix)
        if intertable_id not in self.intertables_config.vars:
            # return a new intertable filename to create
            if not self.create_if_missing:
                raise ApplicationException.get_exc(NO_INTERTABLE_CREATED, details=f'Using {intertable_id}')
            self.intertables_config.check_write()
            filename = self.format_intertablename(prognum='')
            tbl_fullpath = os.path.normpath(os.path.join(self._intertable_dirs['user'], filename))
            i = 1
            while pyg2p.util.files.exists(tbl_fullpath):
                filename = self.format_intertablename(prognum='_{}'.format(i))
                tbl_fullpath = os.path.normpath(os.path.join(self._intertable_dirs['user'], filename))
                i += 1
            return intertable_id, tbl_fullpath

        filename = self.intertables_config.vars[intertable_id]['filename']

        # tbl_fullpath is taken from user path if defined, otherwise comes from global configuration
        tbl_fullpath = None if not self._intertable_dirs.get('user') else os.path.normpath(os.path.join(self._intertable_dirs['user'], filename))
        if self._logger.isEnabledFor(logging.DEBUG):
            self._logger.debug(f'Using {tbl_fullpath} for id {intertable_id}')
        if not tbl_fullpath or not (pyg2p.util.files.exists(tbl_fullpath) or pyg2p.util.files.exists(tbl_fullpath + '.gz')):
            tbl_fullpath = os.path.normpath(os.path.join(self._intertable_dirs['global'], filename))
            if not (pyg2p.util.files.exists(tbl_fullpath) or pyg2p.util.files.exists(tbl_fullpath + '.gz')):
                # will create a new intertable but with same filename/id
                # as an existing configuration was already found but file is missing for some reasons
                if not self.create_if_missing:
                    raise ApplicationException.get_exc(NO_INTERTABLE_CREATED, details=f'Tried to create {tbl_fullpath}')
                self.intertables_config.check_write()
                tbl_fullpath = os.path.normpath(os.path.join(self._intertable_dirs['user'], filename))
                tbl_fullpath = tbl_fullpath if tbl_fullpath.endswith('.gz') else tbl_fullpath + '.gz'
                self._logger.warning(f'An entry in configuration was found for {filename} but intertable does not exist.')
        return intertable_id, tbl_fullpath

    def _read_intertable(self, tbl_fullpath):

        if tbl_fullpath not in self._LOADED_INTERTABLES:
            f = tbl_fullpath
            if tbl_fullpath.endswith('.gz'):
                f = gzip.GzipFile(tbl_fullpath, 'r')
                intertable = np.load(f)
                f.close()
            else:
                try:
                    intertable = np.load(tbl_fullpath)
                except FileNotFoundError:
                    f = tbl_fullpath + '.gz'
                    if not pyg2p.util.files.exists(f):
                        raise ApplicationException.get_exc(NO_INTERTABLE_CREATED, details=f'Tried to read both {tbl_fullpath} and {f} but none was found')
                    f = gzip.GzipFile(f, 'r')
                    intertable = np.load(f)
                    f.close()
            self._LOADED_INTERTABLES[tbl_fullpath] = intertable
            self._log(f'Using interpolation table: {tbl_fullpath}', 'INFO')
        else:
            intertable = self._LOADED_INTERTABLES[tbl_fullpath]

        if self._mode == 'grib_nearest':
            # grib nearest neighbour table
            return intertable[0], intertable[1], intertable[2]
        elif self._mode == 'grib_invdist':
            # grib inverse distance table is a "recorded numpy array" with keys 'indexes' and 'coeffs'
            indexes = intertable['indexes']  # first two arrays of this group are target xs and ys indexes
            coeffs = intertable['coeffs']
            return indexes[0], indexes[1], indexes[2], indexes[3], indexes[4], indexes[5], coeffs[0], coeffs[1], coeffs[2], coeffs[3]
        else:
            # self._mode in ('invdist', 'adw', 'cdd', 'nearest', 'bilinear', 'triangulation', 'bilinear_delaunay'):
            # return indexes and weighted distances (only used with nnear > 1)
            indexes = intertable['indexes']
            coeffs = intertable['coeffs']
            return indexes, coeffs

    # ####### SCIPY INTERPOLATION ###################################
    def _interpolate_scipy_append_mv(self, v, weights, indexes, nnear):
        # append the MV efas value at the end because of how KDTree algo works
        # It gives (last_index + 1) from original values when value can't be computed.
        # These "last_index + 1" indexes are stored in intertable so we artificially add a missing value
        # v[last_index + 1] = mv
        v = np.append(v, self.mv_output)
        orig_mask = False if not isinstance(v, ma.core.MaskedArray) else v.mask
        if nnear == 1:
            if isinstance(orig_mask, np.ndarray):
                result = ma.masked_where(orig_mask[indexes], v[indexes], copy=False)
            else:
                result = v[indexes]
        else:
            result = np.einsum('ij,ij->i', weights, v[indexes])
            if isinstance(orig_mask, np.ndarray):
                # there are masks. logic sum of masks from all values used
                mask = None
                for i in range(0, indexes.shape[1]):
                    mask = orig_mask[indexes.T[i]] if mask is None else mask | orig_mask[indexes.T[i]]
                result = ma.masked_where(mask, result, copy=False)
        return result

    def interpolate_scipy(self, latgrib, longrib, v, grid_id, grid_details=None):
        lonefas = self._target_coords.lons
        latefas = self._target_coords.lats
        if DEBUG_BILINEAR_INTERPOLATION:
            # target_lats=target_lats[1800-(9*20):1800-(-16*20), 3600+(-15*20):3600+(16*20)]
            # target_lons=target_lons[1800-(9*20):1800-(-16*20), 3600+(-15*20):3600+(16*20)]
            if self._target_coords.lats.shape==(3600,7200):
                # Global_3arcmin DEBUG
                latefas=self._target_coords.lats[1800-int(DEBUG_MAX_LAT*20):1800-int(DEBUG_MIN_LAT*20), 3600+int(DEBUG_MIN_LON*20):3600+int(DEBUG_MAX_LON*20)]
                lonefas=self._target_coords.lons[1800-int(DEBUG_MAX_LAT*20):1800-int(DEBUG_MIN_LAT*20), 3600+int(DEBUG_MIN_LON*20):3600+int(DEBUG_MAX_LON*20)]
            else:
                # European_1arcmin DEBUG
                selection_lats = np.logical_and(self._target_coords.lats[:,0]>=DEBUG_MIN_LAT,self._target_coords.lats[:,0]<=DEBUG_MAX_LAT)
                selection_lons = np.logical_and(self._target_coords.lons[0,:]>=DEBUG_MIN_LON,self._target_coords.lons[0,:]<=DEBUG_MAX_LON)
                latefas=self._target_coords.lats[selection_lats,:][:,selection_lons]
                lonefas=self._target_coords.lons[selection_lats,:][:,selection_lons]

            intertable_id, intertable_name = 'DEBUG','DEBUG.npy'
        else:
            intertable_id, intertable_name = self._intertable_filename(grid_id)

        if DEBUG_ADW_INTERPOLATION:
            # to debug create a limited controlled set of input values
            #
            # np.random.seed(0)
            # latgrib = np.random.uniform(low=3, high=11, size=10)
            # longrib = np.random.uniform(low=46, high=50, size=10)
            # v = np.random.uniform(low=100, high=200, size=10)
            # latgrib = np.array([ 7.39050803,  8.72151493,  7.82210701,  7.35906546,  6.38923839,
            #     8.1671529,  6.50069769, 10.13418401, 10.70930208,  6.06753215])
            # longrib = np.array([49.16690015, 48.11557968, 48.27217824, 49.70238655, 46.28414423,
            #     46.3485172, 46.08087359, 49.33047938, 49.112627, 49.48004859])
            # v = np.array([197.86183422, 179.91585642, 146.14793623, 178.05291763, 111.82744259,
            #     163.99210213, 114.33532874, 194.4668917, 152.18483218, 141.466194  ])
            # latgrib = np.array([ 7.39050803,  8.72151493,  7.82210701,  7.35906546])
            # longrib = np.array([49.16690015, 48.11557968, 48.27217824, 49.70238655])
            # v = np.array([100, 133, 166, 200  ])
            latgrib = np.array([ 8,  8,  8,  8])
            longrib = np.array([45, 48.5, 49, 50])
            v = np.array([200, 100, 100, 100  ])
            intertable_id, intertable_name = 'DEBUG_ADW','DEBUG_ADW.npy'

        nnear = self.scipy_modes_nnear[self._mode]

        if (not DEBUG_ADW_INTERPOLATION) and \
            (pyg2p.util.files.exists(intertable_name) or pyg2p.util.files.exists(intertable_name + '.gz')):
                indexes, weights = self._read_intertable(intertable_name)
                result = self._interpolate_scipy_append_mv(v, weights, indexes, nnear)

        elif self.create_if_missing:
            self.intertables_config.check_write()
            if latgrib is None:
                self._log('Trying to interpolate without grib lat/lons. Probably a malformed grib!', 'ERROR')
                raise ApplicationException.get_exc(5000)

            self._log('\nInterpolating table not found\n Id: {}\nWill create file: {}'.format(intertable_id, intertable_name), 'WARN')
            scipy_interpolation = ScipyInterpolation(longrib, latgrib, grid_details, v.ravel(), nnear, self.mv_out,
                                          self._mv_grib, target_is_rotated=self._rotated_target_grid,
                                          parallel=self.parallel, mode=self._mode, use_broadcasting=self._adw_broadcasting)
            _, weights, indexes = scipy_interpolation.interpolate(lonefas, latefas)
            result = self._interpolate_scipy_append_mv(v, weights, indexes, nnear)

            # saving interpolation lookup table
            intertable = np.rec.fromarrays((indexes, weights), names=('indexes', 'coeffs'))
            if intertable_name.endswith('.gz'):
                f = gzip.GzipFile(intertable_name, 'w')
                np.save(f, intertable)
                f.close()
            else:
                np.save(intertable_name, intertable)
            self.update_intertable_conf(intertable, intertable_id, intertable_name, v.shape)
        else:
            raise ApplicationException.get_exc(NO_INTERTABLE_CREATED, details=intertable_name)

        # reshape to target (e.g. efas, glofas...)
        grid_data = result.reshape(lonefas.shape)
        return grid_data

    # #### GRIB API INTERPOLATION ####################
    def interpolate_grib(self, v, gid, grid_id, is_second_res=False):
        return self.grib_methods[self._mode](v, gid, grid_id, is_second_res=is_second_res)

    def grib_nearest(self, v, gid, grid_id, is_second_res=False, intertable_id=None, intertable_name=None):
        if not intertable_name:
            intertable_id, intertable_name = self._intertable_filename(grid_id)
        result = np.empty(self._target_coords.lons.shape)
        result.fill(self.mv_out)
        if gid == -1 and not pyg2p.util.files.exists(intertable_name):
            # calling recursive grib_nearest
            # aux_gid and aux_values are only used to create the interlookuptable
            if is_second_res:
                self.grib_nearest(self._aux_2nd_res_val, self._aux_2nd_res_gid, grid_id,
                                  intertable_name=intertable_name, intertable_id=intertable_id,
                                  is_second_res=is_second_res)
            else:
                self.grib_nearest(self._aux_val, self._aux_gid, grid_id,
                                  intertable_name=intertable_name, intertable_id=intertable_id)

        if pyg2p.util.files.exists(intertable_name):
            # interpolation using intertables
            xs, ys, idxs = self._read_intertable(intertable_name)

        elif self.create_if_missing:
            if gid == -1:
                raise ApplicationException.get_exc(6000, details='GRIB message reference was not found.')
            self.intertables_config.check_write()
            self._log('\nInterpolating table not found\n Id: {}\nWill create file: {}'.format(intertable_id, intertable_name), 'WARN')
            xs, ys, idxs = getattr(grib_interpolation_lib, 'grib_nearest{}'.format('' if not self.parallel else '_parallel'))(gid, self._target_coords.lats, self._target_coords.lons, self._target_coords.mv)
            intertable = np.asarray([xs, ys, idxs])
            if intertable_name.endswith('.gz'):
                f = gzip.GzipFile(intertable_name, 'w')
                np.save(f, intertable)
                f.close()
            else:
                np.save(intertable_name, intertable)
            self.update_intertable_conf(intertable, intertable_id, intertable_name, v.shape)
        else:
            if intertable_id not in self.intertables_config.vars:
                d = {'filename': pyg2p.util.files.filename(intertable_name),
                     'method': self._mode,
                     'source_shape': v.shape,
                     'target_shape': self._target_coords.lons.shape}
                self._log('If you already have an intertable file, add this configuration to intertables.json and change filename. {} {}'.format(intertable_id, d), 'INFO')
            raise ApplicationException.get_exc(NO_INTERTABLE_CREATED, details=intertable_name)
        result[xs, ys] = pyg2p.util.numeric.result_masked(v[idxs], self.mv_output)
        return result

    def grib_inverse_distance(self, v, gid, grid_id, is_second_res=False, intertable_id=None, intertable_name=None):
        if not intertable_name:
            intertable_id, intertable_name = self._intertable_filename(grid_id)

        result = np.empty(self._target_coords.lons.shape)
        result.fill(self.mv_out)

        # check if gid is due to the recursive call
        if gid == -1 and not pyg2p.util.files.exists(intertable_name):
            # aux_gid and aux_values are only used to create the interlookuptable
            # since manipulated values messages don't have gid reference to grib file any longer
            aux_gid = self._aux_gid
            aux_val = self._aux_val
            if is_second_res:
                aux_gid = self._aux_2nd_res_gid
                aux_val = self._aux_2nd_res_val
            self.grib_inverse_distance(aux_val, aux_gid, grid_id, intertable_name=intertable_name,
                                       intertable_id=intertable_id, is_second_res=is_second_res)

        if pyg2p.util.files.exists(intertable_name):
            # interpolation using intertables
            xs, ys, idxs1, idxs2, idxs3, idxs4, coeffs1, coeffs2, coeffs3, coeffs4 = self._read_intertable(intertable_name)
        elif self.create_if_missing:
            # assert...
            if gid == -1:
                raise ApplicationException.get_exc(6000)

            self._log('\nInterpolating table not found. Will create file: {}'.format(intertable_name), 'WARN')
            lonefas = self._target_coords.lons
            latefas = self._target_coords.lats
            mv = self._target_coords.mv
            intrp_result = getattr(grib_interpolation_lib, 'grib_invdist{}'.format('' if not self.parallel else '_parallel'))(gid, latefas, lonefas, mv)
            xs, ys, idxs1, idxs2, idxs3, idxs4, coeffs1, coeffs2, coeffs3, coeffs4 = intrp_result
            indexes = np.asarray([xs, ys, idxs1, idxs2, idxs3, idxs4])
            coeffs = np.asarray([coeffs1, coeffs2, coeffs3, coeffs4, np.zeros(coeffs1.shape), np.zeros(coeffs1.shape)])
            intertable = np.rec.fromarrays((indexes, coeffs), names=('indexes', 'coeffs'))
            # saving interpolation lookup table
            if intertable_name.endswith('.gz'):
                f = gzip.GzipFile(intertable_name, 'w')
                np.save(f, intertable)
                f.close()
            else:
                np.save(intertable_name, intertable)
            self.update_intertable_conf(intertable, intertable_id, intertable_name, v.shape)

        else:
            if intertable_id not in self.intertables_config.vars:
                d = {'filename': pyg2p.util.files.filename(intertable_name),
                     'method': self._mode,
                     'source_shape': v.shape,
                     'target_shape': self._target_coords.lons.shape}
                self._log('If you already have an intertable file, add this configuration to intertables.json and change filename. {} {}'.format(intertable_id, d), 'INFO')
            raise ApplicationException.get_exc(NO_INTERTABLE_CREATED, details=intertable_name)

        res = v[idxs1] * coeffs1 + v[idxs2] * coeffs2 + v[idxs3] * coeffs3 + v[idxs4] * coeffs4
        result[xs, ys] = pyg2p.util.numeric.result_masked(res, self.mv_output)
        return result

    def update_intertable_conf(self, intertable, intertable_id, intertable_name, source_shape):
        self._LOADED_INTERTABLES[intertable_name] = intertable
        new_intertable_conf_item = {'filename': pyg2p.util.files.filename(intertable_name),
                                    'method': self._mode,
                                    'source_shape': source_shape,
                                    'target_shape': self._target_coords.lons.shape}
        # update global configuration
        self.intertables_config.vars[intertable_id] = new_intertable_conf_item

        # Dumps only user configuration to ~/.pyg2p/intertables.json
        self.intertables_config.user_vars[intertable_id] = new_intertable_conf_item
        self.intertables_config.dump()

    # set aux gids for grib interlookup creation
    def aux_for_intertable_generation(self, aux_g, aux_v, aux_g2, aux_v2):
        self._aux_gid = aux_g
        self._aux_val = aux_v
        self._aux_2nd_res_gid = aux_g2
        self._aux_2nd_res_val = aux_v2

    @property
    def mv_output(self):
        return self.mv_out


# python3
import sys

def compute_min_refills(distance, tank, stops):
    """
    Find the minimum number of refuelling stops along a distance AB where the
    vehicle has a certain tank capacity and fuel stops are arranged randomly at
    some distance from A.
    """
    stops.insert(0, 0)
    stops.append(distance)
    num_refills, cur_refill = 0, 0
    n = len(stops)-1
    while cur_refill < n:  # if it is n, it has reached destination.
        last_refill = cur_refill
        while cur_refill < n and stops[cur_refill+1] - stops[last_refill] <= tank:
            cur_refill += 1
        if cur_refill == last_refill:
            return -1
        if cur_refill < n:
            num_refills += 1
    return num_refills

if __name__ == '__main__':
    # d = int(input())
    # m = int(input())
    # n = int(input())
    # stops = list(map(int, input().split()))
    d, m, n, *stops = map(int, sys.stdin.read().split())
    print(compute_min_refills(d, m, stops))


from setuptools import setup, find_packages
from os import path
from io import open

here = path.abspath(path.dirname(__file__))

with open(path.join(here, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()

setup(
	name='Zeek-Indenter',
	version='0.1.0',
	description='Python package to indent Zeek scripts.',
	long_description=long_description,
	url='http://pypi.python.org/pypi/ZeekIndenter/',
	author='Mohan Dhawan',
	author_email='mohan@corelight.com',
	packages=find_packages(),
	python_requires='>=3.6',
	install_requires=['lark-parser'],
	package_data={
		'indenter': ['*.txt', 'utils/zeek.lark', 'utils/zeek-lalr.lark', 'utils/zeek-earley.lark']
	},
	classifiers=[
        'Programming Language :: Python :: 3.6',
    ],
)


import uproot#3 as uproot
import numpy as np
import pandas as pd
from tqdm import tqdm

import torch

import dgl
from dgl import backend as F

from torch.utils.data import Dataset, DataLoader, Sampler

#from modules.fixed_radius_graph import FixedRadiusNNGraph
#from dgl.geometry.pytorch import FarthestPointSampler

layer_name = {'PreSamplerB' : [0, 1540.00],
              'PreSamplerE' : [1, 1540.00],
              'EMB1' : [0, 1532.18],
              'EMB2' : [0, 1723.89],
              'EMB3' : [0, 1923.02],
              'EME1' : [1, 3790.03],
              'EME2' : [1, 3983.68],
              'EME3' : [1, 4195.84],
              'HEC0' : [1, 4461.25],
              'HEC1' : [1, 4869.50],
              'HEC2' : [1, 5424.50],
              'HEC3' : [1, 5905.00],
              'TileBar0' : [0, 2450.00],
              'TileBar1' : [0, 2995.00],
              'TileBar2' : [0, 3630.00],
              'TileGap1' : [0, 3215.00],
              'TileGap2' : [0, 3630.00],
              'TileGap3' : [0, 2246.50],
              'TileExt0' : [0, 2450.00],
              'TileExt1' : [0, 2870.00],
              'TileExt2' : [0, 3480.00]
             }

cluster_var_dict_musig = {

    'cluster_e_' : {'mean': 217.2536030809038, 'std': 335.4177626448296} ,
    'cluster_EM_PROBABILITY'  :  {'mean': 0.13739075, 'std': 0.23810464} ,
    'cluster_HAD_WEIGHT'  :  {'mean': 1.0977454, 'std': 0.105446674} ,
    'cluster_OOC_WEIGHT'  :  {'mean': 1.3992951, 'std': 0.43550345} ,
    'cluster_DM_WEIGHT'  :  {'mean': 1.1528628, 'std': 0.2928971} ,
    'cluster_CENTER_MAG'  :  {'mean': 3703.2527, 'std': 1174.078} ,
    'cluster_FIRST_ENG_DENS'  :  {'mean': 1.7587054e-05, 'std': 8.9226814e-05} ,
    'cluster_CENTER_LAMBDA'  :  {'mean': 864.2519, 'std': 821.3119} ,
    'cluster_ISOLATION'  :  {'mean': 0.8162972, 'std': 0.2107719} ,
    'trackPt'  :  {'mean': 201.44667, 'std': 1793.1217} ,
    'trackP'  :  {'mean': 333.57788, 'std': 2367.859} ,
    'trackMass'  :  {'mean': 0.12962861, 'std': 0.4628284} ,
    'trackEta'  :  {'mean': 0.0128200175, 'std': 1.365982} ,
    'trackPhi'  :  {'mean': -0.0047495714, 'std': 1.8068546} ,
    'trackNumberOfPixelHits'  :  {'mean': 4.205281217365359, 'std': 0.9478835493717127} ,
    'trackNumberOfSCTHits'  :  {'mean': 8.432492913620766, 'std': 1.3268142597502794} ,
    'trackNumberOfPixelDeadSensors'  :  {'mean': 0.08175443831120394, 'std': 0.28097955502041233} ,
    'trackNumberOfSCTDeadSensors'  :  {'mean': 0.09279427122184096, 'std': 0.412992406261207} ,
    'trackNumberOfInnermostPixelLayerHits'  :  {'mean': 0.9870207369834403, 'std': 0.36292256189756517} ,
    'trackNumberOfNextToInnermostPixelLayerHits'  :  {'mean': 1.0522154259286887, 'std': 0.35834182262430175} ,
    'trackExpectInnermostPixelLayerHit'  :  {'mean': 0.9749365955542294, 'std': 0.15631772197469573} ,
    'trackExpectNextToInnermostPixelLayerHit'  :  {'mean': 0.9684469640459495, 'std': 0.17480687022005978} ,
    'trackNumberOfTRTHits'  :  {'mean': 23.086379233179173, 'std': 13.239640400661633} ,
    'trackNumberOfTRTOutliers'  :  {'mean': 1.3385051469491274, 'std': 6.073115255017552} ,
    'trackChiSquared'  :  {'mean': 35.072063, 'std': 17.583935} ,
    'trackNumberDOF'  :  {'mean': 34.92943458153066, 'std': 12.928489800018584} ,
    'trackD0'  :  {'mean': -0.011262955, 'std': 1.268558} ,
    'trackZ0'  :  {'mean': -0.49036446, 'std': 43.61} ,
    'truthPartE'  :  {'mean': 324.16019827205093, 'std': 465.8594184884767}
}

# --- K_NN graph dataclass ----------------#
class MLPionsDataset_KNN(Dataset):
    def __init__(self, filename, k_val, cluster_var, nstart, nstop, cluster_var_dict_musig=cluster_var_dict_musig ):

        self.k = k_val
        self.f = uproot.open(filename)
        self.cluster_var = cluster_var

        self.ev_tree =  self.f['EventTree;1']
        self.cell_geo_tree = self.f['CellGeo;1']

        self.nstart = nstart
        self.nstop = nstop

        if(self.nstop - self.nstart > self.ev_tree.num_entries) :
            self.nstop = self.nstart + self.ev_tree.num_entries

        self.n_events = self.nstop - self.nstart

        self.cluster_var_dict_musig = cluster_var_dict_musig

#         for ivar in self.cluster_var :
#             var = np.concatenate(self.ev_tree[ivar].array(library='np'))
#             self.cluster_var_dict_musig[ivar] =  {'mean' : var.mean(), 'std' : var.std()}

        self.cell_positions, self.id_to_position,\
        self.id_to_deta, self.id_to_dphi = self.get_all_cells()

        self.all_graphs = []

        for i in tqdm(range( self.nstart, self.nstop, 1 )):
            event_dict = self.get_single_event(i)
            #if(event_dict['truth_E'].item() >=0. ) :
            self.all_graphs.append(event_dict)

#         self.n_eff = len(self.all_graphs)

    def get_single_event(self,event_idx):

        # ------- building the cluster graph ---------- #

        cluster_cell_ID = self.ev_tree['cluster_cell_ID'].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]
        cluster_cell_E = self.ev_tree['cluster_cell_E'].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]
        cluster_E = self.ev_tree['cluster_E'].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]

        n_clusters = len(cluster_cell_ID)
        ev_flag = 1

        # -- empty dict to store all the node features --- #
        node_var_dict = { var : [] for var in self.cluster_var}

        nTrack = self.ev_tree['nTrack'].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]

        if(n_clusters == 0) :
            #print('Empty cluster event')
            ev_flag = -1
            return {'gr' : [dgl.rand_graph(2,1)], 'truth_E' : torch.tensor([-1.]), 'truth_eta' : torch.tensor([-99.])}#, ev_flag

        if(nTrack > 1) :
            #print('Empty cluster event')
            ev_flag = -1
            return {'gr' : [dgl.rand_graph(2,1)], 'truth_E' : torch.tensor([-1.]), 'truth_eta' : torch.tensor([-99.])}#, ev_flag
        # ----------- determining track_xyz ----------------- #
        track_layer_eta_phi =\
        {
          lname : np.array(
                    [
                     self.ev_tree['trackEta_'+lname].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0],
                     self.ev_tree['trackPhi_'+lname].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]
                    ]
            )#.reshape(2,)

              for lname in layer_name
        }

        ftrack_lep =\
        {
          lname : value.reshape(2,)  for lname, value in track_layer_eta_phi.items()\
            if len(value) > 0 and  value[0] > -20

        }

        n_trhits = len(ftrack_lep)

        if(n_trhits == 0) :
            ev_flag = -1
            return {'gr' : [dgl.rand_graph(2,1)], 'truth_E' : torch.tensor([-1.]), 'truth_eta' : torch.tensor([-99.])}#, ev_flag

        track_xyz = []

        for ft in ftrack_lep :
            region = layer_name[ft][0]
            rperp = layer_name[ft][1]
            eta   = ftrack_lep[ft][0]
            phi   = ftrack_lep[ft][1]

            theta = 2*np.arctan( np.exp(-eta) )

            if(region == 1) :
                rperp = rperp/np.sin(theta)

            trk_x = rperp*np.cos(phi)
            trk_y = rperp*np.sin(phi)
            trk_z = rperp/np.tan(theta)

            track_xyz.append( torch.tensor([trk_x, trk_y, trk_z]) )

        track_xyz = torch.vstack(track_xyz)

        trackP = self.ev_tree['trackP'].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]

        # ------------------------------------------------------ #
        cluster_var_dict = {}

        for ivar in self.cluster_var :
            cluster_var_dict[ivar] =\
             ( torch.tensor(self.ev_tree[ivar].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0])
                - self.cluster_var_dict_musig[ivar]['mean']
                )/self.cluster_var_dict_musig[ivar]['std']

        graph_list, clus_var  = [], []
        cell_E, cluster_cell_pos, cluster_cell_deta, cluster_cell_dphi = [], [], [], []
        # ---- loop over clusters ---- #
        for ic in range(n_clusters) :

            if(cluster_E[ic] > 0.5) :
                #cell_E.append( cluster_cell_E[ic] )
                cell_E += cluster_cell_E[ic].tolist()
                cell_idx = np.array(cluster_cell_ID[ic])
                n_cell = len(cell_idx)

                #print([ torch.tensor(self.id_to_deta[x]) for x in cell_idx])

                cluster_cell_pos.append( torch.cat([ torch.tensor([self.id_to_position[x]]) for x in cell_idx]) )
                cluster_cell_deta.append( torch.cat([ torch.tensor([self.id_to_deta[x]]) for x in cell_idx]) )
                cluster_cell_dphi.append( torch.cat([ torch.tensor([self.id_to_dphi[x]]) for x in cell_idx]) )

                for ivar in self.cluster_var :

                    if(ivar.find('track') == -1) :

                        node_var_dict[ivar].append(
                                        torch.repeat_interleave(
                                            torch.reshape( cluster_var_dict[ivar][ic] , (1, 1) ), n_cell, dim=0
                                        )  # repeat_interleave
                                       ) # append
                    else :

                        node_var_dict[ivar].append(
                                        torch.repeat_interleave(
                                            torch.reshape( cluster_var_dict[ivar] , (1, 1) ), n_cell, dim=0
                                        )  # repeat_interleave
                                       ) # append

        # -- check if any cluster survives ---- #
        if( len(cluster_cell_deta) == 0 ) :
            ev_flag = -1
            return {'gr' : [dgl.rand_graph(2,1)], 'truth_E' : torch.tensor([-1.])}#, ev_flag

        # --- filling for the track nodes --- #
        for ivar in self.cluster_var :

                if(ivar.find('track') == -1) :

                    node_var_dict[ivar].append(
                                    torch.repeat_interleave(
                                        torch.reshape( cluster_var_dict[ivar].mean() , (1, 1) ), n_trhits, dim=0
                                    )  # repeat_interleave
                                   ) # append
                else :

                    node_var_dict[ivar].append(
                                    torch.repeat_interleave(
                                        torch.reshape( cluster_var_dict[ivar] , (1, 1) ), n_trhits, dim=0
                                    )  # repeat_interleave
                                   ) # append

        #cell_E.append( torch.tensor([ trackP for _ in range(n_trhits) ]) )
        cell_E = cell_E + [ trackP[0] for _ in range(n_trhits) ]
        cluster_cell_pos.append( track_xyz)
        cluster_cell_deta.append( torch.tensor([ torch.cat(cluster_cell_deta, dim=0).mean() for _ in range(n_trhits) ])  )
        cluster_cell_dphi.append(  torch.tensor([ torch.cat(cluster_cell_dphi, dim=0).mean() for _ in range(n_trhits) ])  )

        #print(cell_E)
        cell_E = torch.tensor(cell_E)
        #print('cell_E shape : ', cell_E.shape)
        cluster_cell_pos = torch.cat(cluster_cell_pos, dim=0)
        cluster_cell_deta = torch.cat(cluster_cell_deta, dim=0)
        cluster_cell_dphi = torch.cat(cluster_cell_dphi, dim=0)

        n_part = len(cluster_cell_pos)

        if(n_part < self.k) :
            knn_g = dgl.knn_graph(cluster_cell_pos , n_part)
        else :
            knn_g = dgl.knn_graph(cluster_cell_pos , self.k)

        knn_g.ndata['x'] = cluster_cell_pos.float()

        clus_var.append( torch.reshape(cluster_cell_deta, (cluster_cell_deta.shape[0], 1) ) )
        clus_var.append( torch.reshape(cluster_cell_dphi, (cluster_cell_dphi.shape[0], 1) ) )

        clus_var.insert(0, torch.reshape(cell_E, (cell_E.shape[0], 1) ) )

        for var in self.cluster_var :

            #print(var, torch.cat(node_var_dict[var], dim=0).shape )
            clus_var.append(torch.cat(node_var_dict[var], dim=0))

        knn_g.ndata['en'] = torch.stack(clus_var, dim=2).float()

        #graph_list.append(knn_g)
        # -------- #

        cluster_energy_truth =\
        self.ev_tree['truthPartE'].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]

        truth_eta = self.ev_tree['truthPartEta'].array(entry_start=event_idx,entry_stop=event_idx+1,library='np')[0]

        #cluster_energy_truth = (cluster_energy_truth - self.cluster_var_dict_musig['truthPartE']['mean'])/self.cluster_var_dict_musig['truthPartE']['std']
        # ---------------------------------------------------------------- #
        return {'gr' : knn_g, 'truth_E' : torch.tensor(cluster_energy_truth), 'truth_eta' : torch.tensor(truth_eta) }#, ev_flag

    def get_all_cells(self):
        rperp = self.cell_geo_tree['cell_geo_rPerp'].array(library='np')[0]
        cell_eta = self.cell_geo_tree['cell_geo_eta'].array(library='np')[0]
        cell_theta = 2*np.arctan( np.exp(-cell_eta) )
        cell_phi = self.cell_geo_tree['cell_geo_phi'].array(library='np')[0]

        cell_deta = self.cell_geo_tree['cell_geo_deta'].array(library='np')[0]
        cell_dphi = self.cell_geo_tree['cell_geo_dphi'].array(library='np')[0]

        cell_x = rperp*np.cos(cell_phi)
        cell_y = rperp*np.sin(cell_phi)
        cell_z = rperp/np.tan(cell_theta)
        cell_positions = np.column_stack([cell_x,cell_y,cell_z])
        cell_geo_ID = self.cell_geo_tree['cell_geo_ID'].array(library='np')[0]

        id_to_position = {c_id : pos  for c_id,pos in zip(cell_geo_ID,cell_positions)}
        id_to_deta     = {c_id : deta for c_id,deta in zip(cell_geo_ID,cell_deta)}
        id_to_dphi     = {c_id : dphi for c_id,dphi in zip(cell_geo_ID,cell_dphi)}

        return cell_positions, id_to_position, id_to_deta, id_to_dphi

    def __len__(self):

            #if(self.num_ev == -1) :
            #return self.n_eff
            # else :
            return self.n_events

    def __getitem__(self, idx):

            return self.all_graphs[idx]
            #return self.get_single_event(idx)

# -------------------------------------------------- #

# -- dataset for Set based model --- #

class MLPionsDataset_Set(Dataset):
    def __init__(self, filename, cluster_var, track_var, nstart, nstop, cluster_var_dict_musig=cluster_var_dict_musig):

        self.f = pd.read_hdf(filename)
        self.cluster_var = cluster_var
        self.track_var = track_var

        self.cluster_var_dict_musig = cluster_var_dict_musig

        self.nstart = nstart
        self.nstop = nstop

        if(self.nstop - self.nstart) > len(self.f.index) :
            self.nstop = self.nstart + len(self.f.index)

        self.n_events = self.nstop - self.nstart

        #self.cluster_var_dict_musig = cluster_var_dict_musig

        self.all_graphs = []

        for i in tqdm(range( self.nstart, self.nstop, 1 )):
            event_dict = self.get_single_event(i)
            #if(event_dict['truth_E'].item() >=0. ) :
            self.all_graphs.append(event_dict)

#         self.n_eff = len(self.all_graphs)

    def get_single_event(self,event_idx):

        # ------- building the cluster graph ---------- #

        NClus, NClus_Max = 0, 25

        for ic in range(NClus_Max) :
            if(self.f["cluster_e_%i" % (ic)].to_numpy()[event_idx] > 0.) :
                NClus += 1

        if(NClus == 0) :
            #print('Empty cluster event')
            #ev_flag = -1
            return {'gr' : [dgl.rand_graph(2,1)], 'truth_E' : torch.tensor([-9999999.])}

        gr = dgl.rand_graph(NClus, 0)

        # -- making the cluster variables -- #
        var_val = []

        for ic in range(NClus) :

            var_val_clus = []
            for var in self.cluster_var :

                # var_val_clus.append( ( self.f[var + str(ic)].to_numpy()[event_idx] - self.cluster_var_dict_musig[var]['mean'])/self.cluster_var_dict_musig[var]['std']
                #                    )
                var_val_clus.append( ( self.f[var + str(ic)].to_numpy()[event_idx] )
                                   )

            var_val.append(torch.tensor(var_val_clus))

        var_val = torch.stack(var_val, dim=0)

        track_val = torch.stack(
            [ torch.repeat_interleave( torch.tensor( [ (self.f[var].to_numpy()[event_idx] - self.cluster_var_dict_musig[var]['mean'])/self.cluster_var_dict_musig[var]['std'] ] ).reshape(1,) , NClus, dim=0)\
              for var in self.track_var ]
            , dim=1)

        clus_track_val = torch.cat([var_val, track_val], dim=1)

        gr.ndata['en'] = clus_track_val.float()

        #truthE = torch.tensor( [ (self.f['truth_particle_e'].to_numpy()[event_idx] - self.cluster_var_dict_musig['truthPartE']['mean'] )/self.cluster_var_dict_musig['truthPartE']['std'] ]).float()
        truthE = torch.tensor( [ (self.f['truth_particle_e'].to_numpy()[event_idx]) ] ).float()

        return {'gr' : gr, 'truth_E' : truthE}

    def __len__(self):

            #if(self.num_ev == -1) :
            #return self.n_eff
            # else :
            return self.n_events

    def __getitem__(self, idx):

            return self.all_graphs[idx]
            #return self.get_single_event(idx)

# ----------------------------------------------------- #

def collate_graphs(event_list) :

    n_batch = len(event_list)
    full_gr_list = []
    energy_list = []

    for ib in range(n_batch) :

        #print(event_list[ib])
        gr_list = event_list[ib]['gr']
        tr_elist = event_list[ib]['truth_E']
        #energy_list.append(event_list[ib]['truth_E'])

        #for i in range(len(gr_list)) :
        if( tr_elist.item() > -9999999. ) :
            full_gr_list.append(gr_list)
            energy_list.append(tr_elist)

    energy_list = torch.tensor(energy_list)

    return dgl.batch(full_gr_list), energy_list.reshape(energy_list.shape[0], 1)

def collate_graphs_eta(event_list) :

    n_batch = len(event_list)
    full_gr_list = []
    energy_list = []
    eta_list = []

    for ib in range(n_batch) :

        #print(event_list[ib])

        #print(event_list[ib])
        gr_list = event_list[ib]['gr']
        tr_elist = event_list[ib]['truth_E']

        #tr_etal  = event_list[ib]['truth_eta']
        #energy_list.append(event_list[ib]['truth_E'])

        #for i in range(len(gr_list)) :
        if( tr_elist.item() >=0. ) :
            full_gr_list.append(gr_list)
            energy_list.append(tr_elist)
            eta_list.append(event_list[ib]['truth_eta'])

    return dgl.batch(full_gr_list), torch.tensor(energy_list), torch.tensor(eta_list)


import ConfigParser
import logging
from logging.config import fileConfig

from base import Base
from mootdao import MootDao

class Achievements(Base):

    def __init__(self, user_id):
        Base.__init__(self, __name__)
        self.user_id = user_id
        self.config = ConfigParser.ConfigParser()
        self.config.read('config.ini')
        self.all_achievements = MootDao().get_achievements(self.user_id)
        self.all_products = MootDao().get_products(self.user_id)

    def check_all_achievements(self):
        achievements_earned = []
        for attr in dir(self):
            if(attr.startswith('test_')):
                test = getattr(self, attr)
                test_result = test()
                try:
                    should_award = test_result[0]
                    achievement_name = test_result[1]
                    if should_award:
                        db = MootDao()
                        db.award_achievement(self.user_id, achievement_name)
                        self.logger.info("Awarded achievement '{0}' to user "
                                         "'{1}".format(achievement_name,
                                                       self.user_id))
                        achievements_earned.append(achievement_name)
                    else:
                        self.logger.debug("Not awarding achievement '{0}' to "
                                          "user '{1}'".format(achievement_name,
                                                              self.user_id))
                except TypeError:
                    self.logger.critical("Problem with test result")

        if len(achievements_earned) > 0:
            achievements = []
            for ach in achievements_earned:
                dict = {}
                info = MootDao().get_achievement_info(ach)
                dict["name"] = ach
                dict["description"] = info["description"]
                achievements.append(dict)
            return achievements
        return achievements_earned

    def is_new_achievement(self, achievement_name):
        """
        Determines whether an achievement is unearned for a particular user

        :param achievement_name: (String) corresponding to name in
        achievement table

        :return: True if user does not have the achievement
                 or False if user has already earned the achievement
        """
        for ach in self.all_achievements:
            if ach["name"] == achievement_name:
                return False
        return True

    def test_new_moot(self):
        """
        Tests whether user should be awarded "New Moot" Achievement

        :return:    Tuple in the form (Name, Boolean)
                    Name = String (corresponds to name in achievement table)
                    Boolean = Whether achievement should be awarded
        """
        self.logger.debug("test_new_moot()")
        name = "New Moot on the Block"
        if self.is_new_achievement(name):
            return (True, name)
        else:
            self.logger.debug("User '{0}' already earned '{1}'"
                              .format(self.user_id, name))
        return (False, name)

    def test_1000_moot_points(self):
        """
        Tests whether user should be awarded "Savings Account" Achievement

        :return:    Tuple in the form (Name, Boolean)
                    Name = String (corresponds to name in achievement table)
                    Boolean = Whether achievement should be awarded
        """
        self.logger.debug("test_100_moot_points()")
        name = "Savings Account"
        if self.is_new_achievement(name):
            db = MootDao()
            points = db.get_points(self.user_id)
            if points >= 1000:
                return (True, name)
        else:
            self.logger.debug("User '{0}' already earned '{1}'"
                              .format(self.user_id, name))
        return (False, name)

    def test_taste_the_rainbow(self):
        """
        Tests whether user should be awarded "Taste The Rainbow" Achievement

        :return:    Tuple in the form (Name, Boolean)
                    Name = String (corresponds to name in achievement table)
                    Boolean = Whether achievement should be awarded
        """
        self.logger.debug("test_taste_the_rainbow()")
        name = "Taste The Rainbow"
        if self.is_new_achievement(name):
            colors = set()
            for p in self.all_products:
                color = p["color"]
                colors.add(color)
                if len(colors) == 8:
                    return (True, name)
        else:

            self.logger.debug("User '{0}' already earned '{1}'"
                              .format(self.user_id, name))
        return (False, name)

    def test_easy_as_abc(self):
        """
        Tests whether user should be awarded "Easy as ABC" Achievement

        :return:    Tuple in the form (Name, Boolean)
                    Name = String (corresponds to name in achievement table)
                    Boolean = Whether achievement should be awarded
        """
        self.logger.debug("test_easy_as_abc()")
        name = "Easy as ABC"
        if self.is_new_achievement(name):
            all_letters = set()
            for p in self.all_products:
                first_letter = p["product_name"][0]
                if first_letter.isalpha():
                    all_letters.add(first_letter.upper())
                if len(all_letters) == 26:
                    return (True, name)
        else:
            self.logger.debug("User '{0}' already earned '{1}'"
                              .format(self.user_id, name))
        return (False, name)


#!/usr/bin/env python

# Author: Mandeep Singh
# Contact: msingh98@uw.edu
# Developed for: ServiceNow
#
# This is the main script that runs the Software_Spend_Reporter.

import sys
import os
from Company import Company
from pandas import read_csv

# The following if else statements stop the execution of the script if
# the path to the file is not provided or if the path to the file is
# invalid
if len(sys.argv) < 2:
    print("Please enter path to file")
    sys.exit()
elif not os.path.exists(sys.argv[1]):
    print("file not found!")
    sys.exit()

# Create a dictionary of product data by companies from the given path
# to the CSV file
#   path_to_csv: path to CSV file entered in the command line
#   returns: returns a dictionary containing company name as key
#            and Company object as value
def create_companies_dictionary(path_to_csv):
    csv_data = read_csv(path_to_csv)
    companies = dict()
    for index, row in csv_data.iterrows():
        vendor = row['Vendor']
        if vendor not in companies.keys():
            company_temp = Company(vendor)
            companies[vendor] = company_temp
        company = companies[vendor]
        company.add_product(row['Product'], row['Amount'])
    return companies

companies_dict = create_companies_dictionary(sys.argv[1])

# Prints the required output by iterating through a sorted list of companies
for company in sorted(companies_dict.keys()):
    companies_dict[company].print_cost()


#!/usr/bin/python
# -*- coding: utf-8 -*-
import backlight
import subprocess

subprocess.run(f"xbacklight -inc {backlight.diff}", shell=True)

brightness = backlight.getBrightness()
if brightness < backlight.diff:
    brightness = 100
backlight.notifyBrightness(brightness)


# Script to process hyperopt log and summarise results. Useful for multiple hyperopts in one file (e.g. from hyp_exchange.sh)

import sys
import os
from re import search
import statistics
import pandas
import numpy
from tabulate import tabulate

infile = None
curr_line = ""
strat_results = {}
strat_summary = {}

# routine to skip to requested pattern
def skipto(pattern, anywhere=False) -> bool:
    global curr_line
    global infile

    if infile is None:
        print("ERR: file not open")
        return False

    curr_line = infile.readline()

    while curr_line:
        if anywhere:
            found = (pattern in curr_line) # pattern is anywhere in the string
        else:
            found = curr_line.lstrip().startswith(pattern) # string starts with pattern (ignoring whitespace)
        if found:
            break
        curr_line = infile.readline()

    if curr_line:
        return True
    else:
        return False

# copies the input file and prints each line until pattern is found.
# Note: prints current line but not the final line
def copyto(pattern, anywhere=False, include_str=""):
    global curr_line
    global infile

    while curr_line:
        if anywhere:
            found = (pattern in curr_line) # pattern is anywhere in the string
        else:
            found = curr_line.lstrip().startswith(pattern) # string starts with pattern (ignoring whitespace)
        if found:
            break

        if (len(include_str) == 0) or (include_str in curr_line):
            print(curr_line.rstrip())
        curr_line = infile.readline()

    if curr_line:
        return True
    else:
        return False

def process_totals(strat, line):
    global strat_summary
    global strat_results

    # format of line:
    # 97/100:     94 trades. 63/0/31 Wins/Draws/Losses. Avg profit   0.59%. Median profit   1.15%. Total profit 1658.03907912 USD (  16.58%). Avg duration 22:16:00 min. Objective: -30.83651
    cols = " ".join(line[1:].split()) # get rid of multiple spaces (and 1st character, which could be '*')
    cols = cols.strip().split(" ")

    # print("cols: ", cols)

    entry = {}
    entry['entries'] = int(cols[1])
    wins, draws, losses = cols[3].strip().split("/")
    entry['ave_profit'] = float(cols[7].split('%')[0])
    entry['tot_profit'] = float(cols[16].split('%')[0])
    entry['win_pct'] = 100.0 * float(wins) / float(entry['entries'])

    strat_summary[strat] = entry

    return

def print_results():

    global strat_summary
    global strat_results

    print("")
    print("Summary:")

    if len(strat_summary) > 0:
        # convert associative array into 'plain' array
        strat_stats = []
        # calculate stats for each strategy
        for strategy in strat_summary:
            strat_stats.append([strategy,
                                strat_summary[strategy]['entries'], strat_summary[strategy]['ave_profit'],
                                strat_summary[strategy]['tot_profit'], strat_summary[strategy]['win_pct'],
                               0.0])

        # create dataframe
        df = pandas.DataFrame(strat_stats,
                              columns=["Strategy", "Trades", "Average(%)", "Total(%)", "Win%", "Rank"])

        df["Rank"] = df["Total(%)"].rank(ascending=False, method='min')

        pandas.set_option('display.precision', 2)
        print("")
        hdrs = df.columns.values
        print(tabulate(df.sort_values(by=['Rank'], ascending=True),
                       showindex="never", headers=hdrs,
                       colalign=("left", "center", "decimal", "decimal", "decimal", "center"),
                       floatfmt=('.0f', '.0f', '.2f', '.2f', '.2f', '.0f'),
                       numalign="center", tablefmt='psql')
              )
    else:
        print("No results found")

    return

def main():
    global curr_line
    global infile

    args = sys.argv[1:]

    file_name = args[0]
    if not os.path.isfile(file_name):
        print("File {} does not exist. Exiting...".format(file_name))
        sys.exit()

    infile = open(file_name)

    # repeatedly scan file and find header of new run, then print results
    while skipto("------------------"):
        print("")
        print(curr_line.rstrip())
        curr_line = infile.readline()
        strategy = curr_line.strip()

        copyto(("------------------"))
        print(curr_line.rstrip())
        # skip anything between header & results
        if skipto('+--------'):
            print(curr_line.rstrip())
            # get the best results line
            if copyto('Wins/Draws/Losses', anywhere=True, include_str="|"):
                process_totals(strategy, curr_line.strip())

                # copy everything up to end of results (assuming we don't need anything past ROI table)
                copyto('# ROI table:')

    print_results()

if __name__ == '__main__':
    main()


from django.contrib import admin
from payment.models import PaidMember, UserInfo

class PaidMemberAdmin(admin.ModelAdmin):
    """ Premium User Admin """
    list_display = (
        'user',
        'start_date',
        'end_date',
        'subscription',
    )

admin.site.register(PaidMember, PaidMemberAdmin)

class UserInfoAdmin(admin.ModelAdmin):
    """ User Info Admin """
    list_display = (
        'user',
        'first_name',
        'last_name',
        'first_line_address',
        'postcode',
    )

admin.site.register(UserInfo, UserInfoAdmin)


def Square_and_Multiply(a, x, n):
    b = bin(x)[2:]
    b = str(b)
    y = 1
    for i in range(len(b) - 1, -1, -1):
        if b[i] == '1':
            y = y * a % n
            #print('y=',y)
        a = a * a % n
        # print('a=',a)
    return y
def keygen(e1,d,p):
    e2=Square_and_Multiply(e1,d,p)
    return e2
def chkprm(e1,p):
    y=Square_and_Multiply(e1,p-1,p)
    if(y==1):
        for i in range(1,(p-1)):
            y=Square_and_Multiply(e1,i,p)
            if(y==1):
                print('not primitive root')
                exit()
    else:
        print('not primitive root')
        exit()

def siggen(e1,r,p,m):
    s1=Square_and_Multiply(e1,r,p)
    print('s1',s1)
    f.write('s1 ' + str(s1)  + '\n')
    rin=ExEucMethod(p-1,r)
    print('rin',rin)
    f.write('rin ' + str(rin)  + '\n')
    s2=((m-(d*s1))*rin)%(p-1)
    print('s2',s2)
    f.write('s2 ' + str(s2)  + '\n')
    return s1,s2
def sigver(s1,s2,m):
    v1=Square_and_Multiply(e1,m,p)
    v2=(Square_and_Multiply(e2,s1,p)*Square_and_Multiply(s1,s2,p))%p
    print('v1: ',v1)
    f.write('v1 ' + str(v1)  + '\n')
    print('v2: ',v2)
    f.write('v2 ' + str(v2)  + '\n')
    if(v1==v2):
        print('signature is verified')
    else:
        print('signature is not verified')
def ExEucMethod(a, b):
    r1, r2 = a, b
    s1, s2 = 1, 0
    t1, t2 = 0, 1
    while (r2 > 0):
        q = int(r1 / r2)
        r = r1 - q * r2
        r1 = r2
        r2 = r
        s = s1 - q * s2
        s1 = s2
        s2 = s
        t = t1 - q * t2
        t1 = t2
        t2 = t
    s = s1
    t = t1
    return t%a
p=int(input('enter the prime no p: '))
e1=int(input('enter the value of e1: '))
chkprm(e1,p)
r=int(input('enter the value of r: '))
d=int(input('enter the value of d: '))
mi=input('enter the Message: ')
m=''
for i in mi:
    m+=str(ord(i))
m=int(m)
e2=int(input('enter e2: '))
print('public key',e1,e2,p)
print('private key',d)
f = open("Elgamal", "w+")
f.write('enter the prime no p: ' + str(p) + '\n')
f.write('enter the prime no e1: ' + str(e1) + '\n')
f.write('enter the prime no e2: ' + str(e2) + '\n')
f.write('enter the prime no d: ' + str(d) + '\n')
f.write('enter the prime no r: ' + str(r) + '\n')
s1,s2=siggen(e1,r,p,m)
sigver(s1,s2,m)
f.close()


# Odin M. Moron-Garcia
# Date of Creation 21st September, 2021

# For our purposes we need Doc2Vec since it is suitable for downstream machine learning applications
# And this script will refurbish the original Doc2Vec tutorial so the models are calculated for KEGG, COGs and pFAm
# datasets for the GenePhene2 bacterias data set - and soon for FAPROTAX, MDB and Hiding

#### Input files

# The genomes are generated by Sebastien Radigueau using some custom scripts that result in
# BED like files that I have collected as "position" "Ortholog gene" files and now put together using

# for file in *KEGG*; do echo -n $file $'\t' >>../GenePhene2_Doc2Vec_KEGG.txt ;cat ${file}|cut -f 2|tail -n +2| tr '\n' $'\t' >> ../GenePhene2_Doc2Vec_KEGG.txt; echo '' >> ../GenePhene2_Doc2Vec_KEGG.txt ;done
#  for file in *COG*; do echo -n $file $'\t' >>../GenePhene2_Doc2Vec_COGS.txt ;cat ${file}|cut -f 2|tail -n +2| tr '\n' $'\t' >> ../GenePhene2_Doc2Vec_COGS.txt; echo '' >> ../GenePhene2_Doc2Vec_COGs.txt ;done
# for file in *pFam*; do echo -n $file $'\t' >>../GenePhene2_Doc2Vec_pFam.txt ;cat ${file}|cut -f 2|tail -n +2| tr '\n' $'\t' >> ../GenePhene2_Doc2Vec_pFam.txt; echo '' >> ../GenePhene2_Doc2Vec_pFam.txt ;done

# That contain a first column with the genome file and the rest of columns

#### Output files

	# Models as binary files like : GenePhene2_Doc2Vec_KEGG.dat
	# Exported also as text files for using in my previous R pipeline - colon separated valued

#### SCRIPT ####

## Preamble :

## Script copy-pasted from : https://radimrehurek.com/gensim/auto_examples/tutorials/run_doc2vec_lee.html
# With some modifications for tokenizing and tagging the genome

from os.path import join
import logging
import gensim
import time

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

## Handling file and folder names - rustic version

Absolute_Folder = "/Users/moronga/Documents/Earlham/trainw2v/W2V_GenePhene2/"
Ortho = "COGS"

if Ortho == "KEGG":
    File_Name = "GenePhene2_Doc2Vec_KEGG.txt"
    Model_Filename = "GenePhene2_Doc2Vec_KEGG.dat"
    Export_Filename = "GenePhene2_Doc2Vec_KEGG.csv"
elif Ortho == "COGS":
    File_Name = "GenePhene2_Doc2Vec_COGS.txt"
    Model_Filename = "GenePhene2_Doc2Vec_COGS.dat"
    Export_Filename = "GenePhene2_Doc2Vec_COGS.csv"

elif Ortho == "pFam":
    File_Name = "GenePhene2_Doc2Vec_pFam.txt"
    Model_Filename = "GenePhene2_Doc2Vec_pFam.dat"
    Export_Filename = "GenePhene2_Doc2Vec_pFam.csv"
else:
    print("No good option")
    exit()

Genome_File = join(Absolute_Folder,File_Name)
Model_File = join(Absolute_Folder,Model_Filename)
Export_File = join(Absolute_Folder,Export_Filename)

# Check
print(Genome_File)
print(Model_File)
print(Export_File)

import smart_open

def read_corpus(fname, tokens_only=False):
    with smart_open.open(fname, encoding="iso-8859-1") as f:
        for i, line in enumerate(f):
            tokens = tokenize_genome(line)
            if tokens_only:
                yield tokens
            else:
                # For training data, add tags
                #yield gensim.models.doc2vec.TaggedDocument(tokens, [i])
                #modified to get the tag as the genome ID
                yield gensim.models.doc2vec.TaggedDocument(tokens[1:len(tokens)],[tokens[0]])
## Helper functions

def tokenize_genome(line):
		ll = line.split("\t") #Notice the change that the input files are tab files rather than colon separated
		return ll

##### SCRIPT ####

# Print the time to check how long does it takes

t = time.localtime()
current_time = time.strftime("%H:%M:%S", t)
print(current_time)

## Start processing the genomes

train_corpus = list(read_corpus(Genome_File))

model = gensim.models.doc2vec.Doc2Vec(vector_size=50, min_count=2, epochs=40)

model.build_vocab(train_corpus)

t = time.localtime()
current_time = time.strftime("%H:%M:%S", t)
print(current_time)

# Save the model for later (time for Jupyter?)
model.save(Model_File)
print("The model has been saved at:",Model_File)

# ready for the export
with open(Export_File,'wt') as fd:
    for idx in range(0,len(model.docvecs)):
        fd.write(model.docvecs.index2entity[idx]+ ";" +  ';'.join([ str(x) for x in model.docvecs[idx]]) + '\n')
    fd.close()
print("The model has been saved at:",Export_File)

print("Script Finished")


#!/usr/bin/env python3

import rospy
import numpy as np
from sensor_msgs.msg import LaserScan

from ...nodes.update import Update

class CalcAvgFrontDist(Update):

    def __init__(self, scan_var_name, dist_var_name, fov):

        super().__init__()

        self.scan_var_name = scan_var_name

        self.dist_var_name = dist_var_name

        self.view_frac = fov/720

    def update_blackboard(self, blackboard:dict) -> str:

        try:

            ranges = np.array(blackboard['/scan'].ranges)

            ranges[ranges <= 0.1] = 0

            n = ranges.size

            wall_to_left = ranges[0:int(n*self.view_frac)]
            wall_to_right = ranges[n-int(n*self.view_frac):]

            total_avg = (np.average(wall_to_left) + np.average(wall_to_right))/2

            blackboard[self.dist_var_name] = total_avg

            return "success"

        except:

            return "failure"


from typing import cast

from fastapi import Request
from starlette.datastructures import UploadFile

from fcg.infrastructure.types import OutputFormat
from fcg.viewmodels import parse
from fcg.viewmodels.form_base_viewmodel import FormBaseViewModel

class MosViewModel(FormBaseViewModel):
    def __init__(self, request: Request):
        super().__init__(request)
        self.mos_mask_file: UploadFile | None = None
        self.background_image: str | UploadFile = ""
        self.output_format: OutputFormat = "pdf"
        self.errors: dict[str, str] = dict()

    async def load(self) -> None:
        form = await self.request.form()

        super().load_common_data(form)

        # MOS mask file
        self.mos_mask_file = cast(
            UploadFile, parse.parse_mos_mask_file(form, self.errors)
        )

        # background image
        self.background_image = parse.parse_background_image(form, self.errors)

        # output format
        self.output_format = parse.parse_output_format(form, self.errors)


"""
DEFINE YOUR FUNCTIONS BELOW
"""

def get_final_price():
    """
    Takes a list of prices and calculates what the final price of the purchase will be.

    pre-condition: The function needs the subtotal of the order (the total of all the prices entered added together) to be greater than or equal to 1000.

    post-condition: The function has added the numbers together, applied a sales tax of 8%, and, if there were more than 10 items, applied a 20% post-tax discount. It will print the final price (and alert you to your discount, if you were eligible for it).
    """
    subtotal = 0
    num_items = 0
    while subtotal < 1000:
        item_price = float(input("Enter the price of your item: "))
        subtotal += item_price
        num_items += 1
    final_cost = subtotal + (0.08 * subtotal)
    if num_items > 10:
        print("20% discount applied!")
        final_cost = final_cost - (0.2 * final_cost)
    print("The total price is " + str(final_cost) + ".")

"""
DEFINE YOUR FUNCTIONS ABOVE
"""

def main():
    """
    Executes get_final_price().

    pre-condition: Nothing has yet been executed.

    post-condition: get_final_price() has been executed.
    """
    get_final_price()

# DO NOT WRITE CODE BELOW THIS LINE

if __name__ == '__main__':
    main()


# coding: utf-8

import sys
import time
import dataset
import sorting

from collections import defaultdict

TESTS = ["basico", "ordenado", "ordenado_inverso"]

# gets the list of supported sorting algorithms from the `sorting` module
ALGORITHMS = [f for f in dir(sorting) if callable(getattr(sorting, f)) and not f.startswith('_')]

USAGE = """
Calcula los tiempos de ejecución de un algoritmo de ordenamiento para distintos
tamaños de listas.
Ejecuta 100 para cada `n` y toma la menor de las mediciones.

Uso: ./{} sets_num tipo_test algoritmo

  sets_num      La cantidad de sets a generar (int).
  tipo_test     El tipo de test a ejecutar (basico, ordenado, ordenado_inverso)
  algoritmo     El algoritmo al cuál ejecutarle las pruebas:
                  * """.format(__file__) + '\n                  * '.join(ALGORITHMS)

def test(algorithm, basedata_func):
    """Runs the test on a given `algorithm` with the given `basedata`."""

    # gets the function using the name
    algorithm_fn = getattr(sorting, algorithm)

    # number of iterations to run
    iterations = 100

    result = {}
    for n in (50, 100, 500, 1000, 2000, 3000, 4000, 5000, 7500, 10000):
        print('n:', n, end='     \r')
        measurements = []
        for _ in range(iterations):
            # builds the dataset
            data = basedata_func(10000)[:n]

            # runs the algorithm
            start = time.perf_counter()
            algorithm_fn(data)
            elapsed = time.perf_counter() - start

            measurements.append(elapsed)

        # stores the minimun result
        result[n] = min(measurements) * 1000
    return result

def test_basic(algorithm, sets_num):
    """Runs the test on a given `algorithm`, using 10 different random sets."""

    result = defaultdict(list)

    # runs the test with 10 different sets (using different seeds)
    results = []
    for seed in range(sets_num):
        results.append(test(algorithm, lambda n: dataset.get_data(n, seed)))

    # normalizes the results into lists for each value of `n`
    for interm_result in results:
        for n, time_ms in interm_result.items():
            result[n].append(time_ms)

    # calculates the average for each `n`
    for n in result:
        time_list = result[n]
        result[n] = sum(time_list) / len(time_list)

    return result

def test_ordered_data(algorithm):
    """Runs the test on a given `algorithm` with a ordered dataset"""
    return test(algorithm, dataset.get_ordered_data)

def test_inverse_ordered_data(algorithm):
    """Runs the test on a given `algorithm` with a inverse ordered dataset"""
    return test(algorithm, dataset.get_inverse_ordered_data)

def print_result(result):
    print(algorithm)
    print('n,time (ms)')
    print('\n'.join('{},{:.4f}'.format(n, result[n]) for n in sorted(result)))

if __name__ == '__main__':
    if '--help' in sys.argv or '-h' in sys.argv:
        print(USAGE)
        exit(0)
    if len(sys.argv) != 4:
        print(USAGE)
        exit(1)

    sets_num, test_type, algorithm = int(sys.argv[1]), sys.argv[2], sys.argv[3]

    if (algorithm not in ALGORITHMS) or (test_type not in TESTS):
        if algorithm not in ALGORITHMS:
            print('Algoritmo "{}" no soportado'.format(algorithm))
        else:
            print('Tipo de test "{}" no soportado'.format(test_type))
        print("Usar './{} --help' para ver las opciones".format(__file__))
        exit(1)

    if test_type == "ordenado":
        result = test_ordered_data(algorithm)
    elif test_type == "ordenado_inverso":
        result = test_inverse_ordered_data(algorithm)
    else:
        result = test_basic(algorithm, sets_num)

    # outputs the result in CSV format
    print_result(result)


from django.shortcuts import render, redirect
from .models import *

# course filter
from django.template.loader import render_to_string
from django.http import JsonResponse

# total duration sum
from django.db.models import Sum

def home(request):
    course_menu_category = Categories.get_all_category(Categories)
    # category = Categories.objects.all().order_by('id')[0:5]
    category = Categories.objects.all().order_by('id')
    courses = Course.objects.filter(status='PUBLISH').order_by('-id')
    context = {
        'course_menu_category': course_menu_category,
        'category': category,
        'course': courses,
    }
    return render(request, 'main/home.html', context)

def contact(request):
    course_menu_category = Categories.get_all_category(Categories)
    context = {
        'course_menu_category': course_menu_category,
    }
    return render(request, 'main/contact.html', context)

def about(request):
    course_menu_category = Categories.get_all_category(Categories)
    context = {
        'course_menu_category': course_menu_category,
    }
    return render(request, 'main/about.html', context)

def course(request):
    category = Categories.get_all_category(Categories)
    course_menu_category = Categories.get_all_category(Categories)
    level = Level.objects.all()
    course = Course.objects.all()
    author = Author.objects.all()

    context = {
        'course_menu_category': course_menu_category,
        'category': category,
        'level': level,
        'course': course,
        'author': author,
    }
    return render(request, 'main/course.html', context)

def course_filter(request):
    course_menu_category = Categories.get_all_category(Categories)
    categories = request.GET.getlist('category[]')
    author = request.GET.getlist('author[]')
    level = request.GET.getlist('level[]')

    if categories:
        course = Course.objects.filter(
            category__id__in=categories).order_by('-id')
    elif author:
        course = Author.objects.filter(author__id__in=author).order_by('-id')
    elif level:
        course = Course.objects.filter(level__id__in=level).order_by('-id')
    else:
        course = Course.objects.all().order_by('-id')

    context = {
        'course_menu_category': course_menu_category,
        'course': course,
    }

    t = render_to_string('course/course_filter.html', context)

    return JsonResponse({'data': t})

def course_detail(request, slug):
    course_menu_category = Categories.get_all_category(Categories)
    duration = Video.objects.filter(course__slug=slug).aggregate(sum=Sum('duration'))

    course = Course.objects.filter(slug=slug)

    if course.exists():
        course = course.first()
    else:
        return redirect('404')
    context = {
        'course_menu_category': course_menu_category,
        'course': course,
        'duration': duration,
    }
    return render(request, 'course/course_detail.html', context)

def search(request):
    course_menu_category = Categories.get_all_category(Categories)
    query = request.GET['query']
    course = Course.objects.filter(title__icontains=query)
    context = {
        'course_menu_category': course_menu_category,
        'course': course,
    }
    return render(request, 'course/search.html', context)

def page_not_found(request):
    course_menu_category = Categories.get_all_category(Categories)
    context = {
        'course_menu_category': course_menu_category,
    }
    return render(request, 'erorr/404.html', context)

def course_watch(request, slug):
    course_menu_category = Categories.get_all_category(Categories)
    duration = Video.objects.filter(course__slug=slug).aggregate(sum=Sum('duration'))
    lecture = request.GET.get('lecture')
    video = Video.objects.get(id= lecture)

    course = Course.objects.filter(slug=slug)

    if course.exists():
        course = course.first()
    else:
        return redirect('404')
    context = {
        'course_menu_category': course_menu_category,
        'course': course,
        'duration': duration,
        'video': video
    }
    return render(request, 'course/course_watch.html', context)


import sys
snput = lambda: sys.stdin.readline().rstrip()
m_snput = lambda: map(int, snput().split())

if __name__ == "__main__":
    n, m = m_snput()
    count = (n * (n - 1) + m * (m - 1)) // 2
    print(count)
    """
    input_str = snput()
    input_num = int(snput())
    some_map = m_snput()
    """


# Author: Jordan Cain, 2015-16

import re
import sys
import time
import parse
import walker
from debugUtil import Trace
from methodHolder import Method
from classHolder import Class
from optimisations import Recursion
from optimisations import LoopToUnroll

def detect(parent, debugObj):
    global debug
    debug = debugObj
    debug.writeTrace("Detecting Optimisations, parent: " + parent.getName())
    recursions = recursionDetect(parent)
    unrollables = forLoopUnrollDetect(parent)
    return recursions, unrollables

#Function to print all of the optimisations
def output(recursions, loops):
    debug.writeTrace("Output optimisations")
    if recursions:
        print("The JVM struggles to optimise recurssion, consider iterative conversion")
        for recursion in recursions:
            recursion.toString()
        print("\n###################################\n")
    if loops:
        for loop in loops:
            loop.toString()
            unrollLoop(loop)
    if not loops:
        print ("No unrollable for loops")
    if not recursions:
        print("No recusrions")

#Function that will find any occourences of a for loop that can be unrolled
def forLoopUnrollDetect(parent):
    debug.writeTrace("Detect for loops to unroll")
    loops = walker.getForLoops(parent, debug)
    unrollableLoops = []
    #Check if loops use a constant number for the upper range
    #E.g for(int i=0; i<=5; i++)
    for loop in loops:
        if walker.checkIfCStyleLoop(loop, debug):
            condition = loop.getName()[loop.getName().find(';')+1:loop.getName().rfind(';')].lstrip()
            condLeft, condRight = splitCondition(condition)
            iterator, initTo = getConditionIterator(loop.getName())
            #If the iterator is a digit we may be able to unroll
            if initTo.isdigit():
                #If the iterator is used in the condition its more likely
                if iterator in condition:
                    if condLeft.lstrip().isdigit() or condRight.lstrip().isdigit():
                        unrollableLoops.append(LoopToUnroll(loop, iterator, initTo, condRight))
    return unrollableLoops

def unrollLoop(loop):
    loopObject = loop.getLoop() #Get the actual loop object
    if len(loopObject.getChildren()) < 4:
        print("Unrolling loop, Replace current for loop with: ")
        i = 0;
        while i < int(loop.getCondRight()) - int(loop.getInitto()):
            for statement in loopObject.getChildren():
                statement.printNode();
            i += 1
    else:
        print("Loop too long to unroll, \nconsider manually unrolling")

#Function that will find any occorunces of recursion in a method
#Params: parent is the highest level of the tree, debug will add extra output to console
def recursionDetect(parent):
    debug.writeTrace("Recursion Detect")
    #Initialise our return array which will hold recursion objects
    recursions = []
    #Get all the methods in the tree
    methods = walker.getMethods(parent, debug)
    for method in methods:
        #For each method we need to analyse the statements inside it
        statements = walker.getStatements(method, debug)
        #TODO:: Oppurtunity to implement threading here
        for statement in statements:
            debug.writeTrace("\tstatement: " + statement.getName() + " #### parent: " + statement.getParent().getName())
            if method.getName() in statement.getName():
                debug.writeTrace(statement.getName() + "\tin method: " + method.getName() + "Line: " + str(method.getLineNo()))
                statementName = statement.getName()
                methodName = method.getName()
                #Create a substring of the method call and parameters
                statementName = statementName[statementName.index(methodName):]
                #TODO:: if a param is a function call this will break
                statementName = statementName[:statementName.index(')')+1]
                #Get the params of the statement and method
                params = method.getParams()
                methodParamTypes = getMethodParamTypes(params)
                params = parse.getParams(statementName)
                statementParamTypes = getStatementParamTypes(params, method)

                #If paramater types match it's a recurisve call
                if statementParamTypes == methodParamTypes:
                    recursions.append(Recursion(statement, method))
                    debug.writeTrace("We found an actual recursion")
                    debug.writeTrace("Method:    " + method.toString() + " | line: " + str(method.getLineNo()))
                    debug.writeTrace("Statement: " + statement.getName().lstrip() + " | line: " + str(statement.getLineNo()))
                else:
                    debug.writeTrace("Not a recursive call")
                debug.writeTrace("Method param types: " + str(methodParamTypes))
                debug.writeTrace("Statement param types: " + str(statementParamTypes))
    return recursions

#Function to help for loop unroll, splits a condition at the operator index
#Param: Loop condition as a string
def splitCondition(condition):
    debug.writeTrace("Split condition: " + condition)
    if '>' in condition:
        condLeft = condition[0:condition.find('>')].lstrip()
        condRight = condition[condition.find('>')+1:].lstrip()
    elif '<' in condition:
        condLeft = condition[0:condition.find('<')].lstrip()
        condRight = condition[condition.find('<')+1:].lstrip()
    elif '=' in condition:
        condLeft = condition[0:condition.find('=')].lstrip()
        condRight = condition[condition.find('=')+1:].lstrip()
    #if we had <= or == we have to trim an extra character off
    if '=' in condRight:
        condRight = condRight.replace('=','').lstrip()
    return condLeft, condRight

#Fucntion to get the iterator variable name and the intialised value
#Param: loop decleration as string
#TODO:: Function will fail if the iterator name contains a number
def getConditionIterator(loop):
    debug.writeTrace("getConditionIterator: " + loop)
    iterator = loop[loop.find('(')+1:loop.find(';')]
    #Strip the type off, E.g int
    iterator = iterator[iterator.find(' '):].lstrip()
    return iterator[:iterator.find(' ')], re.findall(r'\d+', iterator)[0]

def getMethodParamTypes(params):
    debug.writeTrace("Method params: " + str(params))
    paramTypes = []
    for param in params:
        #SOURCE:: http://stackoverflow.com/questions/959215/removing-starting-spaces-in-python
        param = param.lstrip()
        param = param.split(' ')
        paramTypes.append(param[0])
    return paramTypes

def getStatementParamTypes(params, method):
    debug.writeTrace("Statement params: " + str(params))
    paramTypes = []
    for param in params:
        debug.writeTrace("Current param: " + param)
        #Check for literals?
        if '(' in param and ')' in param:
            debug.writeTrace("found a function call")
            #TODO::walk the tree to find the return type
        elif param.isdigit():
            paramTypes.append("int")
        elif re.match("\d+\.\d+(f)", param):
            paramTypes.append("float")
        elif '"' in param or "'" in param:
            paramTypes.append("String")
        elif param.lstrip().isalpha():
            #parameter is just a variable
            #Find the type of the variable
            paramTypes.append(findVariable(param.lstrip(), method))
        else:
            paramTypes.append(cleanParam(param.lstrip()))
        debug.writeTrace("ParamTypes: " + str(paramTypes))
    return paramTypes

def cleanParam(param):
    debug.writeTrace("Cleaning param: " + param)
    #Lets check if param is a number
    if '-' in param:
        operatorIndex = param.index('-')
    elif '+' in param:
        operatorIndex = param.index('+')
    elif '/' in param:
        operatorIndex = param.index('/')
    elif '*' in param:
        operatorIndex = param.index('*')
    else:
        return "Unable To Clean Param"

    left = param[:operatorIndex]
    right = param[operatorIndex+1:]
    param = getType(left, right)

    debug.writeTrace("left of op: " + left + " right of op: " + right)
    debug.writeTrace("Returning: " + param)
    return param

def getType(left, right):
    debug.writeTrace("Get type: left: " + left + " right: " + right)
    if left.isdigit() or right.isdigit():
        debug.writeTrace("Returning int")
        return "int"
    if re.match("\d+\.\d+(f)", left) or re.match("\d+\.\d+(f)", right):
        debug.writeTrace("Returning float")
        return "float"

def findVariable(variable, method):
    debug.writeTrace("Find Variable: " + variable)
    #Get a list of all statements in the class to check variable against
    statements = walker.getStatements(method, debug)
    for statement in statements:
        if '=' in statement.getName() and variable in statement.getName():
            debug.writeTrace("Found assignment: " + statement.getName())
            return getVariableType(statement.getName())
    return "ERROR: UNABLE TO DETERMINE VARIABLE TYPE"

#Function is a helper method for findVariable()
#Takes a line as parameter and returns the type
def getVariableType(line):
    debug.writeTrace("Get variable type: " + line)
    line = line.lstrip()
    line = line[:line.index(' ')]
    return line

#line ender


import logging
import os

from scrapy.exceptions import CloseSpider
from scrapy.linkextractors import LinkExtractor

import scrapy
from scrapy.spiders import CrawlSpider, Rule

class SpiderOne(scrapy.Spider):
    name = "sp1"
    counter = 0
    linkextractor = LinkExtractor(allow=('https://en.wikipedia.org/wiki/(.)'))
    # Nastavenie na BFS algoritmus
    custom_settings = {
        'DEPTH_PRIORITY': '1',
        'SCHEDULER_DISK_QUEUE': 'scrapy.squeues.PickleFifoDiskQueue',
        'SCHEDULER_MEMORY_QUEUE': 'scrapy.squeues.FifoMemoryQueue',
    }

    def start_requests(self):
        urls = [
            'https://en.wikipedia.org/wiki/List_of_aircraft',
            #"https://en.wikipedia.org/wiki/List_of_aircraft_(0%E2%80%93Ah)",
            #"https://en.wikipedia.org/wiki/List_of_aircraft_(Ai%E2%80%93Am)",
            #'https://en.wikipedia.org/wiki/List_of_aircraft_by_date_and_usage_category',
            #'https://en.wikipedia.org/wiki/List_of_civil_aircraft'
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response, i=0):
        """
                This function is used in Scrapy Crawling mechanism. It defines what to do or find next links
                via LinkExtractor() function. This function downloads web pages from crawled URLs.

                @:type  page: string
                @:param page: name of the page / url it got
                @:type  link: string
                @:param link: url link for next page to be crawled
                @:type links: list
                @:param links: list of links
        """

        page = response.url.split("/")[-1]
        filename = f'{self.counter}-{page}.html'

        with open(f"data/{filename}", 'wb') as f:
            f.write(response.body)
        self.log(f'Saved file {filename}')

        self.counter += 1

        link = LinkExtractor(allow='https://en.wikipedia.org/wiki/(.)',
                             restrict_css='#mw-content-text > div.mw-parser-output')
        links = link.extract_links(response)

        #if self.counter == 500:
            #raise CloseSpider('Reached limit 500')

        for _link in links:
            # yield scrapy.Request('http://www.66ip.cn/areaindex_1/1.html', callback=self.parse_list)
            yield scrapy.Request(_link.url, callback=self.parse)


import wiotp.sdk.application
import json
import uuid
from time import sleep
import jarHelper
import bot

class ApplicationClient:

    def __init__(self):
        f = open('../../properties.json')
        properties = json.load(f)
        self.typeId = properties['DEVICE']['DEVICE_TYPE']
        self.deviceId = properties['DEVICE']['DEVICE_ID']
        options = wiotp.sdk.application.parseConfigFile("../../application.yaml")
        self.client = wiotp.sdk.application.ApplicationClient(config=options)
        self.client.connect()
        self.client.deviceEventCallback = self.onMessage

    def sendCommand(self, commandId, data):
        self.client.publishCommand(self.typeId, self.deviceId, commandId, "json", data)
        # print(data)
        # print('Command Sent')

    def onMessage(self, event):
        print(event.eventId, event.data)
        for key in jarHelper.get_info().keys():
            if key in event.data:
                print("received new " + key)
                jarHelper.update(key, event.data[key])
                if (key == 'weight'):
                    jarHelper.newWeight = True
                    bot.checkForLowCount()

if __name__ == "__main__":
    try:
        client = ApplicationClient()
        while True:
            eventData = {'Test' : True}
            client.sendCommand('Jar', eventData)
            sleep(5)

    except Exception as e:
        print("Exception: ", e)


import string
import time
from copy import deepcopy
from math import sqrt
from random import shuffle, sample, random, choice
from typing import Set, List
import numpy as np
from tensorflow.python.keras.utils.np_utils import to_categorical

from utils import Grid, Region_map, Rule, Move, calc_dim, calc_moveset, EMPTY, Case

class Sudoku:
    grid: Grid
    solution: Grid
    region_map: Region_map
    ruleset: Set[Rule]
    dim: int
    moveset: Set[Move]
    solve_time: float
    move_history: List[List[int]]

    def __init__(self, region_map: Region_map, ruleset: Set[Rule]):
        self.region_map = region_map
        self.ALL_COORD = self.build_all_coord()
        self.dim = calc_dim(self.region_map)
        self.moveset = calc_moveset(self.dim)
        self.ruleset = ruleset
        self.move_history = list()
        self.cycle = 0
        self.grid = [[EMPTY if case is not None else None for case in row] for row in self.region_map]

    def __str__(self):
        return '\n'.join([
            '  '.join([
                hex(self.grid[i][j])[2:].upper()
                if self.grid[i][j] is not EMPTY else '.'
                if self.grid[i][j] is not None else '#'
                for j in range(len(self.grid[i]))])
            for i in range(len(self.grid))
        ]) + f"\n{sum([case in self.moveset for row in self.grid for case in row])} / " \
             f"{sum([case is not None for row in self.grid for case in row])}"

    @classmethod
    def solve_grid(cls, region_map: Region_map, ruleset: Set[Rule], grid: Grid, show=False, solution=None):
        sudoku = cls(region_map, ruleset)
        for row in range(len(grid)):
            for col in range(len(grid)):
                if grid[row][col] in sudoku.moveset:
                    sudoku.place(row, col, grid[row][col])
        start = time.perf_counter()
        if show:
            print(sudoku)

        sudoku.solution = solution
        sudoku.solve(find=1)
        if show:
            print(sudoku)
        return time.perf_counter() - start, sudoku.calc_valid_proportion()

    def is_case(self, row: int, col: int) -> bool:
        return 0 <= row < len(self.grid) and 0 <= col < len(self.grid[row])

    def calc_valid_proportion(self) -> float:
        return sum((self.grid[i][j] == self.solution[i][j] for i, j in self.ALL_COORD)) / len(self.ALL_COORD)

    def place(self, row: int, col: int, move: Move) -> None:
        self.move_history.append([row, col, move])
        self.grid[row][col] = move

    def calc_possible_moves(self, row: int, col: int) -> Set[Move]:
        moveset = set(self.moveset)
        for rule in self.ruleset:
            moveset &= rule(self, row, col)
        return moveset

    def solve_thin(self):
        return Sudoku.solve(self, find=2)

    def solve(self, find: int = 1, save: bool = False) -> int:
        def solve_aux(row: int = 0, col: int = 0, find: int = 1) -> int:
            if row == len(self.grid):
                return True
            next_row, next_col = row + (col == (len(self.grid[row]) - 1)), (col + 1) % len(self.grid[row])
            if self.grid[row][col] != EMPTY:
                return solve_aux(next_row, next_col, find)
            l_move = list(self.calc_possible_moves(row, col))
            shuffle(l_move)
            found = 0
            for move in l_move:
                self.place(row, col, move)
                found += solve_aux(next_row, next_col, find-found)
                if found >= find:
                    return found
            self.place(row, col, EMPTY)
            return found

        self.move_history.clear()
        res = solve_aux(0, 0, find)
        if save:
            self.solution = deepcopy(self.grid)
        return res

    def thin_random(self, difficulty: int):
        case_order = [(i, j) for i in range(len(self.grid)) for j in range(len(self.grid[i]))]
        shuffle(case_order)
        thinned_sudoku = deepcopy(self)
        for i, j in case_order:
            self.place(i, j, EMPTY)
            if self.solve_thin() == 1 and (random() * 100) <= difficulty:
                thinned_sudoku.place(i, j, EMPTY)
            self.update_as(thinned_sudoku)

    def build_all_coord(self) -> List[Case]:
        return [(i, j) for i in range(len(self.region_map)) for j in range(len(self.region_map[i]))]

    def update_as(self, other_sudoku: 'Sudoku'):
        self.grid = deepcopy(other_sudoku.grid)

    def old_variation_permutation(self) -> Grid:
        l_map = list(self.moveset)
        shuffle(l_map)
        d_map = {old_move: l_map[i] for i, old_move in enumerate(self.moveset)}
        return [
            [d_map[move] if move in self.moveset else move for move in row]
            for row in self.grid
        ]

    def variation_rotation(self) -> None:
        for grid in [self.grid, self.solution]:
            grid[:] = [[grid[j-1][-i] for j in range(1, self.dim+1)] for i in range(1, self.dim+1)]

    def variation_shuffle_row(self) -> None:
        dim_reg = int(sqrt(self.dim))
        dim_gp = list(map(lambda x: x*dim_reg, range(dim_reg)))
        i_sample = sample(list(range(dim_reg)), dim_reg)
        j_sample = sample(dim_gp, len(dim_gp))
        for grid in [self.grid, self.solution]:
            grid[:] = [grid[i+j] for j in j_sample for i in i_sample]

    def variation_symmetry_horizontal(self) -> None:
        for grid in [self.grid, self.solution]:
            grid[:] = grid[::-1]

    def variation_symmetry_diagonal(self) -> None:
        for grid in [self.grid, self.solution]:
            grid[:] = [[grid[self.dim-j][self.dim-i]for j in range(1, self.dim+1)] for i in range(1, self.dim+1)]

    def build_variation(self, degree: int) -> 'Sudoku':
        sudoku_variation = deepcopy(self)
        l_func_variation = [
                    func for func in dir(self.__class__)
                    if func.startswith("variation_")
                ]
        for i in range(degree):
            func_variation = getattr(
                self.__class__,
                choice(l_func_variation)
            )
            func_variation(sudoku_variation)
        return sudoku_variation

    def string_to_grid(self, string: str) -> Grid:
        d_map = {hex(move)[2:]: move for move in sorted(self.moveset | {0})}
        return [[d_map[x] for x in string[i*self.dim:(i+1)*self.dim]] for i in range(self.dim)]

    def grid_to_string(self) -> str:
        moveset = set(string.printable[:self.dim + 1])
        d_map = {i: move for i, move in enumerate(sorted(moveset))}
        return ''.join(''.join([d_map[x] for x in row]) for row in self.grid)

    def string_to_tensor(self, string_grid: str) -> np.array:
        moveset = set(string.printable[:self.dim + 1])
        d_map = {move: i for i, move in enumerate(sorted(moveset))}
        flat = np.array(
            [np.reshape([d_map[move] for move in string_grid], (self.dim, self.dim))]
        )
        return to_categorical(flat).astype('float32')


# usr/bin/env python3
# -*- coding:utf-8- -*-
from gui import GUI
from tkinter import Tk

TEXT = {
    "title": "RA3录像自动分析工具",

    "info_1": "请先选择一个录像文件",
    "browse_file": "选择文件",
    "export_1": "导出流程图信息",
    "export_2": "导出所有命令信息",

    "No Support": "无法获取电脑的操作",
    "Invalid Faction": "不支持该阵营（帝国）",
    "Error": "报错: ",

    "OK": "成功导出到json文件: \n",
    "name": "玩家名",
    "faction": "阵营",
    "team": "队伍",

    "About": "关于作者",
    "More": "详细信息",

    "Author": "该工具作者是大爽歌.\n"
              "他的b站: https://space.bilibili.com/149259132\n"
              "他的GitHub: https://github.com/BigShuang"
              "他的CSDN: https://blog.csdn.net/python1639er\n",
    "Details": "详情请查看该工具的readme文档: \n"
               "https://github.com/BigShuang/Red-Alert-3-Battle-Flow-Chart",

    "map_name": "地图名: ",
    "factions": {
        "S": "苏联",
        "E": "帝国",
        "A": "盟军",
        "Rnd": "随机"
    }
}

win = Tk()
win.title(TEXT["title"])
GUI(win, TEXT, width=700, height=400, bg="#ddd")
win.mainloop()


# encoding:utf-8
from common.douyu_request import dyreq
from common.logger import logger
from common.config import conf
from common.get_secrets import get_secrets
from lxml import etree
import re
import math
import requests

def get_badge():
    """
    :return: 获取具有粉丝牌的房间号、当前经验、升级所需经验、升级还需要的经验
    """
    badges_url = "/member/cp/getFansBadgeList"
    badges = dyreq.request("get", badges_url)
    html = etree.HTML(badges.text, etree.HTMLParser())
    num = len(html.xpath('//*[@id="wrap"]/div/div[2]/div[2]/div[3]/table/tbody/tr'))
    re_now = r'(?<= )\d.*\d(?=\/\d)'
    re_up = r'(?<=\/)\d.*\d'
    badge_dict = {}
    exp_list = []
    for path in range(num):
        path += 1
        room_id = html.xpath('//*[@id="wrap"]/div/div[2]/div[2]/div[3]/table/tbody/tr[%s]/@data-fans-room' % path)[
            0]
        anchor = html.xpath('//*[@id="wrap"]/div/div[2]/div[2]/div[3]/table/tbody/tr[%s]/td[2]/a/text()' % path)[0]
        exp = html.xpath('//*[@id="wrap"]/div/div[2]/div[2]/div[3]/table/tbody/tr[%s]/td[3]/text()' % path)[0]
        exp_now = float(re.findall(re_now, exp)[0])
        up_grade = float(re.findall(re_up, exp)[0])
        exp_need = round((up_grade - exp_now), 1)
        exp_list.append(exp_need)
        badge_dict[room_id] = anchor
    return badge_dict, exp_list

def get_room_list():
    """
    :return:通过数组方式返回房间号
    """
    room_list = []
    for room in get_badge()[0]:
        room_list.append(room)
    return room_list

def get_need_exp():
    """
    :return:通过数组方式返回升级所需经验
    """
    nums = conf.get_conf_list('selfMode', 'giftCount')
    for i in range(len(get_badge()[1])):
        days_require = int(math.ceil(int(math.ceil(get_badge()[1][i])) / int(nums[i])))
        logger.info("房间号%s升级还需%s点经验,还需%s天" % (get_room_list()[i], get_badge()[1][i], days_require))
        barkurl = get_secrets('BARKURL')
        if barkurl.startswith('http'):
            requests.get(barkurl + "/房间号%s/升级还需%s点经验,+%s天" % (get_room_list()[i], get_badge()[1][i], days_require))

if __name__ == '__main__':
    a = get_room_list()
    get_need_exp()


import csv
from Functions import IsNumber, TypeChange

class SmallData:
    # Each SmallData object corresponds to a line of intensities for 1 unique compound
    ID = 0
    mz = ''
    driftTime = 0 # Not required, samples with a drift time will be marked so
    intensities = []
    name = ''   # Name of experiment, from filename.d
    lineNum = 0
    maxInt = 0  # Only the first SmallData per medData has a maxInt(ensity)
    width = 0   # Width of sample area
    height = 0  # Height of sample area (must have the same units as width )

def OpenTSV(filename):
    # Reads in a .tsv Skyline export
    bigData = []    # Holds all the data
    medData = []    # One medData has all the data for one unique m/z image
    maxInt = 0

    with open(filename) as tsv:
        reader = csv.reader(tsv, 'excel-tab')
        next(reader) # Skips the header
        for line in reader: # Scan the data into an array of smallData objects, File must be .tsv with comma separated sublists
            smallData = SmallData()
            smallData.ID = line[0]
            smallData.mz = line[1]
            smallData.driftTime = float(line[2])
            smallData.intensities = TypeChange(line[4].split(','), int)
            for intensity in smallData.intensities:
                if intensity > maxInt:
                    maxInt = intensity ## Find a better way to find the max int of a whole image
            smallData.name = line[5]
            # Determines line number by scanning the last places of the filename.
            # Assumes filename in the vein of experiment_conditions_line999.d
            if IsNumber(line[6][-3]): # Just add another if statement if you have more than 1000 lines
                smallData.lineNum = int(line[6][-3:])
            elif IsNumber(line[6][-2]):
                smallData.lineNum = int(line[6][-2:])
            else:
                smallData.lineNum = int(line[6][-1])
            try:
                if (smallData.ID == medData[-1].ID):
                    medData.append(smallData)
                else:
                    medData[0].maxInt = maxInt
                    bigData.append(medData)
                    maxInt = 0
                    medData = []
                    medData.append(smallData)
            except IndexError:
                medData.append(smallData)
    medData[0].maxInt = maxInt
    bigData.append(medData)
    return(bigData)

def OpenTxt(filename):
    # Reads in a txt file (created in Imaging.py)
    medData = []
    settings = []

    with open(filename) as txt:
        settings = txt.readline().rstrip().split()
        i = 1
        for line in txt.readlines():
            smallData = SmallData()
            smallData.lineNum = i
            smallData.intensities = TypeChange(line.split(), int)
            if 'DT' in filename:
                smallData.mz = filename[-21:-13]
                smallData.driftTime = filename[-9:-4]
            else:
                smallData.mz = filename[-9:-4]
            medData.append(smallData)
            i += 1

    maxInt = 0
    for smallData in medData:
        for intensity in smallData.intensities:
            if intensity > maxInt:
                maxInt = intensity
        smallData.name = settings[2]
        smallData.width = int(settings[0])
        smallData.height = int(settings[1])
    medData[0].maxInt = maxInt
    return(medData)