#!/usr/bin/env python
# Copyright 2017 Calico LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =========================================================================

from __future__ import print_function
from optparse import OptionParser
import os
import random
import sys
import time

import h5py
import joblib
import matplotlib
matplotlib.use('PDF')
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import pyBigWig
from scipy.stats import spearmanr, poisson
import seaborn as sns
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.metrics import roc_auc_score, roc_curve, precision_recall_curve, average_precision_score
import tensorflow as tf

import basenji

'''
basenji_test.py

Test the accuracy of a trained model.

Notes
 -This probably needs work for the pooled large sequence version. I tried to
  update the "full" comparison, but it's not tested. The notion of peak calls
  will need to completely change; we probably want to predict in each bin.
'''

################################################################################
# main
################################################################################
def main():
    usage = 'usage: %prog [options] <params_file> <model_file> <test_hdf5_file>'
    parser = OptionParser(usage)
    parser.add_option('--ai', dest='accuracy_indexes', help='Comma-separated list of target indexes to make accuracy plots comparing true versus predicted values')
    parser.add_option('--clip', dest='target_clip', default=None, type='float', help='Clip targets and predictions to a maximum value [Default: %default]')
    parser.add_option('-d', dest='down_sample', default=1, type='int', help='Down sample test computation by taking uniformly spaced positions [Default: %default]')
    parser.add_option('-g', dest='genome_file', default='%s/assembly/human.hg19.genome'%os.environ['HG19'], help='Chromosome length information [Default: %default]')
    parser.add_option('--mc', dest='mc_n', default=0, type='int', help='Monte carlo test iterations [Default: %default]')
    parser.add_option('-o', dest='out_dir', default='test_out', help='Output directory for test statistics [Default: %default]')
    parser.add_option('--rc', dest='rc', default=False, action='store_true', help='Average the forward and reverse complement predictions when testing [Default: %default]')
    parser.add_option('-s', dest='scent_file', help='Dimension reduction model file')
    parser.add_option('--save', dest='save', default=False, action='store_true')
    parser.add_option('--shifts', dest='shifts', default='0', help='Ensemble prediction shifts [Default: %default]')
    parser.add_option('-t', dest='track_bed', help='BED file describing regions so we can output BigWig tracks')
    parser.add_option('--ti', dest='track_indexes', help='Comma-separated list of target indexes to output BigWig tracks')
    parser.add_option('-v', dest='valid', default=False, action='store_true', help='Process the validation set [Default: %default]')
    parser.add_option('-w', dest='pool_width', default=1, type='int', help='Max pool width for regressing nucleotide predictions to predict peak calls [Default: %default]')
    (options,args) = parser.parse_args()

    if len(args) != 3:
    	parser.error('Must provide parameters, model, and test data HDF5')
    else:
        params_file = args[0]
        model_file = args[1]
        test_hdf5_file = args[2]

    if not os.path.isdir(options.out_dir):
        os.mkdir(options.out_dir)

    options.shifts = [int(shift) for shift in options.shifts.split(',')]

    #######################################################
    # load data
    #######################################################
    data_open = h5py.File(test_hdf5_file)

    if not options.valid:
        test_seqs = data_open['test_in']
        test_targets = data_open['test_out']
        test_na = None
        if 'test_na' in data_open:
            test_na = data_open['test_na']

    else:
        test_seqs = data_open['valid_in']
        test_targets = data_open['valid_out']
        test_na = None
        if 'test_na' in data_open:
            test_na = data_open['valid_na']

    target_labels = [tl.decode('UTF-8') for tl in data_open['target_labels']]

    #######################################################
    # model parameters and placeholders

    job = basenji.dna_io.read_job_params(params_file)

    job['batch_length'] = test_seqs.shape[1]
    job['seq_depth'] = test_seqs.shape[2]
    job['num_targets'] = test_targets.shape[2]
    job['target_pool'] = int(np.array(data_open.get('pool_width', 1)))

    t0 = time.time()
    dr = basenji.seqnn.SeqNN()
    dr.build(job)
    print('Model building time %ds' % (time.time()-t0))

    # adjust for fourier
    job['fourier'] = 'train_out_imag' in data_open
    if job['fourier']:
        test_targets_imag = data_open['test_out_imag']
        if options.valid:
            test_targets_imag = data_open['valid_out_imag']

    # adjust for factors
    if options.scent_file is not None:
        t0 = time.time()
        test_targets_full = data_open['test_out_full']
        model = joblib.load(options.scent_file)

    #######################################################
    # test

    # initialize batcher
    if job['fourier']:
        batcher_test = basenji.batcher.BatcherF(test_seqs, test_targets, test_targets_imag, test_na, dr.batch_size, dr.target_pool)
    else:
        batcher_test = basenji.batcher.Batcher(test_seqs, test_targets, test_na, dr.batch_size, dr.target_pool)

    # initialize saver
    saver = tf.train.Saver()

    with tf.Session() as sess:
        # load variables into session
        saver.restore(sess, model_file)

        # test
        t0 = time.time()
        # test_loss, test_r2, test_cor, test_preds = dr.test(sess, batcher_test, rc_avg=options.rc, return_preds=True, down_sample=options.down_sample)
        # test_acc = dr.test(sess, batcher_test, rc_avg=options.rc, down_sample=options.down_sample)
        test_acc = dr.test(sess, batcher_test, rc=options.rc, shifts=options.shifts, mc_n=options.mc_n)

        if options.save:
            np.save('%s/preds.npy' % options.out_dir, test_acc.preds)
            np.save('%s/targets.npy' % options.out_dir, test_acc.targets)

        test_preds = test_acc.preds
        print('SeqNN test: %ds' % (time.time()-t0))

        # compute stats
        test_r2 = test_acc.r2(clip=options.target_clip)
        test_log_r2 = test_acc.r2(log=True, clip=options.target_clip)
        test_cor = test_acc.spearmanr()

        # print
        print('Test Loss:      %7.5f' % test_acc.loss)
        print('Test R2:        %7.5f' % test_r2.mean())
        print('Test log R2:    %7.5f' % test_log_r2.mean())
        print('Test SpearmanR: %7.5f' % test_cor.mean())

        acc_out = open('%s/acc.txt' % options.out_dir, 'w')
        for ti in range(len(test_r2)):
            print('%4d  %7.5f  %.5f  %.5f  %.5f  %s' % (ti, test_acc.target_losses[ti], test_r2[ti], test_log_r2[ti], test_cor[ti], target_labels[ti]), file=acc_out)
        acc_out.close()

        # clean up
        del test_acc

        # if test targets are reconstructed, measure versus the truth
        if options.scent_file is not None:
            compute_full_accuracy(dr, model, test_preds, test_targets_full, options.out_dir, options.down_sample)

    #######################################################
    # peak call accuracy

    # sample every few bins to decrease correlations
    ds_indexes_preds = np.arange(0, test_preds.shape[1], 8)
    ds_indexes_targets = ds_indexes_preds + (dr.batch_buffer // dr.target_pool)

    aurocs = []
    auprcs = []

    peaks_out = open('%s/peaks.txt' % options.out_dir, 'w')
    for ti in range(test_targets.shape[2]):
        if options.scent_file is not None:
            test_targets_ti = test_targets_full[:,:,ti]
        else:
            test_targets_ti = test_targets[:,:,ti]

        # subset and flatten
        test_targets_ti_flat = test_targets_ti[:,ds_indexes_targets].flatten().astype('float32')
        test_preds_ti_flat = test_preds[:,ds_indexes_preds,ti].flatten().astype('float32')

        # call peaks
        test_targets_ti_lambda = np.mean(test_targets_ti_flat)
        test_targets_pvals = 1 - poisson.cdf(np.round(test_targets_ti_flat)-1, mu=test_targets_ti_lambda)
        test_targets_qvals = np.array(ben_hoch(test_targets_pvals))
        test_targets_peaks = test_targets_qvals < 0.01

        if test_targets_peaks.sum() == 0:
            aurocs.append(0.5)
            auprcs.append(0)

        else:
            # compute prediction accuracy
            aurocs.append(roc_auc_score(test_targets_peaks, test_preds_ti_flat))
            auprcs.append(average_precision_score(test_targets_peaks, test_preds_ti_flat))

        print('%4d  %6d  %.5f  %.5f' % (ti,test_targets_peaks.sum(), aurocs[-1], auprcs[-1]), file=peaks_out)

    peaks_out.close()

    print('Test AUROC:     %7.5f' % np.mean(aurocs))
    print('Test AUPRC:     %7.5f' % np.mean(auprcs))

    #######################################################
    # BigWig tracks

    # NOTE: THESE ASSUME THERE WAS NO DOWN-SAMPLING ABOVE

    # print bigwig tracks for visualization
    if options.track_bed:
        if options.genome_file is None:
            parser.error('Must provide genome file in order to print valid BigWigs')

        if not os.path.isdir('%s/tracks' % options.out_dir):
            os.mkdir('%s/tracks' % options.out_dir)

        track_indexes = range(test_preds.shape[2])
        if options.track_indexes:
            track_indexes = [int(ti) for ti in options.track_indexes.split(',')]

        bed_set = 'test'
        if options.valid:
            bed_set = 'valid'

        for ti in track_indexes:
            if options.scent_file is not None:
                test_targets_ti = test_targets_full[:,:,ti]
            else:
                test_targets_ti = test_targets[:,:,ti]

            # make true targets bigwig
            bw_file = '%s/tracks/t%d_true.bw' % (options.out_dir,ti)
            bigwig_write(bw_file, test_targets_ti, options.track_bed, options.genome_file, bed_set=bed_set)

            # make predictions bigwig
            bw_file = '%s/tracks/t%d_preds.bw' % (options.out_dir,ti)
            bigwig_write(bw_file, test_preds[:,:,ti], options.track_bed, options.genome_file, dr.batch_buffer, bed_set=bed_set)

        # make NA bigwig
        bw_file = '%s/tracks/na.bw' % options.out_dir
        bigwig_write(bw_file, test_na, options.track_bed, options.genome_file, bed_set=bed_set)

    #######################################################
    # accuracy plots

    if options.accuracy_indexes is not None:
        accuracy_indexes = [int(ti) for ti in options.accuracy_indexes.split(',')]

        if not os.path.isdir('%s/scatter' % options.out_dir):
            os.mkdir('%s/scatter' % options.out_dir)

        if not os.path.isdir('%s/violin' % options.out_dir):
            os.mkdir('%s/violin' % options.out_dir)

        if not os.path.isdir('%s/roc' % options.out_dir):
            os.mkdir('%s/roc' % options.out_dir)

        if not os.path.isdir('%s/pr' % options.out_dir):
            os.mkdir('%s/pr' % options.out_dir)

        for ti in accuracy_indexes:
            if options.scent_file is not None:
                test_targets_ti = test_targets_full[:,:,ti]
            else:
                test_targets_ti = test_targets[:,:,ti]

            ############################################
            # scatter

            # sample every few bins (adjust to plot the # points I want)
            ds_indexes_preds = np.arange(0, test_preds.shape[1], 8)
            ds_indexes_targets = ds_indexes_preds + (dr.batch_buffer // dr.target_pool)

            # subset and flatten
            test_targets_ti_flat = test_targets_ti[:,ds_indexes_targets].flatten().astype('float32')
            test_preds_ti_flat = test_preds[:,ds_indexes_preds,ti].flatten().astype('float32')

            # take log2
            test_targets_ti_log = np.log2(test_targets_ti_flat+1)
            test_preds_ti_log = np.log2(test_preds_ti_flat+1)

            # plot log2
            sns.set(font_scale=1.2, style='ticks')
            out_pdf = '%s/scatter/t%d.pdf' % (options.out_dir,ti)
            basenji.plots.regplot(test_targets_ti_log, test_preds_ti_log, out_pdf, poly_order=1, alpha=0.3, sample=500, figsize=(6,6), x_label='log2 Experiment', y_label='log2 Prediction', table=True)

            ############################################
            # violin

            # call peaks
            test_targets_ti_lambda = np.mean(test_targets_ti_flat)
            test_targets_pvals = 1 - poisson.cdf(np.round(test_targets_ti_flat)-1, mu=test_targets_ti_lambda)
            test_targets_qvals = np.array(ben_hoch(test_targets_pvals))
            test_targets_peaks = test_targets_qvals < 0.01
            test_targets_peaks_str = np.where(test_targets_peaks, 'Peak', 'Background')

            # violin plot
            sns.set(font_scale=1.3, style='ticks')
            plt.figure()
            df = pd.DataFrame({'log2 Prediction':np.log2(test_preds_ti_flat+1), 'Experimental coverage status':test_targets_peaks_str})
            ax = sns.violinplot(x='Experimental coverage status', y='log2 Prediction', data=df)
            ax.grid(True, linestyle=':')
            plt.savefig('%s/violin/t%d.pdf' % (options.out_dir,ti))
            plt.close()

            # ROC
            plt.figure()
            fpr, tpr, _ = roc_curve(test_targets_peaks, test_preds_ti_flat)
            auroc = roc_auc_score(test_targets_peaks, test_preds_ti_flat)
            plt.plot([0,1], [0,1], c='black', linewidth=1, linestyle='--', alpha=0.7)
            plt.plot(fpr, tpr, c='black')
            ax = plt.gca()
            ax.set_xlabel('False positive rate')
            ax.set_ylabel('True positive rate')
            ax.text(0.99, 0.02, 'AUROC %.3f'%auroc, horizontalalignment='right') # , fontsize=14)
            ax.grid(True, linestyle=':')
            plt.savefig('%s/roc/t%d.pdf' % (options.out_dir,ti))
            plt.close()

            # PR
            plt.figure()
            prec, recall, _ = precision_recall_curve(test_targets_peaks, test_preds_ti_flat)
            auprc = average_precision_score(test_targets_peaks, test_preds_ti_flat)
            plt.axhline(y=test_targets_peaks.mean(), c='black', linewidth=1, linestyle='--', alpha=0.7)
            plt.plot(recall, prec, c='black')
            ax = plt.gca()
            ax.set_xlabel('Recall')
            ax.set_ylabel('Precision')
            ax.text(0.99, 0.95, 'AUPRC %.3f'%auprc, horizontalalignment='right') # , fontsize=14)
            ax.grid(True, linestyle=':')
            plt.savefig('%s/pr/t%d.pdf' % (options.out_dir,ti))
            plt.close()

    data_open.close()

def ben_hoch(p_values):
    ''' Convert the given p-values to q-values using Benjamini-Hochberg FDR. '''
    m = len(p_values)

    # attach original indexes to p-values
    p_k = [(p_values[k],k) for k in range(m)]

    # sort by p-value
    p_k.sort()

    # compute q-value and attach original index to front
    k_q = [(p_k[i][1],p_k[i][0]*m//(i+1)) for i in range(m)]

    # re-sort by original index
    k_q.sort()

    # drop original indexes
    q_values = [k_q[k][1] for k in range(m)]

    return q_values

def bigwig_open(bw_file, genome_file):
    ''' Open the bigwig file for writing and write the header. '''

    bw_out = pyBigWig.open(bw_file, 'w')

    chrom_sizes = []
    for line in open(genome_file):
        a = line.split()
        chrom_sizes.append((a[0],int(a[1])))

    bw_out.addHeader(chrom_sizes)

    return bw_out

def bigwig_write(bw_file, signal_ti, track_bed, genome_file, buffer=0, bed_set='test'):
    ''' Write a signal track to a BigWig file over the regions
         specified by track_bed.

    Args
     bw_file:     BigWig filename
     signal_ti:   Sequences X Length array for some target
     track_bed:   BED file specifying sequence coordinates
     genome_file: Chromosome lengths file
     buffer:      Length skipped on each side of the region.
    '''

    bw_out = bigwig_open(bw_file, genome_file)

    si = 0
    bw_entries = []

    # set entries
    for line in open(track_bed):
        a = line.split()
        if a[3] == bed_set:
            chrom = a[0]
            start = int(a[1])
            end = int(a[2])

            preds_pool = (end - start - 2*buffer) // signal_ti.shape[1]

            bw_start = start + buffer
            for li in range(signal_ti.shape[1]):
                bw_end = bw_start + preds_pool
                bw_entries.append((chrom,bw_start,bw_end,signal_ti[si,li]))
                bw_start = bw_end

            si += 1

    # sort entries
    bw_entries.sort()

    # add entries
    for line in open(genome_file):
        chrom = line.split()[0]

        bw_entries_chroms = [be[0] for be in bw_entries if be[0] == chrom]
        bw_entries_starts = [be[1] for be in bw_entries if be[0] == chrom]
        bw_entries_ends = [be[2] for be in bw_entries if be[0] == chrom]
        bw_entries_values = [float(be[3]) for be in bw_entries if be[0] == chrom]

        if len(bw_entries_chroms) > 0:
            bw_out.addEntries(bw_entries_chroms, bw_entries_starts, ends=bw_entries_ends, values=bw_entries_values)

    bw_out.close()

def compute_full_accuracy(dr, model, test_preds, test_targets_full, out_dir, down_sample):
    ''' Compute accuracy on the saved full target set, as opposed to a
         reconstructed version via dim reduction and/or fourier. '''

    full_targets = test_targets_full.shape[2]

    # determine non-buffer region
    buf_start = dr.batch_buffer // dr.target_pool
    buf_end = (dr.batch_length - dr.batch_buffer) // dr.target_pool
    buf_len = buf_end - buf_start

    # uniformly sample indexes
    ds_indexes = np.arange(0, buf_len, options.down_sample)

    # filter down full test targets
    test_targets_full_ds = test_targets_full[:,buf_start+ds_indexes,:]
    test_na_ds = test_na[:,buf_start+ds_indexes]

    # inverse transform in length batches
    t0 = time.time()
    test_preds_full = np.zeros((test_preds.shape[0], test_preds.shape[1], full_targets), dtype='float16')
    for li in range(test_preds.shape[1]):
        test_preds_full[:,li,:] = model.inverse_transform(test_preds[:,li,:])
    print('PCA transform: %ds' % (time.time()-t0))

    print(test_preds_full.shape)
    print(test_targets_full_ds.shape)

    # compute R2 by target
    t0 = time.time()
    test_r2_full = np.zeros(full_targets)
    for ti in range(full_targets):
        # flatten
        # preds_ti = test_preds_full[:,:,ti].flatten()
        # targets_ti = test_targets_full_ds[:,:,ti].flatten()
        preds_ti = test_preds_full[np.logical_not(test_na_ds),ti]
        targets_ti = test_targets_full_ds[np.logical_not(test_na_ds),ti]

        # compute R2
        tmean = targets_ti.mean(dtype='float64')
        tvar = (targets_ti-tmean).var(dtype='float64')
        pvar = (targets_ti-preds_ti).var(dtype='float64')
        test_r2_full[ti] = 1.0 - pvar/tvar
    print('Compute full R2: %d' % (time.time()-t0))

    print('Test full R2: %7.5f' % test_r2_full.mean())

    acc_out = open('%s/acc_full.txt' % out_dir, 'w')
    for ti in range(len(test_r2_full)):
        print('%4d  %.4f' % (ti,test_r2_full[ti]), file=acc_out)
    acc_out.close()

################################################################################
# __main__
################################################################################
if __name__ == '__main__':
    main()


from __future__ import absolute_import

from celery import Celery

app = Celery('main',
             broker='redis://localhost:6379/0',
             backend='redis://localhost:6379/0',
             include=[
                    'tasks.email_tasks.email_tasks',
                    'demos.product_similarity.engine.tasks'])

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')

# @app.task(bind=True)
# def debug_task(self):
#     print('Request: {0!r}'.format(self.request))

CELERY_TIMEZONE = 'UTC'


q = [2, 1, 5, 3, 4]

def countBribes(Q):
    numberOfBribes = 0
    Q = [val-1 for val in Q]
    print(Q)
    for currentIndex, val in enumerate(Q):
        print(currentIndex,val)
        if val - currentIndex > 2:
            print("Too chaotic",val)
            return
        for j in range(max(val-1,0),currentIndex):
            if Q[j] > val:
                numberOfBribes += 1
    print(numberOfBribes)
countBribes(q)


"""
Convert a string into a number
Tags: parsing, parse, state
"""

# This is for programming languages with limitations on integer size
INT_MAX = (2 ** 31) - 1
INT_MIN = -(2 ** 31)

def str_to_i(s):
    number = 0
    parsing = False
    negative = False
    digits = range(48, 57+1)
    minus_sign = (45,)
    plus_sign = (43,)
    space = (32,)
    for c in s:
        ordinal = ord(c)
        digit = ordinal - 48
        if parsing:
            if ordinal in digits:
                number = number * 10 + digit
            else:
                break
        else:
            if ordinal in digits:
                parsing = True
                number = digit
            elif ordinal in minus_sign:
                parsing = True
                negative = True
            elif ordinal in plus_sign:
                parsing = True
            elif ordinal in space:
                continue
            else:
                return 0
    if negative:
        number = -number
    if number < INT_MIN:
        number = INT_MIN
    elif number > INT_MAX:
        number = INT_MAX
    return number

if __name__ == '__main__':
    assert str_to_i("   -42") == -42
    assert str_to_i("42 ans something else") == 42
    assert str_to_i("-42") == -42
    assert str_to_i("somethin else and -42") == 0
    print("Tests passed!")


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

"""
This module contains the definitions of returned errors and package constants.

@author: Ioannis Stenos, Nick Vrionis
"""
import os

# Definitions of return value success and errors
error_syntax_clustersize = -1
error_syntax_cpu_master = -2
error_syntax_ram_master = -3
error_syntax_disk_master = -4
error_syntax_cpu_slave = -5
error_syntax_ram_slave = -6
error_syntax_disk_slave = -7
error_syntax_logging_level = -8
error_syntax_disk_template = -9
error_quotas_cyclades_disk = -10
error_quotas_cpu = -11
error_quotas_ram = -12
error_quotas_cluster_size = -13
error_quotas_network = -14
error_flavor_id = -15
error_image_id = -16
error_syntax_token = -17
error_ready_reroute = -18
error_no_arguments = -19
error_fatal = -20
error_user_quota = -22
error_flavor_list = -23
error_get_list_servers = -24
error_get_list_projects = -25
error_get_network_quota = -28
error_create_network = -29
error_get_ip = -30
error_create_server = -31
error_syntax_auth_token = -32
error_ansible_playbook = -34
error_ssh_client = -35
error_cluster_not_exist = -69
error_cluster_corrupt = -70
error_proj_id = -71
error_multiple_entries = -72
error_project_quota = -73
error_authentication = -99
error_replication_factor = -36
SUCCESS = 0

# Package constants
REPORT = 25  # Define logging level of REPORT
SUMMARY = 29  # Define logging level of SUMMARY
auth_url = 'https://accounts.okeanos.grnet.gr/identity/v2.0'
default_image = 'Debian Base'
default_logging = 'summary'
login_endpoint = '/api/users'
cluster_endpoint = '/api/clusterchoices'
job_endpoint = '/api/jobs'
hdfs_endpoint = '/api/hdfs'
vre_endpoint = '/api/vreservers'
wait_timer_create = 30
wait_timer_delete = 5
const_cluster_status_destroyed = "0"
const_cluster_status_active = "1"
const_cluster_status_pending = "2"
const_cluster_status_failed = "3"
const_hadoop_status_started = "1"
const_hadoop_status_stopped = "0"
const_escience_uuid = "ec567bea-4fa2-433d-9935-261a0867ec60"
HADOOP_PATH = '/usr/local/hadoop/bin/hdfs'
DEFAULT_HDFS_DIR = ['/user/hduser', '/user/hduser/']
FNULL = open(os.devnull, 'w')
block_size = 67108864 # block size in bytes,used in division when transfering files from hdfs to pithos


import os
import sqlite3
import uuid
from typing import List

from pydantic import BaseModel, EmailStr, Field

class NotFound(Exception):
    pass

class Article(BaseModel):
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    author: EmailStr
    title: str
    content: str

    @classmethod
    def get_by_id(cls, article_id: str):
        con = sqlite3.connect(os.getenv('DATABASE_NAME', 'database.db'))
        con.row_factory = sqlite3.Row

        cur = con.cursor()
        cur.execute("SELECT * FROM articles WHERE id=?", (article_id,))

        record = cur.fetchone()

        if record is None:
            raise NotFound

        article = cls(**record)  # Row can be unpacked as dict
        con.close()

        return article

    @classmethod
    def get_by_title(cls, title: str):
        con = sqlite3.connect(os.getenv('DATABASE_NAME', 'database.db'))
        con.row_factory = sqlite3.Row

        cur = con.cursor()
        cur.execute("SELECT * FROM articles WHERE title = ?", (title,))

        record = cur.fetchone()

        if record is None:
            raise NotFound

        article = cls(**record)  # Row can be unpacked as dict
        con.close()

        return article

    @classmethod
    def list(cls) -> List['Article']:
        con = sqlite3.connect(os.getenv('DATABASE_NAME', 'database.db'))
        con.row_factory = sqlite3.Row

        cur = con.cursor()
        cur.execute("SELECT * FROM articles")

        records = cur.fetchall()
        articles = [cls(**record) for record in records]
        con.close()

        return articles

    def save(self) -> 'Article':
        with sqlite3.connect(os.getenv('DATABASE_NAME', 'database.db')) as con:
            cur = con.cursor()
            cur.execute(
                "INSERT INTO articles (id,author,title,content) VALUES(?, ?, ?, ?)",
                (self.id, self.author, self.title, self.content)
            )
            con.commit()

        return self

    @classmethod
    def create_table(cls, database_name='database.db'):
        conn = sqlite3.connect(database_name)

        conn.execute(
            'CREATE TABLE IF NOT EXISTS articles (id TEXT, author TEXT, title TEXT, content TEXT)'
        )
        conn.close()


from numpy import repeat
from numpy import zeros

from gwlfe.Input.LandUse.NLU import NLU

def NConc(NRur, NUrb, NitrConc, ManNitr, ManuredAreas, FirstManureMonth, LastManureMonth, FirstManureMonth2,
          LastManureMonth2):
    nlu = NLU(NRur, NUrb)
    result = zeros((12, nlu))
    for i in range(12):
        for l in range(NRur):
            result[i][l] = NitrConc[l]
            if l < ManuredAreas and i >= FirstManureMonth and i <= LastManureMonth:
                result[i][l] = ManNitr[l]
            if l < ManuredAreas and i >= FirstManureMonth2 and i <= LastManureMonth2:
                result[i][l] = ManNitr[l]
    return result

def NConc_f(NRur, NUrb, NitrConc, ManNitr, ManuredAreas, FirstManureMonth, LastManureMonth, FirstManureMonth2,
            LastManureMonth2):
    if (FirstManureMonth < 0 or FirstManureMonth2 < 0 or LastManureMonth < 0 or LastManureMonth2 < 0):
        return repeat(NitrConc[None, :], 12, axis=0)

    else:
        result = repeat(NitrConc[None, :], 12, axis=0)
        result[FirstManureMonth:LastManureMonth + 1, :ManuredAreas] = ManNitr
        result[FirstManureMonth2:LastManureMonth2 + 1, :ManuredAreas] = ManNitr
        return result


import rospy
import time
from vipo_msgs.msg import VipoMsg

METHOD_KEYS = ['name', 'vipo_msg_type', 'topic_name']
PROPERTY_KEYS = ['name', 'value']

def convert_rdf_to_dict(rdf):
    # print({attr: getattr(rdf, attr) for attr in rdf.__slots__})
    return {attr: getattr(rdf, attr) for attr in rdf.__slots__}

class Context(object):
    """Keep track of all connected IoTs and robots in the format of RDF"""
    def __init__(self):
        self.ctx = {}  # use a dict to store the id and rdf class

    def update(self, rdf):
        device_id = rdf.id
        if device_id in self.ctx:
            device = self.ctx[device_id]
            device.update_rdf(rdf)
        else:
            device = RdfDevice(rdf)
            self.ctx[device_id] = device

    def diff(self, new_rdf):
        "Return the difference between new_rdf and old one as a dictionary"
        device = self.get(new_rdf.id)
        return device.diff(new_rdf)

    def get(self, device_id):
        return self.ctx.get(device_id, None)

class RdfDevice(object):
    """Convert a RDF msg into a class
    We overload each func in rdf.methods as `self.func()`

    e.g.,
    A RDF msg may look like below
    rdf = {
        "id": "robot_123",
        "properties": "jobStatus,0.8;temperature,400",
        "methods": "move,Location,topic_name;cure,Time,topic_name",
        "done": false
    }
    After convert:
    robot = RdfDevice(rdf)
    robot.move(args)
    """
    def __init__(self, rdf):
        # a dict to store the topic_name and initiated publisher
        self.topic_pub_dict = {}
        self.old_rdf = None
        # set method only once, as rdf.methods usally do not change
        self._set_method_as_attr(rdf)
        self.update_rdf(rdf)

    def update_rdf(self, rdf):
        self.id = rdf.id
        self.location = rdf.location
        self.done = rdf.done
        self._set_property_as_attr(rdf)

    def diff(self, new_rdf):
        if not self.old_rdf:
            self.old_rdf = new_rdf
            return convert_rdf_to_dict(new_rdf)
        df = {}
        for key, value in convert_rdf_to_dict(new_rdf).items():
            if value != getattr(self.old_rdf, key):
                df[key] = value
        self.old_rdf = new_rdf
        return df

    def _set_method_as_attr(self, rdf):
        for func, _type, topic_name in self._parse_attrs(rdf.methods, METHOD_KEYS):
            setattr(self, func, self._convert(topic_name))

    def _set_property_as_attr(self, rdf):
        for prop, value in self._parse_attrs(rdf.properties, PROPERTY_KEYS):
            setattr(self, prop, value)

    def _parse_attrs(self, attrs, keys):
        if not attrs:
            return []
        if isinstance(attrs, str):
            return [attr.split(',') for attr in attrs.split(';')]
        elif isinstance(attrs, list):
            return [[getattr(attr, key) for key in keys] for attr in attrs]
        else:
            raise TypeError('invalid attrs', type(attrs), attrs)

    def _get_publisher(self, topic_name):
        "Get publisher by topic_name or create new one and save to cache"
        if topic_name in self.topic_pub_dict:
            return self.topic_pub_dict[topic_name]
        pub = rospy.Publisher(topic_name, VipoMsg, queue_size=10)
        self.topic_pub_dict[topic_name] = pub
        return pub

    def _convert(self, topic_name):
        max_wait_cycle = 100
        def inner_func(msg):
            pub = self._get_publisher(topic_name)
            vipomsg = VipoMsg()
            for key in msg:
                setattr(vipomsg, key, msg[key])
            print(vipomsg)

            # wait for one command to finish before starting the next command
            # self.done will be updated in self.update_rdf(rdf)
            # which is called by context.update(rdf)
            wait_cycle = 0
            while not self.done:
                print('wait cycle', wait_cycle)
                pub.publish(vipomsg)
                wait_cycle += 1
                if wait_cycle > max_wait_cycle:
                    break
                time.sleep(1)
            print('done')

        return inner_func

# class RdfDeviceV2(object):
#     """Convert a RDF msg into a class
#     We overload each method/property in rdf.methods as `self.func()`

#     e.g.,
#     A RDF msg may look like below
#     rdf = {
#         "id": "robot_123",
#         "methods": [{"move": "topic_name"}],
#         "properties": [{"jobStatus": 0.8}, {"temperature": 400}],
#         "done": false
#     }
#     After convert:
#     robot = RdfDevice(rdf)
#     robot.move(args)
#     """
#     def __init__(self, rdf):
#         self.topic_pub_dict = {}
#         self.update_rdf(rdf)

#     def update_rdf(self, rdf):
#         self.id = rdf.id
#         self.location = rdf.location
#         self.done = rdf.done
#         for prop in rdf.properties:
#             setattr(self, prop, rdf.properties[prop])
#         for func in self.methods:
#             setattr(self, func, self.__parse(rdf.methods[func]))

#     def get_publisher(self, topic_name):
#         if topic_name in self.topic_pub_dict:
#             return self.topic_pub_dict[topic_name]
#         pub = rospy.Publisher(topic_name, VipoMsg, queue_size=10)
#         self.topic_pub_dict[topic_name] = pub
#         return pub

#     def __parse(self, func_detail):
#         topic_name, _ = func_detail.split(',')
#         max_wait_cycle = 10
#         def inner_func(msg):
#             # wait for one command to finish before starting the next command
#             pub = self.get_publisher(topic_name)
#             pub.publish(msg)
#             wait_cycle = 0
#             while not self.done:
#                 print('wait cycle', wait_cycle)
#                 wait_cycle += 1
#                 if wait_cycle > max_wait_cycle:
#                     break
#                 time.sleep(1)

#         return inner_func

# Abandon
# class RdfDeviceV1(object):
#     """Convert a RDF msg into a class
#     We use self.do(func) to call each func in rdf.funcs

#     e.g.,
#     A RDF msg may look like below
#     rdf = {"id": "robot_123", "funcs": {"move": "details here"}}
#     After convert:
#     robot = RdfDevice(rdf)
#     robot.do("move", args)
#     """
#     def __init__(self, rdf):
#         self.id = rdf.id
#         self.funcs = rdf.funcs

#     def update(self, rdf):
#         self.funcs = rdf.funcs

#     def do(self, func):
#         # the detail of each func of the device is saved in self.funcs
#         # NOTE: the exact way to exec the detail is TBD
#         exec(self.funcs[func], args)


import requests

from subprocess import getoutput

def get_repo_url():
    url = getoutput("git remote get-url --all upstream")
    if "fatal" in url:
        url = getoutput("git remote get-url --all origin")
    if "fatal" in url:
        raise ValueError(
            f"Unknown error. `git get-url --all upstream|origin` returned {url}"
        )
    return url

def get_repo_name():
    repo_url: str = get_repo_url()
    repo_url = repo_url.replace("https://github.com/", "")
    repo_url = repo_url.replace("git@github.com:", "")
    repo_name = repo_url.replace(".git", "")
    return repo_name

def get_reservation_list():
    issues = requests.get(
        "https://api.github.com/repos/" + get_repo_name() + "/issues"
    ).json()
    reservations = {
        issue["title"].split()[-1].lower(): issue["user"]["login"] for issue in issues
    }
    return reservations


#!/usr/bin/env python
import serial
import time
import struct
import numpy as np
from picar_msgs.msg import WheelSpeedStamped
import rospy

F_CPU = 16000000.0
PRESCALER = 256.0
BAUD = 57600

ticks_per_sec = F_CPU/PRESCALER
pulses_per_rev = 10

class Node(object):
    def __init__(self):
        self.serial = serial.Serial("/dev/ttyUSB0", BAUD, timeout=1.0)
        time.sleep(2.0)
        rospy.init_node("wheel_speed_node")
        self.publisher = rospy.Publisher(
            "~wheel_speed",
            WheelSpeedStamped,
            queue_size=1)

if __name__ == "__main__":
    n = Node()
    speeds = [0, 0, 0]
    index = 0
    data = n.serial.read()
    print(len(data))
    while not rospy.is_shutdown():
        time.sleep(0.1)
        n.serial.write(b"\x01")
        data = n.serial.read(8)
        print(len(data))
        data = struct.unpack('>HHHH', data)
        speed = []
        for ticks in data:
            speed.append(ticks_per_sec/ticks/pulses_per_rev*2*3.1416 if ticks > 0 else 0.0)
        print(data)
        print(speed)
        message = WheelSpeedStamped()
        message.header.stamp = rospy.Time.now()
        message.front_left = speed[0]
        message.front_right = speed[1]
        message.rear_left = speed[2]
        message.rear_right = speed[3]
        n.publisher.publish(message)


from django.conf import settings
from django.contrib.auth import get_user_model
from rest_framework import serializers

from compliance_linc.core.models import Company
from compliance_linc.core.serializers import CompanySerializer
from compliance_linc.core.utils import send_email_to_account
from compliance_linc.reports.models import ComplianceReportRecipient
from compliance_linc.reports.serializers import ComplianceReportSerializer
from .models import Location, Space, LocationSubcategory, LocationCategory

class LocationCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = LocationCategory
        fields = ['id', 'name']

class LocationSubcategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = LocationSubcategory
        fields = ['id', 'name', 'category']

class LocationChoicesSerializer(serializers.ModelSerializer):
    location_types = LocationSubcategorySerializer(source='subcategories', many=True, read_only=True)

    class Meta:
        model = LocationCategory
        fields = ['id', 'name', 'location_types']

class RelatedSpacesField(serializers.RelatedField):
    def to_representation(self, value):
        data = SpaceSerializer(value).data
        return data

class BaseLocationSerializer(serializers.ModelSerializer):
    company = CompanySerializer()
    type = LocationSubcategorySerializer()

    class Meta:
        model = Location
        fields = ['id', 'type', 'company', 'name', 'street_number', 'street_name',
                  'suburb', 'postal_code', 'state', 'manager']

class LocationSerializer(BaseLocationSerializer):
    spaces = RelatedSpacesField(many=True, read_only=True)
    compliance_report_recipients = ComplianceReportSerializer(many=True, required=False)

    class Meta:
        model = BaseLocationSerializer.Meta.model
        fields = BaseLocationSerializer.Meta.fields + ['spaces',
                                                       'compliance_report_recipients',
                                                       'type', ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.context.get('request') and self.context.get('request').method in ['POST', 'PATCH']:
            self.fields['company'] = serializers.IntegerField(source='company_id', write_only=True)
            self.fields['type'] = serializers.IntegerField(source='type.id')

    def validate_type(self, value):
        try:
            return LocationSubcategory.objects.get(id=value).id
        except LocationSubcategory.DoesNotExist:
            raise serializers.ValidationError('Invalid or wrong id for location type.')

    def validate_company(self, value):
        if Company.objects.filter(id=value).exists():
            return value
        else:
            raise serializers.ValidationError('No company with that ID exists')

    def create(self, validated_data):
        compliance_reports_recipients = validated_data.pop('compliance_report_recipients', None)
        location_type = validated_data.pop('type')
        validated_data['type_id'] = location_type['id']
        location = Location.objects.create(**validated_data)

        if compliance_reports_recipients:
            for recipient in compliance_reports_recipients:
                recipient['location'] = location
                ComplianceReportRecipient.objects.create(**recipient)

        if settings.SEND_NOTIFICATION_EMAILS:
            email_subject = "New Primary Location Was Created"
            superadmin_user = get_user_model().objects.get(profile__type='super_admin')
            if location.company.admin.user.email:
                send_email_to_account('info@compliancelinc.com', location.company.admin.email, email_subject,
                                      "test email")
            if superadmin_user.email:
                send_email_to_account('info@compliancelinc.com', superadmin_user.email, email_subject, "test email")

        return location

    def update(self, instance, validated_data):

        if validated_data.get('type', None):
            location_type = validated_data.pop('type')
            instance.type_id = location_type['id']
            instance.save()

        if validated_data.get('manager', None) and validated_data.get('company_id', None):
            company = Company.objects.get(id=validated_data['company_id'])
            instance.company = company
            instance.manager = validated_data['manager']
            instance.save()

        return super().update(instance, validated_data)

class SpaceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Space
        fields = ['id', 'name', 'location', 'description']

from compliance_linc.compliances.serializers import ComplianceSerializer

class ReadSpaceSerializer(serializers.ModelSerializer):
    location = BaseLocationSerializer()
    compliances = ComplianceSerializer(many=True)

    class Meta:
        model = Space
        fields = ['id', 'name', 'location', 'description', 'compliance_measure_ids', 'compliances']


# *-* coding: utf-8 *-*
# This file is part of butterfly
#
# butterfly Copyright (C) 2015  Florian Mounier
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import sys
import tornado.options
import tornado.process
import tornado.escape
import tornado.web
import tornado.websocket
from mimetypes import guess_type
from collections import defaultdict
from butterfly import url, Route, utils, __version__
from butterfly.terminal import Terminal

def u(s):
    if sys.version_info[0] == 2:
        return s.decode('utf-8')
    return s

@url(r'/(?:user/(.+))?/?(?:wd/(.+))?/?(?:session/(.+))?')
class Index(Route):
    def get(self, user, path, session):
        if not tornado.options.options.unsecure and user:
            raise tornado.web.HTTPError(400)
        return self.render('index.html')

@url(r'/theme/([^/]+)/style.css')
class Theme(Route):

    def get(self, theme):
        self.log.info('Getting style')
        try:
            import sass
            sass.CompileError
        except Exception:
            self.log.error(
                'You must install libsass to use sass '
                '(pip install libsass)')
            return
        base_dir = self.get_theme_dir(theme)

        style = None
        for ext in ['css', 'scss', 'sass']:
            probable_style = os.path.join(base_dir, 'style.%s' % ext)
            if os.path.exists(probable_style):
                style = probable_style

        if not style:
            raise tornado.web.HTTPError(404)

        sass_path = os.path.join(
            os.path.dirname(__file__), 'sass')

        css = None
        try:
            css = sass.compile(filename=style, include_paths=[
                base_dir, sass_path])
        except sass.CompileError:
            self.log.error(
                'Unable to compile style (filename: %s, paths: %r) ' % (
                    style, [base_dir, sass_path]), exc_info=True)
            if not style:
                raise tornado.web.HTTPError(500)

        self.log.debug('Style ok')
        self.set_header("Content-Type", "text/css")
        self.write(css)
        self.finish()

@url(r'/theme/([^/]+)/(.+)')
class ThemeStatic(Route):

    def get(self, theme, name):
        if '..' in name:
            raise tornado.web.HTTPError(403)

        base_dir = self.get_theme_dir(theme)

        fn = os.path.normpath(os.path.join(base_dir, name))
        if not fn.startswith(base_dir):
            raise tornado.web.HTTPError(403)

        if os.path.exists(fn):
            self.set_header("Content-Type", guess_type(fn)[0])
            with open(fn, 'rb') as s:
                while True:
                    data = s.read(16384)
                    if data:
                        self.write(data)
                    else:
                        break
            self.finish()
        raise tornado.web.HTTPError(404)

@url(r'/ws'
     '(?:/user/(?P<user>[^/]+))?/?'
     '(?:session/(?P<session>[^/]+))?/?'
     '(?:/wd/(?P<path>.+))?')
class TermWebSocket(Route, tornado.websocket.WebSocketHandler):
    session_history_size = 50000
    # List of websockets per session per user
    # dict: user -> dict: session -> [TermWebSocket]
    sessions = defaultdict(dict)

    # Terminal for session per user
    # dict: user -> dict: session -> Terminal
    terminals = defaultdict(dict)

    # All terminals sockets for systemd socket deactivation
    sockets = []

    # Session history
    history = {}

    def open(self, user, path, session):
        self.session = session
        self.closed = False
        self.secure_user = None

        # Prevent cross domain
        if self.request.headers['Origin'] not in (
                'http://%s' % self.request.headers['Host'],
                'https://%s' % self.request.headers['Host']):
            self.log.warning(
                'Unauthorized connection attempt: from : %s to: %s' % (
                    self.request.headers['Origin'],
                    self.request.headers['Host']))
            self.close()
            return

        TermWebSocket.sockets.append(self)

        self.log.info('Websocket opened %r' % self)
        self.set_nodelay(True)

        socket = utils.Socket(self.ws_connection.stream.socket)
        opts = tornado.options.options

        if not opts.unsecure:
            user = utils.parse_cert(
                self.ws_connection.stream.socket.getpeercert())
            assert user, 'No user in certificate'
            try:
                user = utils.User(name=user)
            except LookupError:
                raise Exception('Invalid user in certificate')

            # Certificate authed user
            self.secure_user = user

        elif socket.local and socket.user == utils.User():
            # Local to local returning browser user
            self.secure_user = socket.user

        # Handling terminal session
        if session:
            if session in self.user_sessions:
                # Session already here, registering websocket
                self.user_sessions[session].append(self)
                self.write_message('S' + TermWebSocket.history[session])
                # And returning, we don't want another terminal
                return
            else:
                # New session, opening terminal
                self.user_sessions[session] = [self]
                TermWebSocket.history[session] = ''

        terminal = Terminal(
            user, path, session, socket,
            self.request.headers['Host'], self.render_string, self.write)

        terminal.pty()

        if session:
            if not self.secure_user:
                self.log.error(
                    'No terminal session without secure authenticated user'
                    'or local user.')
                self._terminal = terminal
                self.session = None
            else:
                self.log.info('Openning session %s for secure user %r' % (
                    session, self.secure_user))
                self.user_terminals[session] = terminal
        else:
            self._terminal = terminal

    @property
    def user_sessions(self):
        """Return the dict session of socket lists"""
        if not self.secure_user:
            return {}
        return TermWebSocket.sessions[self.secure_user.name]

    @property
    def user_terminals(self):
        """Return the dict session of terminal"""
        if not self.secure_user:
            return {}
        return TermWebSocket.terminals[self.secure_user.name]

    @classmethod
    def close_all(cls, session, user):
        terminals = TermWebSocket.terminals.get(user.name)
        del terminals[session]

        sessions = TermWebSocket.sessions.get(user.name)
        if sessions:
            sockets = sessions[session]
        for socket in sockets[:]:
            socket.on_close()
            socket.close()
        del sessions[session]

    @classmethod
    def broadcast(cls, session, message, user, emitter=None):
        if message[0] == 'S':
            cls.history[session] += message[1:]
        if len(cls.history[session]) > cls.session_history_size:
            cls.history[session] = cls.history[session][
                -cls.session_history_size:]
        sessions = cls.sessions.get(user.name, [])

        for session in sessions[session]:
            try:
                if session != emitter:
                    session.write_message(message)
            except Exception:
                session.log.exception('Error on broadcast')
                session.close()

    def write(self, message):
        if self.session and self.secure_user:
            if message is None:
                TermWebSocket.close_all(self.session, self.secure_user)
            else:
                TermWebSocket.broadcast(
                    self.session, message, self.secure_user)
        else:
            if message is None:
                self.on_close()
                self.close()
            else:
                self.write_message(message)

    def on_message(self, message):
        if self.session and self.secure_user:
            term = self.user_terminals.get(self.session)
            term and term.write(message)
            if message[0] == 'R':
                # Broadcast resize
                TermWebSocket.broadcast(
                    self.session, message, self.secure_user, self)
        else:
            self._terminal.write(message)

    def on_close(self):
        if self.closed:
            return
        self.closed = True
        self.log.info('Websocket closed %r' % self)
        TermWebSocket.sockets.remove(self)
        if self.session:
            self.user_sessions[self.session].remove(self)
        elif hasattr(self, '_terminal'):
            self._terminal.close()
        else:
            self.log.error(
                'Socket with neither session nor terminal %r' % self)
        opts = tornado.options.options
        if opts.one_shot or (
                self.application.systemd and
                not len(TermWebSocket.sockets) and
                not sum([
                    len(sessions)
                    for user, sessions in TermWebSocket.terminals.items()])):
            sys.exit(0)

@url(r'/sessions/list.json')
class SessionsList(Route):
    """Get the theme list"""

    def get(self):
        if tornado.options.options.unsecure:
            raise tornado.web.HTTPError(403)

        cert = self.request.get_ssl_certificate()
        user = utils.parse_cert(cert)

        if not user:
            raise tornado.web.HTTPError(403)

        self.set_header('Content-Type', 'application/json')
        self.write(tornado.escape.json_encode({
            'sessions': sorted(
                TermWebSocket.sessions.get(user, [])),
            'user': user
        }))

@url(r'/themes/list.json')
class ThemesList(Route):
    """Get the theme list"""

    def get(self):

        if os.path.exists(self.themes_dir):
            themes = [
                theme
                for theme in os.listdir(self.themes_dir)
                if os.path.isdir(os.path.join(self.themes_dir, theme)) and
                not theme.startswith('.')]
        else:
            themes = []

        if os.path.exists(self.builtin_themes_dir):
            builtin_themes = [
                'built-in-%s' % theme
                for theme in os.listdir(self.builtin_themes_dir)
                if os.path.isdir(os.path.join(
                    self.builtin_themes_dir, theme)) and
                not theme.startswith('.')]
        else:
            builtin_themes = []

        self.set_header('Content-Type', 'application/json')
        self.write(tornado.escape.json_encode({
            'themes': sorted(themes),
            'builtin_themes': sorted(builtin_themes),
            'dir': self.themes_dir
        }))

@url('/local.js')
class LocalJsStatic(Route):
    def get(self):
        self.set_header("Content-Type", 'application/javascript')
        if os.path.exists(self.local_js_dir):
            for fn in os.listdir(self.local_js_dir):
                if not fn.endswith('.js'):
                    continue
                with open(os.path.join(self.local_js_dir, fn), 'rb') as s:
                    while True:
                        data = s.read(16384)
                        if data:
                            self.write(data)
                        else:
                            self.write(';')
                            break
        self.finish()


import numpy as np
import tensorflow as tf
from model import DCRNN,LSTM
from data_utils import *
import yaml
import os
from sys import argv
import time

if __name__=='__main__':
    with open('config.yaml') as f:
        config = yaml.load(f)
    model = DCRNN(config)
    print('Model Setup Done.')
    data = dataset(config)

    #os.environ['CUDA_VISIBLE_DEVICES'] = str(config['gpu_device'])
    version = time.strftime('%Y%m%d_%H%M%S')
    np.random.seed(2333333)
    tf.set_random_seed(2333333)
    tfcfg = tf.ConfigProto()
    saver = tf.train.Saver()
    #tfcfg.gpu_options.allow_growth = True
    with tf.Session(config=tfcfg) as sess:
        if len(argv)==1 or 'train' in argv[1]:
            sess.run(tf.global_variables_initializer())
            #saver.restore(sess, save_path='model/'+'ReiWa20190404_124825'+'/model')
            os.mkdir('model/'+config['ModelName']+version)
            lr = float(config['learning_rate'])
            best_model_recorder = config['BaseLineMAE']
            moving_average_recorder = 0
            for epoch in range(config['epoch_num']):
                train_ls = []
                for batch_num in range(data.tr_batch_num):
                    batch_mid,batch_set = data.tr_get_batch()
                    feed_dict = {model.learning_rate:lr}
                    for i,batch in enumerate(batch_set):
                        feed_dict[model.input_set[i]] = batch
                    _,ls = sess.run([model.train_op,model.loss],feed_dict)
                    #ls2 = sess.run([model.loss_mid]+[model.loss_set[i] for i in config['city_number']],feed_dict)
                    train_ls.append(ls)

                if (epoch+1)%config['print_every_n_epochs'] == 0:
                    train_ls = np.mean(train_ls)*500
                    print('['+config['ModelName']+version+']epoch ',epoch,'/',config['epoch_num'],' Done, Train loss ',round(train_ls,4))

                if (epoch+1)%config['learning_rate_decay_every_n_epochs'] == 0:
                    lr = lr/config['learning_rate_decay']
                    print('['+config['ModelName']+version+']epoch ',epoch,'/',config['epoch_num'],', Learning rate decay to ',lr)

                if (epoch+1)%config['test_every_n_epochs'] == 0:
                    test_ls = []
                    test_ls2 = []
                    test_ls3 = []
                    for batch_num in range(data.te_batch_num):
                        batch_mid,batch_set = data.te_get_batch()
                        feed_dict = {model.learning_rate:lr}
                        for i,batch in enumerate(batch_set):
                            feed_dict[model.input_set[i]] = batch
                        ls1 = sess.run(model.loss,feed_dict)
                        ls2 = sess.run([model.loss_mid]+[model.loss_set[i] for i in range(config['city_number'])],feed_dict)
                        ls3 = sess.run(model.loss_rmse_set,feed_dict)
                        test_ls.append(ls1)
                        test_ls2.append(ls2)
                        test_ls3.append(ls3)
                    test_ls = np.mean(test_ls)*500
                    test_ls2 = np.mean(test_ls2,0)*500
                    test_ls3 = np.sqrt(np.mean(test_ls3,0))*500
                    moving_average_recorder = config['moving_average_factor']*moving_average_recorder+(1-config['moving_average_factor'])*test_ls
                    print('['+config['ModelName']+version+']epoch ',epoch,'/',config['epoch_num'],' Done, Test loss ',round(test_ls,4),'/',np.round(test_ls2,4),'/',np.round(test_ls3,4))
                    if test_ls2[1]<best_model_recorder:
                        saver.save(sess,'model/'+config['ModelName']+version+'/model')
                        print('['+config['ModelName']+version+']epoch ',epoch,'/',config['epoch_num'],' Model Save Success. New record ',test_ls2[1])
                        lr = lr/(config['learning_rate_decay_at_best']*best_model_recorder/test_ls2[1]-config['learning_rate_decay_at_best']+1)
                        print('['+config['ModelName']+version+']epoch ',epoch,'/',config['epoch_num'],', Learning rate decay to ',lr)
                        best_model_recorder = test_ls2[1]

            print('==============')
            print('['+config['ModelName']+version+']Training DONE. ')
            print('best_model_recorder ',best_model_recorder)
            print('moving_average_recorder ',moving_average_recorder)

            _debug = np.array([2,3,3])
        if len(argv)>1 and 'test' in argv[1]:
            test_ls = []
            test_ls2 = []
            test_ls3 = []
            for batch_num in range(data.te_batch_num):
                batch_mid,batch_set = data.te_get_batch()
                feed_dict = {model.learning_rate:lr}
                for i,batch in enumerate(batch_set):
                    feed_dict[model.input_set[i]] = batch
                ls1 = sess.run(model.loss,feed_dict)
                ls2 = sess.run([model.loss_mid]+[model.loss_set[i] for i in range(config['city_number'])],feed_dict)
                ls3 = sess.run(model.loss_rmse_set,feed_dict)
                test_ls.append(ls1)
                test_ls2.append(ls2)
                test_ls3.append(ls3)
            test_ls = np.mean(test_ls)*500
            test_ls2 = np.mean(test_ls2,0)*500
            test_ls3 = np.sqrt(np.mean(test_ls3,0))*500
            moving_average_recorder = config['moving_average_factor']*moving_average_recorder+(1-config['moving_average_factor'])*test_ls
            print('['+config['ModelName']+version+']epoch ',epoch,'/',config['epoch_num'],' Done, Test loss ',round(test_ls,4),'/',np.round(test_ls2,4),'/',np.round(test_ls3,4))


__author__ = 'leha'

from time import time
from math import pi

def nextCase():
    fileName = "A.in"
    fileName = "A-large.in"
#   fileName = "A-small-practice.in"
#   fileName = "A-large-practice.in"
    input = open(fileName, 'r')
    T = int(input.readline())
    for i in range(T):
        A, N = tuple([int(x) for x in input.readline().split(' ')])
        S = [int(x) for x in input.readline().split(' ')]
        yield A, N, S

def solve(T):
	A, N, S = T
	S = list(sorted(S))

	def optimalFix(currWeight, moteWeight):
		count = 0
		s = currWeight

		if 1 == currWeight: return 10**10, currWeight

		while s <= moteWeight:
			count += 1
			s += s - 1

		return count, s

	cache = dict()
	def engine(i, w):
		if i == N: return 0, w

		if (i, w) in cache: return cache[(i, w)]

		if S[i] < w: r, w = engine(i + 1, w + S[i])
		else:
			count, newWeight = optimalFix(w, S[i])
			newWeight += S[i]

			r1, w1 = engine(i + 1, newWeight)
			r1 += count

			r2, w2 = N - i, w

			if r2 > r1: r, w = r1, w1
			else: r, w = r2, w2

		cache[(i, w)] = r, w
		return r, w

	r, w  = engine(0, A)

	return r

start = time()

i = 1
for T in nextCase():
	print("Case #%d: %s" % (i, solve(T)))
	i += 1

#print(time() - start)


#!usr/bin/env python

import pika
from pika import channel

connection = pika.BlockingConnection(
    pika.ConnectionParameters(host='localhost')
)

channel = connection.channel()
channel.queue_declare(queue = 'esp8266.pub',durable='True', auto_delete='False')
channel.basic_publish(exchange='amq.topic', routing_key='esp8266.test', body="hello world!")
channel.close()

# channel = connection.channel()

# def callback(ch,method,properties,body):
#     print("[x] Received %r" % body)

# channel.basic_consume(
#     queue='mqtt-subscription-ESP8266Clientqos0', on_message_callback=callback, auto_ack=True
# )

# print('[X] Waiting for messages to exit press ctrl +c')
# channel.start_consuming()


import io
import sys
f = io.StringIO("""
100 91
""".strip())
sys.stdin = f
# ----------------------

x, y = input().split()

x = sum([int(d) for d in x])
if x >= 10:
    x = int(str(x)[-1])

y = sum([int(d) for d in y])
if y >= 10:
    y = int(str(y)[-1])

if x > y:
    print("Bob")
elif y > x:
    print("Alice")
else:
    print("Draw")


"""
    1. 如果设置了daemon=True，join()生效，主线程等待3s以后结束执行，精灵线程也跟着死亡
    2. 如果设置了daemon=Fasle, join()依旧有效，只不过是主线程等待3秒以后结束执行，其它线程均自己执行完自行了断
    3. 可见join()的作用就是为了阻塞主线程用的
    4. 如果join()里面啥玩意儿都没有，就等待所有的线程都执行完了，主线程才会结束执行
    5. 如果join()不写的话，并不会等待3秒，主线程自己执行完就死掉了，其它线程也是各管各的。
    6. CSDN上面都是写什么垃圾玩意儿。。。
"""
import threading
import time

def doThreadTest():
    print('start thread time:', time.strftime('%H:%M:%S'))
    time.sleep(10)
    print('stop thread time:', time.strftime('%H:%M:%S'))

print('start main thread time:', time.strftime('%H:%M:%S'))
threads = []
for i in range(3):
    thread1 = threading.Thread(target = doThreadTest)
    thread1.setDaemon(False)    # True
    threads.append(thread1)

for t in threads:
    t.start()

# for t in threads:
#     t.join()

print('stop main thread time:', time.strftime('%H:%M:%S'))


from utils.helper import StrLabelConverter
from utils.keys import plate_keys

import cv2
import numpy as np

import torch

class CRNNCollate(object):
    def __init__(self, h=32, w=100):
        self.h = h
        self.w = w
        self.converter = StrLabelConverter(plate_keys)

    def __call__(self, batch):
        images, labels = zip(*batch)

        assert len(images) == len(labels)
        inputs = np.zeros((len(images), 1, self.h, self.w), dtype=np.float32)
        for i, image in enumerate(images):
            image = cv2.resize(image, (self.w, self.h))
            center=(self.w//2,self.h//2)
            import random
            M = cv2.getRotationMatrix2D(center, random.randint(-15,15), 1.0)  #0,15,10,8
            image = cv2.warpAffine(image, M, (self.w, self.h))
            image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            image = image.astype(np.float32)
            image -= 127.5
            image /= 127.5
            inputs[i, 0, ...] = image.astype(np.float32)
        labels = [label.replace('#', '') for label in labels]
        targets, lengths = self.converter.encode(labels)

        inputs = torch.FloatTensor(inputs)
        targets = torch.IntTensor(targets)
        lengths = torch.IntTensor(lengths)

        return inputs, labels, targets, lengths


'''
file_writer_mod writes
-the COOR_ZONES.csv which contains the coordinates and radii of the search zones
-the LIST_ZONES.csv which contains the names of the search zones in such a way as to indicate which belong to the same region
-the config.csv which serves as guide for SearcAlgo an pop_general to load the data from the directory
'''
import os
import load_utilities as lu
import sys
import string
import csv

def reg_coor_write(list_csv_files, data_path):
    '''
    Takes in csvs of the coordinates of the search zones and writes COOR_ZONES.csv
    consolidating the information in a single csv
    '''
    alphabet = list(string.ascii_lowercase) #used to name the different circles that make up a single region
    coor_list = []
    for file in list_csv_files:

        with open('draw_data'+ '/' + file, 'r') as f:
            reader = csv.reader(f)
            data_list = list(reader)

        alpha_counter = 0
        for i in range(0,len(data_list[0]),3):
            zone_name = file.split('.')[0] + '-' + alphabet[alpha_counter]
            alpha_counter += 1
            lat = data_list[0][i]
            lng = data_list[0][i+1]
            radius = data_list[0][i+2].split('.')[0][:-3]+'.'+data_list[0][i+2].split('.')[0][-3:]
            coor_data = lat+','+lng+','+radius+'km'
            coor_list_entry = [zone_name,coor_data]
            coor_list.append(coor_list_entry)

    with open('COOR_ZONES.csv', 'w') as f:
        writer = csv.writer(f,delimiter=' ')
        writer.writerow(['ZONES','COOR'])
        for coor_list_entry in coor_list:
            writer.writerow(coor_list_entry)

def reg_list_write(list_csv_files, data_path):
    '''
    Takes in csvs of the coordinates of the search zones and writes LIST_ZONES.csv
    in such a way as to indicate which belong to the same region
    '''
    alphabet = list(string.ascii_lowercase)
    reg_list = []
    for file in list_csv_files:

        with open('draw_data'+ '/' + file, 'r') as f:
            reader = csv.reader(f)
            data_list = list(reader)

        zones_number = int(len(data_list[0])/3)

        zones_list = []

        for i in range(0,zones_number):
            zone_name = file.split('.')[0] + '-' + alphabet[i]
            zones_list.append(zone_name)
        reg_list.append(zones_list)

    with open('LIST_ZONES.csv', 'w') as f:
        writer = csv.writer(f,delimiter=' ')
        for region in reg_list[:]:
            writer.writerow(region)

def main():

    if len(sys.argv) is 1:

        data_path = input('Where do you want to save the files:')

    else:
        data_path = sys.argv[1]

    os.chdir(data_path)
    cur_dir = os.getcwd()
    os.chdir('draw_data')
    coor_csv_files = [csv_file for csv_file in os.listdir(os.getcwd()) if csv_file.endswith('.csv')]
    os.chdir(cur_dir)

    reg_coor_write(coor_csv_files, data_path)
    reg_list_write(coor_csv_files, data_path)

    map_dir,labels_feature = lu.load_map_file()

    with open('config.csv', 'w') as f:
        writer = csv.writer(f,delimiter=',')
        writer.writerow(['TYPE','FILE'])
        writer.writerow(['regions_list','LIST_ZONES.csv'])
        writer.writerow(['coor_dict','COOR_ZONES.csv'])
        writer.writerow(['map',map_dir])
        writer.writerow(['labels_feature',labels_feature])

if __name__ == "__main__":
    main()


#!/usr/bin/env python2
#
# Show Kylie's model, for cell 5
#
# Compare with her simulation and score
#
from __future__ import division
from __future__ import print_function
import os
import sys
import pints
import pints.io
import numpy as np
import myokit

# Load beattie model and prior
sys.path.append(os.path.abspath('..'))
import beattie

# Check input arguments
args = sys.argv[1:]
if len(args) == 1:
    filename = args[0]
else:
    print('Syntax:  mcmc.py <filename>')
    sys.exit(1)

#
# Select cell
#
cell = 5

#
# Select protocols
#
protocols = [
    'pr1-activation-kinetics-1',
    'pr2-activation-kinetics-2',
    'pr3-steady-activation',
    'pr4-inactivation',
    'pr5-deactivation',
]

#
# Select data files
#
root = os.path.realpath(os.path.join('..', '..'))
data_files = [
    os.path.join(root, 'traditional-data', p + '-cell-' + str(cell) + '.csv')
    for p in protocols]

#
# Load protocols
#
print('Loading all protocols')
protocol_files = [
    os.path.join(root, 'traditional-data', p + '.mmt')
    for p in protocols]
protocols = [myokit.load_protocol(p) for p in protocol_files]

#
# Cell-specific parameters
#
temperature = beattie.temperature(cell)
lower_conductance = beattie.conductance_limit(cell)

#
# Load initial parameters
#
parameter_filename = 'solution1.txt'
print('Loading parameters from ' + parameter_filename)
with open(parameter_filename, 'r') as f:
    initial_parameters = [float(x) for x in f.readlines()]
initial_parameters = np.array(initial_parameters)

#
# Load data
#
print('Loading all data files')
times = []
currents = []
voltages = []
for data_file in data_files:
    log = myokit.DataLog.load_csv(data_file).npview()
    times.append(log.time())
    currents.append(log['current'])
    voltages.append(log['voltage'])
    del(log)

#
# Estimate noise from start of data (first 200ms, safe for all protocols)
#
sigma_noise = [np.std(current[:2000], ddof=1) for current in currents]

#
# Apply capacitance filtering based on protocols
#
print('Applying capacitance filtering')
for i, protocol in enumerate(protocols):
    times[i], voltages[i], currents[i] = beattie.capacitance(
        protocol, 0.1, times[i], voltages[i], currents[i])

#
# Create forward models
#
print('Creating forward models')
models = [
    beattie.BeattieModel(protocol, temperature, sine_wave=False)
    for protocol in protocols]

#
# Define problem
#
print('Defining problems')
problems = []
for i, model in enumerate(models):
    problems.append(pints.SingleOutputProblem(model, times[i], currents[i]))

#
# Define log-posterior
#
print('Defining log-likelihood, log-prior, and log-posterior')
log_likelihoods = []
for i, problem in enumerate(problems):
    log_likelihoods.append(
        pints.KnownNoiseLogLikelihood(problem, sigma_noise[i]))
log_likelihood = pints.SumOfIndependentLogLikelihoods(log_likelihoods)
log_prior = beattie.BeattieLogPrior(lower_conductance)
log_posterior = pints.LogPosterior(log_likelihood, log_prior)

#
# Run
#

# Create sampler
nchains = 3
x0 = [initial_parameters] * nchains
sigma0 = np.diag(initial_parameters) * 1e-36

mcmc = pints.MCMCSampling(log_posterior, nchains, x0, sigma0)
mcmc.set_log_to_file('log.txt')
mcmc.set_max_iterations(250000)
mcmc.set_adaptation_free_iterations(0)
mcmc.set_parallel(True)

# Run
#with np.errstate(all='ignore'): # Tell numpy not to issue warnings
chains = mcmc.run()

# Store results
pints.io.save_samples(chain_filename, *chains)

print('Done')


import json
import fire
import torch
import pickle
from pathlib import Path
from torch.utils.data import DataLoader
from model.utils import batchify
from model.data import Corpus, Tokenizer
from model.net import SAN
from mecab import MeCab
from tqdm import tqdm

def get_accuracy(model, data_loader, device):
    if model.training:
        model.eval()

    correct_count = 0

    for mb in tqdm(data_loader, desc='steps'):
        queries_a_mb, queries_b_mb, y_mb = map(lambda elm: elm.to(device), mb)
        queries_mb = (queries_a_mb, queries_b_mb)

        with torch.no_grad():
            score, _, _ = model(queries_mb)
            y_mb_hat = torch.max(score, 1)[1]
            correct_count += (y_mb_hat == y_mb).sum().item()
    else:
        acc = correct_count / len(data_loader.dataset)
    return acc

def main(json_path):
    cwd = Path.cwd()
    with open(cwd / json_path) as io:
        params = json.loads(io.read())

    # tokenizer
    vocab_path = params['filepath'].get('vocab')
    with open(cwd / vocab_path, mode='rb') as io:
        vocab = pickle.load(io)
    tokenizer = Tokenizer(vocab=vocab, split_fn=MeCab().morphs)

    # model (restore)
    save_path = cwd / params['filepath'].get('ckpt')
    ckpt = torch.load(save_path)
    num_classes = params['model'].get('num_classes')
    lstm_hidden_dim = params['model'].get('lstm_hidden_dim')
    hidden_dim = params['model'].get('hidden_dim')
    da = params['model'].get('da')
    r = params['model'].get('r')
    model = SAN(num_classes=num_classes, lstm_hidden_dim=lstm_hidden_dim, hidden_dim=hidden_dim,
                da=da, r=r, vocab=tokenizer.vocab)
    model.load_state_dict(ckpt['model_state_dict'])

    # evaluation
    batch_size = params['training'].get('batch_size')
    tr_path = cwd / params['filepath'].get('tr')
    val_path = cwd / params['filepath'].get('val')
    tr_ds = Corpus(tr_path, tokenizer.split_and_transform)
    tr_dl = DataLoader(tr_ds, batch_size=batch_size, num_workers=4, collate_fn=batchify)
    val_ds = Corpus(val_path, tokenizer.split_and_transform)
    val_dl = DataLoader(val_ds, batch_size=batch_size, num_workers=4, collate_fn=batchify)

    device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
    model.to(device)

    tr_acc = get_accuracy(model, tr_dl, device)
    val_acc = get_accuracy(model, val_dl, device)

    print('tr_acc: {:.2%}, val_acc: {:.2%}'.format(tr_acc, val_acc))

if __name__ == '__main__':
    fire.Fire(main)


import autofit as af
from autolens.pipeline.phase import phase_imaging
from .hyper_galaxy_phase import HyperGalaxyPhase
from .hyper_phase import HyperPhase
from .inversion_phase import InversionBackgroundBothPhase
from .inversion_phase import InversionBackgroundNoisePhase
from .inversion_phase import InversionBackgroundSkyPhase
from .inversion_phase import InversionPhase
from .inversion_phase import VariableFixingHyperPhase

class CombinedHyperPhase(HyperPhase):
    def __init__(
        self, phase: phase_imaging.PhaseImaging, hyper_phase_classes: (type,) = tuple()
    ):
        """
        A hyper_combined hyper_galaxies phase that can run zero or more other hyper_galaxies phases after the initial phase is
        run.

        Parameters
        ----------
        phase : phase_imaging.PhaseImaging
            The phase wrapped by this hyper_galaxies phase
        hyper_phase_classes
            The classes of hyper_galaxies phases to be run following the initial phase
        """
        super().__init__(phase, "hyper_combined")
        self.hyper_phases = list(map(lambda cls: cls(phase), hyper_phase_classes))

    @property
    def phase_names(self) -> [str]:
        """
        The names of phases included in this hyper_combined phase
        """
        return [phase.hyper_name for phase in self.hyper_phases]

    def run(
        self,
        data,
        results: af.ResultsCollection = None,
        mask=None,
        positions=None,
        **kwargs
    ) -> af.Result:
        """
        Run the phase followed by the hyper_galaxies phases. Each result of a hyper_galaxies phase is attached to the
        overall result object by the hyper_name of that phase.

        Finally, a phase in run with all of the variable results from all the individual hyper_galaxies phases.

        Parameters
        ----------
        positions
        mask
        data
            the data
        results
            Results from previous phases
        kwargs

        Returns
        -------
        result
            The result of the phase, with hyper_galaxies results attached by associated hyper_galaxies names
        """
        results = results.copy() if results is not None else af.ResultsCollection()
        result = self.phase.run(
            data, results=results, mask=mask, positions=positions, **kwargs
        )
        results.add(self.phase.phase_name, result)

        for phase in self.hyper_phases:
            hyper_result = phase.run_hyper(data=data, results=results, **kwargs)
            setattr(result, phase.hyper_name, hyper_result)

        setattr(result, self.hyper_name, self.run_hyper(data=data, results=results))
        return result

    def combine_variables(self, result) -> af.ModelMapper:
        """
        Combine the variable objects from all previous results in this hyper_combined hyper_galaxies phase.

        Iterates through the hyper_galaxies names of the included hyper_galaxies phases, extracting a result
        for each name and adding the variable of that result to a new variable.

        Parameters
        ----------
        result
            The last result (with attribute results associated with phases in this phase)

        Returns
        -------
        combined_variable
            A variable object including all variables from results in this phase.
        """
        variable = af.ModelMapper()
        for name in self.phase_names:
            variable += getattr(result, name).variable
        return variable

    def run_hyper(self, data, results, **kwargs) -> af.Result:
        variable = self.combine_variables(results.last)

        phase = self.make_hyper_phase()
        phase.optimizer.phase_tag = ""
        phase.optimizer.variable = variable

        phase.phase_tag = ""

        return phase.run(
            data,
            results=results,
            mask=results.last.mask,
            positions=results.last.positions,
        )


#!/usr/bin/env python3

class CelestialObject:
    def __init__(self, name):
        self.name = name
        self.orbiting = None

    def orbits(self, target):
        self.orbiting = target

    def checksum(self):
        if self.orbiting is None:
            return 0
        return self.orbiting.checksum() + 1

    def path(self):
        if self.orbiting is None:
            return []
        return self.orbiting.path() + [self.orbiting.name]

def distance(a, b):
    patha = a.path()
    pathb = b.path()
    return len(set(patha) ^ set(pathb))

with open('input', 'r') as f:
    lines = f.read().splitlines()

orbit_map = dict()
for o in lines:
    a, b = o.split(')')
    if a not in orbit_map:
        orbit_map[a] = CelestialObject(a)
    if b not in orbit_map:
        orbit_map[b] = CelestialObject(b)
    orbit_map[b].orbits(orbit_map[a])

print(distance(orbit_map['SAN'], orbit_map['YOU']))


def SMA(A,n,m):
    # 设置alpha的比例
    alpha = m/n
    #通过ewm计算递归函数
    return A.ewm(alpha=alpha, adjust=False).mean()

def run_formula(dv, param = None):
    defult_param = {'t1':13,'t2':2,'t3':13,'t4':2}
    if not param:
        param = defult_param

    BIAS_SMA = dv.add_formula('BIAS_SMA',
               "100*((close-SMA(close,%s,%s))/SMA(close,%s,%s))"%(param['t1'],param['t2'],param['t3'],param['t4'])
             , is_quarterly=False, add_data=True,
             register_funcs={"SMA":SMA}
             )
    return BIAS_SMA


import datetime
from haystack import indexes
from students.models import Student

class StudentIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    surname = indexes.CharField(model_attr='surname')
    first_name = indexes.CharField(model_attr='first_name')
    middle_name = indexes.CharField(model_attr='middle_name')
    # autocomplete
    surname_auto = indexes.EdgeNgramField(model_attr='surname')
    firstname_auto = indexes.EdgeNgramField(model_attr='first_name')
    middlename_auto = indexes.EdgeNgramField(model_attr='middle_name')

    def get_model(self):
        return Student

    def index_queryset(self, using=None):
        """Used when the entire index for model is updated."""
        return self.get_model().objects.filter(admission_date__lte=datetime.datetime.now())


import bpy, random
from ... base_types.node import AnimationNode
from ... events import propertyChanged

class SetVertexColor(bpy.types.Node, AnimationNode):
    bl_idname = "an_SetVertexColor"
    bl_label = "Set Vertex Color"

    inputNames = { "Object" : "object",
                   "Color" : "color" }
    outputNames = { "Object" : "object" }

    enabled = bpy.props.BoolProperty(default = True, update = propertyChanged)
    vertexColorName = bpy.props.StringProperty(default = "Col", update = propertyChanged)
    checkIfColorIsSet = bpy.props.BoolProperty(default = True)

    def create(self):
        self.inputs.new("an_ObjectSocket", "Object")
        self.inputs.new("an_ColorSocket", "Color")
        self.outputs.new("an_ObjectSocket", "Object")

    def draw_buttons(self, context, layout):
        layout.prop(self, "enabled", text = "Enabled")
        layout.prop(self, "checkIfColorIsSet", text = "Check Color")

    def execute(self, object, color):
        if not self.enabled: return object
        if object is None: return object

        mesh = object.data

        colorLayer = mesh.vertex_colors.get(self.vertexColorName)
        if colorLayer is None:
            colorLayer = mesh.vertex_colors.new(self.vertexColorName)

        color = color[:3]
        if self.checkIfColorIsSet:
            oldColor = colorLayer.data[0].color
            if abs(color[0] * 100 + color[1] * 10 + color[2] - oldColor[0] * 100 - oldColor[1] * 10 - oldColor[2]) < 0.001:
                return object

        for meshColor in colorLayer.data:
            meshColor.color = color
        return object


import requests
import datetime
import re
import html
import db_context
from urllib.parse import urlparse
from bs4 import BeautifulSoup
from collections import OrderedDict
from itertools import count

# Naver 검색 API 이용
def get_api_result(keyword, display, start):
    url = "https://openapi.naver.com/v1/search/blog?query=" + keyword + "&display=" + str(display) + "&start=" + str(start)
    result = requests.get(urlparse(url).geturl(),
                          headers={"X-Naver-Client-Id": "Secret",
                                   "X-Naver-Client-Secret": "Secret"})

    return result.json()

# HTML 태그 제거
def remove_tag(content):
   cleanr =re.compile('<.*?>')
   cleantext = re.sub(cleanr, '', content)
   cleantext = html.unescape(cleantext)
   return cleantext

# 출력, 불러오기
def call_and_print(keyword, page):
    json_obj = get_api_result(keyword, 100, page)

    if int(json_obj['total']) <= page - 1:
        temp = []
        return temp, temp, temp, temp, temp, int(json_obj['total'])

    title_array = []
    link_array = []
    context_array = []
    date_array = []
    nicname_array = []

    count = 1
    for item in json_obj['items']:
        title = remove_tag(item['title'])
        description = remove_tag(item['description'])
        postdate = datetime.datetime.strptime(item['postdate'], "%Y%m%d").date()
        bloggername = remove_tag(item['bloggername'])

        # print("================================================================")
        # print("ID : " + str(page + count - 1))
        # print("제목 : " + title)
        title_array.append(title)

        # print("링크 : " + item['link'])
        link_array.append(item['link'])

        # print("이미지 링크 : null")
        # print("이미지 개수 : 0")

        # print("내용(간략) : " + description)
        context_array.append(description)

        # print("날짜 : " + str(postdate))
        date_array.append(postdate)

        # print("닉네임 : " + bloggername)
        nicname_array.append(bloggername)
        # print("")

        count += 1

    return title_array, link_array, context_array, date_array, nicname_array, int(json_obj['total'])

def naver_content_cralwler(url):
    hrd = {'User-Agent':'Mozilla/5.0', 'referer':'http://naver.com'}
    param = { 'where': 'post' }

    try:
        response = requests.get(url, params=param, headers=hrd)
        soup_temp = BeautifulSoup(response.text, 'html.parser')
        area_temp = soup_temp.find(id='screenFrame')
        url2 = area_temp.get("src")
    except:
        try:
            area_temp = soup_temp.find(id='mainFrame')
            url3 = area_temp.get("src")
            url4 = "https://blog.naver.com" + url3
            return url4
        except:
            return ""

    try:
        response = requests.get(url2, params=param, headers=hrd)
        soup_temp = BeautifulSoup(response.text, 'html.parser')
        area_temp = soup_temp.find(id='mainFrame')
        url3 = area_temp.get("src")
        url4 = "https://blog.naver.com" + url3
        return url4
    except:
        return ""

    return ""

def naver_content_text_cralwler(url):
    hrd = {'User-Agent':'Mozilla/5.0', 'referer':'http://naver.com'}
    param = { 'where': 'post' }

    try:
        response = requests.get(url, params=param, headers=hrd)
        soup_temp = BeautifulSoup(response.text, 'html.parser')
        area_temp = soup_temp.find_all("div", {"class" : "sect_dsc"})
        img_temp = soup_temp.find_all("div", {"id" : "postListBody"})

        for tag2 in area_temp:
            text1 = re.sub('  |  | \n|\t|\r', '', tag2.text)
            text2 = re.sub('\n\n', '', text1)
            text3 = re.sub('<.+?>', '', text2, 0).strip()
            return " ".join(text3.split()), str(img_temp).count("<img")
    except:
        return "", 0

    try:
        area_temp = soup_temp.find_all("div", {"id" : "postViewArea"})
        img_temp = soup_temp.find_all("div", {"id" : "postListBody"})

        for tag2 in area_temp:
            text1 = re.sub('  |  | \n|\t|\r', '', tag2.text)
            text2 = re.sub('\n\n', '', text1)
            text3 = re.sub('<.+?>', '', text2, 0).strip()
            return " ".join(text3.split()), str(img_temp).count("<img")
    except:
        return "", 0

    try:
        area_temp = soup_temp.find_all("div", {"class" : "se-main-container"})
        img_temp = soup_temp.find_all("div", {"id" : "postListBody"})

        for tag2 in area_temp:
            text1 = re.sub('  |  | \n|\t|\r', '', tag2.text)
            text2 = re.sub('\n\n', '', text1)
            text3 = re.sub('<.+?>', '', text2, 0).strip()
            return " ".join(text3.split()), str(img_temp).count("<img")
    except:
        return "", 0

    return "", 0

# API 검색 세팅
def api_setting(conn, input_search):
    title_array = []
    link_array = []
    context_array = []
    date_array = []
    nicname_array = []
    img_array = []
    img_numx = []
    data_array = []

    total = 0

    for x in range(1, 100, 100):
        try:
            title_temp, link_temp, context_temp, date_temp, nicname_temp, cnt = call_and_print(input_search, x)
            if len(title_temp) > 0:
                title_array.extend(title_temp)
                link_array.extend(link_temp)
                context_array.extend(context_temp)
                date_array.extend(date_temp)
                nicname_array.extend(nicname_temp)
                total = cnt
        except:
            pass

    cnt = 0
    if total > 100:
        cnt = 100
    else:
        cnt = total

    for x in range(cnt):
        final_url = naver_content_cralwler(link_array[x])
        data_context, img_numx_temp = naver_content_text_cralwler(final_url)
        data_array.append(data_context)
        img_numx.append(img_numx_temp)
        img_array.append("null")

        print("=================================================================")
        print("ID : " + str(x+1))
        print("제목 : " + title_array[x])
        print("링크 : " + link_array[x])
        print("이미지 링크 : " + img_array[x])
        print("이미지 개수 : " + str(img_numx[x]))
        print("내용(간략) : " + context_array[x])
        print("날짜 : " + str(date_array[x]))
        print("닉네임 : " + nicname_array[x])
        print("내용 길이 : " + str(len(data_array[x])))
        print("")

        db_context.insert(conn, str(x+1), str(title_array[x]), str(link_array[x]),
            str(img_numx[x]), str(context_array[x]), str(date_array[x]), str(nicname_array[x]), "미판정", "미판정", "미판정")

    return cnt, title_array, link_array, img_array, img_numx, context_array, data_array, date_array, nicname_array