import csv
import gc
import pickle as pkl

import numpy as np

from collections import Counter
from datetime import datetime
from pathlib import Path

from hdbscan import HDBSCAN
from gensim.models.doc2vec import Doc2Vec
from cuml.cluster import HDBSCAN as gpu_HDBSCAN
from cuml.cluster import DBSCAN, KMeans
from sklearn.metrics import calinski_harabasz_score, davies_bouldin_score
from cuml.metrics.cluster.silhouette_score import cython_silhouette_score
from cuml.metrics.cluster.entropy import cython_entropy

def parse_distance_file(dataset, distance):
    if distance == 'wmd':
        mid_string = '_'.join(dataset.split('_')[:-1])
        size = int(dataset.split('_')[-1])
        if size == 300:
            size = 256
        filename = f'{distance}_dist_{mid_string}_{size}.npy'
    else:
        filename = f'{distance}_dist_{dataset}.npy'
    return filename

def export_results(path, data=None):
    if not path.is_file():
        with open(path, 'w') as file:
            writer = csv.writer(file)
            writer.writerow(data.keys())
            if data is not None:
                writer.writerow(data.values())
    else:
        with open(path, 'a') as file:
            writer = csv.writer(file)
            writer.writerow(data.values())

def load_labels(file):
    with open(file, 'rb') as handle:
        labels = pkl.load(handle)

    return labels

def export_labels(labels, file):
    with open(file, 'wb') as handle:
        pkl.dump(labels, handle, protocol=pkl.HIGHEST_PROTOCOL)

def get_kmeans(data, dataset, distance, n_clusters):
    labels_file = Path(labels_dir, f'labels_km_{dataset}_{n_clusters:02d}_{distance}.pkl')
    if labels_file.is_file():
        labels = load_labels(labels_file)
    else:
        # distance_file = Path(data_dir, distance, parse_distance_file(dataset, distance))

        # if distance_file.is_file():
            # data = np.load(distance_file)
        # else:
            # print(f'{distance.capitalize()} distance matrix not found.')

        km = KMeans(n_clusters=n_clusters)
        km.fit(data)
        labels = km.labels_.tolist()
        export_labels(labels, labels_file)

    return labels

def get_dbscan(data, dataset, distance, epsilon, min_pts):
    labels_file = Path(labels_dir, f'labels_dbscan_{dataset}_{str(epsilon)[:7]}_{min_pts:02d}_{distance}.pkl')
    if labels_file.is_file():
        labels = load_labels(labels_file)
    else:
        distance_file = Path(data_dir, distance, parse_distance_file(dataset, distance))
        if distance_file.is_file():
            data = np.load(distance_file)
            distance = 'precomputed'
        else:
            print(f'{distance.capitalize()} distance matrix not found.')

        db = DBSCAN(eps=epsilon,
                    min_samples=min_pts,
                    metric=distance
                   ).fit(data)
        labels = db.labels_
        export_labels(labels, labels_file)

    return labels

def get_hdbscan(data, dataset, distance, min_clt_size, min_samples):
    labels_file = Path(labels_dir, f'labels_hdbscan_{dataset}_{min_clt_size:02d}_{min_samples:02d}_{distance}.pkl')
    if labels_file.is_file():
        labels = load_labels(labels_file)
    else:
        if distance == 'euclidean':
            clusterer = gpu_HDBSCAN(
                min_cluster_size=min_clt_size,
                min_samples=min_samples,
                metric=distance
                ).fit(data)
            labels = clusterer.labels_
        else:
            distance_file = Path(data_dir, distance, parse_distance_file(dataset, distance))
            if distance_file.is_file():
                data = np.load(distance_file)
                distance = 'precomputed'
                clusterer = HDBSCAN(
                    min_cluster_size=min_clt_size,
                    min_samples=min_samples,
                    metric=distance
                    ).fit(data.astype(np.float64))
                labels = clusterer.labels_
            else:
                print(f'{distance.capitalize()} distance matrix not found. Terminating program.')
                exit()

        export_labels(labels, labels_file)

    return labels

def evaluate_cluster(data, labels, distance, method, n_clusters=None):

    results = {}

    if distance == 'wmd' or distance == 'km':
        distance = 'euclidean'

    if method != 'km':
        count_clust = Counter(labels)
        n_clusters = len([key for key in count_clust.keys() if key != -1])
        results['n_clusters'] = n_clusters

        if -1 in count_clust:
            n_noise = count_clust[-1]
            results['n_noise'] = n_noise

        clust_data = []
        clust_labs = []
        for i, label in enumerate(labels):
            if label != -1:
                clust_data.append(data[i])
                clust_labs.append(labels[i])
    else:
        clust_data = data
        clust_labs = labels
        n_clusters = n_clusters
        results['n_clusters'] = n_clusters

    clust_data = np.asarray(clust_data)
    clust_labs = np.asarray(clust_labs)

    if n_clusters < 2:
        results.update({'sl_score': None, 'ch_score': None, 'db_score': None, 'entropy': None})

    else:
        results.update({
            'sl_score': cython_silhouette_score(clust_data, clust_labs, metric=distance),
            'ch_score': calinski_harabasz_score(clust_data, clust_labs),
            'db_score': davies_bouldin_score(clust_data, clust_labs),
            'entropy' : cython_entropy(clust_labs.astype(np.int32))
        })

    return results

def get_results(data, filename, labels, dataset, distance, method, **kwargs):
    if method=='km':
        n_clusters = kwargs['n_clusters']
        cls_res = evaluate_cluster(data, labels, distance, method, n_clusters)
    elif method=='dbscan':
        cls_res = evaluate_cluster(data, labels, distance, method)
        cls_res = {'epsilon': kwargs['epsilon'], 'min_pts': kwargs['min_pts'], 'nn': kwargs['nn']}  | cls_res
    elif method=='hdbscan':
        cls_res = evaluate_cluster(data, labels, distance, method)
        cls_res = {'min_clt_size': kwargs['min_clt_size'], 'min_samples': kwargs['min_samples']}  | cls_res

    results = {'distance': distance, 'dataset': dataset} | cls_res
    export_results(Path(eval_dir, filename + '.csv'), results)

def main(path, method, distance, **kwargs):

    filename = f'eval_{method}_{int(datetime.today().timestamp())}'

    model = Doc2Vec.load(str(path))
    data = model.dv.vectors
    dataset = '_'.join(path.stem.split('_')[1:])

    t0 = datetime.now()

    if method=='km':
        for nclust in range(6,21): # range(2,51), range(21,101) range(2,6)
            print(f'Performing {method} and evaluating for {dataset} points with {nclust} clusters')
            labels = get_kmeans(data, dataset, distance, nclust)
            get_results(data, filename, labels, dataset, distance, method, n_clusters=nclust)

    elif method=='dbscan':
        nn_file = Path(nn_dir, f"nn_{'_'.join(path.stem.split('_')[1:])}.npy")
        eps_range = np.load(nn_file)
        # eps_range = [round(e*0.01,3) for e in range(20,101)]
        min_pts_range = [min_pts for min_pts in range(2,16)]
        for nn, epsilon in eps_range:
            for min_pts in min_pts_range:
                print(f'Performing {method} and evaluating for {dataset} points with epsilon {epsilon} and {min_pts} minimum points')
                labels = get_dbscan(data, dataset, distance, epsilon, min_pts)
                get_results(data, filename, labels, dataset, distance, method, epsilon=epsilon, min_pts=min_pts, nn=nn)
                gc.collect()

    elif method=='hdbscan':
        mcs_range = [mcs for mcs in range(2,6)] # range(2,10)
        min_samples_range = [ms for ms in range(21,25)] #  range(2,25)
        for mcs in mcs_range:
            for minsample in min_samples_range:
                print(f'Performing {method} and evaluating for {dataset} points with {mcs} minimum cluster size and {minsample} minimum sample size')
                labels = get_hdbscan(data, dataset, distance, mcs, minsample)
                get_results(data, filename, labels, dataset, distance, method, min_clt_size=mcs, min_samples=minsample)
                gc.collect()

    t1 = datetime.now()
    print(f'Took: {t1-t0}')

data_dir = Path('data/interim')
labels_dir = Path(data_dir, 'labels_3')
eval_dir = Path(data_dir, 'evals_5')
models_dir = Path('models')
nn_dir = Path(data_dir, 'nn')

mod_paths = sorted([mod_path for mod_path in Path(models_dir).glob('d2v*.model')])

start = datetime.now()

# for path in mod_paths:
#     nn_file = Path(nn_dir, f"nn_{'_'.join(path.stem.split('_')[1:])}.npy")
#     epsilons = np.load(nn_file)
#     print(path.stem)
#     print(epsilons)

# KMeans
# for p in mod_paths:
#     main(p, 'km', 'euclidean')
#     gc.collect()

# DBSCAN
# for p in mod_paths:
    # main(p, 'dbscan', 'euclidean')
    # gc.collect()
    # main(p, 'dbscan', 'cosine')
    # gc.collect()
    # main(p, 'dbscan', 'wmd')
    # gc.collect()
    # main(p, 'dbscan', 'l2')
    # gc.collect()

# HDBSCAN
for p in mod_paths[2:]:
    # main(p, 'hdbscan', 'euclidean')
    # gc.collect()
    # main(p, 'hdbscan', 'cosine')
    # gc.collect()
    main(p, 'hdbscan', 'wmd')
    gc.collect()
    # main(p, 'hdbscan', 'l2')
    # gc.collect()

print(f'Finished all datasets. Took {datetime.now()-start}')


from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import generics
from rest_framework import status
from datetime import date
from django.utils import timezone
from core_api.models import *
from core_api.serializers import *

# from core_api.send_mail import send_mail

#########################################################################
##  Start WhoAmI  ##
#########################################################################
# Whoami for basic
@api_view(['GET',])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def WhoAmIView(request):
    if request.method == 'GET':
        data = {}
        account = Account.objects.get(pk=request.user.user_id)
        data['username'] = account.username
        data['email'] = account.email
        data['mobile_number'] = account.mobile_number
        data['user_id'] = account.user_id
        data['user_type'] = account.user_type

        shop = Shop.objects.get(shop_license=request.user.shop)
        data['shop_name'] = shop.shop_name
        data['shop_address_1'] = shop.shop_address
        data['shop_address_2'] = shop.shop_address_2
        data['shop_address_3'] = shop.shop_address_3
        data['invoice_prefix'] = shop.invoice_prefix
        data['gsit'] = shop.gsit
        data['shop_logo'] = shop.shop_logo.url

        try:
            # Bank details
            bank = Bankdetails.objects.filter(shop=shop)
            data['bank_name'] = bank[0].bank_name
            data['bank_account_no'] = bank[0].bank_account_no
            data['bank_branch'] = bank[0].bank_branch
            data['bank_ifsc'] = bank[0].bank_ifsc
            data['upi_id'] = bank[0].UPI_id
        except:
            return Response(data)

        return Response(data)

