from server.db.schema.sentences import GET_ALL_SENTENCES_BY_DATASET, GET_RANDOM_CORPA_AFTER, GET_STARTING_INDEX_SENTENCES_BY_DATASET, GET_TOTAL_CORPA_LEN_FORDB
from server.main.utils import get_session
import calendar
import datetime
import json
import os
import random
from server.config import Config
import shutil
import sys
import time
from pathlib import Path

from flask import (current_app, jsonify, redirect, render_template, request,
                   send_from_directory, session, url_for)
from flask_jwt_extended import jwt_required
from werkzeug.utils import secure_filename

import server.tasks_split.save as save
from server import cache
from server.db import UserFileSystem
from server.db.user import *
from server.main import main

DB = Database("data/data.db")
SENTENCEDB = Database("data/sentences.db")

# here it should be parents[2]
up_one = Path(__file__).parents[2]
# print(up_one)
folder = up_one / 'web_app' / 'src'

@main.route('/')
def index():
    return render_template('index.html')

def get_self_info():
    # get cookie by sending username & pass
    # TODO add a register server page
    # then redirect to the central server register page
    # save those here
    try:
        session = get_session()
        r = session.get(Config.CENTRAL_SERVER_INFO_URL)
        return r.json()
    except Exception:
        pass
    return {}

@main.route('/home')
def public_home():
    # TODO get request to the central server and get our own info
    # TODO self public info
    self_info = get_self_info()

    dataset_types = []
    # dataset_types = ['eng', 'hin', 'tel', 'mix-hin-tel']
    for dire in (up_one / 'corpora' / 'uploads').iterdir():
        if dire.is_dir():
            dataset_types.append(dire.name)

    collections = []
    # TODO store in cache
    config_data = {}
    with open('config.json', 'r') as config:
        config_data = json.load(config)

    print(config_data)

    for dt in dataset_types:
        datasets = []
        selected_index = 0
        index = 0
        for file in (up_one / 'corpora' / 'uploads' / dt).iterdir():
            if file.is_file():
                new_file = file.stat().st_ctime
                selected = False
                if dt in config_data['categories'] and config_data['categories'][dt]:
                    current = config_data['categories'][dt]['current']
                    if current:
                        current = current.strip()
                        if current == str(file.name):
                            selected = True
                            selected_index = index
                datasets.append(
                    {
                        'name': str(file.name),
                        'current': selected,
                        'new': new_file
                    })
                index += 1

        collections.append({'dset': datasets, 'type': dt})

    # TODO show languages and datasets
    # TODO login on server startup and keep session, use the same session on every request
    print(self_info)

    # return render_template('home.html', collections=collections, types=",".join(dataset_types))
    return render_template('home.html', collections=collections, types=",".join(dataset_types), self_info=self_info)

@main.route('/central')
def central_home():
    return render_template("central.html")

@main.route('/login')
def login_alt():
    return redirect(url_for('auth.login'))

@main.route('/signup')
def signup_alt():
    return redirect(url_for('auth.new_user'))

# TODO
# https://stackoverflow.com/a/51013358/8608146

@main.route('/files')
@jwt_required
def all_files():
    items = []
    for i in Path(current_app.config['UPLOAD_FOLDER']).iterdir():
        path = str(i)
        items.append({
            'date': i.split('.')[0][4:],
            'size': os.stat(path).st_size,
            'id': i
        })
    return render_template("files.html", items=items)  # , as_attachment=True)

@main.route('/logout')
def logout():
    return redirect('/')

@main.route('/dashboard')
def dashboard_home():
    # print('x' not in cache)
    running = cache.get('running_zip_tasks')
    print(running)

    session['x'] = (0, 1, 2, 3)
    print(session['x'])
    users = DB.get_users()
    for x in users:
        audiofiles = UserFileSystem(x['username']).get_audio_files()
        x['count'] = len(audiofiles)
    newlist = sorted(users, key=lambda k: k['count'], reverse=True)
    return render_template('dashboard.html', users=newlist)

@main.route('/manage/del', methods=['DELETE'])
def dashboard_settings_del_lang():
    langname = request.json['langcode']
    print(f"Warning: {langname} is scheduled for a deletion")
    dirpath = up_one / 'corpora' / 'uploads' / langname
    dest = up_one / 'corpora' / 'trash'
    try:
        os.makedirs(dest)
    except Exception as e:
        print(e)
    try:
        shutil.move(str(dirpath), str(dest))
    except:
        shutil.move(str(dirpath), str(dest) +
                    str(random.randint(100, 2832989)))
    return jsonify({'success': True, 'error': None})

@main.route('/manage/add', methods=['POST'])
def dashboard_settings_add_lang():
    langname = request.json['langname']
    langs = request.json['langs']
    langtype = request.json['type']
    if not langname or not langs:
        return jsonify({'success': False, 'error': 'Values cannot be empty please try again'}), 403

    langs = [x.strip() for x in langs.split(',')]
    if len(langs) < 1 and langtype == 'mixed':
        return jsonify({'success': False, 'error': 'Select single if need to have only one language, or a comma is missing please try again'}), 403

    # TODO do something with the langname

    dirname = langs[0]
    if len(langs) > 1:
        dirname = "-".join(['mix', *langs])

    dirpath = up_one / 'corpora' / 'uploads' / dirname

    try:
        os.makedirs(dirpath)
    except Exception as e:
        return jsonify({'success': False, 'error': str(e)}), 403
    print(langname, langs, dirname)

    return jsonify({'success': True})

@main.route('/manage/upload', methods=['POST'])
def dashboard_settings_upload():
    langcode = (request.form['langcode'])
    if not langcode:
        return jsonify({
            'status': 'failed',
            'msg': 'no langcode was specified'
        }), 403
    if 'file' not in request.files:
        # return redirect(request.url)
        return jsonify({'status': 'failed', 'msg': 'No file uploaded try again'}), 404
    file = request.files['file']
    if file.filename == '':
        return jsonify({'status': 'failed', 'msg': 'No file selected for uploading'}), 404
    if file and allowed_settings_file(file.filename):
        filename = secure_filename(file.filename)
        filepath = up_one / 'corpora' / 'uploads' / langcode / filename

        try:
            os.makedirs(filepath.parents[0])
        except Exception:
            pass

        file.save(filepath)
        size = os.stat(filepath).st_size
        # TODO shedule celery task to split new uploaded dataset

        print(filepath.absolute(), type(filepath.absolute()))

        task = save.split_corpora.apply_async(
            kwargs={
                "file_path": str(filepath.absolute()),
                "split_path": f'split-{langcode}',
                "langcode": langcode,
                "filename": filename,
            },
            queue="split_queue",
        )
        return jsonify({
            'status': 'ok',
            'msg': None,
            'path': filename,
            'size': size,
            'taskid': task.id
        })
    else:
        return jsonify({
            'status': 'failed',
            'msg': f'invalid file type {file.filename} ' + 'only ' + ", ".join(ALLOWED_SETTINGS_EXTENSIONS) + ' file types are allowed'
        }), 403

@main.route('/manage', methods=['GET', 'POST'])
def dashboard_settings():
    if request.method == 'GET':
        dataset_types = []
        # dataset_types = ['eng', 'hin', 'tel', 'mix-hin-tel']
        for dire in (up_one / 'corpora' / 'uploads').iterdir():
            if dire.is_dir():
                dataset_types.append(dire.name)

        collections = []
        # TODO store in cache
        config_data = {}
        with open('config.json', 'r') as config:
            config_data = json.load(config)

        print(config_data)

        for dt in dataset_types:
            datasets = []
            selected_index = 0
            index = 0
            for file in (up_one / 'corpora' / 'uploads' / dt).iterdir():
                if file.is_file():
                    new_file = file.stat().st_ctime
                    selected = False
                    if dt in config_data['categories'] and config_data['categories'][dt]:
                        current = config_data['categories'][dt]['current']
                        if current:
                            current = current.strip()
                            if current == str(file.name):
                                selected = True
                                selected_index = index
                    datasets.append(
                        {
                            'name': str(file.name),
                            'current': selected,
                            'new': new_file
                        })
                    index += 1

            collections.append({'dset': datasets, 'type': dt})

        return render_template('settings.html', collections=collections, types=",".join(dataset_types))
    else:
        try:
            selected = request.json['selected']
            langcode = request.json['langcode']
        except:
            return jsonify({
                'success': False,
                'error': 'One of selected and langcode was not provided'
            }), 403
        config_data = {}
        with open('config.json', 'r') as config:
            config_data = json.load(config)

        if 'categories' not in config_data:
            config_data['categories'] = {}

        # for k in config_data['categories'].keys():
        #     config_data['categories'][k]['current'] = None

        config_data['categories'][langcode] = {
            'current': selected
        }

        with open('config.json', 'w+') as config:
            json.dump(config_data, config)

        print(config_data, selected, langcode)

        return jsonify({'success': True})

@main.route('/manage/<string:langcat>', methods=['GET', 'POST'])
def dashboard_settings_lang(langcat: str):
    # TODO check if a valid lang category
    if request.method == 'GET':
        config_data = {}
        with open('config.json', 'r') as config:
            config_data = json.load(config)

        datasets = []
        default_index = None
        selected_index = default_index
        index = 0
        for file in (up_one / 'corpora' / 'uploads' / langcat).iterdir():
            if file.is_file():
                selected = False
                if langcat in config_data['categories'] and config_data['categories'][langcat]:
                    current = config_data['categories'][langcat]['current']
                    if current:
                        current = current.strip()
                        if current == str(file.name):
                            selected = True
                            selected_index = index
                index += 1
                datasets.append({'name': str(file.name), 'current': selected})

        selected = None
        if len(datasets) > 0 and selected_index is not None:
            selected = datasets[selected_index]
            selected['index'] = selected_index

        print(datasets)
        print(selected)
        return render_template(
            'lang-settings.html',
            datasets=datasets,
            langcode=langcat,
            selected=selected
        )
    else:
        langcode = langcat
        if 'file' not in request.files:
            # return redirect(request.url)
            return jsonify({'status': 'failed', 'msg': 'No file uploaded try again'}), 404
        file = request.files['file']
        if file.filename == '':
            return jsonify({'status': 'failed', 'msg': 'No file selected for uploading'}), 404
        if file and allowed_settings_file(file.filename):
            filename = secure_filename(file.filename)
            filepath = up_one / 'corpora' / 'uploads' / langcode / filename

            try:
                os.makedirs(filepath.parents[0])
            except Exception as e:
                print(e)

            file.save(filepath)
            size = os.stat(filepath).st_size
            return jsonify({
                'status': 'ok',
                'msg': None, 'path': filename, 'size': size
            })
        else:
            return jsonify({
                'status': 'failed',
                'msg': f'invalid file type {file.filename} ' + 'only ' + ", ".join(ALLOWED_SETTINGS_EXTENSIONS) + ' file types are allowed'
            }), 403

def is_jsonable(x):
    try:
        json.dumps(x)
        return True
    except (TypeError, OverflowError):
        return False

@main.route('/_cache/clear')
def clear_cache():
    cache.clear()
    return jsonify(read_cache())

# TODO cahce experimentaion
# Use cache to cache file results (?)
@main.route('/_cache', methods=['GET', 'POST'])
def export_cache():
    if request.method == 'GET':
        return jsonify(read_cache())
    else:
        try:
            print('try')
            session['x']
        except:
            print('except')
            session['x'] = {}
        cache.set('time', datetime.datetime.now())
        cache.set(f'time-{random.randint(1, 100000)}', datetime.datetime.now())
        cache_dat = read_cache()
        ret = {}
        print(session['x'], cache_dat)
        if (len(session['x'].keys()) > len(cache_dat.keys())):
            ret['changes'] = {'x': session['x'], 'new': cache_dat}

        session['x'] = cache_dat
        ret['cache'] = cache_dat
        ret['x'] = session['x']
        return jsonify(ret)