@api_view(['POST'])
def FirstPingView(request):
    if request.method == 'POST':
        # Variables
        data = {}
        valuation = monthly_revenue = monthly_profit = weekly_revenue = weekly_profit = 0

        #########################################################################
        # Basic data
        shop = Shop.objects.get(shop_license=request.user.shop)
        data['shop_license'] = shop.shop_license
        data['shop_name'] = shop.shop_name
        data['shop_logo'] = shop.shop_logo.url

        account = Account.objects.get(pk=request.user.user_id)
        data['username'] = account.username
        data['mobile_number'] = account.mobile_number

        products = Products.objects.filter(shop=request.user.shop)
        data['no_products'] = len(products)
        for i in range(0, len(products)):
            valuation += (products[i].product_buy_price *
                          products[i].product_stock)
        data['valuation'] = valuation
        #########################################################################

        #########################################################################
        # Initial Analytics
        current = datetime.now(tz=timezone.utc)
        past = current - timedelta(days=7)
        monthly_orders = Order.objects.filter(time_stamp__month=current.month)
        for i in range(0, len(monthly_orders)):
            monthly_revenue += monthly_orders[i].order_price
            for j in range(0, len(monthly_orders[i].order_items.all())):
                current_pd = monthly_orders[i].order_items.all()[j].product
                monthly_profit += (current_pd.product_mrp_price -
                                   current_pd.product_buy_price) * monthly_orders[i].order_items.all()[j].quantity
        data['monthly_profit'] = monthly_profit
        data['monthly_revenue'] = monthly_revenue

        weekly_orders = Order.objects.filter(time_stamp__range=[past, current])
        for i in range(0, len(weekly_orders)):
            weekly_revenue += weekly_orders[i].order_price
            for j in range(0, len(weekly_orders[i].order_items.all())):
                current_pd = weekly_orders[i].order_items.all()[j].product
                weekly_profit += (
                    current_pd.product_mrp_price - current_pd.product_buy_price
                ) * weekly_orders[i].order_items.all()[j].quantity
        data['weekly_profit'] = weekly_profit
        data['weekly_revenue'] = weekly_revenue
        #########################################################################

        return Response(data)

@api_view(['POST'])
def check_username(request):
    if request.method == 'POST':
        isExist = False
        account = Account.objects.filter(
            shop=request.user.shop).all()
        data = request.data.get('data').lower()
        print(data)
        for i in range(0, len(account)):
            if str(data) == account[i].username:
                isExist = True
            if str(data) == account[i].email:
                isExist = True
        if isExist:
            message = {'message': "taken"}
        else:
            message = {'message': "available"}

        return Response(message)

#########################################################################
##  End WhoAmI  ##
#########################################################################

#########################################################################


import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.ticker import FormatStrFormatter

from .datasets import sets

Y_MIN = -0.1
Y_MAX = 1.3
Y_MAX_COLD = 6.5

def plot_speedup():
    plt.style.use(["./custom-ggplot.mplstyle", "./matplotlibrc"])

    for name, title, roundtrip, data in sets:

        labels  = []
        markers = []
        lines   = []
        table   = None

        for data_per_lib in data:

            for label, filename, marker, line in data_per_lib:

                data = pd.read_csv(filename.format(1), comment=";")

                if not data["success"].isin(["Warmup", "Success"]).all():
                    raise ValueError(f"Error processing file {file}:\n"
                                     f"\tNot all runs were Warmup/Success.")

                def max_unary(x): return max(1, x)

                data = data[data["success"] == "Success"]
                data["n"] = data["nx"] \
                        * data["ny"].apply(max_unary) \
                        * data["nz"].apply(max_unary)

                if roundtrip:
                    data["Time_FFT [ms]"] = data["Time_FFT [ms]"].add(data["Time_iFFT [ms]"])

                data = data[["n", "Time_FFT [ms]"]]
                data_grouped = data.groupby(["n"])

                data_agg = data_grouped.agg(np.median)
                data_agg.columns = [label]
                data_agg.reset_index(level=0, inplace=True)
                data_agg.set_index("n", inplace=True)

                if table is not None:
                    table = pd.merge(table, data_agg, on="n")
                else:
                    table = data_agg

                labels  += [label]
                markers += [marker]
                lines   += [line]

        table = table.div(table["Skylake MKL"], axis=0)
        table = table.applymap(lambda x: 1/x)

        axes = table.plot(kind="line")
        for i, line in enumerate(axes.get_lines()):
            line.set_marker(markers[i])
            line.set_linestyle(lines[i])

        ymax = Y_MAX_COLD if "cold" in name else Y_MAX
        axes.set_xscale('log', base=2)
        axes.set_xticks(table.index)

        if not "case1" in name:
            axes.get_xaxis().set_major_formatter(FormatStrFormatter('%d'))

        xmin, xmax = plt.xlim()
        xminNew = 2**(np.log2(xmin)-0.05*np.log2(xmax/xmin))
        xmaxNew = 2**(np.log2(xmax)+0.05*np.log2(xmax/xmin))
        plt.xlim((xminNew, xmaxNew))
        plt.ylim((Y_MIN, ymax))

        axes.legend(labels, loc="upper left", bbox_to_anchor=(1.0, 1.0))

        plt.title(title)
        plt.xlabel("problem size (# samples)")
        plt.ylabel("performance ratio compared with Skylake")

        plt.savefig(f"plots/fft-speedup-{name}.pdf")

        plt.close()


### parse hmmer output
import pandas as pd
from Bio import SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
import argparse

parser = argparse.ArgumentParser(description = 'Extract sequences of interest')
parser.add_argument('-i', '--infile', help = 'input file', required=True)
parser.add_argument('-m', '--inhmm', help = 'hmmer output that lists hmm hits and is provided as input')
parser.add_argument('-o', '--outfile', help = 'output filename', required=True)
args = vars(parser.parse_args())

hmm = pd.read_csv(args["inhmm"], sep = "\t", comment = "#", header =None)
#hmm = pd.read_csv("/Users/jy17/Dropbox/Tick/borrelia/borreliaseq/results/annotation/short_read2/UMA8_pfam.out", sep = "\t", comment = "#", header =None)
seqs_to_extract = hmm[0].tolist()
seqs_to_extract = [i.split()[0] for i in seqs_to_extract]

outlist = []
for seq_record in SeqIO.parse(args["infile"], "fasta"):
  if seq_record.id in seqs_to_extract:
    outlist.append(seq_record)
    #print(seq_record.id)

SeqIO.write(outlist,args["outfile"], format = "fasta")


from django.shortcuts import render
from django.forms import ModelForm

from election.models import LGA, AgentName, AnnouncedPuResults, Party, PollingUnit

# Create your views here.

class PuResultsForm(ModelForm):
    class Meta:
        model = AnnouncedPuResults
        fields = '__all__'

def home(request):
    template_name = 'home.html'
    return_query = {'polling_unit': '', 'result': ''}

    if request.method == "POST":
        q = request.POST['unitid']
        unit = PollingUnit.objects.get(polling_unit_number=q)
        parties = Party.objects.all()
        results = {}
        for party in parties:
            results[party.partynmae] = 0

        if unit:
            result = AnnouncedPuResults.objects.filter(
                polling_unit_uniqueid=unit.polling_unit_id)
            for i in result:
                results[i.party_abbreviation] += i.party_score

            return_query = {'polling_unit': unit, 'result': results}

        return render(request, template_name, return_query)

    return render(request, template_name)

def lga(request):
    template_name = 'lga.html'
    lgas = LGA.objects.all()
    context = {'lgas': lgas}
    results = {}
    context['results'] = results
    parties = Party.objects.all()
    for party in parties:
        results[party.partynmae] = 0

    if request.method == 'POST':
        lga_name = request.POST['lga']
        try:
            lga = LGA.objects.get(lga_name=lga_name)
            if lga:
                context['lga'] = lga
                lga_polling_units = PollingUnit.objects.filter(
                    lga_id=lga.lga_id)
                # print(lga_polling_units)

                for polling_unit in lga_polling_units:
                    res = AnnouncedPuResults.objects.filter(
                        polling_unit_uniqueid=polling_unit.polling_unit_id)
                    print('============')
                    print(res)
                    print('============')

                    for i in res:
                        # print(i)
                        results[i.party_abbreviation] = results[i.party_abbreviation] + i.party_score
                    # context['results'] = results

            else:
                context['lga'] = ['LGA not found']
        except:
            pass

        return render(request, template_name, context)
    # return
    return render(request, template_name, context)

def addpage(request):
    template_name = 'addpage.html'
    parties = Party.objects.all()

    if request.method == 'POST':
        for party in parties:
            AnnouncedPuResults.objects.create(
                polling_unit_uniqueid=request.POST['polling_id'],
                entered_by_user=request.POST['user'],
                user_ip_address=request.POST['ip'],
                party_abbreviation=party.partyid,
                party_score=int(request.POST[party.partyid])
            )
            print(request.POST)
    return render(request, template_name, {'parties': parties})


"""Code to compute internal coordinates and their derivatives."""
import logging
import pickle
from collections import defaultdict
from functools import partial
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union

import numpy as np
import pandas as pd
from geometric.internal import Angle, Dihedral, Distance
from rdkit import Chem
from rdkit.Chem import AllChem
from scipy.optimize import (
    LinearConstraint,
    NonlinearConstraint,
    OptimizeResult,
    minimize,
)

from . import chem, utils

BACKBONE_ATOM_LABELS = ["N", "Calpha", "CO"]
BACKBONE_ATOM_IDS = [0, 1, 2]
BACKBONE_ATOM_ID_TO_LABEL = dict(zip(BACKBONE_ATOM_IDS, BACKBONE_ATOM_LABELS))

def get_macrocycle_distances_and_angles_from_file(
    fname: Union[str, Path]
) -> Dict[str, Union[List[str], List[int], pd.DataFrame]]:
    with open(fname, "rb") as f:
        ensemble_data = pickle.load(f)
    mol = ensemble_data["rd_mol"]

    # Get macrocycle indices in N to C direction starting at an N
    macrocycle_idxs = chem.get_macrocycle_idxs(mol, n_to_c=True)
    if macrocycle_idxs is None:
        raise ValueError(f"Could not get macrocycle indices for '{fname}'")
    assert len(macrocycle_idxs) % 3 == 0
    reps = len(macrocycle_idxs) // 3
    atom_labels = BACKBONE_ATOM_LABELS * reps
    atom_ids = BACKBONE_ATOM_IDS * reps

    distances = get_macrocycle_bond_distances(mol, macrocycle_idxs)
    angles = get_macrocycle_bond_angles(mol, macrocycle_idxs)
    dihedrals = get_macrocycle_dihedrals(mol, macrocycle_idxs)

    return {
        "atom_labels": atom_labels,
        "atom_ids": atom_ids,
        "distance": distances,
        "angle": angles,
        "dihedral": dihedrals,
    }

def get_macrocycle_bond_idxs(macrocycle_idxs: List[int]) -> List[Tuple[int, int]]:
    return list(utils.get_overlapping_sublists(macrocycle_idxs, 2))

def get_macrocycle_angle_idxs(macrocycle_idxs: List[int]) -> List[Tuple[int, int, int]]:
    # Shift indices by one
    macrocycle_idxs = macrocycle_idxs.copy()
    macrocycle_idxs.insert(0, macrocycle_idxs.pop())
    return list(utils.get_overlapping_sublists(macrocycle_idxs, 3))

def get_macrocycle_dihedral_idxs(
    macrocycle_idxs: List[int],
) -> List[Tuple[int, int, int, int]]:
    # For the first dihedral to correspond to the bond between the first two atoms, the
    # first element in the list has to be the last atom
    macrocycle_idxs = macrocycle_idxs.copy()
    macrocycle_idxs.insert(0, macrocycle_idxs.pop())
    return list(utils.get_overlapping_sublists(macrocycle_idxs, 4))