def read_cache():
    k_prefix = cache.cache.key_prefix
    keys = cache.cache._write_client.keys(k_prefix + '*')
    keys = [k.decode('utf8') for k in keys]
    keys = [k.replace(k_prefix, '') for k in keys]
    values = cache.get_many(*keys)
    ret = {}
    for k, v in zip(keys, values):
        if is_jsonable(v):
            ret[k] = v
        else:
            ret[k] = str(v)
    return ret

@main.route('/users')
def users_home():
    users = DB.get_users()
    for x in users:
        audiofiles = UserFileSystem(x['username']).get_audio_files()
        x['count'] = len(audiofiles)
    newlist = sorted(users, key=lambda k: k['count'], reverse=True)
    return render_template('users.html', users=newlist)

@main.route('/user/<string:username>')
def user_page(username: str):
    userinfo = DB.get_user(username)
    sens = UserFileSystem(username).get_sentences()
    return render_template('user.html', user=userinfo, sentences=sens)

@main.route('/search', methods=['POST'])
def search():
    print(request.json)

    return jsonify({})

@main.route('/userfile/<string:filename>')
def user_file(filename: str):
    # filename is username_sid.wav
    # username can be x_yayya_xx
    username = "_".join(filename.split('_')[:-1])
    dirname = (up_one / 'data')
    print("User name is ", username, secure_filename(username))
    for d in dirname.iterdir():
        d = os.path.basename(d)
        safeusername = secure_filename(str(d))
        if safeusername == username:
            print(safeusername)
            dirname = (up_one / 'data' / d)
            break
    return send_from_directory(str(dirname), filename)

@main.route('/upload', methods=['POST'])
@jwt_required
def upload_file():
    # TODO in the app when logged out
    # 401 code is sent so this method is not called
    # Show failed message
    # user = (User(session['user'][0]).attach_DB(DB))
    print(session['user'])  # tuple (username, age, gender)
    print("-"*(200))
    sys.stdout.flush()

    if request.method == 'POST':
        # check if the post request has the file part
        # print(request)
        if 'file' not in request.files:
            # return redirect(request.url)
            return jsonify({'status': 'failed', 'msg': 'No file uploaded try again'})
        file = request.files['file']
        if file.filename == '':
            return jsonify({'status': 'failed', 'msg': 'No file selected for uploading'})
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            filepath = Path(current_app.config['UPLOAD_FOLDER']
                            ) / session['user'][0] / filename
            try:
                os.makedirs(filepath.parents[0])
            except Exception as e:
                print(e)

            file.save(filepath)
            size = os.stat(filepath).st_size
            return jsonify({
                'status': 'ok',
                'msg': None, 'path': filename, 'size': size
            })
        else:
            return jsonify({'status': 'failed', 'msg': f'invalid file type {file.filename}'})

# TODO @jwt_required
@main.route('/data/<string:langcat>/<string:dbname>')
def random_corpa(langcat: str, dbname: str):
    results = SENTENCEDB.execute(GET_TOTAL_CORPA_LEN_FORDB, (langcat, dbname))
    count = results[0]['COUNT(*)']
    start_x = SENTENCEDB.execute(
        GET_STARTING_INDEX_SENTENCES_BY_DATASET, (langcat, dbname))
    start_idx = start_x[0]['id']
    start_x = random.randint(1, count) + start_idx
    results = SENTENCEDB.execute(
        GET_RANDOM_CORPA_AFTER, (langcat, dbname, start_x, 100))
    return jsonify(results)

@main.route('/data/list')
def public_list():
    dataset_types = []
    # dataset_types = ['eng', 'hin', 'tel', 'mix-hin-tel']
    for dire in (up_one / 'corpora' / 'uploads').iterdir():
        if dire.is_dir():
            dataset_types.append(dire.name)

    collections = []
    # TODO store in cache
    config_data = {}
    with open('config.json', 'r') as config:
        config_data = json.load(config)

    print(config_data)

    for dt in dataset_types:
        datasets = []
        selected_index = 0
        index = 0
        for file in (up_one / 'corpora' / 'uploads' / dt).iterdir():
            if file.is_file():
                new_file = file.stat().st_ctime
                selected = False
                if dt in config_data['categories'] and config_data['categories'][dt]:
                    current = config_data['categories'][dt]['current']
                    if current:
                        current = current.strip()
                        if current == str(file.name):
                            selected = True
                            selected_index = index
                datasets.append(
                    {
                        'name': str(file.name),
                        'current': selected,
                        'new': new_file
                    })
                index += 1

        collections.append({'dset': datasets, 'type': dt})

    return jsonify(collections=collections, dataset_types=dataset_types)

@main.route('/skipped', methods=['POST'])
@jwt_required
def handle_skip():

    sentence_ids = request.json['ids']
    username = session['user'][0]

    with open('corpora/split/skipped.txt', 'a+') as skipper:
        for sentence_id in sentence_ids:
            skipper.write(f"{sentence_id}||{username}\n")

    return 'ok', 200

@main.route('/files/<path:filename>', methods=['GET', 'DELETE', 'PUT'])
@jwt_required
def download_file(filename):
    print(session['user'])
    if request.method == 'GET':
        print("accessing file: " + filename, time.asctime())
        print((request.headers))
        return send_from_directory(current_app.config['UPLOAD_FOLDER'],
                                   filename)  # , as_attachment=True)
    elif request.method == 'DELETE':
        # TODO
        # check if client has the ownership
        print("Delete", filename)
        try:
            os.remove(os.path.join(
                current_app.config['UPLOAD_FOLDER'], filename))
        except FileNotFoundError as e:
            return jsonify({'status': 'failed', 'msg': str(e)})
        return jsonify({'status': 'ok'})
    elif request.method == 'PUT':
        # https://pythonise.com/series/learning-flask/flask-http-methods
        return jsonify({'status': 'ok'})

# file upload
ALLOWED_EXTENSIONS = set(['wav', 'mp3', 'ogg', 'webm', 'aac'])

# Settings dashboard file upload
ALLOWED_SETTINGS_EXTENSIONS = set(['txt', 'csv'])

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[-1].lower() in ALLOWED_EXTENSIONS

def allowed_settings_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[-1].lower() in ALLOWED_SETTINGS_EXTENSIONS


import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from detikcrawler import items
import timegenerator

class inet(CrawlSpider):
    name = 'inet'
    urls = timegenerator.generate_datetime(1,12,2015)
    start_urls = []
    for url in urls:
        start_urls.append('https://inet.detik.com/indeks?date='+url)

    rules = (
    	Rule(LinkExtractor(allow=r'cyberlife/'),callback="parse_item"),
        Rule(LinkExtractor(allow=r'consumer/'),callback="parse_item"),
        Rule(LinkExtractor(allow=r'tips-dan-trik/'),callback="parse_item"),
        Rule(LinkExtractor(allow=r'games-news/'),callback="parse_item"),
        Rule(LinkExtractor(allow=r'fotostop-news/'),callback="parse_item"),
    	)
    def parse_item(self, response):
    	item = items.DetikcrawlerItem()
    	item['title'] = response.xpath('//div[@class="jdl"]/h1/text()').extract()
    	str_cont = response.xpath('//*[@id="detikdetailtext"]/text()').extract()
    	str_cont = " ".join(str_cont).strip()
    	item['content'] = str_cont[2:]

    	return item


import numpy as np
import cmath
from numpy import linalg as LA
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

c = 340

def Slepian_weights(M, dist, f, thetaBW):
    u0 = 2*np.pi*f*dist*np.sin(thetaBW/2)/c
    B = np.zeros((M,M))

    for i in range(0,M):
        for j in range(0,M):
            if (i==j):
                    B[i][j] = 2*u0

            else:
                B[i][j] = 2*np.sin((i-j)*u0)/(i-j)

    A = B/np.pi

    e, V = LA.eig(A)
    idx = e.argsort()[::-1]
    e = e[idx]
    V = V[:,idx]
    w = V[:,0]/np.sum(np.absolute(V[:,0]))

    return w

def Slepian_vector(M, dist, f, phi):
	d = np.zeros((M, 181), dtype = complex)
	N = np.int((M-1)/2)
	for m in range(M):
		for i in range(181):
			theta = (i-90)*np.pi/180
			n = np.int(m - N)
			d[m][i] = cmath.exp(-complex(0,n*2*np.pi*f*dist*np.sin(theta-phi)/c))

	return d

def Slepian_beampattern(w, d):
    Db = np.zeros((181))

    for i in range(181):
        Db[i] = 20*np.log10(np.absolute(np.inner(np.conjugate(w), d[:,i])))

    return Db

def Slepian_plot_beampattern(Db):

	plt.figure(figsize=(10,10))
	plt.plot(np.arange(-90,91,1),Db)
	plt.xticks(np.arange(-90,91,10))
	plt.grid(True)

def Slepian_band_weights(M, dist, f_L, f_H, bins, thetaBW):
    f = np.arange(f_L, f_H, (f_H - f_L)/bins)
    W = np.zeros((bins, M), dtype=complex)

    for k in range(bins):
        u0 = 2*np.pi*f[k]*dist*np.sin(thetaBW/2)/c
        B = np.zeros((M,M))

        for i in range(0,M):
            for j in range(0,M):
                if (i==j):
                    B[i][j] = 2*u0

                else:
                    B[i][j] = 2*np.sin((i-j)*u0)/(i-j)

        A = B/np.pi

        e, V = LA.eig(A)
        idx = e.argsort()[::-1]
        e = e[idx]
        V = V[:,idx]
        W[k,:] = V[:,0]/np.sum(np.absolute(V[:,0]))

    return W

def Slepian_band_vector(M, dist, f_L, f_H, bins, phi):
    f = np.arange(f_L, f_H, (f_H - f_L)/bins)
    d = np.zeros((M*bins, 181), dtype = complex)
    N = np.int((M-1)/2)

    for i in range(bins*M):
        for j in range(181):
            theta = (j-90)*np.pi/180
            m = np.int(i%M)
            k = np.int(i/M)
            n = np.int(m - N)
            d[i][j] = cmath.exp(-complex(0,n*2*np.pi*f[k]*dist*np.sin(theta)/c))

    return d

def Slepian_band_beampattern(W, d):
    bins = np.int(W.shape[0])
    M = np.int(W.shape[1])
    D = np.zeros((bins, 181))

    for k in range(bins):
        for theta in range(181):
            D[-(k+1)][theta] = 20*np.log10(np.absolute(np.inner(np.conjugate(W[k,:]), d[k*M:k*M+M,theta])))

    return D

def Slepian_band_plot_beampattern(D):
    plt.figure(figsize=(20,20))
    ax = plt.gca()
    im = ax.imshow(D, cmap='jet')

    # create an axes on the right side of ax. The width of cax will be 5%
    # of ax and the padding between cax and ax will be fixed at 0.05 inch.
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", size="5%", pad=0.05)

    plt.colorbar(im, cax=cax)

    plt.show()
    #im.set_clim(vmin=-3, vmax=0)


from splinter import Browser
from bs4 import BeautifulSoup
import pandas as pd
import datetime as dt
import time

def scrape_all():

    # Initiate headless driver for deployment
    browser = Browser("chrome", executable_path="chromedriver", headless=True)
    news_title, news_paragraph = mars_news(browser)

    # Run all scraping functions and store in dictionary.
    data = {
        "news_title": news_title,
        "news_paragraph": news_paragraph,
        "featured_image": featured_image(browser),
        "hemispheres": hemispheres(browser),
        "weather": twitter_weather(browser),
        "facts": mars_facts(),
        "last_modified": dt.datetime.now()
    }

    # Stop webdriver and return data
    browser.quit()
    return data

def mars_news(browser):
    url = "https://mars.nasa.gov/news/"
    browser.visit(url)

    #write your code here
    return news_title, news_p

def featured_image(browser):
    url = "https://www.jpl.nasa.gov/spaceimages/?search=&category=Mars"
    browser.visit(url)
    #write your code here
    return img_url

def hemispheres(browser):

    # A way to break up long strings
    url = (
        "https://astrogeology.usgs.gov/search/"
        "results?q=hemisphere+enhanced&k1=target&v1=Mars"
    )

    browser.visit(url)
    #write your code here
    return hemisphere_image_urls

def twitter_weather(browser):
    url = "https://twitter.com/marswxreport?lang=en"
    browser.visit(url)
    #write your code here
    return mars_weather

def mars_facts():
    try:
        df = pd.read_html("http://space-facts.com/mars/")[0]
    except BaseException:
        return None

    df.columns = ["description", "value"]
    df.set_index("description", inplace=True)

    # Add some bootstrap styling to <table>
    return df.to_html(classes="table table-striped")

if __name__ == "__main__":

    # If running as script, print scraped data
    print(scrape_all())


import urllib.request
import urllib.parse
import json

while 1:
    content = input("请输出翻译的内容（q!退出）：")
    if content != "q!":
        url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=https://www.sogou.com/sie"
        urll = urllib.request.Request(url)
        urll.add_header = ("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0")
        data = {}
        data["type"] = "AUTO"
        data["i"] = content
        data["doctype"] = "json"
        data["xmlVersion"] = "1.8"
        data["Keyfrom"] ="fanyi.web"
        data["ue"] = "UTF-8"
        data["action"]="FY_BY_CLICKBUTTON"
        data["typoResult"] = "true"

        data = urllib.parse.urlencode(data).encode("utf-8")

        response = urllib.request.urlopen(urll,data)
        html = response.read().decode("utf-8")

        target = json.loads(html)
        result = target['translateResult'][0][0]['tgt']
        print("翻译结果为：" + result)
        continue
    else:
        print("结束！")
        break


import html
import urllib

import demjson3
import re
from bs4 import BeautifulSoup
from decimal import Decimal

from storescraper.product import Product
from storescraper.store import Store
from storescraper.utils import session_with_proxy, check_ean13, \
    html_to_markdown

class WalmartBrazil(Store):
    @classmethod
    def categories(cls):
        return [
            'StorageDrive',
            'ExternalStorageDrive',
            'MemoryCard',
            'UsbFlashDrive',
            'SolidStateDrive',
        ]

    @classmethod
    def discover_urls_for_category(cls, category, extra_args=None):
        category_paths = [
            ['C:6552/6593/6597/', 'StorageDrive'],
            ['C:6552/6593/6604/', 'SolidStateDrive'],
            ['C:6552/6605/6609/', 'ExternalStorageDrive'],
            ['C:6552/6605/6614/', 'UsbFlashDrive'],
            ['C:6552/6578/6582/', 'MemoryCard'],
        ]

        product_urls = []
        session = session_with_proxy(extra_args)

        for category_paths, local_category in category_paths:
            if local_category != category:
                continue

            page = 1

            while True:
                category_url = 'https://www.walmart.com.br/_search?fq={}' \
                               '&PS=40&O=OrderByTopSaleDESC&PageNumber={}' \
                               ''.format(urllib.parse.quote(category_paths,
                                                            safe=''), page)
                print(category_url)

                if page >= 200:
                    raise Exception('Page overflow: ' + category_url)

                soup = BeautifulSoup(session.get(category_url).text,
                                     'html.parser')

                containers = soup.findAll('section', 'card')

                if not containers:
                    if page == 1:
                        raise Exception('Empty category: ' + category_url)
                    break

                skipped = 0

                for container in containers:
                    if container.find('p', 'warning'):
                        skipped += 1
                        continue

                    product_path = container.find('figure').parent['href']
                    product_url = 'https://www.walmart.com.br' + product_path
                    product_urls.append(product_url)

                if skipped == 40:
                    break

                page += 1

        return product_urls

    @classmethod
    def products_for_url(cls, url, category=None, extra_args=None):
        session = session_with_proxy(extra_args)
        page_source = session.get(url).text

        soup = BeautifulSoup(page_source, 'html.parser')

        picture_urls = []

        for tag in soup.findAll('li', 'owl-item'):
            picture_path = tag.find('a')['data-zoom'].replace(
                ' ', '%20').strip()

            if not picture_path:
                picture_path = tag.find('a')['data-normal'].replace(
                    ' ', '%20').strip()

            if not picture_path:
                continue
            picture_url = 'https:' + picture_path
            picture_urls.append(picture_url)

        if not picture_urls:
            picture_urls = None

        pricing_data = demjson3.decode(re.search(
            r'dataLayer = ([\S\s]+?);dataLayer', page_source).groups()[0])[0]

        products = []

        for product_entry in pricing_data['product']:
            name = product_entry['productName']
            sku = str(product_entry['productSku'])
            price = Decimal(product_entry['productDiscount'])

            if product_entry['productAvailable']:
                stock = -1
            else:
                stock = 0

            description = html_to_markdown(html.unescape(
                product_entry['productDescription']))

            p = Product(
                name,
                cls.__name__,
                category,
                url,
                url,
                sku,
                stock,
                price,
                price,
                'BRL',
                sku=sku,
                description=description,
                picture_urls=picture_urls
            )
            products.append(p)

        return products


import numpy as np
import pandas as pd
import seaborn as sns
import keras
from tensorflow.keras import Input, activations
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Reshape, Flatten, GRU, Conv2D, Layer, Embedding, concatenate, Softmax, Multiply, Average
from keras.layers import BatchNormalization, PReLU, cudnn_recurrent
from tensorflow.keras import backend as K
from tensorflow.keras.optimizers import Adam

from layers.seq_gcn import SequentialGraphCNN

seq_len = 8
height = 32
width = 40
n_nodes = height*width
gru_activation = 'elu'
n_features = 1
context_feats = 29
num_filters_dist = 4
num_filters_poi = 4
num_filters_transport = 4
output_dim_first = 64
output_dim_second = 32
gru_units = 512
learning_rate = 0.00015

graph_conv_filters_dist = np.load('filters/distance_matrix.npy')
graph_conv_filters_poi = np.load('filters/poi_matrix.npy')
graph_conv_filters_transport = np.load('filters/transport_matrix.npy')

# Create a model
def create_model():

  X_input = Input(shape=(seq_len, n_nodes, n_features))

  context_input = Input(shape=(3,))

  seq_context_input = Input(shape=(seq_len, 3))

  tfidf_input = Input(shape=(height*width, 9))

  context = Embedding(input_dim=context_feats, output_dim=5, input_length=3)(context_input)

  context = Flatten()(context)

  seq_context = Embedding(input_dim=context_feats, output_dim=5, input_length=3)(seq_context_input)

  seq_context = Flatten()(seq_context)

  seq_context = Reshape(target_shape=(seq_len, -1))(seq_context)

  #---------------------------------Distance------------------------------------------
  x_dist = SequentialGraphCNN(output_dim=output_dim_first, num_filters=num_filters_dist,
                        seq_len=seq_len, graph_conv_filters=graph_conv_filters_dist,
                        activation='relu')(X_input)

  x_dist = SequentialGraphCNN(output_dim=output_dim_second, num_filters=num_filters_dist,
                        seq_len=seq_len, graph_conv_filters=graph_conv_filters_dist,
                        activation='relu')(x_dist)

  x_dist = Flatten()(x_dist)

  x_dist = Reshape(target_shape=(seq_len, -1))(x_dist)

  x_dist = concatenate([x_dist, seq_context], axis=2)

  x_dist = cudnn_recurrent.CuDNNGRU(gru_units, activation=gru_activation, return_sequences=False)(x_dist)

  x_dist = Reshape([height*width, 1])(x_dist)

  x_dist = Dense(1, activation=None)(x_dist)

  #---------------------------------POI------------------------------------------
  x_poi = SequentialGraphCNN(output_dim=output_dim_first, num_filters=num_filters_poi,
                        seq_len=seq_len, graph_conv_filters=graph_conv_filters_poi,
                        activation='relu')(X_input)

  x_poi = SequentialGraphCNN(output_dim=output_dim_second, num_filters=num_filters_poi,
                        seq_len=seq_len, graph_conv_filters=graph_conv_filters_poi,
                        activation='relu')(x_poi)

  x_poi = Flatten()(x_poi)

  x_poi = Reshape(target_shape=(seq_len, -1))(x_poi)

  x_poi = concatenate([x_poi, seq_context], axis=2)

  x_poi = cudnn_recurrent.CuDNNGRU(gru_units, activation=gru_activation, return_sequences=False)(x_poi)

  x_poi = Reshape([height*width, 1])(x_poi)

  x_poi = Dense(1, activation=None)(x_poi)

  #---------------------------------Transportation------------------------------------------
  x_transport = SequentialGraphCNN(output_dim=output_dim_first, num_filters=num_filters_transport,
                        seq_len=seq_len, graph_conv_filters=graph_conv_filters_transport,
                        activation='relu')(X_input)

  x_transport = SequentialGraphCNN(output_dim=output_dim_second, num_filters=num_filters_transport,
                        seq_len=seq_len, graph_conv_filters=graph_conv_filters_transport,
                        activation='relu')(x_transport)

  x_transport = Flatten()(x_transport)

  x_transport = Reshape(target_shape=(seq_len, -1))(x_transport)

  x_transport = concatenate([x_transport, seq_context], axis=2)

  x_transport = cudnn_recurrent.CuDNNGRU(gru_units, activation=gru_activation, return_sequences=False)(x_transport)

  x_transport = Reshape([height*width, 1])(x_transport)

  x_transport = Dense(1, activation=None)(x_transport)

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

  context = tf.expand_dims(context, 1)
  context = tf.tile(context, [1, 1280, 1])

  x_total = concatenate([x_dist, x_poi, x_transport], axis=2)

  total_context = concatenate([x_total, context, tfidf_input], axis=2)

  total_context = Dense(3, 'relu')(total_context)

  context_atten = Softmax(axis=2)(total_context)

  x_total = Multiply()([x_total, context_atten])

  out = K.sum(x_total, axis=2, keepdims=False)

  model = Model(inputs=[X_input, context_input, seq_context_input, tfidf_input], outputs=out)
  adam = Adam(lr = learning_rate)

  model.compile(loss='mse', optimizer=adam)

  return model


from django.urls import path

from . import views

app_name = 'job'

urlpatterns = [
    # 任务列表
    path('jobs/', views.jobs_view, name='jobs'),

    # 任务详情
    path('jobs/<int:job_id>/detail/', views.job_detail_view, name='job_detail'),

    # 删除任务
    path('jobs/ajax/delete/', views.job_delete_view, name='job_delete'),

    # 回调更新任务信息
    path('remote_update/<int:job_id>/', views.jobs_remote_update_view, name='remote_update'),
]


# -*- coding: utf-8 -*-
"""Fixing required fields

Revision ID: 8d2b3386d63f
Revises: 995d4fa1bfd0
Create Date: 2017-05-23 18:23:45.911491

"""
from alembic import op
from sqlalchemy import String, Integer, Text
from sqlalchemy.sql import table, column, text

# revision identifiers, used by Alembic.
revision = '690a19ef85c0'
down_revision = '8d2b3386d63f'
branch_labels = None
depends_on = None

def _insert_operation():
    tb = table('operation',
               column("id", Integer),
               column("slug", String),
               column('enabled', Integer),
               column('type', String),
               column('icon', String),
               )
    all_ops = (
        (82, 'execute-python', 1, 'TRANSFORMATION', 'fa-code'),
        (83, 'entity-matching', 1, 'TRANSFORMATION', 'fa-vcard-o'),
    )
    rows = [dict(list(zip([c.name for c in tb.columns], operation))) for operation in
            all_ops]

    op.bulk_insert(tb, rows)

def _insert_operation_translation():
    tb = table(
        'operation_translation',
        column('id', Integer),
        column('locale', String),
        column('name', String),
        column('description', String), )

    all_ops = [
        (82, 'en', 'Execute Python code', 'Execute Python code'),
        (82, 'pt', 'Executar código Python', 'Executar código Python'),
        (83, 'en', 'Entity matching', 'Entity matching'),
        (83, 'pt', 'Resolução de entidades', 'Resolução de entidades'),
    ]
    rows = [dict(list(zip([c.name for c in tb.columns], operation))) for operation in
            all_ops]

    op.bulk_insert(tb, rows)