def get_macrocycle_bond_distances(mol: Chem.Mol, macrocycle_idxs: List[int]) -> pd.DataFrame:
    bond_idxs = get_macrocycle_bond_idxs(macrocycle_idxs)
    macrocycle_distances = defaultdict(list)

    # Dictionary keys are the first atoms of each bond
    for conformer in mol.GetConformers():
        for atom_idx, bond_atom_idxs in zip(macrocycle_idxs, bond_idxs):
            macrocycle_distances[atom_idx].append(
                AllChem.GetBondLength(conformer, *bond_atom_idxs)
            )

    # Each row in dataframe are the distances for a conformer
    distance_df = pd.DataFrame(data=macrocycle_distances)
    distance_df.index.name = "conf_idx"

    return distance_df

def get_macrocycle_bond_angles(mol: Chem.Mol, macrocycle_idxs: List[int]) -> pd.DataFrame:
    angle_idxs = get_macrocycle_angle_idxs(macrocycle_idxs)
    macrocycle_angles = defaultdict(list)

    # Dictionary keys are the central atoms of each angle
    for conformer in mol.GetConformers():
        for atom_idx, angle_atom_idxs in zip(macrocycle_idxs, angle_idxs):
            macrocycle_angles[atom_idx].append(AllChem.GetAngleRad(conformer, *angle_atom_idxs))

    # Each row in dataframe are the angles for a conformer
    angle_df = pd.DataFrame(data=macrocycle_angles)
    angle_df.index.name = "conf_idx"

    return angle_df

def get_macrocycle_dihedrals(mol: Chem.Mol, macrocycle_idxs: List[int]) -> pd.DataFrame:
    dihedral_idxs = get_macrocycle_dihedral_idxs(macrocycle_idxs)
    macrocycle_dihedrals = defaultdict(list)

    # Dictionary keys are the first atoms of each bond
    for conformer in mol.GetConformers():
        for atom_idx, dihedral_atom_idxs in zip(macrocycle_idxs, dihedral_idxs):
            macrocycle_dihedrals[atom_idx].append(
                AllChem.GetDihedralRad(conformer, *dihedral_atom_idxs)
            )

    # Each row in dataframe are the dihedrals for a conformer
    dihedral_df = pd.DataFrame(data=macrocycle_dihedrals)
    dihedral_df.index.name = "conf_idx"

    return dihedral_df

def modify_macrocycle_geometry(
    mol: Chem.Mol,  # Should have one conformer with 3D geometry
    bond_dists: Union[np.ndarray, pd.Series],
    bond_angles: Union[np.ndarray, pd.Series],
    dihedrals: Union[np.ndarray, pd.Series],
    macrocycle_idxs: Optional[List[int]] = None,
    shift: int = 0,  # Shift indices to the right by this amount
) -> Chem.Mol:
    """Sequentially set distances, angles, and dihedrals of macrocycle.

    Extraneous degrees of freedom are skipped, i.e., last distance, first and last angle, first and
    last two dihedrals.
    """
    assert len(bond_dists) == len(bond_angles) == len(dihedrals)
    if macrocycle_idxs is None:
        assert isinstance(bond_dists, pd.Series)
        macrocycle_idxs = bond_dists.index
        bond_dists = bond_dists.to_numpy()
    else:
        assert len(macrocycle_idxs) == len(bond_dists)

    if isinstance(bond_angles, pd.Series):
        bond_angles = bond_angles.loc[macrocycle_idxs].to_numpy()
    if isinstance(dihedrals, pd.Series):
        dihedrals = dihedrals.loc[macrocycle_idxs].to_numpy()

    macrocycle_idxs = list(map(int, macrocycle_idxs))

    mol = Chem.Mol(mol)  # Make copy

    # Circular shift (also works for negative shift)
    macrocycle_idxs = macrocycle_idxs[-shift:] + macrocycle_idxs[:-shift]
    bond_dists = np.roll(bond_dists, shift)
    bond_angles = np.roll(bond_angles, shift)
    dihedrals = np.roll(dihedrals, shift)

    rwmol = Chem.RWMol(mol)

    # Temporarily remove all bonds so that we can set all internal coordinates without
    # running into issues due to atoms being in a ring (e.g., when there's a proline)
    removed_bonds = {}
    for bond in mol.GetBonds():
        idx1 = bond.GetBeginAtomIdx()
        idx2 = bond.GetEndAtomIdx()
        bt = bond.GetBondType()
        rwmol.RemoveBond(idx1, idx2)
        removed_bonds[(idx1, idx2)] = bt

    # Add back in all but the last ring bond so that we can set distances and angles in
    # the macrocycle sequentially
    bond_idxs = get_macrocycle_bond_idxs(macrocycle_idxs)
    for idx1, idx2 in bond_idxs[:-1]:
        key = (idx1, idx2)
        key = key if key in removed_bonds else (idx2, idx1)
        bt = removed_bonds[key]
        rwmol.AddBond(idx1, idx2, bt)
        del removed_bonds[key]

    # Initialize ring info so that we don't get errors when setting internal coords
    Chem.GetSSSR(rwmol)

    conf = rwmol.GetConformer()
    angle_idxs = get_macrocycle_angle_idxs(macrocycle_idxs)
    dihedral_idxs = get_macrocycle_dihedral_idxs(macrocycle_idxs)

    # Skip bond that we removed
    for i in range(len(bond_idxs) - 1):
        idxs = bond_idxs[i]
        val = float(bond_dists[i])
        AllChem.SetBondLength(conf, *idxs, val)

    # Skip first and last bond angle because we removed bond
    for i in range(1, len(angle_idxs) - 1):
        idxs = angle_idxs[i]
        val = float(bond_angles[i])
        AllChem.SetAngleRad(conf, *idxs, val)

    # Skip first and last two dihedrals because we removed bond
    for i in range(1, len(dihedral_idxs) - 2):
        idxs = dihedral_idxs[i]
        val = float(dihedrals[i])
        AllChem.SetDihedralRad(conf, *idxs, val)

    # Add back in all the other bonds
    for (idx1, idx2), bt in removed_bonds.items():
        rwmol.AddBond(idx1, idx2, bt)

    new_mol = rwmol.GetMol()
    return new_mol

def set_macrocycle_geometry_with_best_dists(
    mol: Chem.Mol,
    bond_dists: Union[np.ndarray, pd.Series],
    bond_angles: Union[np.ndarray, pd.Series],
    dihedrals: Union[np.ndarray, pd.Series],
    macrocycle_idxs: Optional[List[int]] = None,
) -> Chem.Mol:
    """Sequentially set distances, angles, and dihedrals of macrocycle starting at each atom and
    return the molecule that has the smallest distance error."""
    min_dist_sse = float("inf")
    mol_best_dists = None

    if macrocycle_idxs is None:
        assert isinstance(bond_dists, pd.Series)
        macrocycle_idxs = bond_dists.index.tolist()

    for shift in range(len(macrocycle_idxs)):
        mol_tmp = modify_macrocycle_geometry(
            mol,
            bond_dists,
            bond_angles,
            dihedrals,
            macrocycle_idxs=macrocycle_idxs,
            shift=shift,
        )

        actual_bond_dists = get_macrocycle_bond_distances(mol_tmp, macrocycle_idxs).loc[0]
        distance_sse = np.sum((actual_bond_dists - bond_dists) ** 2)

        if distance_sse < min_dist_sse:
            min_dist_sse = distance_sse
            mol_best_dists = mol_tmp

    return mol_best_dists

class InternalCoordinates:
    def __init__(
        self,
        bond_idxs: Optional[List[Tuple[int, int]]] = None,
        angle_idxs: Optional[List[Tuple[int, int, int]]] = None,
        dihedral_idxs: Optional[List[Tuple[int, int, int, int]]] = None,
    ) -> None:
        if bond_idxs is None:
            bond_idxs = []
        if angle_idxs is None:
            angle_idxs = []
        if dihedral_idxs is None:
            dihedral_idxs = []

        self.distances = [Distance(*idxs) for idxs in bond_idxs]
        self.angles = [Angle(*idxs) for idxs in angle_idxs]
        self.dihedrals = [Dihedral(*idxs) for idxs in dihedral_idxs]

    def compute_distances(self, xyz: np.ndarray) -> np.ndarray:
        return np.array([distance.value(xyz) for distance in self.distances])

    def compute_angles(self, xyz: np.ndarray) -> np.ndarray:
        return np.array([angle.value(xyz) for angle in self.angles])

    def compute_dihedrals(self, xyz: np.ndarray) -> np.ndarray:
        return np.array([dihedral.value(xyz) for dihedral in self.dihedrals])

    def compute_distance_jacobian(self, xyz: np.ndarray) -> np.ndarray:
        return np.array([distance.derivative(xyz).ravel() for distance in self.distances])

    def compute_angle_jacobian(self, xyz: np.ndarray) -> np.ndarray:
        return np.array([angle.derivative(xyz).ravel() for angle in self.angles])

    def compute_dihedral_jacobian(self, xyz: np.ndarray) -> np.ndarray:
        return np.array([dihedral.derivative(xyz).ravel() for dihedral in self.dihedrals])