def _insert_operation_platform():
    tb = table(
        'operation_platform',
        column('operation_id', Integer),
        column('platform_id', Integer))

    all_ops = [
        (82, 1),
        (83, 1),
    ]
    rows = [dict(list(zip([c.name for c in tb.columns], operation))) for operation in
            all_ops]

    op.bulk_insert(tb, rows)

def _insert_operation_port():
    tb = table(
        'operation_port',
        column('id', Integer),
        column('type', String),
        column('tags', String),
        column('operation_id', Integer),
        column('order', Integer),
        column('multiplicity', String), )

    all_ops = [
        (177, 'INPUT', None, 82, 1, 'ONE'),
        (178, 'INPUT', None, 82, 2, 'ONE'),
        (179, 'OUTPUT', None, 82, 1, 'MANY'),
        (180, 'OUTPUT', None, 82, 1, 'MANY'),

        (181, 'INPUT', None, 83, 1, 'ONE'),
        (182, 'INPUT', None, 83, 2, 'ONE'),
        (183, 'OUTPUT', None, 83, 1, 'MANY'),
    ]
    rows = [dict(list(zip([c.name for c in tb.columns], operation))) for operation in
            all_ops]

    op.bulk_insert(tb, rows)

def _insert_operation_port_translation():
    tb = table(
        'operation_port_translation',
        column('id', Integer),
        column('locale', String),
        column('name', String),
        column('description', String), )

    all_ops = [
        (177, 'en', 'input data 1', 'Input 1'),
        (178, 'en', 'input data 2', 'Input 2'),
        (179, 'en', 'output data 1', 'Output 1'),
        (180, 'en', 'output data 2', 'Output 2'),

        (177, 'pt', 'dados entrada 1', 'Entrada 1'),
        (178, 'pt', 'dados entrada 2', 'Entrada 2'),
        (179, 'pt', 'dados saída 1', 'Saída 1'),
        (180, 'pt', 'dados saída 2', 'Saída 2'),

        (181, 'en', 'input data 1', 'Input 1'),
        (182, 'en', 'input data 2', 'Input 2'),
        (183, 'en', 'output data 1', 'Output 1'),

        (181, 'pt', 'dados entrada 1', 'Entrada 1'),
        (182, 'pt', 'dados entrada 2', 'Entrada 2'),
        (183, 'pt', 'dados saída 1', 'Saída 1'),
    ]
    rows = [dict(list(zip([c.name for c in tb.columns], operation))) for operation in
            all_ops]

    op.bulk_insert(tb, rows)

def _insert_operation_port_interface_operation_port():
    tb = table(
        'operation_port_interface_operation_port',
        column('operation_port_id', Integer),
        column('operation_port_interface_id', Integer))

    columns = [c.name for c in tb.columns]
    data = [
        (177, 1),
        (178, 1),
        (179, 1),
        (180, 1),

        (181, 1),
        (182, 1),
        (183, 1),
    ]
    rows = [dict(list(zip(columns, cat))) for cat in data]

    op.bulk_insert(tb, rows)

def _insert_operation_category_operation():
    tb = table(
        'operation_category_operation',
        column('operation_id', Integer),
        column('operation_category_id', Integer))

    columns = [c.name for c in tb.columns]
    data = [
        (82, 13),
        (83, 13),
    ]
    rows = [dict(list(zip(columns, cat))) for cat in data]

    op.bulk_insert(tb, rows)

def _insert_operation_form():
    tb = table(
        'operation_form',
        column('id', Integer),
        column('enabled', Integer),
        column('order', Integer),
        column('category', String), )

    columns = [c.name for c in tb.columns]
    data = [
        (97, 1, 1, 'execution'),
        (98, 1, 1, 'execution'),
    ]
    rows = [dict(list(zip(columns, row))) for row in data]

    op.bulk_insert(tb, rows)

def _insert_operation_operation_form():
    tb = table(
        'operation_operation_form',
        column('operation_id', Integer),
        column('operation_form_id', Integer))

    columns = [c.name for c in tb.columns]
    data = [
        (82, 97),
        (82, 41),

        (83, 98),
        (83, 41),
    ]
    rows = [dict(list(zip(columns, row))) for row in data]

    op.bulk_insert(tb, rows)

def _insert_operation_form_translation():
    tb = table(
        'operation_form_translation',
        column('id', Integer),
        column('locale', String),
        column('name', String)
    )

    columns = [c.name for c in tb.columns]
    data = [
        (97, 'en', 'Execution'),
        (97, 'pt', 'Execução'),

        (98, 'en', 'Execution'),
        (98, 'pt', 'Execução'),
    ]
    rows = [dict(list(zip(columns, row))) for row in data]

    op.bulk_insert(tb, rows)

def _insert_operation_form_field():
    tb = table(
        'operation_form_field',
        column('id', Integer),
        column('name', String),
        column('type', String),
        column('required', Integer),
        column('order', Integer),
        column('default', Text),
        column('suggested_widget', String),
        column('values_url', String),
        column('values', String),
        column('scope', String),
        column('form_id', Integer), )

    columns = [c.name for c in tb.columns]
    data = [
        (229, 'code', 'TEXT', 1, 0,
         ('# Write your Python code here\n'
          '# Inputs are available as in1 and in2, '
          'outputs are out1 and out2'), 'code',
         None, None, 'EXECUTION', 97),

        (230, 'algorithm', 'TEXT', 1, 0,
         '', 'dropdown',
         None, '[{"key": "BULMA", "value": "Geospatial Data - Bulma"}]',
            'EXECUTION', 98),
    ]
    rows = [dict(list(zip(columns, row))) for row in data]
    op.bulk_insert(tb, rows)

def _insert_operation_form_field_translation():
    tb = table(
        'operation_form_field_translation',
        column('id', Integer),
        column('locale', String),
        column('label', String),
        column('help', String), )

    columns = [c.name for c in tb.columns]
    data = [
        (229, 'en', 'Code', 'Code'),
        (229, 'pt', 'Código', 'Código'),

        (230, 'en', 'Algorithm', 'Algorithm'),
        (230, 'pt', 'Algoritmo', 'Algoritmo'),
    ]
    rows = [dict(list(zip(columns, row))) for row in data]
    op.bulk_insert(tb, rows)

all_commands = [
    (_insert_operation, 'DELETE FROM operation WHERE id BETWEEN 82 AND 83'),
    (_insert_operation_translation,
     'DELETE FROM operation_translation WHERE id BETWEEN 82 AND 83'),
    (_insert_operation_port, 'DELETE FROM operation_port '
                             'WHERE operation_id BETWEEN 82 AND 83'),
    (_insert_operation_port_translation,
     'DELETE FROM operation_port_translation WHERE id IN '
     '(SELECT id FROM operation_port WHERE operation_id BETWEEN 82 AND 83)'),
    (_insert_operation_port_interface_operation_port,
     'DELETE FROM operation_port_interface_operation_port '
     'WHERE operation_port_id IN (SELECT id FROM operation_port '
     'WHERE operation_id BETWEEN 82 AND 83)'),
    (_insert_operation_category_operation,
     'DELETE FROM operation_category_operation '
     'WHERE operation_id BETWEEN 82 AND 83;'),
    (_insert_operation_platform, 'DELETE FROM operation_platform '
                                 'WHERE operation_id BETWEEN 82 AND 83'),
    (_insert_operation_form,
     'DELETE FROM operation_form WHERE id BETWEEN 97 AND 98'),
    (_insert_operation_operation_form, 'DELETE FROM operation_operation_form '
                                       'WHERE operation_id BETWEEN 82 AND 83'),
    (_insert_operation_form_translation,
     'DELETE FROM operation_form_translation WHERE id BETWEEN 97 AND 98'),
    (_insert_operation_form_field,
     'DELETE FROM operation_form_field WHERE form_id BETWEEN 97 AND 98'),
    (_insert_operation_form_field_translation,
     'DELETE FROM operation_form_field_translation '
     'WHERE id IN (SELECT id FROM operation_form_field '
     '   WHERE form_id BETWEEN 97 AND 98)'),
]

def upgrade():
    try:
        op.execute(text('START TRANSACTION'))
        for cmd in all_commands:
            cmd[0]()
        op.execute(text('COMMIT'))
    except:
        op.execute(text('ROLLBACK'))
        raise

def downgrade():
    try:
        op.execute(text('START TRANSACTION'))
        for cmd in reversed(all_commands):
            op.execute(text(cmd[1]))
        op.execute(text('COMMIT'))
    except:
        op.execute(text('ROLLBACK'))
        raise


import os

import maya.cmds as cmds
import maya.mel as mel

import Utilities.utilityFunctions as uf

def set_and_export(filepath):

    pathField = None
    fileField = None
    filepath = uf.fix_path(filepath)
    path = "/".join(filepath.split("/")[:-1])
    file = os.path.basename(filepath).split(".")[0]
    # open the exporter
    mel.eval("gameFbxExporter;")

    # get the exporter nodes (I'm still not sure which one, so we'll use the last later)
    nodes = mel.eval("gameExp_GetGameFbxExporterNodeList()")
    # preset = "X:/Production/Code/Maya/Tools/PipelineTools/Python/Publishing/assetAnimGameExpPreset.mel"

# can we get the whole frame range?

    # set it to the correct tab
    tab = "gameExporterWindow|gameExporterTabFormLayout|gameExporterTabLayout"
    cmds.tabLayout(tab, e=True, st="gameExporterAnimationTab")

    # assign preset (on the last node?)
    # hold = mel.eval('gameExp_ApplyPresetOnNode("{0}", "{1}");'.format(nodes[-1], preset))

    # find the text fields
    for ctrl in cmds.lsUI(ctl=True, l=True):
        if ctrl.startswith("gameExporterWindow") and ctrl.split("|")[-1]=="anim_gameExporterExportFilename":
            fileField = ctrl
        if ctrl.startswith("gameExporterWindow") and ctrl.split("|")[-1]=="anim_gameExporterExportPath":
            pathField = ctrl

    mel.eval('gameExp_BrowseFolder')
    # populate the text fields
    # changetext = cmds.textField(pathField, e=True, tx=path)
    # cmds.textField(fileField, e=True, tx=file)

    # print mel.eval('getAttr ($gGameFbxExporterCurrentNode + ".exportPath");')

    # mel.eval('connectControl -preventContextualMenu true -fileName {0} ($gGameFbxExporterCurrentNode + ".exportPath");'.format(pathField))
    # mel.eval('connectControl -preventContextualMenu true {0}($gGameFbxExporterCurrentNode + ".exportFilename");'.format(fileField))

    # do the export
    # mel.eval('gameExp_DoExport;')


import requests
import html
import csv
from contextlib import closing
import matplotlib.pyplot as plt

def derivative(x,y,start,end):
    y_prime = []
    prevX = start
    prevY = end
    for i in range(0,len(x)):
        delta_x = x[i] - prevX
        delta_y = y[i] - prevY
        if (delta_x == 0):
            delta_x = 1
        y_prime.append(delta_y/delta_x)
        prevX = x[i]
        prevY = y[i]
    return y_prime

def getCountryData(country):
    url = "https://covid.ourworldindata.org/data/owid-covid-data.csv"

    with closing(requests.get(url, stream=True)) as r:
        f = (line.decode('utf-8') for line in r.iter_lines())
        reader = csv.reader(f, delimiter=',', quotechar='"')
        data = []
        first = True
        for row in reader:
            if first == True:
                data.append(row)
                first = False
            if row[0] == country:
                data.append(row)
        return data

def plotData(Data):
    plt.plot([day for day in range(0,Data["days"])], Data["data"])
    plt.title(Data["title"])
    # naming the x axis
    plt.xlabel(Data["xlabel"])
    # naming the y axis
    plt.ylabel(Data["ylabel"])

    # function to show the plot
    plt.show()

def main():
    USA = getCountryData("USA")
    my_total_cases = 0
    total = 0
    NC_indx = None
    TC_indx = None
    TC_data = []
    NC_data = []
    days = -1
    for row in USA:
        days += 1
        if row == USA[0]:
            for col in row:
                if col == "new_cases":
                    NC_indx = row.index(col)
                if col == "total_cases":
                    TC_indx = row.index(col)
        else:
            TC_data.append(int(row[TC_indx]))
            NC_data.append(int(row[NC_indx]))
            my_total_cases += int(row[NC_indx])
    TC_dict = {
                "days": days,
                "data": TC_data,
                "title": 'Number of total cases',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": 'Total cases'}
    plotData(TC_dict)
    NC_dict = {
                "days": days,
                "data": NC_data,
                "title": 'New Cases Each Day',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": 'New cases'}

    plotData(NC_dict)
    Deriv_dict = {
                "days": days,
                "data": derivative([day for day in range(0,days)],TC_data,0,0),
                "title": 'Derivative of total cases',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": 'Derivative'}

    plotData(Deriv_dict)

    Sec_Deriv_dict = {
                "days": days,
                "data": derivative([day for day in range(0,days)],Deriv_dict["data"],0,0),
                "title": '2nd Derivative of total cases',
                "xlabel": 'days since Dec 31, 2019',
                "ylabel": '2nd Derivative'}

    plotData(Sec_Deriv_dict)

if __name__ == "__main__":
    main()


from rest_framework import serializers
from rest_framework.authtoken.models import Token
from rest_framework.validators import UniqueValidator
from walletservice.models import Wallete, Transactions
from datetime import datetime

class WalletSerializer(serializers.ModelSerializer):
    owner_by = serializers.SerializerMethodField("_owner_")
    status = serializers.SerializerMethodField("_status_")

    def _owner_ (self, obj):
        try:
            token = Token.objects.get(user=obj.owner)
            return token.key
        except: return ""

    def _status_(self, obj):
        if obj.is_enable:
            return "enabled"
        else:  return "desabled"

    class Meta:
        model = Wallete
        fields = ['id', 'owner_by', 'status',
                'enabled_at', 'balance', 'disabled_at']

    def __init__(self, *args, **kwargs):
        fields = kwargs.pop('fields', None)
        super(WalletSerializer, self).__init__(*args, **kwargs)
        if fields is not None:
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

    def update(self, instance, validated_data):
        is_disabled = validated_data.get("is_disabled")
        if is_disabled == "true":
            instance.is_enable=False
            instance.disabled_at = datetime.now()
        else:
            instance.is_enable=True
            instance.enabled_at = datetime.now()
        instance.save()
        return instance

class DepositSerializer(serializers.ModelSerializer):
    deposited_by = serializers.SerializerMethodField("_deposited_by_")
    status = serializers.SerializerMethodField("_status_")
    deposited_at = serializers.SerializerMethodField("_deposited_at_")
    amount = serializers.CharField(required=True, max_length=255)
    reference_id = serializers.CharField(required=True,
                max_length=100, validators=[
                UniqueValidator(
                queryset=Transactions.objects.filter(type="deposit"),
                message="Reference id already exists")])

    def validate(self, attrs):
        amount = attrs.get('amount')
        if float(amount) <= 0:
            raise serializers.ValidationError(
                "Deposit an amount greater than zero")
        return attrs

    def _deposited_at_ (self, obj):
        try:
            return obj.datetime
        except: return ""

    def _deposited_by_ (self, obj):
        try:
            token = Token.objects.get(user=obj.user)
            return token.key
        except: return ""

    def _status_(self, obj):
        if obj.is_success:
            return "Success"
        else:  return "Fail"

    class Meta:
        model = Transactions
        fields = ['id', 'deposited_by', 'status',
                'deposited_at', 'amount', 'reference_id']

    def create(self, validated_data):
        user =  self.context.get('user')
        wallet_obj = self.context.get('wallet_obj')
        amount = validated_data.get("amount")
        reference_id = validated_data.get("reference_id")
        transaction_obj = Transactions.objects.create(amount=amount,
                reference_id=reference_id,
                type='deposit', user=user, wallet=wallet_obj,
                datetime=datetime.now(),
                is_success=True)
        wallet_obj.balance = float(wallet_obj.balance) + float(amount)
        wallet_obj.save()
        return transaction_obj

class WithdrawSerializer(serializers.ModelSerializer):
    withdraw_by = serializers.SerializerMethodField("_withdraw_by_")
    status = serializers.SerializerMethodField("_status_")
    withdraw_at = serializers.SerializerMethodField("_withdraw_at_")
    amount = serializers.CharField(required=True, max_length=255)
    reference_id = serializers.CharField(required=True,
                max_length=100, validators=[
                UniqueValidator(
                queryset=Transactions.objects.filter(
                type="withdraw"),
                message="Reference id already exists")])

    def validate(self, attrs):
        amount = attrs.get('amount')
        wallet_obj = self.context.get('wallet_obj')
        if float(wallet_obj.balance) < float(amount):
            raise serializers.ValidationError(
                "Insufficient balance. Your balance is {balance}".format(
                balance=wallet_obj.balance))
        return attrs

    def _withdraw_at_ (self, obj):
        try:
            return obj.datetime
        except: return ""

    def _withdraw_by_ (self, obj):
        try:
            token = Token.objects.get(user=obj.user)
            return token.key
        except: return ""

    def _status_(self, obj):
        if obj.is_success:
            return "Success"
        else:  return "Fail"

    class Meta:
        model = Transactions
        fields = ['id', 'withdraw_by', 'status',
                'withdraw_at', 'amount', 'reference_id']

    def create(self, validated_data):
        user =  self.context.get('user')
        wallet_obj = self.context.get('wallet_obj')
        amount = validated_data.get("amount")
        reference_id = validated_data.get("reference_id")
        transaction_obj = Transactions.objects.create(amount=amount,
                reference_id=reference_id,
                type='withdraw', user=user, wallet=wallet_obj,
                datetime=datetime.now(),
                is_success=True)
        wallet_obj.balance = float(wallet_obj.balance) - float(amount)
        wallet_obj.save()
        return transaction_obj


from flask import Flask, flash, render_template, request, redirect, url_for
from werkzeug import secure_filename
from Jjson import *
import os
import datetime

Upload_Folder = './stored'
ALLOWED_EXTENSIONS = set(['txt'])

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = Upload_Folder

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/')
def main() -> 'html':
    return render_template('main.html')

@app.route('/upload', methods=['POST'])
def upload() -> 'html':
    Uploadtime = datetime.datetime.now()
    if request.method == 'POST':
        # check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        # if user does not select file, browser also
        # submit a empty part without filename
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            n = os.path.getsize(filename) / 1024.0
            n = round(n, 3)

            if c.find_one():
                for x in c.find():
                    if filename == x["FileName"]:
                        if n == x["DataSize"]:
                            arr = c.find_one({'FileName': filename})
                            count = 0
                            return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"], size=arr["DataSize"])
                    else:
                        count = 1
                if(count == 1):
                    insert(filename, n, Uploadtime)
                    for x in c.find():
                        print(x["FileName"])
                        arr = c.find_one({'FileName': filename})
                    return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"],
                                       size=arr["DataSize"])
            else:
                insert(filename, n, Uploadtime)
                for x in c.find():
                    print(x["FileName"])
                arr = c.find_one({'FileName': filename})
                return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"], size=arr["DataSize"])
        return render_template('main.html')

@app.route('/history', methods=['POST'])
def history()->'html':
    ar = []
    for x in c.find():
        ar.append(x["FileName"])
    print(ar)
    arra = {}
    for x in ar:
        arra[x] = c.find_one({'FileName': x})
    for x in arra:
        print(arra[x]["DATE"])
    return render_template('history.html', NAMEARRAY=ar, DATAARRAY=arra)

@app.route('/result2/<filename>', methods=['GET'])
def result2(filename)->'html':
    arr = c.find_one({'FileName': filename})
    return render_template('result.html', DATA=arr["DATA"], DATE=arr["DATE"], FILENAME=arr["FileName"],
                           size=arr["DataSize"])

def insert(filename, n, Uploadtime):
    wordData = openfile(Upload_Folder, filename)
    print(wordData)

    post = {"FileName": filename, "DataSize": n, "DATE": Uploadtime,
            "DATA": wordData}
    db.word.insert(post, check_keys=False)

app.secret_key = 'thisismysecretsecretsecretkey'

if __name__ == '__main__':
    app.run(debug=True)


from pymatgen import MPRester
from MaterialsProject.com.project.elate import elastic
import numpy as np
import pandas as pd

#######################################NE PAS PRENDRE LES VALEURS -1000 ET -1500 DES MATERIAUX NON CONFORMES
api = MPRester("78OAi0lR9kdkyiAi")

propsTableau = ['material_id', 'pretty_formula', "elasticity.elastic_tensor", 'elasticity.poisson_ratio',
                'elasticity.G_Reuss', 'elasticity.G_Voigt', 'elasticity.G_Voigt_Reuss_Hill',
                'elasticity.K_Reuss', 'elasticity.K_Voigt', 'elasticity.K_Voigt_Reuss_Hill']
composes = ['S', 'O']
# critere1: tous les elements elastiques contenant les composes S,O
critere1 = {"nelements": {'$lte': 6}, 'elements': {'$all': composes}, "elasticity": {'$ne': None},
            "elasticity.G_Reuss": {'$gte': 0}, "elasticity.G_Voigt": {'$gte': 0},
            "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0}, "elasticity.K_Reuss": {'$gte': 0},
            "elasticity.K_Voigt": {'$gte': 0}, "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0}}

# critere2: tous les elements elastiques ratio de poisson negatif
critere2 = {"nelements": {'$lte': 6}, "elasticity": {'$ne': None}, "elasticity.poisson_ratio": {'$lt': 0},
            "elasticity.G_Reuss": {'$gte': 0, '$lte': 1000},
            "elasticity.G_Voigt": {'$gte': 0, '$lte': 1000}, "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Reuss": {'$gte': 0, '$lte': 1000}, "elasticity.K_Voigt": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000}}

critere2EXP = {"nelements": {'$lte': 6}, "elasticity": {'$ne': None}, 'icsd_ids.0': {'$exists': True}, "elasticity.poisson_ratio": {'$lt': 0},
            "elasticity.G_Reuss": {'$gte': 0, '$lte': 1000},
            "elasticity.G_Voigt": {'$gte': 0, '$lte': 1000}, "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Reuss": {'$gte': 0, '$lte': 1000}, "elasticity.K_Voigt": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000}}

# critere3: tous les elements elastiques
critere3 = {"nelements": {'$lte': 6}, "elasticity": {'$ne': None},
            "elasticity.G_Reuss": {'$gte': 0, '$lte': 1000},
            "elasticity.G_Voigt": {'$gte': 0, '$lte': 1000}, "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Reuss": {'$gte': 0, '$lte': 1000}, "elasticity.K_Voigt": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000}}