class RingInternalCoordinates(InternalCoordinates):
    """Create internal coordinate object for given ring indices containing all bonds, angles, and
    dihedrals in the ring."""

    def __init__(self, ring_idxs: List[int]) -> None:
        # The bond, angle, and dihedral indices are NOT numbered based on ring_idxs,
        # instead they correspond to generic indices for a monocyclic ring (i.e.,
        # indices from 0 to number of atoms in the ring minus one). ring_idxs is only
        # needed in order to extract the correct Cartesian coordinates when provided
        # with a Chem.Mol object
        atom_idxs = list(range(len(ring_idxs)))
        bond_idxs = get_macrocycle_bond_idxs(atom_idxs)  # Pairs
        angle_idxs = get_macrocycle_angle_idxs(atom_idxs)  # Triples
        dihedral_idxs = get_macrocycle_dihedral_idxs(atom_idxs)  # Quartets
        super().__init__(bond_idxs, angle_idxs, dihedral_idxs)

        self.ring_idxs = ring_idxs

    def to_cartesian(
        self,
        mol: Chem.Mol,
        distance_vals: Union[np.ndarray, pd.Series],
        angle_vals_target: Union[np.ndarray, pd.Series],
        dihedral_vals_target: Union[np.ndarray, pd.Series],
        angles_as_constraints: bool = False,
        angle_vals_max_devs: Optional[Union[np.ndarray, pd.Series]] = None,
        use_orientation_constraints: bool = False,
        skip_opt: bool = False,  # Just return the results from setting coords in sequence
        print_warning: bool = True,
        return_result_obj: bool = False,
    ) -> Union[pd.DataFrame, Tuple[pd.DataFrame, OptimizeResult]]:
        """Get the Cartesian coordinates of ring atoms in a molecule given a set of redundant (and
        possibly inconsistent) internal bond angles and dihedrals such that the bond distances are
        exactly satisfied."""
        if isinstance(distance_vals, pd.Series):
            distance_vals = distance_vals.loc[self.ring_idxs]
        if isinstance(angle_vals_target, pd.Series):
            angle_vals_target = angle_vals_target.loc[self.ring_idxs]
        if isinstance(dihedral_vals_target, pd.Series):
            dihedral_vals_target = dihedral_vals_target.loc[self.ring_idxs]
        if angle_vals_max_devs is not None:
            if isinstance(angle_vals_max_devs, pd.Series):
                angle_vals_max_devs = angle_vals_max_devs.loc[self.ring_idxs]

        # Get initial guess using sequential approach to setting angles/dihedrals, and
        # select the molecule with the distances that most closely match the true ones
        mol0 = set_macrocycle_geometry_with_best_dists(
            mol,
            distance_vals,
            angle_vals_target,
            dihedral_vals_target,
            macrocycle_idxs=self.ring_idxs,
        )

        xyz0 = mol0.GetConformer().GetPositions()[self.ring_idxs]

        if skip_opt:
            xyz_opt = xyz0

            class DummyResult:
                success = True

            result = DummyResult
        else:
            # Transform to canonical orientation and position
            trans_mat = compute_canonical_transform(xyz0)
            xyz0 = apply_affine_transform(xyz0, trans_mat)
            xyz0 = xyz0.ravel()

            if angles_as_constraints:
                obj_func = partial(
                    dihedral_loss,
                    internal_coords=self,
                    dihedral_vals_target=np.asarray(dihedral_vals_target),
                    grad=True,
                )
            else:
                obj_func = partial(
                    angle_and_dihedral_loss,
                    internal_coords=self,
                    angle_vals_target=np.asarray(angle_vals_target),
                    dihedral_vals_target=np.asarray(dihedral_vals_target),
                    grad=True,
                )

            # Equality constraint for distances
            distance_constraint = NonlinearConstraint(
                self.compute_distances,
                lb=np.asarray(distance_vals),
                ub=np.asarray(distance_vals),
                jac=self.compute_distance_jacobian,
            )
            constraints = [distance_constraint]

            if angles_as_constraints:
                angle_constraint = NonlinearConstraint(
                    self.compute_angles,
                    lb=np.asarray(angle_vals_target) - np.asarray(angle_vals_max_devs),
                    ub=np.asarray(angle_vals_target) + np.asarray(angle_vals_max_devs),
                    jac=self.compute_angle_jacobian,
                )
                constraints.append(angle_constraint)

            if use_orientation_constraints:
                # Constrain centroid to coincide with origin
                # Jacobian of centroid is the linear constraint matrix
                centroid_constraint = LinearConstraint(
                    compute_centroid_jacobian(xyz0),  # xyz0 only needed for matrix dimensions
                    lb=np.zeros(3),
                    ub=np.zeros(3),
                )
                # Constrain off-diagonal elements of gyration tensor to be zero, which means
                # that the principal axes of rotation are aligned with the x-, y-, and z-axes
                # Only need to constrain upper triangular part due to symmetry
                rotation_constraint = NonlinearConstraint(
                    lambda xyz: compute_gyration_tensor(xyz)[[0, 0, 1], [1, 2, 2]],
                    lb=np.zeros(3),
                    ub=np.zeros(3),
                    jac=lambda xyz: compute_gyration_tensor_derivative(xyz)[[0, 0, 1], [1, 2, 2]],
                )
                constraints.extend(
                    [
                        centroid_constraint,
                        rotation_constraint,
                    ]
                )

            result = minimize(
                obj_func,
                xyz0,
                constraints=constraints,
                jac=True,
                options=dict(maxiter=100),
            )
            if not result.success and print_warning:
                logging.warning(
                    f"Optimization terminated unsuccessfully with message: {result.message}"
                )
            xyz_opt = result.x

        angle_vals_opt = self.compute_angles(xyz_opt)
        dihedral_vals_opt = self.compute_dihedrals(xyz_opt)
        internal_coords_opt = pd.DataFrame(
            data={"angle": angle_vals_opt, "dihedral": dihedral_vals_opt}, index=self.ring_idxs
        )

        coords_opt = pd.DataFrame(
            data=xyz_opt.reshape(-1, 3), index=self.ring_idxs, columns=["x", "y", "z"]
        )
        coords_opt = pd.concat([coords_opt, internal_coords_opt], axis=1)

        if return_result_obj:
            return coords_opt, result
        return coords_opt

def compute_centroid(xyz: np.ndarray) -> np.ndarray:
    xyz = xyz.reshape(-1, 3)
    return np.mean(xyz, axis=0)

def compute_centroid_jacobian(xyz: np.ndarray) -> np.ndarray:
    # Jacobian is constant, xyz only needed for its size
    xyz = xyz.reshape(-1, 3)
    num_atoms = len(xyz)
    sum_jac_x = np.tile([1.0, 0.0, 0.0], num_atoms)
    sum_jac_y = np.tile([0.0, 1.0, 0.0], num_atoms)
    sum_jac_z = np.tile([0.0, 0.0, 1.0], num_atoms)
    return np.vstack([sum_jac_x, sum_jac_y, sum_jac_z]) / num_atoms

def compute_gyration_tensor(xyz: np.ndarray) -> np.ndarray:
    xyz = xyz.reshape(-1, 3)
    xyz = xyz - compute_centroid(xyz)
    return xyz.T @ xyz / len(xyz)

def compute_gyration_tensor_derivative(xyz: np.ndarray) -> np.ndarray:
    """Define this derivative as the 3D tensor where the derivative of element (i,j) of the
    gyration tensor is computed as a vector that is extended into the third dimension."""
    xyz = xyz.reshape(-1, 3)
    xyz = xyz - compute_centroid(xyz)
    x, y, z = xyz.T

    num_atoms = len(xyz)
    der = np.zeros((3, 3, num_atoms * 3))

    # Diagonal
    der[0, 0, ::3] = 2 * x
    der[1, 1, 1::3] = 2 * y
    der[2, 2, 2::3] = 2 * z

    # Derivative of xy & yx
    der[0, 1, ::3] = y
    der[0, 1, 1::3] = x
    der[1, 0] = der[0, 1]

    # Derivative of xz & zx
    der[0, 2, ::3] = z
    der[0, 2, 2::3] = x
    der[2, 0] = der[0, 2]

    # Derivative of yz & zy
    der[1, 2, 1::3] = z
    der[1, 2, 2::3] = y
    der[2, 1] = der[1, 2]

    return der / num_atoms

def compute_canonical_transform(xyz: np.ndarray) -> np.ndarray:
    """Compute 4x4 transformation matrix using homoegenous coordinates representing rotation and
    translation of the given Cartesian coordinates such that the principal axes correspond to the
    xyz-axes and the centroid is at the origin."""
    centroid = compute_centroid(xyz)
    gyration_tensor = compute_gyration_tensor(xyz)

    _, eig_vecs = np.linalg.eigh(gyration_tensor)
    eig_vecs = np.fliplr(eig_vecs)  # In order of largest to smallest eig val
    signs = np.where(eig_vecs.sum(axis=0) > 0, 1.0, -1.0)  # Choose appropriate signs
    rot_mat = (signs * eig_vecs).T

    trans_mat = np.eye(4)
    trans_mat[:3, :3] = rot_mat
    trans_mat[:3, 3] = -rot_mat @ centroid

    return trans_mat

def apply_affine_transform(xyz: np.ndarray, trans_mat: np.ndarray) -> np.ndarray:
    """Apply 4x4 transformation matrix to Cartesian coordinates."""
    xyz = xyz.reshape(-1, 3)

    # Get homogeneous coordinates
    xyz_hom = np.ones((len(xyz), 4))
    xyz_hom[:, :3] = xyz

    return (trans_mat @ xyz_hom.T).T[:, :3]

def angle_loss(
    xyz: np.ndarray,  # 1D array of flattened Cartesian coords
    internal_coords: InternalCoordinates,
    angle_vals_target: np.ndarray,
    grad: bool = False,  # Also compute and return analytical gradient
) -> Union[float, Tuple[float, float]]:
    """Compute squared error loss between target angles and angles computed from the given
    Cartesian coordinates.

    internal_coords must contain the appropriate angles that correspond to angle_vals_target when
    evaluated.
    """
    angle_vals = internal_coords.compute_angles(xyz)
    angle_diffs = angle_vals - angle_vals_target
    loss = np.sum(angle_diffs**2)

    if grad:
        angle_jac = internal_coords.compute_angle_jacobian(xyz)
        gradient = 2 * np.dot(angle_diffs, angle_jac)

        return loss, gradient

    return loss

def dihedral_loss(
    xyz: np.ndarray,  # 1D array of flattened Cartesian coords
    internal_coords: InternalCoordinates,
    dihedral_vals_target: np.ndarray,
    grad: bool = False,  # Also compute and return analytical gradient
) -> Union[float, Tuple[float, float]]:
    """Compute squared error loss between target dihedrals and dihedrals computed from the given
    Cartesian coordinates.

    internal_coords must contain the appropriate dihedrals that correspond to dihedral_vals_target
    when evaluated.
    """
    dihedral_vals = internal_coords.compute_dihedrals(xyz)
    dihedral_diffs = utils.modulo_with_wrapped_range(dihedral_vals - dihedral_vals_target)
    loss = np.sum(dihedral_diffs**2)

    if grad:
        dihedral_jac = internal_coords.compute_dihedral_jacobian(xyz)
        gradient = 2 * np.dot(dihedral_diffs, dihedral_jac)

        return loss, gradient

    return loss

def angle_and_dihedral_loss(
    xyz: np.ndarray,  # 1D array of flattened Cartesian coords
    internal_coords: InternalCoordinates,
    angle_vals_target: np.ndarray,
    dihedral_vals_target: np.ndarray,
    dihedral_weight: float = 1.0,  # Weight of dihedral loss relative to angle loss
    grad: bool = False,  # Also compute and return analytical gradient
) -> Union[float, Tuple[float, float]]:
    """Compute squared error loss between target angles/dihedrals and angles/dihedrals computed
    from the given Cartesian coordinates.

    internal_coords must contain the appropriate angles and dihedrals that correspond to
    angle_vals_target and dihedral_vals_target when evaluated.
    """
    angle_loss_val = angle_loss(
        xyz=xyz,
        internal_coords=internal_coords,
        angle_vals_target=angle_vals_target,
        grad=grad,
    )
    dihedral_loss_val = dihedral_loss(
        xyz=xyz,
        internal_coords=internal_coords,
        dihedral_vals_target=dihedral_vals_target,
        grad=grad,
    )

    if grad:
        angle_loss_val, angle_grad_val = angle_loss_val
        dihedral_loss_val, dihedral_grad_val = dihedral_loss_val
        gradient = angle_grad_val + dihedral_weight * dihedral_grad_val

    loss = angle_loss_val + dihedral_weight * dihedral_loss_val

    if grad:
        return loss, gradient
    return loss


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO

from stepper_motor import StepperMotor

# Instance the motor supplying GPIO ports, change mode and delay time
# Instancia al motor indicando los puertos GPIO a los que está conectado, cambia modo y tiempo de espera
motor = StepperMotor(12,16,20,21,3,0.002)

# Go 100 steps forward
# Avanza 100 pasos a la derecha
motor.goForward(100)

# Turns back mode to default
# Cambia el modo al predeterminado
motor.setMode(2)

# Go 150 steps backwards
# Avanza 150 pasos a la izquierda
motor.goBackwards(200)

GPIO.cleanup()


import os, sys, re
import requests
from urllib.parse import urljoin
from urllib.parse import urlparse
from bs4 import BeautifulSoup

def saveFullHtmlPage(url, pagepath='page', session=requests.Session(), html=None):
    """Save web page html and supported contents
        * pagepath : path-to-page
        It will create a file  `'path-to-page'.html` and a folder `'path-to-page'_files`
    """

    def savenRename(soup, pagefolder, session, url, tag, inner):
        if not os.path.exists(pagefolder): # create only once
            os.mkdir(pagefolder)
        for res in soup.findAll(tag):   # images, css, etc..
            if res.has_attr(inner): # check inner tag (file object) MUST exists
                try:
                    filename, ext = os.path.splitext(os.path.basename(res[inner])) # get name and extension
                    filename = re.sub('\W+', '', filename) + ext # clean special chars from name
                    u = urlparse(filename)
                    filename = u.path
                    fileurl = urljoin(url, res.get(inner))
                    filepath = os.path.join(pagefolder, filename)
                    # rename html ref so can move html and folder of files anywhere
                    res[inner] = os.path.join(os.path.basename(pagefolder), filename)
                    if not os.path.isfile(filepath): # was not downloaded
                        with open(filepath, 'wb') as file:
                            filebin = session.get(fileurl, timeout=10)
                            file.write(filebin.content)
                except Exception as exc:
                    print(exc, file=sys.stderr)
    if not html:
        sessionData = session.get(url)
        sessionData.encoding = 'utf-8'
        html = sessionData.text
    soup = BeautifulSoup(html, "html.parser")
    path, _ = os.path.splitext(pagepath)
    pagefolder = path+'/assets' # page contents folder
    tags_inner = {'img': 'src', 'link': 'href', 'script': 'src'} # tag&inner tags to grab
    for tag, inner in tags_inner.items(): # saves resource files and rename refs
        savenRename(soup, pagefolder, session, url, tag, inner)
    with open(path+'/index.html', 'wb') as file: # saves modified html doc
        file.write(soup.prettify('utf-8'))


import re

from django.conf import settings
from django.core.cache import cache

from f5.helpers.Log import Log