critere4 = {"nelements": {'$lte': 6}, "elasticity": {'$ne': None}, "elasticity.poisson_ratio": {'$lt': 0},
            "elasticity.G_Reuss": {'$gte': 0, '$lte': 1000},
            "elasticity.G_Voigt": {'$gte': 0, '$lte': 1000}, "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Reuss": {'$gte': 0, '$lte': 1000}, "elasticity.K_Voigt": {'$gte': 0, '$lte': 1000},
            "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000}}

critere4bis = {"nelements": {'$lte': 6}, "elasticity": {'$ne': None}, "elasticity.poisson_ratio": {'$lt': 0},
               'icsd_ids.0': {'$exists': True},
               "elasticity.G_Reuss": {'$gte': 0, '$lte': 1000},
               "elasticity.G_Voigt": {'$gte': 0, '$lte': 1000},
               "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000},
               "elasticity.K_Reuss": {'$gte': 0, '$lte': 1000}, "elasticity.K_Voigt": {'$gte': 0, '$lte': 1000},
               "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000}}

critere4EXP = {"nelements": {'$lte': 6}, "elasticity": {'$ne': None}, 'icsd_ids.0': {'$exists': True},
               "elasticity.G_Reuss": {'$gte': 0, '$lte': 1000},
               "elasticity.G_Voigt": {'$gte': 0, '$lte': 1000},
               "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000},
               "elasticity.K_Reuss": {'$gte': 0, '$lte': 1000}, "elasticity.K_Voigt": {'$gte': 0, '$lte': 1000},
               "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000}}

critere4HYP = {"nelements": {'$lte': 6}, "elasticity": {'$ne': None}, 'icsd_ids.0': {'$exists': False},
               "elasticity.G_Reuss": {'$gte': 0, '$lte': 1000},
               "elasticity.G_Voigt": {'$gte': 0, '$lte': 1000},
               "elasticity.G_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000},
               "elasticity.K_Reuss": {'$gte': 0, '$lte': 1000}, "elasticity.K_Voigt": {'$gte': 0, '$lte': 1000},
               "elasticity.K_Voigt_Reuss_Hill": {'$gte': 0, '$lte': 1000}}

materials = api.query(criteria=critere2EXP, properties=propsTableau)

# test= elastic.ELATE_MaterialsProject("mp-2133")
# matrix = elastic_tensor

def generateElas(matrix):
    try:
        elas = elastic.Elastic(matrix)
    except ValueError as e:
        print('Error: Invalid stiffness matrix: ')
        print(e.args[0])
        return None

    if elas.isOrthorhombic():
        elas = elastic.ElasticOrtho(elas)
    return elas

def calculMinLC(elas):
    return elastic.minimize(elas.LC, 2)

def calculMaxLC(elas):
    return elastic.maximize(elas.LC, 2)

def calculMinNu(elas):
    return elastic.minimize(elas.Poisson, 3)

def calculMaxNu(elas):
    return elastic.maximize(elas.Poisson, 3)

def calculMinYoung(elas):
    return elastic.minimize(elas.Young, 2)

def calculMaxYoung(elas):
    return elastic.maximize(elas.Young, 2)

def calculMinG(elas):
    return elastic.minimize(elas.shear, 3)

def calculMaxG(elas):
    return elastic.maximize(elas.shear, 3)

propsDisplay_old = ["minLC", "maxLC", "minNu", "maxNu", "K_Voigt_Reuss_Hill", "Emin", "Emax", "Gmin", "Gmax",
                    "elasticity.poisson_ratio"]
propsDisplay = ["minLC", "maxLC", "minNu", "maxNu", "Emin", "Emax", "Gmin", "Gmax",
                'elasticity.G_Reuss', 'elasticity.G_Voigt', 'elasticity.G_Voigt_Reuss_Hill',
                'elasticity.K_Reuss', 'elasticity.K_Voigt', 'elasticity.K_Voigt_Reuss_Hill', 'elasticity.poisson_ratio']

col = len(propsDisplay)
lin = len(materials)
newlin = lin
elements = []
materialIds = []
materialNonConformeEigenvalNegative = []
materialNonConformeMatSinguliere = []

def recup(materials):
    i = 0
    tableau = np.zeros(shape=(lin, col))
    for material in materials:
        print(str(i + 1), "-", str(material.get('material_id')), ":", material.get('pretty_formula'))

        matrix = material.get('elasticity.elastic_tensor')
        elastElement = generateElas(matrix)
        if elastElement:
            eigenval = sorted(np.linalg.eig(elastElement.CVoigt)[0])
            if eigenval[0] > 0:
                elements.append(material.get('pretty_formula'))
                materialIds.append(material.get('material_id'))
                tableau[i, 0] = calculMinLC(elastElement)[1]
                tableau[i, 1] = calculMaxLC(elastElement)[1]
                tableau[i, 2] = calculMinNu(elastElement)[1]
                tableau[i, 3] = calculMaxNu(elastElement)[1]
                tableau[i, 4] = calculMinYoung(elastElement)[1]
                tableau[i, 5] = calculMaxYoung(elastElement)[1]
                tableau[i, 6] = calculMinG(elastElement)[1]
                tableau[i, 7] = calculMaxG(elastElement)[1]
                tableau[i, 8] = material.get('elasticity.G_Reuss')
                tableau[i, 9] = material.get('elasticity.G_Voigt')
                tableau[i, 10] = material.get('elasticity.G_Voigt_Reuss_Hill')
                tableau[i, 11] = material.get('elasticity.K_Reuss')
                tableau[i, 12] = material.get('elasticity.K_Voigt')
                tableau[i, 13] = material.get("elasticity.K_Voigt_Reuss_Hill")
                tableau[i, 14] = material.get("elasticity.poisson_ratio")
                i = i + 1
            else:
                materialNonConformeEigenvalNegative.append(material.get('material_id'))
        else:
            materialNonConformeMatSinguliere.append(material.get('material_id'))

    nb_ligne_supp = lin - len(materialIds)
    if nb_ligne_supp > 0:
        tableau = tableau[:-nb_ligne_supp, :]
    return tableau

def export(donnees, ligne, nomColonnes, fichier):
    my_df = pd.DataFrame(donnees)
    my_df.index = ligne
    my_df.to_csv(fichier, index=ligne, header=nomColonnes)

def importer(fichier):
    return pd.read_csv(fichier, index_col=0)

def export_equal_0(file_name):
    data = importer(file_name)
    extract_data2 = data[(data['elasticity.G_Reuss'] != 0) & (data['elasticity.G_Voigt'] != 0) &
                         (data['elasticity.G_Voigt_Reuss_Hill'] != 0) &
                         (data['elasticity.K_Reuss'] != 0) &
                         (data['elasticity.K_Voigt'] != 0) &
                         (data['elasticity.K_Voigt_Reuss_Hill'] != 0)]
    extract_data3 = data[(data['elasticity.G_Reuss'] == 0) | (data['elasticity.G_Voigt'] == 0) |
                         (data['elasticity.G_Voigt_Reuss_Hill'] == 0) |
                         (data['elasticity.K_Reuss'] == 0) |
                         (data['elasticity.K_Voigt'] == 0) |
                         (data['elasticity.K_Voigt_Reuss_Hill'] == 0)]
    extract_data2.to_csv("elasticElate_ALL_revisionArt_without_Zero_PoissonNega_EXP.csv")
    extract_data3.to_csv("elasticElate_ALL_revisionArt_with_Zero_PoissonNega_EXP.csv")

resultat = recup(materials)

export(resultat, materialIds, propsDisplay, "elasticElate_ALL_revisionArt_PoissonNega_EXP.csv")

export_equal_0("elasticElate_ALL_revisionArt_PoissonNega_EXP.csv")

print("materials non conformes, eigenVal negative:\n" + str(materialNonConformeEigenvalNegative))
print("materials non conformes, matrice singuliere:\n" + str(materialNonConformeMatSinguliere))
print("nbre de materials non conformes, eigenVal negative:\n" + str(materialNonConformeEigenvalNegative.__len__()))
print("nbre de materials non conformes, matrice singuliere:\n" + str(materialNonConformeMatSinguliere.__len__()))


'''
                                        Author:xtncsg（想听你唱首歌）
                                        create；2019-04-18
                                        update；2019-04-19
                                        bug:输入闹钟时间的时候，不能直接把输入框里面的数字全都删除
                                        unknown:ctypes 蜂鸣器
                                                StringVar()绑定变量
                                                局部函数里使用全局变量要global说明
                                                massagebox弹窗的自动关闭
                                                好像没有 RGB(255,255,255)这样生成颜色的宏
                                                同一个标签变量，不能两次放置，只会显示一次
                                                bind() 事件处理的绑定
                                                root.quit 和 root.destroy 的区别
'''

# from tkinter import*   并不鼓励使用from Tkinter import * 说是失去命名空间同时导致名字冲突
import tkinter
from datetime import datetime
import tkinter.messagebox as ms
import time
from threading import Thread
import  ctypes    # 关于系统蜂鸣器的库
player = ctypes.windll.kernel32  # 都是字母 l

# 生成全局窗口
root = tkinter.Tk()
root.title("闹钟定制")
# root.minsize(width = 800,height = 640)
root.geometry("1000x580") # 还可以继续缩小的窗口,中间是英文 x
# root.resizable(width = 1,height = 0)    设置窗口是否可以改变大小

game = tkinter.Label(root,text = "设置好闹钟时间后，若显示为ON则闹钟已经成功开启",height = 5,width = 50,bg = "#33FF00",fg = "#FF0000",font = 6)
game.place(x = 320,y = 5)

'''    必须要先生成窗口，才能绑定变量，因为StringVar 这个类里面，有一个成员函数 __init__(self, master=None, value=None, name=None)，
它的参数MASTER can be given as master widget.    '''

# 获取当前时间
# print(type(datetime.now()))  <class 'datetime.datetime'>
current_hour = datetime.now().hour
current_minute = datetime.now().minute
current_second = datetime.now().second
# print(type(curent_hour))  <class 'int'>

# 能自动刷新的字符串变量，可用set和get方法进行传值和取值
now_hour = tkinter.StringVar(value = current_hour)
now_minute = tkinter.StringVar(value = current_minute)
now_second = tkinter.StringVar(value = current_second)
# print(now_hour)         PY_VAR0
# print(type(now_hour))   <class 'tkinter.StringVar'>

clock_flag = False

# 与按键 ON/OFF 绑定的启动闹钟函数
def boot_clock():
    # global 说明这里的变量与外面的全局变量是一样的
    global clock_flag  #  local variable 'clock_flag' referenced before assignment
    clock_flag = not clock_flag

    clock_hour = int(hour_entry.get())  # 获取输入框里面的时间
    clock_minute = int(minute_entry.get())
    clock_second = int(second_entry.get())
    # print(type(clock_hour))  <class 'str'>

    if(clock_hour >= 24 or clock_minute >= 60 or clock_second >=60):
        ms.showerror("错误","闹钟时间设置错误\n请重新设置")
        # sys.exit(0)  这样整个程序就退出了，还是用 else 吧
    else:
         if(clock_flag):
            ms.showinfo("闹钟已经开启","闹钟将在{}时{}分{}秒时启动\n请注意躲避".format(clock_hour,clock_minute,clock_second))
            # showinfo(),showerror(),showwarning()
            confirm["text"] = "ON"
         else:
            confirm["text"] = "OFF"

# 响铃函数
def ring():
    for i in range(10):
        player.Beep(2000,1000)  # 频率和毫秒

# 时间匹配时，闹钟开始运行
def clock_start():
    Thread(target = ring).start()
    ms.showwarning("闹钟进行","闹钟开始了，大家快跑啊")
# 这里创建线程，要不然弹窗不关闭，就不会响铃

def timer():
    while(1):
        hour_num = int(now_hour.get()) # 获取当前时间
        minute_num = int(now_minute.get())
        second_num = int(now_second.get())
        # print(type(hour_num))  <class 'str'>

        # 非纯数字组成的字符串强转为整型会报错：ValueError: invalid literal for int() with base 10
        # 所以在输入框输入数字的时候，不能一下子把原来的数字都删掉，这样就变成空字符串了
        clock_hour = int(hour_entry.get())  # 获取输入框里面的时间
        clock_minute = int(minute_entry.get())
        clock_second = int(second_entry.get())
        # print(type(clock_hour))  <class 'str'>

        second_num += 1
        if second_num == 60:
            minute_num +=1
            second_num = 0
            if minute_num == 60:
                hour_num += 1
                minute_num =0
                if hour_num == 24:
                    hour_num = 0
        now_hour.set("%02d"%hour_num)  # 指定格式更新数据
        now_minute.set("%02d"%minute_num)
        now_second.set("%02d"%second_num)

        if(clock_flag == True and hour_num == clock_hour and minute_num == clock_minute and second_num == clock_second):
            Thread(target = clock_start).start()
        # 这里创建线程，要不然闹钟开始的时候，时钟就不走了
        # 时间每隔一秒刷新一次
        time.sleep(1)   # 单位是秒

if __name__ == '__main__':
    # 用 RGB 生成颜色
    # current_time = tkinter.Label(root,width = 10,height = 1,text = "现在时间：",font = 3,bg = RGB(20,184,152))

    # "#33FF00"十六进制表示的颜色字符串，R,G,B各占一个字节
    current_time = tkinter.Label(root,width = 10,height = 1,text = "现在时间：",font = 3,bg = "#33FF00",fg = "#FF3333")
    current_time.place(x = 10,y = 5)

    current_time_hour = tkinter.Label(root,width = 2,height = 1,textvariable = now_hour,font = 3,bg = "#3333FF",fg = "#FF3333")
    current_time_hour.place(x = 140,y = 5)

    tmp_1 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_1.place(x = 165,y = 5)

    current_time_minute = tkinter.Label(root,width = 2,height = 1,textvariable = now_minute,font = 3,bg = "#3333FF",fg = "#FF3333")
    current_time_minute.place(x = 190,y = 5)

    # 必须要生成两个临时标签，要不然只会放置一次
    tmp_2 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_2.place(x = 215,y = 5)

    current_time_second = tkinter.Label(root,width = 2,height = 1,textvariable = now_second,font = 3,bg = "#3333FF",fg = "#FF3333")
    current_time_second.place(x = 240,y = 5)

    clock_set = tkinter.Label(root,width = 10,height = 1,text = "设置闹钟：",font = 3,bg = "#FFFF00",fg = "#FF3333")
    clock_set.place(x = 10,y = 80)

    '''Entry 窗口是没有 height 属性的
    Entry等控件中的参数是关键字参数，其由键-值组成。关键字参数是在传递构成中不必按照顺序传递
    必须要提供”传递参数名=传递参数值”形式的参数，而传递过程中也转变为dict的键值对map关系。
    参数里面的 root 是 master，entry 控件的父控件，也就是放置 entry 的控件 '''

    hour_entry = tkinter.Entry(root,width = 2,font = 3,bg = "#66CC33",fg = "#FF3333")   # show = '*'
    hour_entry.place(x = 140,y = 80)

    tmp_3 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_3.place(x = 165,y = 80)

    minute_entry = tkinter.Entry(root,width = 2,font = 3,bg = "#66CC33",fg = "#FF3333")
    minute_entry.place(x = 190,y = 80)

    tmp_4 = tkinter.Label(root,width = 1,height = 1,text = ":",font = 1)
    tmp_4.place(x = 215,y = 80)

    second_entry = tkinter.Entry(root,width = 2,font = 3,bg = "#66CC33",fg = "#FF3333")
    second_entry.place(x = 240,y = 80)

    hour_entry.insert("end","00")  # 必须要指明插入的位置
    minute_entry.insert("end","00")
    second_entry.insert("end","00")

    # command 绑定事件好像只能鼠标左键单击,command 绑定的是一个回调函数
    confirm = tkinter.Button(root,font = 3,bg = "#66CC33",fg= "#FF3300",height = 1,width = 10,activebackground = "#0000FF",text = "OFF",command = boot_clock)
    confirm.place(x = 400,y = 200)

    quit = tkinter.Button(root,font = 3,bg = "#66CC33",fg= "#FF3300",height = 1,width = 10,activeforeground = "#0000FF",text = "退出程序",command = root.destroy)
    # root.destroy 会很快关闭，root.quit 关闭的就很慢
    quit.place(x = 400,y = 300)

    '''confirm.bind( "<Button-1>",start()) 如果不加括号的话，start() takes 0 positional arguments but 1 was given
    用bind() 绑定的时候，没有发生事件也会自动调用 start() 函数
    回调函数与函数：fun与fun（） 作为参数时表示的意义不同，fun作为参数表示是函数，fun（）作为参数时表示一个值 '''

    clock_t = Thread(target = timer)   # 创建线程的时候，这里不能有括号
    clock_t.start()
    # 启动主窗口消息循环
    root.mainloop()


#!/usr/bin/env python
import os
import os.path
import io
import argparse
from dont_query_me_bro.lib.types import resolve_type, VALID_TYPES

def main(query_output_file_directory, new_column_output_file_directory):
    query_output_file_objects = []
    for root, dirs, files in os.walk(query_output_file_directory):
        for f_name in files:
            # append the file handler to the file so we can iterate them later
            query_output_file_objects.append(io.open(os.path.join(root, f_name)))

    source_file_paths = []
    # build sets for each files line ids
    line_id_sets = [list() for i in range(len(query_output_file_objects))]

    # build lists of query results across each column
    for file_obj_index, f_obj in enumerate(query_output_file_objects):
        # the first line of each query result is the source column path.
        # we need this to get the values for fetching the joined rows.
        source_file_paths.append(f_obj.readline().rstrip("\n"))
        for line in f_obj:
            # SHOULD RESOVLE TO INT
            line_id = resolve_type(line, VALID_TYPES)
            line_id_sets[file_obj_index].append(line_id)

    # we only want unique filenames for columns, it wont matter what file is
    # associated to what once we join the rows
    referenced_column_paths = set(source_file_paths)

    # clean up file handlers
    for f_obj in query_output_file_objects:
        f_obj.close()

    # find smallest result and base our join off of it
    # default to 0 since its still a valid index
    smallest_set_index = 0
    for set_index, line_id_set in enumerate(line_id_sets):
        if len(line_id_sets[set_index]) < len(line_id_sets[smallest_set_index]):
            samllest_set_index = set_index

    # used later so we can build the table
    joined_lines = []
    # go ahead and join the columns
    for p_line_id in line_id_sets[smallest_set_index]:
        for line_id_set_index, line_id_set in enumerate(line_id_sets):
            # skip the set we are currently iterating through
            if line_id_set_index == smallest_set_index:
                continue
            # find out if we can join any rows
            if p_line_id in line_id_set:
                joined_lines.append(p_line_id)

    # write out each joined line to the respective new columns.
    for column in referenced_column_paths:
        column_directory, column_name = os.path.split(column)
        # open the column file for iteration
        with io.open(column, "rb") as in_column_obj:
            # write out the new column
            with io.open(os.path.join(new_column_output_file_directory, column_name), "wb") as out_column_obj:
                # needed to maintain state within the iteration of the in_column
                line_counter = 0
                # used to determine whether or not to contine reading the
                # in_column. If we hit as many ids as are in the joined_lines,
                # we can assume there will be no more to find.
                ids_hit = 0
                for line in in_column_obj:
                    # if we have hit the number of ids in our list, we can
                    # expect not to find anything more.
                    if ids_hit == len(joined_lines):
                        break
                    if line_counter in joined_lines:
                        # push the number of ids we have found forward
                        ids_hit += 1
                        # write out value to new column
                        out_column_obj.write(line)
                    # push the line counter forward to maintain state
                    line_counter += 1

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("--query_output_directory", help="The directory containing the query output files to turn into a queryable dataset.")
    parser.add_argument("--new_column_output_directory", help="Directory for the new queryable columns to be written to.")
    args = parser.parse_args()
    main(args.query_output_directory, args.new_column_output_directory)


import pandas as pd
import csv
import json
import requests

url = "https://api.hospitalpriceindex.com/itemList/list"

payload = "{\"defId\":8149,\"priceStatus\":\"published\",\"page\":{\"from\":1,\"size\":50000},\"sortInput\":[{\"reverse\":false,\"by\":\"description\"}],\"listName\":\"priceList\",\"filters\":[{\"property\":\"description\",\"value\":\"\",\"type\":\"all\"}]}"
headers = {
    'authority': 'api.hospitalpriceindex.com',
    'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
    'accept': 'application/json, text/plain, */*',
    'sec-ch-ua-mobile': '?0',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
    'content-type': 'application/json',
    'origin': 'https://search.hospitalpriceindex.com',
    'sec-fetch-site': 'same-site',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'referer': 'https://search.hospitalpriceindex.com/',
    'accept-language': 'en-US,en;q=0.9'
}

response = requests.request("POST", url, headers=headers, data=payload)

# print(response.text)

# response_text = response.text

#
northsideData = response.json()
df = pd.json_normalize(northsideData['result'], record_path=['items'])
# df.transpose
json_data_path = 'C:\\Users\\jackb\\Desktop\\FileOpen\\geraldChampionRegionalMC\\northside\\northsideCherokee.json'
csv_write = r'C:\\Users\\jackb\\Desktop\\FileOpen\\northside\\northsideCherokee.csv'
df.to_csv(csv_write, index=False)

json_data_path = 'C:\\Users\\jackb\\Desktop\\FileOpen\\geraldChampionRegionalMC\\northside\\northsideCherokee.json'
csv_write = r'C:\\Users\\jackb\\Desktop\\FileOpen\\northside\\northsideCherokee.csv'

# json_data.to_csv(csv_write, index=False)
# print(json_data.head)


# -*- coding: utf-8 -*-
"""
Created on Sun Apr 19 18:12:59 2020

Functions dealing with zip code api

@author: gshre
"""

# Dependencies
import requests
import pandas as pd
import os.path
from config import zipcode_url

def get_state_zips_api(state_code):
    '''
    Returns zip codes data frame for a state using API

    Parameters
    ----------
    state_code : TYPE: string
        DESCRIPTION. State Code abbreviation; ex: NC

    Returns
    -------
    TYPE: DataFrame
        DESCRIPTION. Zip Codes data frame

    '''
    url=zipcode_url.replace("{state_code}", state_code)
    response = requests.get(url)
    zip_code_data = response.json()
    return pd.DataFrame(zip_code_data)

def get_state_zips(state_code):
    '''
    Returns zip coes data frame for a state using csv if available
    otherwise it calls API

    Parameters
    ----------
    state_code : TYPE: string
        DESCRIPTION. State Code abbreviation; ex: NC

    Returns
    -------
    df : TYPE: DataFrame
        DESCRIPTION. Zip Codes data frame

    '''
    csv_filename = f"Resources/{state_code}_ZipCodes.csv"
    # try to open file...if it does not exist, then create it
    df = ''
    try:
        df = pd.read_csv(csv_filename)
    except:
        print("Loading zip codes with API")
        df = get_state_zips_api(state_code)
        df.rename(columns = {"zip_codes" : "Zip Codes"}, inplace=True)
        df.to_csv(csv_filename, index=False)
    return df


import numpy as np
import pickle
import random
import argparse
if __name__=="__main__":
    parser = argparse.ArgumentParser(description = 'Graph Preprocessor .',formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('graph',help = 'File containing the graph')
    parser.add_argument('out',help = 'File to store the permutated graph')
    parser.add_argument('size',type=int,help='Graph size')
    parser.add_argument('--scale',type=float, default=0.001,help='The standard deviation of noise..')
    snap_group = parser.add_mutually_exclusive_group(required=False)
    snap_group.add_argument('--fromsnap', dest='fromsnap', action='store_true',help="Inputfiles are from SNAP")
    snap_group.add_argument('--notfromsnap', dest='fromsnap', action='store_false',help="Inputfiles are pre-formatted")
    parser.set_defaults(fromsnap=True)

    parser.add_argument('--noise', choices=['normal', 'laplace', 'both'], help="Noise type")
    parser.add_argument('--mix_noise_weight', type=float, default=0.5, help="The coeff. of normal distributed weights, only relevant if noise is set to 'both'.")

    args = parser.parse_args()

    weights = {}

    #generate weights
    for i in range(args.size):
        for j in range(args.size):
            if (j,i) in weights or (i,j) in weights:
                continue

            if args.noise == 'normal':
                weights[(i,j)] = np.random.normal(loc=0.0,scale=args.scale)
            elif args.noise == 'laplace':
                weights[(i,j)] = np.random.laplace(loc=0.0,scale=args.scale)
            elif args.noise == 'both':
                weights[(i,j)] = args.mix_noise_weight * np.random.normal(loc=0.0,scale=args.scale) + (1-args.mix_noise_weight) * np.random.laplace(loc=0.0,scale=args.scale)

            weights[(j,i)] = weights[(i,j)]

    print (weights[(22, 55)], weights[(55, 22)])

    out_file_name = args.out + '_weights_' + args.noise + str(args.scale)
    if args.noise == 'both':
        out_file_name += '_mixcoeff' + str(args.mix_noise_weight)

    with open(out_file_name, 'wb') as fW:
        pickle.dump(weights, fW)


import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import linregress

def draw_plot():
    # Read data from file
    df = pd.read_csv('epa-sea-level.csv', delimiter=',')
    df2 = df[df['Year'] >= 2000]
    x = df['Year']
    y = df['CSIRO Adjusted Sea Level']
    x2 = df2['Year']
    y2 = df2['CSIRO Adjusted Sea Level']

    # Create scatter plot
    plt.scatter(x, y)

    # Create first line of best fit
    slope, intercept, r_value, p_value, std_err = linregress(x, y)
    sr1 = pd.Series([int(i) for i in range(1880, 2050)])
    plt.plot(sr1, intercept + slope*sr1, 'r')

    # Create second line of best fit
    slope, intercept, r_value, p_value, std_err = linregress(x2, y2)
    sr2 = pd.Series([int(i) for i in range(2000, 2050)])
    plt.plot(sr2, intercept + slope*sr2, 'r')

    # Add labels and title
    plt.xlabel('Year')
    plt.ylabel('Sea Level (inches)')
    plt.title('Rise in Sea Level')

    # Save plot and return data for testing (DO NOT MODIFY)
    plt.savefig('sea_level_plot.png')
    return plt.gca()


#!/usr/bin/env python

import adios2
import random
import numpy as np
import time
import sys
import socket

class mpi:
    UseComm = True

if mpi.UseComm:
    from mpi4py import MPI

if __name__ == "__main__":
    print(socket.gethostname())
    nelems = 10

    if mpi.UseComm:
        comm = MPI.COMM_WORLD
        adios = adios2.ADIOS(comm)
        rank = comm.Get_rank()
        size = comm.Get_size()
    else:
        adios = adios2.ADIOS()
        rank = 0
        size = 1
        comm = None

    #@effis-init comm=comm

    # Test scalars
    if rank == 0:
        KnownInt = np.array([666])
        RandomInt = np.random.randint(0, 1000, size=1)

    # Test arrays
    KnownInts = np.arange(0, nelems, dtype=np.int64)
    RandomInts = np.random.randint(0, 1000, size=nelems, dtype=np.int64)
    RandomInts2 = np.random.randint(0, 1000, size=nelems, dtype=np.int32)

    #@effis-begin engine--->"Jabberwocky"
    io = adios.DeclareIO("Jabberwocky")

    GlobalDims = [size * nelems]
    Offsets = [rank * nelems]
    LocalDims = [nelems]
    vKnownInts  = io.DefineVariable("KnownInts",  KnownInts,  GlobalDims, Offsets, LocalDims)
    vRandomInts = io.DefineVariable("RandomInts", RandomInts, GlobalDims, Offsets, LocalDims)
    vRandomInts2 = io.DefineVariable("RandomInts2", RandomInts2, GlobalDims, Offsets, LocalDims)
    if rank == 0:
        io.DefineVariable("KnownInt",  KnownInt,  [], [], [])
        vRandomInt = io.DefineVariable("RandomInt", RandomInt, [], [], [])

    # Open
    if mpi.UseComm:
        engine = io.Open("Jabberwocky.bp", adios2.Mode.Write, comm)
    else:
        engine = io.Open("Jabberwocky.bp", adios2.Mode.Write)

    # Write
    if rank == 0:
        vKnownInt = io.InquireVariable("KnownInt")
        engine.Put(vKnownInt,  KnownInt)
        engine.Put(vRandomInt, RandomInt)

    for i in range(10):
        #@effis-timer start="LoopTimer", comm=comm

        RandomInts = np.random.randint(0, 1000, size=nelems, dtype=np.int64)
        RandomInts2 = np.random.randint(0, 1000, size=nelems, dtype=np.int64)
        #@effis-timestep physical=i*0.01, number=i

        if i % 5 == 0:
            engine.BeginStep()
            engine.Put(vKnownInts,  KnownInts)
            engine.Put(vRandomInts, RandomInts)
            engine.Put(vRandomInts2, RandomInts2)
            engine.EndStep()

        time.sleep(1)

        #@effis-timer stop="LoopTimer"

    engine.Close()
    #@effis-end

    #@effis-finalize


from __future__ import division

from sklearn import datasets
import numpy as np
import convnet

print ("[X], downloading data...")
mnist = datasets.fetch_mldata("MNIST Original")

index = np.array(range(0, 60000, 1))
testIndex = np.array(range(60000, 70000, 1))

np.random.shuffle(index)
np.random.shuffle(testIndex)

data  = np.array(mnist.data)
target = np.array(mnist.target)

data_test = data[testIndex]
target_test = target[testIndex]

data = data[index]
target = target[index]

n = len(data)
data.resize(n, 28 * 28)
target.resize(n, 1)
y = np.zeros((n, 10))
for i in range(n):
        y[i][int(target[i])] = 1

alpha = 0.00001
k = 10000
batch = 600

data.resize(n, 1, 28, 28)
data = data * 1.01
#data = data / (np.std(data, axis = 0) + 1.01)
print (data)
model = convnet.modelPre()

for i in range(k):
    pos = i % batch
    batch_index = range(pos * 100, pos * 100 + 100, 1)
    data_batch = data[batch_index]
    target_batch = target[batch_index]
    y_batch = y[batch_index]

    cost, rate = convnet.train(data_batch, target_batch, y_batch, model)

    print ("iteration : ", i , "rate : ", rate,  "cost: " , cost)


"""
This file is used for running scalability experiments by varying dataset size and measuring overall __repr__ performance
"""
import sys, os

sys.path.append(os.path.abspath("."))
from utils import data_utils
from accuracy.rank_utils import *

result_dir = "result/"

import time
import numpy as np
import lux
import pandas as pd
import utils

################################################################
############### Custom Experiment Setting  #####################
control = "early_pruning"
# trial_range = np.geomspace(50000, 1e5, num=3) # airbnb test
dataset = "communities"
# trial_range = np.geomspace(5e4, 1.2e6, num=10) # airbnb
# trial_range = np.geomspace(1e5, 9e5, num=5) # communities
trial_range = np.geomspace(5001, 1.9e5, num=10)
# trial_range = np.geomspace(1e5, 7e5, num=5)
################################################################

timing = []  # [cell count, duration]
accuracy = []
# Must turn off sampling, otherwise maintain_rec constant cost
lux.config.sampling = False

if dataset == "airbnb":
    downsample_func = data_utils.downsample_airbnb
elif dataset == "communities":
    downsample_func = data_utils.downsample_communities
# Warm start (somehow this warm start helps 1st datapoint not be extremely high, unclear why)
df = downsample_func(100)
df._repr_html_()

for nPts in trial_range:
    on_off = False
    if control == "early_pruning":
        lux.config.early_pruning = on_off
    elif control == "lazy_maintain":
        lux.config.lazy_maintain = on_off
    elif control == "sampling":
        lux.config.sampling = on_off

    nPts = int(nPts)
    df = downsample_func(nPts)
    df.intent = ["RentHighQ"]
    ################
    start = time.perf_counter()
    df.maintain_metadata()
    end = time.perf_counter()
    t_meta = end - start
    ################
    start = time.perf_counter()
    df.maintain_recs(render=False)
    end = time.perf_counter()
    t_recs = end - start
    ################
    ground_truth = df.recommendation
    print(f"Completed {nPts}")
    # df.expire_recs()
    # df.expire_metadata()
    timing.append([nPts, on_off, t_meta, t_recs])

    on_off = True
    if control == "early_pruning":
        lux.config.early_pruning = on_off
    elif control == "lazy_maintain":
        lux.config.lazy_maintain = on_off
    elif control == "sampling":
        lux.config.sampling = on_off

    nPts = int(nPts)
    df = downsample_func(nPts)
    df.intent = ["RentHighQ"]
    ################
    start = time.perf_counter()
    df.maintain_metadata()
    end = time.perf_counter()
    t_meta = end - start
    ################
    start = time.perf_counter()
    df.maintain_recs(render=False)
    end = time.perf_counter()
    t_recs = end - start
    ################
    timing.append([nPts, on_off, t_meta, t_recs])
    results = df.recommendation

    for action in ground_truth.keys():
        l1 = ground_truth[action]
        l2 = results[action]
        for k in [3, 5, 10, 15]:
            ndcg = compute_ndcg_between_vislists(l1, l2, k)
            accuracy.append([nPts, action, ndcg, k])
    print(f"Completed {nPts}")
timing_df = pd.DataFrame(
    timing,
    columns=["nPts", control, "t_meta", "t_recs"],
)
timing_df.to_csv(f"{result_dir}{control}_time_q2.csv", index=None)

accuracy_df = pd.DataFrame(
    accuracy,
    columns=["nPts", "action", "NDCG", "@k"],
)
accuracy_df.to_csv(f"{result_dir}{control}_accuracy_q2.csv", index=None)


# from matplotlib import pyplot as plt
from vision import VisionModule
import cv2
import samples

WIDTH = 640
HEIGHT = 480

COLORS = {
    "obstacle": (255, 0, 0),
    "cube": (0, 0, 255),
    "green": (0, 255, 0),
    "yellow": (255, 255, 0),
    "base": (0, 255, 255)
}

def load(tgt):

    return cv2.resize(samples.load(int(tgt)), (WIDTH, HEIGHT))

def draw(img, objects):
    cv2.line(img, (0, 240), (640, 240), (255, 255, 255), 2)
    for c in objects:
        cv2.rectangle(
            img,
            (c.rect[0], c.rect[1]),
            (c.rect[0] + c.rect[2], c.rect[1] + c.rect[3]),
            COLORS.get(c.meta), 3)
        cv2.putText(
            img, "{:.2f}".format(c.dist), (c.rect[0], c.rect[1]),
            cv2.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255))

def in_the_way(objs):

    right = 0

    for obj in objs:
        if (
                obj.dist > 0 and
                obj.dist < 25 and
                obj.rect[0] < 300 and
                obj.rect[0] + obj.rect[2] > 340):
            right = max(right, obj.rect[0] + obj.rect[2] - 320)

    return right

def test(target, pause=True):

    import time
    import os

    mod = VisionModule(width=WIDTH, height=HEIGHT)

    total = 0
    n = 0

    srcs = os.listdir(target)
    srcs.sort()

    for img in srcs:
        src = cv2.imread(os.path.join(target, img))

        start = time.time()
        objects, mask, cvxhull = mod.process(src)
        dur = (time.time() - start)

        n += 1
        total += dur

        src = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
        draw(src, objects)
        itw = in_the_way(objects)
        if cvxhull is not None:
            cv2.drawContours(
                src, [cvxhull], -1, (255, 255, 255), 3, cv2.LINE_8)
        cv2.line(src, (itw + 320, 0), (itw + 320, 480), (0, 0, 0), 3)

        src = cv2.cvtColor(src, cv2.COLOR_RGB2BGR)

        cv2.putText(
            src, '{:.1f}fps'.format(n / total), (0, 20),
            cv2.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255))

        cv2.imshow('test_01', src)
        if cv2.waitKey(0 if pause else 1) & 0xFF == ord('q'):
            break

    if pause:
       cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == '__main__':
    # import sys
    test('tests_02')
    # test(sys.argv[1])


#!/usr/bin/env python3

from setuptools import find_packages, setup

INSTALL_REQUIRES = ['numpy', 'statsmodels', 'numba', 'matplotlib',
                    'pandas', 'xarray', 'scipy', 'scikit-learn',
                    'regularized_glm', 'dask', 'patsy', 'networkx', 'joblib']
TESTS_REQUIRE = ['pytest >= 2.7.1']

setup(
    name='replay_trajectory_classification',
    version='0.7.7.dev0',
    license='MIT',
    description=('Classify replay trajectories.'),
    author='Eric Denovellis',
    author_email='edeno@bu.edu',
    url='https://github.com/Eden-Kramer-Lab/replay_trajectory_classification',
    packages=find_packages(),
    install_requires=INSTALL_REQUIRES,
    tests_require=TESTS_REQUIRE,
)