class Lock:
    def __init__(self, objectClass: any, o: dict, objectName: str = "", *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.assetId = ""
        self.partitionName = ""
        self.request = ""
        self.objectClass = objectClass
        self.objectName = objectName

        if "assetId" in o:
            self.assetId = str(o["assetId"])

        if "partitionName" in o:
            self.partitionName = str(o["partitionName"])

        if "request" in o:
            self.request = str(o["request"])

        # String or list of strings allowed, treat as list.
        if isinstance(self.objectClass, str):
            self.objectClass = [
                self.objectClass
            ]

        if self.objectName == "":
            self.objectName = "any"

    ####################################################################################################################
    # Public methods
    ####################################################################################################################

    def isUnlocked(self) -> bool:
        # @todo: isUnlocked() / lock() should be atomic.

        #     C    R    U    D
        # C   *    x    *    *
        #
        # R   x    v    x    x
        #
        # U   *    x    *    *
        #
        # D   *    x    *    *

        # *: yes, on different objects.
        # R: read for both singular (info) and plural (list); @todo: improve.
        # Workflows: "*" becomes "x": so always a big lock.

        table = {
            "POST": {
                "POST": "*",
                "GET": "x",
                "PATCH": "*",
                "DELETE": "*",
            },
            "GET": {
                "POST": "x",
                "GET": "v",
                "PATCH": "x",
                "DELETE": "x",
            },
            "PATCH": {
                "POST": "*",
                "GET": "x",
                "PATCH": "*",
                "DELETE": "*",
            },
            "DELETE": {
                "POST": "*",
                "GET": "x",
                "PATCH": "*",
                "DELETE": "*",
            },
        }

        try:
            # Request HTTP method.
            httpMethod = self.__httpMethod()
            if httpMethod:
                # Check if the API endpoint/s related to objectClass are locked for the asset and partition (if set), on objectName,
                # in regards of the HTTP method "compatibility" (see table).
                for oc in self.objectClass:
                    if oc:
                        if str(httpMethod) in table:
                            for method, compatibility in table[httpMethod].items():
                                entry = oc+":"+str(method)+":"+self.assetId+":"+self.partitionName

                                # <httpMethod>: {
                                #    "POST": "x",
                                #    "GET": "v",
                                #    "PATCH": "*",
                                #    "DELETE": "*",
                                # }

                                if compatibility == "x":
                                    # Always block if entry present (regardless of its value).
                                    c = cache.get(entry)
                                    # If entry present.
                                    if isinstance(c, dict):
                                        if "lock" in c:
                                            if isinstance(c["lock"], list):
                                                if c["lock"]:
                                                    Log.log("Locked on API.")
                                                    Log.log("Available locks: "+str(c))

                                                    return False

                                if compatibility == "*":
                                    # Block if entry present and objectName in the lock list.
                                    c = cache.get(entry)
                                    # If entry present.
                                    if isinstance(c, dict):
                                        if "lock" in c:
                                            if isinstance(c["lock"], list):
                                                if self.objectName in c["lock"]:
                                                    Log.log("Locked on object "+self.objectName)
                                                    Log.log("Available locks: "+str(c))

                                                    return False
        except Exception:
            pass

        return True

    def lock(self) -> None:
        lockedObjects = [self.objectName]

        # Mark the API endpoint/s related to objectClass as locked for the HTTP method,
        # asset and partition (if set), on objectName.
        # For example: pool:POST:1: = { "lock": ... }
        # For example: pool:POST:1:Common = { "lock": ... }

        # Possible values:
        #   Not set
        #   {'lock': ['any']}
        #   {'lock': ['objectName1', 'objectName2', ...]}
        #   {'lock': ['any', 'objectName3', ...]}

        try:
            httpMethod = self.__httpMethod() # request HTTP method.
            if httpMethod:
                for oc in self.objectClass:
                    if oc:
                        # @todo: a Redis cache transaction lock is needed here.
                        entry = oc+":"+str(httpMethod)+":"+self.assetId+":"+self.partitionName
                        c = cache.get(entry)

                        # If some locked objectName already set, add the current one.
                        if isinstance(c, dict):
                            if "lock" in c:
                                if self.objectName not in c["lock"]:
                                    c["lock"].append(self.objectName)

                                #lockedObjects = list(dict.fromkeys(c["lock"])) # deduplicate.
                                lockedObjects = c["lock"]

                        cache.set(entry, { "lock": lockedObjects }, timeout=settings.LOCK_MAX_VALIDITY)
                        Log.log("Lock set for "+entry+", which now values "+str(lockedObjects))
        except Exception:
            pass

    def release(self) -> None:
        # Release the lock for objectName for HTTP method/asset/partition.

        try:
            httpMethod = self.__httpMethod() # request HTTP method.
            if httpMethod:
                for oc in self.objectClass:
                    if oc:
                        entry = oc+":"+str(httpMethod)+":"+self.assetId+":"+self.partitionName
                        c = cache.get(entry)

                        if "lock" in c:
                            if isinstance(c["lock"], list):
                                c["lock"].remove(self.objectName)

                                if c["lock"]:
                                    # Overwrite if c["lock"] not empty.
                                    cache.set(entry, c, timeout=settings.LOCK_MAX_VALIDITY)
                                else:
                                    # Delete the entry completely.
                                    cache.delete(entry)

                                Log.log("Lock released for "+entry+"; now it values: "+str(cache.get(entry)))
        except Exception:
            pass

    ####################################################################################################################
    # Private methods
    ####################################################################################################################

    def __httpMethod(self):
        httpMethod = ""

        if self.request:
            try:
                matches = re.search(r".*:\ (.*)\ '\/", self.request)
                if matches:
                    httpMethod = str(matches.group(1)).strip()
            except Exception:
                pass

        return httpMethod


from sklearn.preprocessing import MinMaxScaler

data = [[-1, 2], [-0.5, 6], [0, 10], [1, 120]]

import pandas as pd
pd.DataFrame(data)

# 实例化
scaler = MinMaxScaler()
# fit，在这里本质是生成 min(x) 和 max(x)，如果 fit 报错了，使用 partial_fit 训练接口，
scaler = scaler.fit(data)
# 通过接口导出结果
result = scaler.transform(data)

# print(result)

# 训练和导出一步完成
result_ = scaler.fit_transform(data)
# 将归一化的结果逆转，归一化之前的数据
reverse = scaler.inverse_transform(result)
# print(reverse)
# 使用 MinMaxScaler 的参数 feature_range 实现将数据归一化到 [0, 1] 以外的范围中
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
scaler = MinMaxScaler(feature_range=[5, 10])
result = scaler.fit_transform(data)
# print(result)

# 使用 numpy 来实现归一化
import numpy as np

X = np.array([[1,2], [-0.5, 6], [0, 10], [1, 18]])
# -0.5
print(X.min())
# [-0.5, 2]
print(X.min(axis=0))
# [ 1.  -0.5  0.   1. ]
print(X.min(axis=1))
x_nor = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
print(x_nor)


# -*- coding: utf-8 -*-
from curling_tools.core.utils import get_default_model_url
from curling_tools.tournament_schenkel.views import (STBaseListView,
                                                     STBaseCreateView,
                                                     STBaseDetailView,
                                                     STBaseUpdateView,
                                                     STBaseDeleteView)

PREFIX_URL_TOURNAMENT = 'tournament/(?P<pk_tournament>\d+)/'
PREFIX_URL_ROUND = '%sschenkelround/(?P<pk_round>\d+)/' % PREFIX_URL_TOURNAMENT
PREFIX_URL_GROUP = '%sschenkelgroup/(?P<pk_group>\d+)/' % PREFIX_URL_ROUND

def ST_get_default_model_url(*args, **kwargs):
    # Get specific Initial Data
    initial_params = {
        'prefix_pattern': PREFIX_URL_TOURNAMENT,
        'prefix_name': 'tournament-',
        'list_view': STBaseListView,
        'detail_view': STBaseDetailView,
        'creation_view': STBaseCreateView,
        'update_view': STBaseUpdateView,
        'delete_view': STBaseDeleteView}
    for param, value in initial_params.items():
        if param not in kwargs:
            kwargs[param] = value
    # Return result of the default function
    return get_default_model_url(*args, **kwargs)


# -*- coding: utf-8 -*-
# @Time    : 2021/6/20 7:47 上午
# @Author  : Hui
# @File    : diffMain.py

import difflib
hd = difflib.HtmlDiff()
loads = ''
with open('D:\difflib\guihuatxt.txt','r') as load:
    loads = load.readlines()
    load.close()

mems = ''
with open('D:\difflib\zichan.txt', 'r') as mem:
    mems = mem.readlines()
    mem.close()

with open('diffout.html','a+') as fo:
    fo.write(hd.make_file(loads,mems))
    fo.close()


import socket
import threading
import pygame as pg
from const import *
from protocol import *
from GameObjects import *

dt = 0
clock = pg.time.Clock()
srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
srv.bind(ADDRESS)

try:
    while True:
        data, addr = srv.recvfrom(DATA_LEN)
        player = clients.get(addr)
        if player:
            player.set_inputs(data)
        else:
            clients[addr] = Player(addr, data)

        srv.sendto(get_state(dt), addr)
        dt = clock.tick(144)
except KeyboardInterrupt:
    print("bye")
finally:
    srv.close()


#!/usr/bin/python3
"""Class Square that inherits of Rectangle"""

from models.rectangle import Rectangle

class Square(Rectangle):
    """Class inherits of rectangle"""

    def __init__(self, size, x=0, y=0, id=None):
        """Method class constructor"""

        super().__init__(size, size, x, y, id)

    def __str__(self):
        """Public method __str__ that returns
        [Square] (<id>) <x>/<y> - <width>/<height>"""

        return f"[Square] ({self.id}) {self.x}/{self.y} - {self.width}"

    @property
    def size(self):
        """Getter function for size"""

        return self.width

    @size.setter
    def size(self, value):
        """Setter function for size"""

        self.width = value
        self.height = value

    def update(self, *args, **kwargs):
        """public method def update(self, *args):
        that assigns an argument to each attribute"""

        if len(args) > 0:
            for i in range(len(args)):
                if i == 0:
                    self.id = args[i]
                if i == 1:
                    self.size = args[i]
                if i == 2:
                    self.x = args[i]
                if i == 3:
                    self.y = args[i]
        else:
            for k in kwargs:
                setattr(self, k, kwargs[k])

    def to_dictionary(self):
        """Public method that return the dictionary
        representation of a square"""
        return {
            'id': self.id,
            'size': self.size,
            'x': self.x,
            'y': self.y,
            }


#------------------------------------------------
# file: nx-functions.py
# desc: defines functions used by the nx-server
#------------------------------------------------

from statistics import median
from statistics import mean
import networkx as nx
import collections
import json
import logging
import requests
import time

####################################
# nx request and response functions

#-----------------------------------------------
# name: nx_do_request()
# desc: performs a request
#-----------------------------------------------
def nx_do_request(request_url, request_payload=None):
    # These two lines enable debugging at httplib level (requests->urllib3->http.client)
    # You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
    # The only thing missing will be the response.body which is not logged.
    try:
        import http.client as http_client
    except ImportError:
        # Python 2
        import httplib as http_client

    http_client.HTTPConnection.debuglevel = 1

    # You must initialize loggi++*ng, otherwise you'll not see debug output.
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True

    # use empty user agent so server's Mod_Security don't complain
    headers= {
        "User-Agent":"",
        "Accept": "*/*",
        'Content-Type': 'application/json'
    }
    # try to get the json input from the server
    try:
        if(request_payload is not None):
            print("setting the data -", request_payload)
            return requests.post(request_url, headers=headers, data=json.dumps(request_payload),verify=False)
        else:
            print("getting the data")
            return requests.request("get", request_url, headers=headers, data=None).json()
    except Exception as e:
        print("ERROR: nx_do_request() - ", e)
        return None
## end nx_do_request()

#-----------------------------------------------
# name: do_request()
# desc: does a request
#-----------------------------------------------
def nx_do_request(request_url, request_payload=None):
    # These two lines enable debugging at httplib level (requests->urllib3->http.client)
    # You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
    # The only thing missing will be the response.body which is not logged.
    try:
        import http.client as http_client
    except ImportError:
        # Python 2
        import httplib as http_client

    http_client.HTTPConnection.debuglevel = 1

    # You must initialize loggi++*ng, otherwise you'll not see debug output.
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True

    # use empty user agent so server's Mod_Security don't complain
    headers= {
        "User-Agent":"",
        "Accept": "*/*",
        'Content-Type': 'application/json'
    }
    # try to get the json input from the server
    try:
        if(request_payload is not None):
            print("setting the data -", request_payload)
            return requests.post(request_url, headers=headers, data=json.dumps(request_payload),verify=False)
        else:
            print("getting the data")
            return requests.request("get", request_url, headers=headers, data=None).json()
    except Exception as e:
        print("ERROR: nx_do_request() - ", e)
        return None
# end nx_do_request()

########################################
# nx get/set/exec call input functions

#--------------------------------------------------------------
# name: nx_get_call_input()
# desc: gets the nx call object containing input to pass to nx
#---------------------------------------------------------------
def nx_get_call_input():
    return nx_do_request("http://www.kevlewis.com/projects/nx/nx-get-call-input.php")

#--------------------------------------------------------------------------
# name: nx_set_call_output()
# desc: sets the nx call object by updating the call object with new data
#--------------------------------------------------------------------------
def nx_set_call_output(output_json):
    return nx_do_request("http://www.kevlewis.com/projects/nx/nx-set-call-output.php", output_json)

#---------------------------------------------------------------
# name: nx_exec_call()
# desc: perform the networkx request
#---------------------------------------------------------------
def nx_exec_call(call_input):
    if(call_input is None):
        return None

    # check if there is a call object
    if(call_input["input"]["function_name"] == "erdos-renyi"):
        return nx_erdos_renyi_graph(call_input)

    if(call_input["input"]["function_name"] == "barabasi-albert"):
        return nx_barabasi_albert_graph(call_input)
    return None
# end nx_exec_call()

##---------------------------------------------------------
## name: nx_update_status()
## desc: updates the status of the call object
##---------------------------------------------------------
def nx_update_status(call_obj, percentage, message):
    status = call_obj["status"]
    status["message"] = message
    status["percentage"] = percentage
    nx_set_call_output(call_obj)

#######################################
# _barabasi albert graphs

##---------------------------------------------------------
## name: nx_barabasi_albert_graph()
## desc:
##---------------------------------------------------------
def nx_barabasi_albert_graph(call_obj):
    function_params = call_obj["input"]["function_params"]
    function_name = call_obj["input"]["function_name"]
    if(function_params is None):
        return

    n = int(function_params["n"])
    m = int(function_params["m"])
    t = int(function_params["t"])
    profiletypes = function_params["vprofiletype"]
    bcharts = bool(function_params["bcharts"])

     # run the er algorithm and return the graph
    output={}
    if(bcharts is False):
        nx_update_status(call_obj, "5", f"Network X Functions - starting barabasi_albert_graph on n={n}, m={m}.....")
        G = nx.barabasi_albert_graph(n, m, seed=None)
        nx_update_status(call_obj, "5", f"Network X Functions - finished barabasi_albert_graph on n={n}, m={m}.....")
        output["nodes"]=[list(G.nodes), None]
        output["edges"]=[list(G.edges), None]
    else:
        nx_update_status(call_obj, "5", f"Network X Functions - Starting ER Trails on n={n}, m={m}, t={t}.....")
        output["charts"] = do_ba_trails(n,m,t,profiletypes,call_obj)
        nx_update_status(call_obj, "90", f"Network X Functions - Completed ER Trails on n={n}, m={m}, t={t}.....")

    if(bcharts):
        output["charts"]["n"] = n
        output["charts"]["m"] = m
        output["charts"]["t"] = t
        output["charts"]["name"] = function_name
        output["charts"]["bcharts"] = bcharts

    # set the output object
    call_obj["output"] = output

    # set the status object
    call_obj["status"]["percentage"] = 100
    call_obj["status"]["message"] = "done"
    return call_obj
## end nx_barabasi_albert_graph()

def do_ba(n,m):
    return nx.barabasi_albert_graph(n, m, seed=None)

##--------------------------------------------------------------
## name: do_ba_trails()
## desc: returns histograms for t generated BA graphs
##--------------------------------------------------------------
def do_ba_trails(n, m, t, profiletypes, call_obj):
    if(t <= 0):
        return None
    histograms = {}
    for i in range(t):
        nx_update_status(call_obj, "50", f"started trail: {i+1}/{t}")
        G = do_ba(n, m)
        profile_sequences = compute_graph_profile_sequences(G, profiletypes)
        for profile_name, profile_sequence in profile_sequences.items():
           # if(profile_name == "deg"):
            try:
                histograms[profile_name] = get_profile_histogram(histograms[profile_name], profile_sequence)
            except:
                histograms[profile_name] = get_profile_histogram({}, profile_sequence)
            histograms[profile_name]["_name"] = profile_name
            nx_update_status(call_obj, "50", f"processing trail: {i+1}/{t} - generating histogram for profile: {profile_name}")

        nx_update_status(call_obj, "50", f"completed trail: {i+1}/{t}")

    return {
        "histograms": histograms,
        "n": n,
        "m": m,
        "t": t
    }
# end do_ba_trails()

#######################################
# erdos renyi graphs

#--------------------------------------------------------------
# name: nx_erdos_renyi_graph()
# desc: perform the er model
#--------------------------------------------------------------
def nx_erdos_renyi_graph(call_obj):
    # get the input
    if(call_obj["input"]):
        function_name = call_obj["input"]["function_name"]
        function_params = call_obj["input"]["function_params"]
        if(function_params):
            n = int(function_params["n"])
            p = float(function_params["p"])
            p2 = float(function_params["p2"])
            t = int(function_params["t"])
            pstep = float(function_params["pstep"])
            bcharts = bool(function_params["bcharts"])
            bpoverx = bool(function_params["bpoverx"])
            profiletypes = function_params["vprofiletype"]
            maxsequencelength = function_params["maxsequencelength"]
            maxvertexcount = function_params["maxvertexcount"]
        # end if
    # end if

    # run the er algorithm and return the graph
    output={}
    if(bcharts is False):
        G = do_er(n, p)
        output["nodes"]=[list(G.nodes), None]
        output["edges"]=[list(G.edges), None]
    elif(bpoverx):
        nx_update_status(call_obj, "5", f"Network X Functions - Starting ER Trails over P on n={n}, p1={p}, p2={p2}, pstep={pstep}, t={t}.....")
        output["charts"] = do_er_trails_over_p(n,p,p2,pstep,t,profiletypes,call_obj)
        nx_update_status(call_obj, "90", f"Network X Functions - Completed ER Trails over P on n={n}, p1={p}, p2={p2}, pstep={pstep}, t={t}.....")
    else:
        nx_update_status(call_obj, "5", f"Network X Functions - Starting ER Trails on n={n}, p={p}, t={t}.....")
        output["charts"] = do_er_trails(n,p,t,profiletypes,call_obj)
        nx_update_status(call_obj, "90", f"Network X Functions - Completed ER Trails on n={n}, p={p}, t={t}.....")

    if(bpoverx or bcharts):
        output["charts"]["name"] = function_name
        output["charts"]["n"] = n
        output["charts"]["p"] = p
        output["charts"]["p1"] = p
        output["charts"]["p2"] = p2
        output["charts"]["pstep"] = pstep
        output["charts"]["t"] = t
        output["charts"]["bcharts"] = bcharts
        output["charts"]["bpoverx"] = bpoverx
        output["charts"]["maxvertexcount"] = maxvertexcount
        output["charts"]["maxsequencelength"] = maxsequencelength

    # set the output object
    call_obj["output"] = output
    # set the status object
    call_obj["status"]["percentage"] = 100
    call_obj["status"]["message"] = "done"

    return call_obj
# end nx_erdos_renyi_graph()

##--------------------------------------------------------------
## name: do_er()
## desc: generates and returns an ER graph
##--------------------------------------------------------------
def do_er(n, p):
    return nx.erdos_renyi_graph(n, p, None, directed=False)
# end do_er()

##--------------------------------------------------------------
## name: do_er_trails()
## desc: returns histograms for t generated ER graphs
##--------------------------------------------------------------
def do_er_trails(n, p, t, profiletypes, call_obj):
    if(t <= 0):
        return None
    histograms = {}
    for i in range(t):
        nx_update_status(call_obj, "50", f"started trail: {i+1}/{t}")
        G = do_er(n, p)
        profile_sequences = compute_graph_profile_sequences(G, profiletypes)
        for profile_name, profile_sequence in profile_sequences.items():
           # if(profile_name == "deg"):
            try:
                histograms[profile_name] = get_profile_histogram(histograms[profile_name], profile_sequence)
            except:
                histograms[profile_name] = get_profile_histogram({}, profile_sequence)
            histograms[profile_name]["_name"] = profile_name
            nx_update_status(call_obj, "50", f"processing trail: {i+1}/{t} - generating histogram for profile: {profile_name}")

        nx_update_status(call_obj, "50", f"completed trail: {i+1}/{t}")

    return {
        "histograms": histograms,
        "n": n,
        "p": p,
        "t": t
    }
# end do_er_trails()

##-------------------------------------------------------------------------------------------
## name: do_er_trails_over_p()
## desc: returns the highest vertexcounts and sequence length over arange of probabilities
##-------------------------------------------------------------------------------------------
def do_er_trails_over_p(n,p1,p2,pstep,t,profiletypes,call_obj):
    p_over_x = []
    highest_vertex_counts = {}
    sequence_lengths = {}
    hists = []
    ##p1 = //int(p1*100)
    ##p2 = int(p2*100)
    ##pstep = int(pstep*100)

    print(n, p1, p2, pstep, t)

    p = p1
    while(p<=p2):
        ##for prob in range(p1,p2+1,pstep):
        ##    p = prob/100
        nx_update_status(call_obj, "50", f"started probability: {p}")
        do_er_trails_out = do_er_trails(n,p,t,profiletypes,call_obj)
        histograms = do_er_trails_out["histograms"]
        p_over_x.append(p)
        hists.append(histograms)
        for profile_name, histogram in histograms.items():
            try:
                highest_vertex_counts[profile_name].append(histogram["_max_vc"])
                sequence_lengths[profile_name].append(histogram["_max_len"])
            except:
                highest_vertex_counts[profile_name]=[]
                highest_vertex_counts[profile_name].append(histogram["_max_vc"])
                sequence_lengths[profile_name]=[]
                sequence_lengths[profile_name].append(histogram["_max_len"])
        nx_update_status(call_obj, "50", f"ending probability: {p}")

        if(p < 1.0 and (p + pstep) > 1.0):
            p = 1.0
        else:
            p += pstep

    return {
        "_p_over_x": p_over_x,
        "_max_vc": highest_vertex_counts,
        "_max_len": sequence_lengths,
        "_histograms": hists
    } ## end return
# end do_er_trails_over_p

##############################
# other functions

#---------------------------------------------------------------
# name: compute_graph_profile_sequences()
# desc: computes the neighborhood profiles for a graph
#---------------------------------------------------------------
def compute_graph_profile_sequences(G, profiletypes):
    g_profile = {}
    for v in list(G.nodes):
        v_profile = compute_vertex_profiles(v, G)
        for profile_type, bused in profiletypes.items():
            ##for profile_type, value in v_profile.items():
            if profile_type not in g_profile:
                g_profile[profile_type] = []
            #g_profile[profile_type].append(value)
            g_profile[profile_type].append(v_profile[profile_type])
        # end for
    # end for
    return g_profile
# end compute_graph_profile_sequences()

#-----------------------------------------------------------------
# name: compute_vertex_profiles()
# desc: computes the neighborhoodcompute_vertex_profiles profile for given vertex
#-----------------------------------------------------------------
def compute_vertex_profiles(v1, G):
    deg1 = G.degree[v1]
    imin = deg1
    imax = deg1
    emax = 0
    emin = 0 if (deg1 <= 0) else deg1
    esum = 0
    isum = deg1
    ifreq = deg1
    efreq = 0
    degtypes = {}
    degrees = []
    if(deg1 > 0):
        for v2 in list(G.adj[v1]):
            deg2 = G.degree[v2]
            degrees.append(deg2)
            isum += deg2
            esum += deg2
            if(degtypes is None or deg2 not in degtypes):
                degtypes[deg2] = 0
            degtypes[deg2] += 1
            imin = int(min(imin,deg2))
            emin = int(min(emin,deg2))
            imax = int(max(imax,deg2))
            emax = int(max(emax,deg2))
        ## end for
    ## end if

    ## set the profiles
    profiles = {}
    profiles["deg"] = deg1
    profiles["imin"] = imin
    profiles["emin"] = emin
    profiles["imax"] = imax
    profiles["emax"] = emax
    profiles["isum"] = isum
    profiles["esum"] = esum
    iavg = (isum/(deg1+1)) if deg1>0 else 0
    eavg = (esum/deg1) if deg1>0 else 0
    profiles["iavg"] = iavg
    profiles["eavg"] = eavg

    # exclusive
    ndegrees = list(degtypes.keys())
    ndegfreq = list(degtypes.values())
    ediv = len(ndegrees)    # diversity of degrees
    emed = median(ndegrees) # median
    ndegfreq.sort(reverse=True)

    efreq = freq(degtypes) #ndegfreq[0] if(len(ndegfreq)>0) else 0
    print(efreq)

    if(deg1 not in degtypes):
        degtypes[deg1] = 0

    # inclusive
    degtypes[deg1] += 1
    degrees.append(deg1)
    ndegrees = list(degtypes.keys())
    ndegfreq = list(degtypes.values())
    idiv = len(ndegrees)
    imed = median(ndegrees)
    ndegfreq.sort(reverse=True)   # sort reverse
    ifreq =  freq(degtypes) #ndegfreq[0] if(len(ndegfreq)>0) else 0

    # set the other profiles
    profiles["ifreq"] = ifreq
    profiles["efreq"] = efreq
    profiles["idiv"] = idiv
    profiles["ediv"] = ediv
    profiles["imed"] = imed
    profiles["emed"] = emed
    profiles["iran"] = imax-imin
    profiles["eran"] = emax-emin
    profiles["hap"] = deg1-eavg

    print(profiles)
    return profiles
# end compute_vertex_profiles()

##----------------------------------------------------------------------
## name: get_profile_histogram()
## desc: returns histograms the histogram for a given profile sequence
##----------------------------------------------------------------------
def get_profile_histogram(histogram, profile_sequence):
    if(len(histogram) == 0):
        histogram = {}
        histogram["_max_len"] = 0
        histogram["_max_vc"] = 0
        histogram["_min_len"] = 0
        histogram["_min_vc"] = 0
        histogram["_seq_prf"] = []
        histogram["_min"] = {}
        histogram["_sum"] = {}
        histogram["_avg"] = {}
        histogram["_max"] = {}
        histogram["_err"] = {}
        histogram["low_degree"] = 0
        histogram["high_degree"] = 0

    _min = histogram["_min"]
    _max = histogram["_max"]
    _sum = histogram["_sum"]
    _avg = histogram["_avg"]
    _err = histogram["_err"]
    _seq_prof = histogram["_seq_prf"]

    degreeCount = collections.Counter(profile_sequence)
    _seq_prof.append(dict(degreeCount))
    histogram["_max_len"] = max(histogram["_max_len"], len(degreeCount))     # the maximum length of the vertex in the sequence
    for degree, count in degreeCount.items():
        _min[degree] = min(_min.get(degree, count), count)
        _max[degree] = max(_max.get(degree, count), count)
        _sum[degree] = _sum.get(degree, 0) + count
        _avg[degree] = _sum[degree]
        _err[degree] = (_max.get(degree) - _min.get(degree)) * 0.5
        histogram["_max_vc"] = max(histogram["_max_vc"], _max.get(degree))     # highest vertex in the sequence
        histogram["low_degree"] = min(histogram["low_degree"], degree)
        histogram["high_degree"] = max(histogram["high_degree"], degree)

    return histogram
# end get_profile_histogram()

def freq(degfreq):
	freqdeg = []
	maxv = -1
	for deg, freq in degfreq.items():
		if(freq > maxv):
			maxv = freq
			freqdeg = [int(deg)]
		elif(freq == maxv):
			freqdeg.append(int(deg))
	if(maxv == -1):
		return 0
	return mean(freqdeg) if(len(freqdeg) > 1) else freqdeg[0]

#G = nx.gnp_random_graph(100,0.02)
#print(compute_graph_profile_sequences(G))
#print(json.dumps(do_er_trails(5,0.5,2), indent=2))
#print("")
#print("")
#print(json.dumps(do_er_trails_over_p(4, 0, 100, 33, 2), indent=2))
#do_er_trails(5,0.5,2)


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

import base64
import datetime
import hashlib
import itertools
import uuid

from Crypto.Cipher import AES

def chunked(it, n):
    """手动分页"""
    marker = object()
    for group in (list(g) for g in itertools.izip_longest(
            *[iter(it)] * n, fillvalue=marker)):
        if group[-1] is marker:
            del group[group.index(marker):]
        yield group

def order_list_and_paginate(target_list, sort_key, offset, limit, reverse=False):
    length = len(target_list)
    if length == 0:
        return target_list, length
    page = offset // limit
    target_list.sort(key=lambda x: x.get(sort_key), reverse=reverse)
    if limit <= 0:
        raise Exception("limit must gte 0")
    elif page > (length // limit):
        raise Exception("offset:[%s] out target_list paginate index[%s]" % (offset, length // limit))
    chunk_res = chunked(target_list, limit)
    chunk = next(itertools.islice(chunk_res, page, None))
    return chunk, length

# 检验是否全是中文字符
def is_all_chinese(strs):
    for _char in strs.decode("utf-8"):
        if not u'\u4e00' <= _char <= u'\u9fff':
            return False
    return True

# 检验是否含有中文字符
def is_contains_chinese(strs):
    for _char in strs.decode("utf-8"):
        if u'\u4e00' <= _char <= u'\u9fff':
            return True
    return False

# 生成uuid
def generate_uuid():
    return str(uuid.uuid4()).replace("-", "")

# 生成VMware vSphere平台ID
def generate_platform_id():
    return "-".join(["plf", generate_uuid()[0:8]])

class Dict(dict):
    __setattr__ = dict.__setitem__
    __getattr__ = dict.__getitem__

def dict_to_obj(dict_obj):
    if not isinstance(dict_obj, dict):
        return dict_obj
    d = Dict()
    for k, v in dict_obj.items():
        d[k] = dict_to_obj(v)
    return d

def get_format_datetime(m_datetime, s_format="%Y-%m-%dT%H:%M:%SZ"):
    """
    返回datetime的格式字符
    """
    return m_datetime.strftime(s_format)

def md5(s):
    if type(s) == str:
        s = s.encode("utf-8")
    m = hashlib.md5()
    m.update(s)
    return m.hexdigest()

def aes_decode(text):
    # 额外的处理

    text = str(text)
    enc = base64.urlsafe_b64decode(text)
    key = "MFwwDQYJKoZIhvcA"
    iv = key.decode('utf-8')
    key = key.decode('utf-8')
    cipher = AES.new(key, AES.MODE_CBC, iv)
    dec = cipher.decrypt(enc)
    return str(dec[0:-ord(dec[-1])].decode('utf-8'))

def format_value_by_timeslice(value, start_time, metric, interval):
    # 将数据按照时间片段分组
    monitor_data = []
    slice_start_time = start_time
    for item in value:
        item = float(item)
        item = 0 if item < 0 else item
        slice_end_time = slice_start_time + datetime.timedelta(seconds=20)
        if metric in ("cpu", "memory", "disk_us"):
            item = round(item / 100, 2)
        monitor_data.append({
            "start_time":
            slice_start_time.strftime("%Y-%m-%d %H:%M:%S"),
            "end_time":
            slice_end_time.strftime("%Y-%m-%d %H:%M:%S"),
            "avg_value":
            item
        })
        slice_start_time = slice_end_time

    # 获取实时数据
    if interval == 0:
        monitor_data = [monitor_data[-1]]
    else:
        # 获取最近interval分钟数据
        last_interval_data_count = interval * 3
        if len(monitor_data) >= last_interval_data_count:
            monitor_data = monitor_data[-last_interval_data_count:]
    return monitor_data


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json

from alipay.aop.api.response.AlipayResponse import AlipayResponse
from alipay.aop.api.domain.OpenBatch import OpenBatch

class KoubeiQualityTestCloudacptBatchQueryResponse(AlipayResponse):

    def __init__(self):
        super(KoubeiQualityTestCloudacptBatchQueryResponse, self).__init__()
        self._activity_id = None
        self._batch_list = None
        self._batch_num = None

    @property
    def activity_id(self):
        return self._activity_id

    @activity_id.setter
    def activity_id(self, value):
        self._activity_id = value
    @property
    def batch_list(self):
        return self._batch_list

    @batch_list.setter
    def batch_list(self, value):
        if isinstance(value, list):
            self._batch_list = list()
            for i in value:
                if isinstance(i, OpenBatch):
                    self._batch_list.append(i)
                else:
                    self._batch_list.append(OpenBatch.from_alipay_dict(i))
    @property
    def batch_num(self):
        return self._batch_num

    @batch_num.setter
    def batch_num(self, value):
        self._batch_num = value

    def parse_response_content(self, response_content):
        response = super(KoubeiQualityTestCloudacptBatchQueryResponse, self).parse_response_content(response_content)
        if 'activity_id' in response:
            self.activity_id = response['activity_id']
        if 'batch_list' in response:
            self.batch_list = response['batch_list']
        if 'batch_num' in response:
            self.batch_num = response['batch_num']


import sys

profit = 0

MENU = {
    "espresso": {
        "ingredients": {
            "water": 50,
            "coffee": 18,
        },
        "cost": 1.5,
    },
    "latte": {
        "ingredients": {
            "water": 200,
            "milk": 150,
            "coffee": 24,
        },
        "cost": 2.5,
    },
    "cappuccino": {
        "ingredients": {
            "water": 250,
            "milk": 100,
            "coffee": 24,
        },
        "cost": 3.0,
    }
}

resources = {
    "water": 300,
    "milk": 200,
    "coffee": 100,
}

# TODO 1. Prompt user
def whatCoffee():
    print("Hello, what would you like? (espresso/latte/cappuccino)")

# TODO 3. Print report
def printResources():
    water = resources["water"]
    milk = resources["milk"]
    coffee = resources["coffee"]

    print("Water: " + str(water) + 'ml')
    print("Milk: " + str(milk) + 'ml')
    print("Coffee: " + str(coffee) + 'g')

    if "money" in resources:
        money = resources["money"]
        print("Money: $" + str(money))

def checkIfSufficentResources(order_ingredients):
    """Returns True when sufficient amount of resources in dict"""
    for item in order_ingredients:
        if order_ingredients[item] >= resources[item]:
            print(f"Sorry there is not enough {item}.")
            return False
    return True

def processCoins():
    """Returns the total amount of coins inserted """
    print("Please insert coins.")
    amount = int(input("how many quarters? ")) * 0.25
    amount += int(input("how many dimes? ")) * 0.10
    amount += int(input("how many nickles? ")) * 0.05
    amount += int(input("how many pennies? ")) * 0.01
    return amount

def checkTransaction(moneyReceived, drinkCost):
    """ Returns true when the payment is accepted. """
    if moneyReceived >= drinkCost:
        change = round(moneyReceived - drinkCost, 2)
        print(f"Here is ${change} in change.")
        global profit
        profit += drinkCost
        return True
    else:
        print("Sorry thats not enough money. Money refunded")
        return False

def dispenseCoffee(drinkName, orderIngredients):
    """Deduct requred ingredients from machine"""
    for item in orderIngredients:
        resources[item] -= orderIngredients[item]
    print(f"Here is your {drinkName}  ☕. Enjoy")

whatCoffee()

is_on = True
while is_on:
    response = input()
    if response == "off":
        is_on = False
        sys.exit("Machine is off")
    elif response == "report":
        printResources()
    else:
        drink = MENU[response]
        if checkIfSufficentResources(drink["ingredients"]):
            payment = processCoins()
            if checkTransaction(payment, drink["cost"]):
                dispenseCoffee(response, drink["ingredients"])


import argparse
import pytest

from pytest_mock import MockerFixture
from unittest.mock import call as MockCall

from ahriman.application.application import Application
from ahriman.application.handlers import Update
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
from ahriman.models.result import Result

def _default_args(args: argparse.Namespace) -> argparse.Namespace:
    """
    default arguments for these test cases

    Args:
        args(argparse.Namespace): command line arguments fixture

    Returns:
        argparse.Namespace: generated arguments for these test cases
    """
    args.package = []
    args.dependencies = True
    args.dry_run = False
    args.exit_code = False
    args.increment = True
    args.aur = True
    args.local = True
    args.manual = True
    args.vcs = True
    args.refresh = 0
    args.username = "username"
    return args

def test_run(args: argparse.Namespace, package_ahriman: Package, configuration: Configuration, repository: Repository,
             mocker: MockerFixture) -> None:
    """
    must run command
    """
    args = _default_args(args)
    result = Result()
    result.add_success(package_ahriman)
    mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
    application_mock = mocker.patch("ahriman.application.application.Application.update", return_value=result)
    check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
    dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies",
                                     return_value=[package_ahriman])
    updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
    on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
    print_mock = mocker.patch("ahriman.application.application.Application.print_updates")

    _, repository_id = configuration.check_loaded()
    Update.run(args, repository_id, configuration, report=False)
    application_mock.assert_called_once_with([package_ahriman],
                                             Packagers(args.username, {package_ahriman.base: "packager"}),
                                             bump_pkgrel=args.increment)
    updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
    dependencies_mock.assert_called_once_with([package_ahriman], process_dependencies=args.dependencies)
    check_mock.assert_has_calls([MockCall(False, False), MockCall(False, False)])
    on_start_mock.assert_called_once_with()
    print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))

def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
                             mocker: MockerFixture) -> None:
    """
    must raise ExitCode exception on empty update list
    """
    args = _default_args(args)
    args.exit_code = True
    args.dry_run = True
    mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
    mocker.patch("ahriman.application.application.Application.updates", return_value=[])
    check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")

    _, repository_id = configuration.check_loaded()
    Update.run(args, repository_id, configuration, report=False)
    check_mock.assert_called_once_with(True, True)

def test_run_update_empty_exception(args: argparse.Namespace, package_ahriman: Package, configuration: Configuration,
                                    repository: Repository, mocker: MockerFixture) -> None:
    """
    must raise ExitCode exception on empty build result
    """
    args = _default_args(args)
    args.exit_code = True
    mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
    mocker.patch("ahriman.application.application.Application.update", return_value=Result())
    mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
    mocker.patch("ahriman.application.application.Application.with_dependencies", return_value=[package_ahriman])
    mocker.patch("ahriman.application.application.Application.print_updates")
    check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")

    _, repository_id = configuration.check_loaded()
    Update.run(args, repository_id, configuration, report=False)
    check_mock.assert_has_calls([MockCall(True, False), MockCall(True, True)])

def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
                     mocker: MockerFixture) -> None:
    """
    must run simplified command
    """
    args = _default_args(args)
    args.dry_run = True
    mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
    application_mock = mocker.patch("ahriman.application.application.Application.update")
    check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
    updates_mock = mocker.patch("ahriman.application.application.Application.updates")

    _, repository_id = configuration.check_loaded()
    Update.run(args, repository_id, configuration, report=False)
    updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
    application_mock.assert_not_called()
    check_mock.assert_called_once_with(False, pytest.helpers.anyvar(int))

def test_log_fn(application: Application, mocker: MockerFixture) -> None:
    """
    must print package updates
    """
    logger_mock = mocker.patch("logging.Logger.info")
    Update.log_fn(application, False)("hello")
    logger_mock.assert_has_calls([MockCall("hello")])


import time
import os
import json

# syslog = 'C:/Users/ironm/Desktop/putty.log'
# sleep_time_in_seconds = 1

# try:
#     with open(syslog, 'r', errors='ignore') as f:
#         while True:
#             for line in f:
#                 if line:
#                     print(line)
#                     # do whatever you want to do on the line
#             time.sleep(sleep_time_in_seconds)
# except IOError as e:
#     print('Cannot open the file {}. Error: {}'.format(syslog, e))

# if os.path.exists(syslog):
#     print("yes")
# with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), "Config.json"),'r',encoding="utf8") as f:
#     setup_dict = json.load(f)

# print(setup_dict["Others"]["WoDa"])
a = set()
a.add("ab")
a.add("cd")
print(a)
if "a" in ','.join(a):
    print("ya")
else:
    print("ne")

# print(','.join(a))


## this code migth not be needed, since dlib libraries uses GPU directly
##!!! NOT TESTED !! ####
# sudo apt-get update
# sudo apt-get install git cmake libpython3-dev python3-numpy
# cd ~/Downloads
# git clone --recursive https://github.com/dusty-nv/jetson-inference
# cd jetson-inference
# mkdir build
# cd build
# cmake ../
# --> jetson interface choose the deep leaning models,(scroll down) all images, all detection models, (facenet)--click "ok"
# --> choose to install pytorch, python 3.6
# make -j$(nproc)
# sudo make install
# sudo ldconfig
# -- webcam specs info program--
# sudo apt-get install v4l-utils
# check the webcam specs, pick one size
# v4l2-ctl -d /dev/video1 --list-formats-ext

import jetson.inference
import jetson.utils
import time
import cv2
import numpy as np
width=1280
height=720
cam=jetson.utils.gstCamera(width,height,'/dev/video1')  # this is for the webcam
# cam=jetson.utils.gstCamera(width,height,'0')
net=jetson.inference.imageNet('googlenet')
timeMark=time.time()
fpsFilter=0
timeMark=time.time()
font=cv2.FONT_HERSHEY_SIMPLEX
while True:
    frame, width, height = cam.CaptureRGBA(zeroCopy=1)
    classID, confidence = net.Classify(frame, width, height)
    item = net.GetClassDesc(classID)
    dt=time.time()-timeMark
    fps=1/dt
    fpsFilter=.95*fpsFilter+.05*fps
    timeMark=time.time()
    frame=jetson.utils.cudaToNumpy(frame,width,height,4)
    frame=cv2.cvtColor(frame, cv2.COLOR_RGBA2BGR).astype(np.uint8)
    cv2.putText(frame,str(round(fpsFilter,1))+'      '+item,(0,30),font,1,(0,0,255),2)
    cv2.imshow('webCam',frame)
    cv2.moveWindow('webCam',0,0)
    if cv2.waitKey(1)==ord('q'):
        break
cam.release()
cv2.destroyAllWindows()


"""From """

# R package names
packnames = ("ggplot2", "hexbin")

# R vector of strings
from rpy2.robjects.vectors import StrVector

# Selectively install what needs to be install.
# We are fancy, just because we can.
names_to_install = [x for x in packnames if not rpackages.isinstalled(x)]
if len(names_to_install) > 0:
    utils.install_packages(StrVector(names_to_install))


# id 52782682

def find_zero(hooms_numb: str, len_street: str) -> str:
    len_street: int = int(len_street)
    res: int = [len_street] * len_street
    position: int = 1

    flag: bool = False
    for up in range(0, len_street):
        if hooms_numb[up] == 0:
            position = 0
            flag = True

        if flag: res[up] = position
        position += 1

    for down in range(len_street-1, -1, -1):
        if hooms_numb[down] == 0:
            position = 0
        if res[down] > position: res[down] = position
        position += 1

    return (" ".join(map(str, res)))

def main():
    len_street = input()
    hooms_numb = list(map(int, input().split()))
    print(find_zero(hooms_numb, len_street))

if __name__ == '__main__':
    main()