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

import sys
import os
from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication, QPushButton, QHBoxLayout, QVBoxLayout, QWidget, QTabWidget, QMenuBar, QLineEdit, QSlider, QLabel, QCheckBox, QComboBox
from simulation import *
from buffer import *
from random_pattern import *
import multiprocessing
import signal

from PyQt5.QtGui import QIcon

class Form(QMainWindow):
    def __init__(self):
        super(Form, self).__init__()
        self.initialize()
        self.t = None

    def start_simulation(self):

        if self.enable_random_cb.isChecked():
            dist_text = self.distribution.currentText()
            dist = "u"
            if dist_text == "Geometric":
                dist = "g"
            if self.number_of_balls.text() == '' or self.max_throw.text() == '' or self.min_throw == '':
                print("invalid input!")
                return
            random_pattern = RandomPattern(int(self.number_of_balls.text()), int(self.min_throw.text()), int(self.max_throw.text()), dist_type=dist)
            buffer = Buffer(random_pattern)
            simulation = Simulation(buffer)
            self.t = multiprocessing.Process(target=simulation.run)
            self.t.daemon = True
            self.t.start()
        else:
            text = str(self.pattern.text())
            if not len(text) > 0:
                return
            p = [int(e) for e in text.split(" ")]
            if p != None:
                s = Pattern(p)
                buffer = Buffer(s)
                simulation = Simulation(buffer)
                self.t = multiprocessing.Process(target=simulation.run)
                self.t.daemon = True
                self.t.start()

    def restart_simulation(self):
        if self.t.is_alive():
            os.kill(self.t.pid, signal.SIGINT)
        #the simulation should be restarted here
        #self.start_simulation()

    def initialize(self):
        self.tab_widget = QTabWidget()
        self.tab1 = QWidget()
        self.tab2 = QWidget()

        self.juggle_button = QPushButton("Juggle")
        #restart_button = QPushButton("Restart")
        self.juggle_button.clicked.connect(self.start_simulation)
        #restart_button.clicked.connect(self.restart_simulation)

        self.hbox = QHBoxLayout()
        self.hbox3 = QVBoxLayout()
        self.min_throw = QLineEdit(self)
        self.max_throw = QLineEdit(self)
        self.pattern = QLineEdit(self)
        self.number_of_balls = QLineEdit(self)
        self.min_label = QLabel(self)
        self.max_label = QLabel(self)
        self.pattern_label = QLabel(self)
        self.number_of_balls_label = QLabel(self)
        self.enable_random_cb = QCheckBox("Enable random pattern", self)
        self.distribution = QComboBox(self)
        self.distribution_label = QLabel(self)
        self.distribution.addItem("Uniform")
        self.distribution.addItem("Geometric")

        self.min_label.setText("min throw")
        self.max_label.setText("max throw")
        self.number_of_balls_label.setText("number of balls")
        self.pattern_label.setText("Pattern (only used if random pattern is not enabled)")
        self.distribution_label.setText("Distribution for the random pattern")

        self.hbox3.addWidget(self.min_label)
        self.hbox3.addWidget(self.min_throw)
        self.hbox3.addStretch(1)
        self.hbox3.addWidget(self.max_label)
        self.hbox3.addWidget(self.max_throw)
        self.hbox3.addWidget(self.number_of_balls_label)
        self.hbox3.addWidget(self.number_of_balls)
        self.hbox3.addWidget(self.pattern_label)
        self.hbox3.addWidget(self.pattern)
        self.hbox3.addWidget(self.enable_random_cb)
        self.hbox3.addWidget(self.distribution_label)
        self.hbox3.addWidget(self.distribution)
        self.hbox.addStretch(1)
        #hbox.addWidget(restart_button)
        self.hbox.addWidget(self.juggle_button)

        self.vbox = QVBoxLayout(self.tab1)

        self.vbox.addLayout(self.hbox3)
        self.vbox.addStretch(1)
        self.vbox.addLayout(self.hbox)

        self.hbox2 = QHBoxLayout(self.tab2)

        self.tab_widget.addTab(self.tab1, "Main")
        #self.tab_widget.addTab(self.tab2, "Other")

        self.setCentralWidget(self.tab_widget)

        self.menubar = self.menuBar()
        self.file_menu = self.menubar.addMenu('&File')
        self.help_menu = self.menubar.addMenu('&Help')
        self.about = self.help_menu.addMenu('&About')
        self.exit_action = QAction(QIcon('exit.png'), '&Exit', self)
        self.exit_action.triggered.connect(qApp.quit)
        self.file_menu.addAction(self.exit_action)

        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('Juggling Simulator')
        self.show()

def main():

    juggling_app = QApplication(sys.argv)

    win = Form()
    sys.exit(juggling_app.exec_())

main()


"""
This file contains the Support Vector Machine Classification functionality
"""
# region imports
from globals import console
from dataset import DatasetHandler

import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC

# endregion imports

# region SupportVectorClassification
class SupportVectorClassification(DatasetHandler):
    def __init__(self):
        super().__init__()
        self._classifier = None
        self._predicted_output = None
        self._selected_prediction_method = None

    def use_linear_kernel(self,
                          penalty_of_error=1,
                          probability=True,
                          maximum_number_of_iterations=20000):
        """
        This method uses the linear classification method of the Support Vector Machine

        :param penalty_of_error: (Number) The penalty parameter C of the error term. (Default: 1)
        :param probability: (Boolean) Whether to enable probability estimates. This must be enabled prior to calling
        fit, and will slow down that method. (Default: True)
        :param maximum_number_of_iterations: (Integer) Hard limit on iterations within solver, or -1 for no limit.
        (Default: 20000)
        :return: Boolean (True or False)
        """
        try:
            self._classifier = SVC(C=penalty_of_error,
                                   kernel='linear',
                                   probability=probability,
                                   max_iter=maximum_number_of_iterations)

            self._selected_prediction_method = 'linear'
            return True
        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def use_polynomial_kernel(self, penalty_of_error=1, degree=3, gamma='auto'):
        """
        This method uses the polynomial classification method of the Support Vector Machine

        :param penalty_of_error: (Number) The penalty parameter C of the error term. (Default: 1)
        :param degree: (Integer) The degree of the polynomial (Default: 3)
        :param gamma: (Number) Kernel coefficient (Default: 'auto')
        :return: Boolean (True or False)
        """
        try:
            self._classifier = SVC(C=penalty_of_error,
                                   kernel='poly',
                                   degree=degree,
                                   gamma=gamma)

            self._selected_prediction_method = 'polynomial'
            return True
        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def use_radial_basis_function_kernel(self, penalty_of_error=1, gamma='auto'):
        """
        This method uses the radial basic function classification method of the Support Vector Machine

        :param penalty_of_error: (Number) The penalty parameter C of the error term. (Default: 1)
        :param gamma: (Number) Kernel coefficient (Default: 'auto')
        :return: Boolean (True or False)
        """
        try:
            self._classifier = SVC(C=penalty_of_error,
                                   kernel='rbf',
                                   gamma=gamma)

            self._selected_prediction_method = 'radial_basis_function'
            return True
        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def fit_svc_on_training_set(self):
        """
        This method is used on order to fit the "self._classifier" in the training set

        :return: Boolean (True or False)
        """
        try:
            self._classifier.fit(X=self.get_training_set()['X'],
                                 y=self.get_training_set()['y'])

            return True
        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def fit_svc_on_whole_set(self):
        """
        This method is used on order to fit the "self._classifier" in the training set

        :return: Boolean (True or False)
        """
        try:
            self._classifier.fit(X=self.get_whole_set()['X'],
                                 y=self.get_whole_set()['y'])

            return True
        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def get_classification_prediction(self, test_set=None):
        """
        This method predicts the classification of a set of data based on previous training

        :param test_set: (Array) The input variables state space (Default: The input variables from the test set)
        :return: (Array) The SVC predicted output
        """
        try:
            if test_set is not None:
                self._predicted_output = self._classifier.predict(X=test_set)
            else:
                self._predicted_output = self._classifier.predict(X=self.get_whole_set()['X'])

            return self._predicted_output
        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def get_classification_prediction_probability(self, test_set=None):
        """
        This method compute probabilities of possible outcomes for samples in the test set

        :param test_set: (Array) The input variables state space (Default: The input variables from the test set)
        :return: (Array) The probabilities of possible outcomes from samples in the test set
        """
        try:
            if test_set is not None:
                return self._classifier.predict_proba(X=test_set)
            else:
                return self._classifier.predict_proba(X=self.get_test_set()['y'])

        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def get_decision_function(self, test_set=None):
        """
        This method evaluates the decision function for the samples in the test set

        :param test_set: (Array) The input variables state space (Default: The input variables from the test set)
        :return: (Array) The SVC decision function
        """
        try:
            if test_set is not None:
                return self._classifier.decision_function(X=test_set)
            else:
                return self._classifier.decision_function(X=self.get_test_set()['X'])

        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def plot_results(self, regressor='all', title=None, x_label=None, y_label=None):
        """
        This method plots the predicted data of the selected "self._classifier"

        :param regressor: (String) The regressor selected
        :param title: (String) The plot title (Default: No Title)
        :param x_label: (String) The X-Axis label (Default: No Label)
        :param y_label: (String) The Y-Axis label (Default: No Label)
        :return: Boolean (True or False)
        """
        try:
            plt.figure(1)
            plt.scatter(x=np.arange(self._whole_set['y'].size),
                        y=self._whole_set['y'],
                        color='red',
                        label='Real Data')

            plt.plot(self._predicted_output,
                     linestyle='-',
                     color='blue',
                     label=('Predicted Trend Using the \"%s\" classification method' %
                            str(self._selected_prediction_method))
                     )

            plt.grid(color='silver',
                     linestyle='--',
                     linewidth=1)

            plt.legend(loc='best')
            if title is not None and \
                    isinstance(title, str):
                plt.title(title)

            if x_label is not None and \
                    isinstance(x_label, str):
                plt.xlabel(x_label)

            if y_label is not None and \
                    isinstance(y_label, str):
                plt.ylabel(y_label)

            plt.show()
        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False

    def return_error(self, regressor='both'):
        """
        This method returns the error between the real output and the predicted output throwout the whole set

        :param regressor: (String) The regressor selected
        :return: (List) The error between the real output and the predicted output
        """
        try:
            error_value = np.square(
                self.get_whole_set()['y'] - self._predicted_output
            )

            if np.mean(error_value) != 0:
                error_value = np.interp(
                    np.mean(error_value),
                    (error_value.min(), error_value.max()),
                    (0, 100)
                )
            else:
                error_value = 0

            return {
                    'label': self._selected_prediction_method,
                    'value': error_value
            }

        except Exception as error_message:
            console.log(error_message, console.LOG_ERROR)
            return False
# endregion SupportVectorClassification

# region exports
support_vector_classification = SupportVectorClassification()
# endregion exports


import bpy

from bl_ui.properties_material import MaterialButtonsPanel

class MATERIAL_PT_pr_context_material(MaterialButtonsPanel, bpy.types.Panel):
    bl_label = ""
    bl_options = {'HIDE_HEADER'}
    COMPAT_ENGINES = {'PEARRAY_RENDER'}

    @classmethod
    def poll(cls, context):
        # An exception, don't call the parent poll func because
        # this manages materials for all engine types

        engine = context.scene.render.engine
        return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)

    def draw(self, context):
        layout = self.layout

        mat = context.material
        ob = context.object
        slot = context.material_slot
        space = context.space_data
        is_sortable = (len(ob.material_slots) > 1)

        if ob:
            rows = 1
            if is_sortable:
                rows = 4

            row = layout.row()

            row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)

            col = row.column(align=True)
            col.operator("object.material_slot_add", icon='ZOOMIN', text="")
            col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")

            col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")

            if is_sortable:
                col.separator()

                col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
                col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'

            if ob.mode == 'EDIT':
                row = layout.row(align=True)
                row.operator("object.material_slot_assign", text="Assign")
                row.operator("object.material_slot_select", text="Select")
                row.operator("object.material_slot_deselect", text="Deselect")

        split = layout.split(percentage=0.65)

        if ob:
            split.template_ID(ob, "active_material", new="material.new")
            row = split.row()

            if slot:
                row.prop(slot, "link", text="")
            else:
                row.label()
        elif mat:
            split.template_ID(space, "pin_id")
            split.separator()

class MATERIAL_PT_pr_preview(MaterialButtonsPanel, bpy.types.Panel):
    bl_label = "Preview"
    COMPAT_ENGINES = {'PEARRAY_RENDER'}

    def draw(self, context):
        self.layout.template_preview(context.material)

class MATERIAL_PT_pr_bsdf(MaterialButtonsPanel, bpy.types.Panel):
    bl_label = "BSDF"
    COMPAT_ENGINES = {'PEARRAY_RENDER'}

    @classmethod
    def poll(cls, context):
        engine = context.scene.render.engine
        return context.material and (engine in cls.COMPAT_ENGINES)

    def draw(self, context):
        layout = self.layout

        mat = context.material
        type = mat.pearray.bsdf

        split = layout.split()

        col = split.column()
        col.prop(mat.pearray, "bsdf")

        split = col.split()
        col = split.column()
        col.prop(mat.pearray, "cast_shadows")
        col.prop(mat.pearray, "cast_self_shadows")

        col = split.column()
        col.prop(mat.pearray, "is_camera_visible")
        col.prop(mat.pearray, "is_shadeable")

        if type == 'COOK_TORRANCE':
            layout.separator()
            split = layout.split()
            col = split.column(align=True)
            col.prop(mat.pearray, "ct_fresnel_mode")
            col.prop(mat.pearray, "ct_distribution_mode")
            col.prop(mat.pearray, "ct_geometry_mode")

class MATERIAL_PT_pr_diffuse(MaterialButtonsPanel, bpy.types.Panel):
    bl_label = "Diffuse"
    COMPAT_ENGINES = {'PEARRAY_RENDER'}

    @classmethod
    def poll(cls, context):
        engine = context.scene.render.engine
        return context.material and (context.material.pearray.bsdf in {'DIFFUSE', 'ORENNAYAR', 'WARD', 'COOK_TORRANCE'}) and (engine in cls.COMPAT_ENGINES)

    def draw(self, context):
        layout = self.layout

        mat = context.material
        type = mat.pearray.bsdf

        split = layout.split()

        col = split.column()
        color_template(mat, col, "diffuse_color")
        if type == 'ORENNAYAR' or type == 'COOK_TORRANCE':
            col.prop(mat, 'roughness')

class MATERIAL_PT_pr_grid(MaterialButtonsPanel, bpy.types.Panel):
    bl_label = "Grid"
    COMPAT_ENGINES = {'PEARRAY_RENDER'}

    @classmethod
    def poll(cls, context):
        engine = context.scene.render.engine
        return context.material and (context.material.pearray.bsdf == 'GRID') and (engine in cls.COMPAT_ENGINES)

    def draw(self, context):
        layout = self.layout

        mat = context.material
        type = mat.pearray.bsdf

        split = layout.split()

        col = split.column()

class MATERIAL_PT_pr_specular(MaterialButtonsPanel, bpy.types.Panel):
    bl_label = "Specular"
    COMPAT_ENGINES = {'PEARRAY_RENDER'}

    @classmethod
    def poll(cls, context):
        engine = context.scene.render.engine
        return context.material and (context.material.pearray.bsdf in {'GLASS', 'MIRROR', 'WARD', 'COOK_TORRANCE'}) and (engine in cls.COMPAT_ENGINES)

    def draw(self, context):
        layout = self.layout

        mat = context.material
        type = mat.pearray.bsdf

        split = layout.split()

        col = split.column()
        color_template(mat, col, "specular_color")
        if type == 'MIRROR' or type == 'GLASS' or type == 'COOK_TORRANCE':
            ior_template(mat, col, "specular_ior")
        if type == 'WARD' or type == 'COOK_TORRANCE':
            col2 = col.column(align=True)
            col2.prop(mat.pearray, 'spec_roughness_x')
            col2.prop(mat.pearray, 'spec_roughness_y')
            col.prop(mat.pearray, 'reflectivity')
        if type == 'GLASS':
            col.prop(mat.pearray, 'glass_is_thin')

class MATERIAL_PT_pr_emission(MaterialButtonsPanel, bpy.types.Panel):
    bl_label = "Emission"
    COMPAT_ENGINES = {'PEARRAY_RENDER'}

    @classmethod
    def poll(cls, context):
        engine = context.scene.render.engine
        return context.material and (not context.material.pearray.bsdf == 'GRID') and (engine in cls.COMPAT_ENGINES)

    def draw(self, context):
        layout = self.layout

        mat = context.material
        type = mat.pearray.bsdf

        split = layout.split()

        col = split.column()
        color_template(mat, col, "emission_color")

def color_template(obj, layout, name):
    sub_obj = obj
    if not hasattr(obj, name):
        sub_obj = obj.pearray

    type = getattr(obj.pearray, '%s_type' % name)

    col = layout.column(align=True)
    col.row(align=True).prop(obj.pearray, '%s_type' % name, expand=True)
    if type == 'TEMP':
        r = col.row(align=True)
        r.prop(obj.pearray, '%s_temp_type' % name, text="")
        r.prop(obj.pearray, '%s_temp_factor' % name, text='Factor')
        col.prop(obj.pearray, '%s_temp' % name, text="")
    elif type == 'TEX' and hasattr(obj.pearray, '%s_tex_slot' % name):
        col.prop(obj.pearray, '%s_tex_slot' % name)
    else:
        col.prop(sub_obj, name, text="")

def ior_template(obj, layout, name):
    sub_obj = obj
    if not hasattr(obj, name):
        sub_obj = obj.pearray

    type = getattr(obj.pearray, '%s_type' % name)

    col = layout.column(align=True)
    col.row(align=True).prop(obj.pearray, '%s_type' % name, expand=True)
    if type == 'VALUE':
        col.prop(obj.pearray, '%s_value' % name, text="Ior")
    else:
        col.prop(obj.pearray, '%s_color' % name, text="Ior")


import argparse
import logging
from Apps import DE_cnn
from Apps import DE_mlp

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("--trait", help="Trait to run optimization", default="height")
    parser.add_argument("-k", "--num_snps", help="Number of SNPs", default=10000, type=int)
    parser.add_argument("--unif", help="Use uniformly spaced spns", action='store_true')
    parser.add_argument("--population", help="Population GA",default=30, type=int)
    parser.add_argument("--generations",help="Number of generations GA",default= 8,type=int)

    group = parser.add_mutually_exclusive_group()
    group.add_argument('--mlp', action='store_true')
    group.add_argument('--cnn', action='store_true')

    args = parser.parse_args()

    if args.mlp:
        filename = "log_" + args.trait + "_" + str(args.num_snps / 1000) + "k.txt"
        # Setup logging.
        logging.basicConfig(
            format='%(asctime)s - %(levelname)s - %(message)s',
            datefmt='%m/%d/%Y %I:%M:%S %p',
            level=logging.INFO,
            filename=filename
        )
        DE_mlp.main(trait=args.trait, k=args.num_snps, population=args.population, generations = args.generations)
    if args.cnn:
        filename = "log_" + args.trait + "_" + str(args.num_snps / 1000) + "k_cnn.txt"
        # Setup logging.
        logging.basicConfig(
            format='%(asctime)s - %(levelname)s - %(message)s',
            datefmt='%m/%d/%Y %I:%M:%S %p',
            level=logging.INFO,
            filename=filename
        )
        DE_cnn.main(trait=args.trait, k=args.num_snps, population=args.population, generations = args.genrations)


# -*- coding: utf-8 -*-
"""
Created on Fri Apr  1 13:32:06 2016

@author: jmwilson
@co-author: mark yoder
#
# comments (yoder): we'll need to code this for Python3 compatibility.
#    ... and i'd rewrite some of this to separate code from data.
#
######           Obsolete, use etas_to_gmp.py instead             ######
"""

import numpy as np
import math
import itertools
import matplotlib as mpl
import matplotlib.pyplot as plt
import time
import multiprocessing as mpp
import os
import sys
#
import rtree
from rtree import index
#from geographiclib.geodesic import Geodesic
#
# define the color-cycle for fancy plotting:
_colors =  mpl.rcParams['axes.color_cycle']
#
#==============================================================================
# Extended Magnitude range attenuation relationships for S-wave horizontal acceleration
#               a       b           c 1     c 2     d       e           sig
# PGA   rock    0.73    -7.2x10-4   1.16    0.96    -1.48   -0.42       0.31
#       soil    0.71    -2.38x10-3  1.72    0.96    -1.44   -2.45x10-2  0.33
# PGV   rock    0.86    -5.58x10-4  0.84    0.98    -1.37   -2.58       0.28
#       soil    0.89    -8.4x10-4   1.39    0.95    -1.47   -2.24       0.32
#==============================================================================
#R1 = np.sqrt(R**2+9)
#C = c1*exp(c2*(M-5))*(np.arctan(M-5)+np.pi/2.0)
#Y = 10**(a*M + b*(R1 + C) + d*np.log10(R1 + C) + e)
#
#motion_type_prams = {'PGA-rock':{'a':0.73, 'b':-7.2e-4, 'c1':1.16, 'c2':0.96, 'd':-1.48, 'e':-0.42}, ...}
# but i'm lazier than that too, and i want to minimize mistakes made by mistyping a variable, so let's code it...
motion_type_prams_lst_vars = ['a', 'b', 'c1', 'c2', 'd', 'e']
motion_type_prams_lst = {'PGA-rock':[0.73, -7.2e-4, 1.16, 0.96, -1.48, -0.42],
                     'PGA-soil':[0.71, -2.38e-3, 1.72, 0.96, -1.44, -2.45e-2],
                     'PGV-rock':[0.86, -5.58e-4, 0.84, 0.98, -1.37, -2.58],
                     'PGV-soil':[0.89, -8.4e-4, 1.39, 0.95, -1.47, -2.24]}
motion_type_prams = {key:{ky:vl for ky,vl in zip(motion_type_prams_lst_vars, vals)} for key,vals in motion_type_prams_lst.items()}
#print('mtp: ', motion_type_prams)

def f_Y(R,M, a=None, b=None, c1=None, c2=None, d=None, e=None, motion_type='PGA-soil'):
	# experimenting a bit with this quasi-recursive call structure. this approach might be slow, and maybe we should just separate this into
	# two separate functions.
	# from original implementation; Y() should (nominally) look like this:
	# return 10**(a*M + b*(np.sqrt(R**2+9) + C(M, c1, c2)) + d*np.log10(np.sqrt(R**2+9) + C(M, c1, c2)) + e)
	if motion_type!=None:
		return f_Y(R,M, motion_type=None, **motion_type_prams[motion_type])
	else:
		return 10**(a*M + b*(np.sqrt(R**2+9) + C(M, c1, c2)) + d*np.log10(np.sqrt(R**2+9) + C(M, c1, c2)) + e)
		# it might be a little bit faster to calculate it this way:
		#return (10**(a*M + b*(np.sqrt(R**2+9) + C(M, c1, c2)) + e)) * (np.sqrt(R**2+9) + C(M, c1, c2))**d

def C(M, c1, c2):
    return c1*np.exp(c2*(M-5))*(np.arctan(M-5)+np.pi/2.0)
#
# ... but let's do this a different way as well. let's separate data from code, so put this into a dictionary (which is then a global
# variable, but that's ok... we can use a couple of trick, then, to pull the variables out into function calls. we can use,
# __dict__.update(motion_type_prams[mt]) to set local variables, or we can calla funciton like f(**motion_type_prams[mt]).

def Y(R, M, motiontype):
    if motiontype == "PGA-rock":
        a = 0.73
        b = -7.2e-4
        c1 = 1.16
        c2 = 0.96
        d = -1.48
        e = -0.42
    elif motiontype == "PGA-soil":
        a = 0.71
        b = -2.38e-3
        c1 = 1.72
        c2 = 0.96
        d = -1.44
        e = -2.45e-2
    elif motiontype == "PGV-rock":
        a = 0.86
        b = -5.58e-4
        c1 = 0.84
        c2 = 0.98
        d = -1.37
        e = -2.58
    elif motiontype == "PGV-soil":
        a = 0.89
        b = -8.4e-4
        c1 = 1.39
        c2 = 0.95
        d = -1.47
        e = -2.24
    else:
        print("Motion Type not recognized\n")
        return 0

    return 10**(a*M + b*(np.sqrt(R**2+9) + C(M, c1, c2)) + d*np.log10(np.sqrt(R**2+9) + C(M, c1, c2)) + e)
#
def etas_to_GM(etas_src='../globalETAS/etas_outputs/etas_xyz.xyz', fname_out='GMPE_rec.p', motion_type='PGA-soil', n_procs=None):
	# "ETAS to Ground-Motion:
	#xyz = open('../globalETAS/etas_outputs/etas_xyz.xyz', 'r')
	n_procs=(n_procs or mpp.cpu_count())
	#
	#
	print('open etas_src file: ', etas_src)
	#
	with open(etas_src, 'r') as xyz:
		# i don't know why, except maybe because it does handle exceptions/crashes before the file is closed, but this
		# "open()" syntax seems to be recommended over open(), close() implicit blocks.
		#
		ETAS_array = []
		GMPE_array = []
		#
		#ETAS_array = [[float(x), float(y), float(z)] for x,y,z in xyz]
		ETAS_array = [[float(x) for x in rw.split()] for rw in xyz if not rw[0] in ('#', chr(32), chr(10), chr(13), chr(9))]
		#
	#
	GMPE_array = [[x,y,0.] for x,y,z in ETAS_array]
	lons = sorted(list(set([x for x,y,z in ETAS_array])))
	lats = sorted(list(set([y for x,y,z in ETAS_array])))
	#
		#xyz.close()
	#
	print('etas_src loaded. load data into arrays and process.')
	#
	# this syntax burns memory and time, which will become important later. instead of x.transopse(), we can use zip(*x)... unless
	# it is otherwise known that zip(*x) is slow.
	#ETAS_array = np.array(ETAS_array)
	#ETAS_rec = np.core.records.fromarrays(ETAS_array.transpose(), dtype = [('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
	ETAS_rec = np.core.records.fromarrays(zip(*ETAS_array), dtype = [('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
	#
	# so what are the parameters? for now, assume we have a rectangular grid;
	# define parameters from which to construct a GMPE array.
	d_lon = lons[1]-lons[0]
	d_lat = lats[1]-lats[0]		# maybe need something more robust than this, but it should do...
	lon_range = (min(lons), max(lons)+d_lon, d_lon)
	lat_range = (min(lats), max(lats)+d_lat, d_lat)
	#GMPE_array = np.array(GMPE_array)
	#GMPE_rec = np.core.records.fromarrays(GMPE_array.transpose(), dtype = [('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
	#GMPE_rec = np.core.records.fromarrays(zip(*GMPE_array), dtype = [('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
	#
	l_etas = len(ETAS_rec)
	#
	t0 = time.time()
	# how do we parallelize this? i think first, we want to use iterools(), so we can break up the whole nested loop into one list.
	# we can avoid doing extra arithmetic by doing the round() operations first -- loop over [[round(x), round(y), z], ...]
	# and calc the source magnitude, again, in the first loop  over the ETAS array. at that point, all the rows are independent and
	# we can parse them out to processes.
	#
	m_reff=0.
	#
	if n_procs>1:
		#
		# multi-process.
		P = mpp.Pool(n_procs)
		#
		#we want to construct the GMP_{sub}_arrays at the process level, so we don't have to pipe the whole array to the process.
		# note: the [[x,y], ...] part of the array is like:
		# [[x,y] for x,y in itertools.product(np.arange(*lon_range), np.arange(*lat_range))]
		#
		#
		# so we'll need to write calc_gmps() (aka, copy the single process bit).
		chunk_size = int(np.ceil(l_etas/n_procs))		# "chunk" size, or length of sub-arrays for parallel processing.

		resultses = [P.apply_async(calc_GMPEs, (), {'ETAS_rec':ETAS_rec[j_p*chunk_size:(j_p+1)*chunk_size], 'lon_range':lon_range, 'lat_range':lat_range, 'm_reff':5.0, 'just_z':True}) for j_p in range(n_procs)]

		P.close()
		#
		# not sure of this syntax just yet. it is admittedly a little bit convoluted. it might be better to just suck it up and
		# do an extra loop through the array: set up the zero-value initial array, then add all the returns. here, we're trying to
		# squeeze out a little bit of performance by setting up the array and the first results simultaneously.
		GMP_rec = np.core.records.fromarrays(zip(*[[x,y,z] for (x,y),z in zip(itertools.product(np.arange(*lon_range), np.arange(*lat_range)), resultses[0].get())]), dtype = [('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
		for j,res in enumerate(resultses[1:]):
			GMPE_rec['z']+=np.array(res.get()['z'])
			pass
		#
		# look in vc_parser for proper syntax using Pool() objects with close() and join().
		#P.join()
	#
	if n_procs==1:
		GMPE_rec = calc_GMPEs(ETAS_rec=ETAS_rec, lat_range=None, lon_range=None)
		'''
		j_prev=0
		for (j, (lon1, lat1, z_e)), (k, (lon2, lat2, z_g)) in itertools.product(enumerate(ETAS_rec), enumerate(GMPE_rec)):
			# M=rate_to_m(z_e)
			if j!=j_prev:
				print('new row: ', j)
				j_prev=j
			#
			M = m_from_rate(z_e, m_reff)
			#M = 2.0
			#
			distance = spherical_dist(lon_lat_from=[lon1, lat1], lon_lat_to=[lon2, lat2])
			#g = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
			#distance = g['s12']
			#
			#S_Horiz_Soil_Acc = Y(distance, M, "PGA-soil")
			S_Horiz_Soil_Acc = f_Y(distance, M, motion_type)
			GMPE_rec['z'][k] = max(GMPE_rec['z'][k], S_Horiz_Soil_Acc)
		#
		'''
		#
		'''
		for j,line1 in enumerate(ETAS_rec):
			lon1 = round(line1['x'],1)
			lat1 = round(line1['y'],1)
			M = #TODO: Mapping from ETAS rate to source magnitude, we might need data for each region's background seismicity
			M=2.0
			print('line: %d/%d' % (j,l_etas))
			#
			for i, line2 in enumerate(GMPE_rec):
				lon2 = round(line2['x'],1)
				lat2 = round(line2['y'],1)
				#
				# geographic_lib distances can be expensive, so let's try this spherical formula for starters...
				#spherical_dist(lon_lat_from=[0., 0.], lon_lat_to=[0.,0.], Rearth = 6378.1):
				distance = spherical_dist(lon_lat_from=[lon1, lat1], lon_lat_to=[lon2, lat2])
				#g = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
				#distance = g['s12']
				#
				#S_Horiz_Soil_Acc = Y(distance, M, "PGA-soil")
				S_Horiz_Soil_Acc = f_Y(distance, M, motion_type)
				#
				GMPE_rec[i]['z'] = max(GMPE_rec[i]['z'], S_Horiz_Soil_Acc)
			'''
	#
	t1 = time.time()
	print(t1 - t0)
	#
	GMPE_rec.dump(fname_out)
#

def calc_GMPEs(ETAS_rec=None, lat_range=None, lon_range=None, m_reff=5.0, motion_type="PGA-soil", just_z=False):
	# what is the correct syntax to return a subset of columns of a recarray? (the fastest way, of course)?
	#
	# construct GMP array and calculate GM from ETAS. this function to be used as an mpp.Pool() worker.
	#GMPE_rec =[[x,y,0.] for x,y in itertools.product(np.arange(*lon_range), np.arange(*lat_range))]	# check these for proper
	#
	# create an empty GMPE array.																		# sequenceing and grouping.
	GMPE_rec = np.core.records.fromarrays(zip(*[[x,y,0.] for x,y in itertools.product(np.arange(*lon_range), np.arange(*lat_range))]), dtype = [('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
	#GMPE_rec = np.core.records.fromarrays(zip(*GMPE_array), dtype = [('x', '>f8'), ('y', '>f8'), ('z', '>f8')])
	#
	j_prev=0
	for (j, (lon1, lat1, z_e)), (k, (lon2, lat2, z_g)) in itertools.product(enumerate(ETAS_rec), enumerate(GMPE_rec)):
		# M=rate_to_m(z_e)
		if j!=j_prev:
			print('new row[{}]: {}'.format(os.getpid(), j))
			j_prev=j
		#
		M = m_from_rate(z_e, m_reff)
		#M = 2.0
		#
		#distance = spherical_dist(lon_lat_from=[lon1, lat1], lon_lat_to=[lon2, lat2])

		distance = spherical_dist(lon_lat_from=[ETAS_rec['lon'][0], ETAS_rec['lat'][0]], lon_lat_to=[lon2, lat2])

		#g = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
		#distance = g['s12']
		#
		#S_Horiz_Soil_Acc = Y(distance, M, "PGA-soil")
		S_Horiz_Soil_Acc = f_Y(distance, M, motion_type)
		#S_Horiz_Siol_Acc = 1.0/(10.+distance)
		#
		#GMPE_rec['z'][k] = max(GMPE_rec['z'][k], S_Horiz_Soil_Acc)
		GMPE_rec['z'][k] = max(z_g, S_Horiz_Soil_Acc)
		#GMPE_rec['z'][k] += S_Horiz_Soil_Acc
	#
	if just_z:
		return GMP_rec['z']
	else:
		return GMPE_rec

#
def calc_GMPE(lon1, lat1, lon2, lat2, z_etas, m_reff):
	m_reff=0.
	M = m_from_rate(z_e, m_reff)
	#M = 2.0
	#
	distance = spherical_dist(lon_lat_from=[lon1, lat1], lon_lat_to=[lon2, lat2])
	#g = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
	#distance = g['s12']
	#
	S_Horiz_Soil_Acc = f_Y(distance, M, motion_type)
	GMPE_rec['z'][k] = max(GMPE_rec['z'][k], S_Horiz_Soil_Acc)

def m_from_rate(rate=None, m_reff=0.):
	# compute a source magnitude based on ETAS rate and a reference magnitude (or something).
	#
	# but for now, just a constant
	return 2.0
#
def spherical_dist(lon_lat_from=[0., 0.], lon_lat_to=[0.,0.], Rearth = 6378.1):
	# Geometric spherical distance formula...
	# displacement from inloc...
	# inloc is a vector [lon, lat]
	# return a vector [dLon, dLat] or [r, theta]
	# return distances in km.
	#
	# also, we need to get the proper spherical angular displacement (from the parallel)
	#
	#Rearth = 6378.1	# km
	deg2rad=2.0*math.pi/360.
	#
	# note: i usually use phi-> longitude, lambda -> latitude, but at some point i copied a source where this is
	# reversed. oops. so just switch them here.
	# phi: latitude
	# lon: longitude
	#
	#phif  = inloc[0]*deg2rad
	#lambf = inloc[1]*deg2rad
	#phis  = self.loc[0]*deg2rad
	#lambs = self.loc[1]*deg2rad

	phif  = lon_lat_to[1]*deg2rad
	lambf = lon_lat_to[0]*deg2rad
	phis  = lon_lat_from[1]*deg2rad
	lambs = lon_lat_from[0]*deg2rad
	#
	#print ('phif: ', phif)
	#print('lambf: ', lambf)
	#
	dphi = (phif - phis)
	dlambda = (lambf - lambs)
	#this one is supposed to be bulletproof:
	sighat3 = math.atan( math.sqrt((math.cos(phif)*math.sin(dlambda))**2.0 + (math.cos(phis)*math.sin(phif) - math.sin(phis)*math.cos(phif)*math.cos(dlambda))**2.0 ) / (math.sin(phis)*math.sin(phif) + math.cos(phis)*math.cos(phif)*math.cos(dlambda))  )
	R3 = Rearth * sighat3
	#
	return R3

# yoder: let's code this up for both command line and interactive use:
if __name__=='__main__':
	#
	kwds={}
	pargs=[]		# poositional arguments.
	for arg in sys.argv[1:]:
		# assume some mistakes might be made. fix them here.
		arg.replace(',', '')
		#
		# note: module name is the first argument.
		if '=' in arg:
			kwds.update(dict([arg.split('=')]))
		else:
			pargs+=[arg]
		#
	#
	# enforce float types:
	#kwds = {key:float(val) for key,val in kwds.items()}
	#pargs = [float(x) for x in pargs]
	#
	X=etas_to_GM(*pargs, **kwds)
else:
	plt.ion()
	pass
#


from datetime import datetime
from dateutil.relativedelta import relativedelta

def next_clinic_date(community_clinic_days, base_datetime=None, allow_same_day=None, subtract=None):
    """Returns next clinic date that is not today or None.

    community_clinic_days format is a ClinicDaysTuple. See bcpp_household.mappers for format.

    """
    clinic_dates = []
    next_clinic_datetime = None
    if community_clinic_days:
        base_datetime = base_datetime or datetime.today()
        for DAY in community_clinic_days.days:
            if allow_same_day:
                clinic_dates.append(base_datetime + relativedelta(weekday=DAY(+1)))
            elif base_datetime + relativedelta(weekday=DAY(+1)) != base_datetime:
                clinic_dates.append(base_datetime + relativedelta(weekday=DAY(+1)))
        next_clinic_datetime = datetime(min(clinic_dates).year, min(clinic_dates).month, min(clinic_dates).day, 7, 30, 0)
        if subtract:
            # work back to a clinic day, e.g the nearest clinic day within two weeks
            days = list(community_clinic_days.days)
            days.reverse()
            base_datetime = datetime(base_datetime.year, base_datetime.month, base_datetime.day, 7, 30, 0)
            for DAY in days:
                next_clinic_datetime = next_clinic_datetime + relativedelta(weekday=DAY(-1))
                if allow_same_day and next_clinic_datetime == base_datetime:
                    break
                elif next_clinic_datetime < base_datetime:
                    break
    return next_clinic_datetime


import logging
import os

def compress_video(source_video_path, target_video_path, scale=(224, 224), crf=20):
    command = 'ffmpeg -threads 4 -y -i ' + source_video_path + ' -vf "scale=' + str(scale[0]) + ':' + str(scale[1]) + \
              '" -crf ' + str(crf) + ' -vcodec libx264 -preset fast -strict experimental ' + target_video_path
    logging.info(command)
    os.system(command)

def detect_black_log(video_path, log_path, d=0.5):
    """
    d means: black duration
    pci_th means: black pix div all pix
    pic_th means: how black means black
    :param video_path:
    :param log_path:
    :param d:
    :return:
    """
    command = 'FFREPORT=file=' + log_path + ':level=32 ffmpeg -loglevel 32 -i ' + video_path + \
              ' -vf blackdetect=d=' + str(d) + ':pic_th=0.95:pix_th=0.05 -an -f null -'
    logging.info(command)
    os.system(command)

def cut_video(source_path, target_path, video_start, video_duration):
    command = 'ffmpeg -i ' + source_path + ' -ss ' + video_start + ' -t ' + video_duration + \
              ' -vcodec copy -acodec copy ' + target_path
    logging.info(command)
    os.system(command)

def transcoding_mp4(source_video_path, target_video_path, crf=20):
    command = 'ffmpeg -threads 4 -y -i ' + source_video_path + '  -crf ' + str(crf) + \
              ' -vcodec libx264 -preset fast -strict experimental ' + target_video_path
    logging.info(command)
    os.system(command)

def capture_image(source_video_path, image_path, name_prefix, cap_rate=1):
    command = 'ffmpeg -i ' + source_video_path + ' -f image2 -vf fps=fps=1/' + str(cap_rate) + ' ' + \
              os.path.join(image_path, name_prefix + '%d.png')
    logging.info(command)
    os.system(command)


from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from forms import RegistrationForm, RegForm
from django.shortcuts import render_to_response, render, get_object_or_404
from django.template.context import RequestContext
from models import *

# Create your views here.

def index(request):
    return render(request, 'hackathon/index.html', {})

def register(request):
    if request.method == 'POST':
        form = RegForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            mobile = form.cleaned_data['mobile']
            team = form.cleaned_data['team']
            email = form.cleaned_data['email']
            problem = form.cleaned_data['problem']
            year = form.cleaned_data['year']
            course = form.cleaned_data['course']
            branch = form.cleaned_data['branch']
            mess = form.cleaned_data['mess']
            roll_no = form.cleaned_data['roll_no']
            tee = form.cleaned_data['tee']
            gender = form.cleaned_data['gender']

            participant = Participant(name=name,mobile=mobile,team=team,email=email,problem=problem,year=year,course=course,
                                      branch=branch,mess=mess,roll_no=roll_no,tee_shirt_size=tee,gender=gender)
            participant.save()

            return render_to_response("hackathon/success.html", RequestContext(request,{'name':name}))
        else:
            return render_to_response("hackathon/register.html", RequestContext(request, {'form' : form}))

    form = RegForm()
    return render(request,'hackathon/register.html',{'form':form})

def get_email(request):
    if request.user.is_superuser:
        participants = Participant.objects.all()
        emails = []
        for participant in participants:
            emails.append(participant.email)

        return render(request,"hackathon/emails.html",{'emails':emails})
    else:
        return HttpResponseRedirect('/admin/')

def get_email_by_prob_statement(request,problem_id):
    if request.user.is_superuser:
        participants = Participant.objects.all().filter(problem_id=problem_id)
        emails = []
        for participant in participants:
            emails.append(participant.email)

        return render(request,"hackathon/emails.html",{'emails':emails})
    else:
        return HttpResponseRedirect('/admin/')

def problems(request):
    problem_sts = ProblemStatement.objects.all()
    context = {'problems':problem_sts}
    return render(request, 'hackathon/problems.html',context)

def get_problem_statement(request,problem_id):
    problem = get_object_or_404(ProblemStatement,pk=problem_id)
    context = {'problem':problem}
    return render(request,'hackathon/problem_statement.html',context)

def faq(request):
    return render(request,'hackathon/faq.html')

def student_details(request):
    if request.user.is_superuser:
        participants = Participant.objects.all()
        return render(request,'hackathon/students.html',{'students':participants})
    else:
        return HttpResponseRedirect('/admin')


"""
Tests for HTTP email API views
"""
from unittest.mock import Mock, patch
from django.core.urlresolvers import reverse
from django.db.models.signals import post_save
from rest_framework.test import APITestCase
from rest_framework.response import Response
from rest_framework.status import (
    HTTP_200_OK,
    HTTP_400_BAD_REQUEST,
    HTTP_403_FORBIDDEN,
)
from factory.django import mute_signals

from profiles.factories import ProfileFactory
from courses.factories import ProgramFactory
from roles.models import Role
from roles.roles import Staff

def mocked_json(return_data=None):
    """Mocked version of the json method for the Response class"""
    if return_data is None:
        return_data = {}

    def json(*args, **kwargs):  # pylint:disable=unused-argument, missing-docstring
        return return_data
    return json

@patch('mail.views.prepare_and_execute_search')  # pylint: disable=missing-docstring
@patch('mail.views.MailgunClient')  # pylint: disable=missing-docstring
class MailViewsTests(APITestCase):
    @classmethod
    def setUpTestData(cls):
        cls.mail_url = reverse('mail_api')
        cls.program = ProgramFactory.create(live=True)
        # create a user with a role for one program
        with mute_signals(post_save):
            staff_profile = ProfileFactory.create()
            cls.staff = staff_profile.user
        Role.objects.create(
            user=cls.staff,
            program=cls.program,
            role=Staff.ROLE_ID
        )
        cls.request_data = {
            'search_request': {},
            'email_subject': 'email subject',
            'email_body': 'email body'
        }

    def setUp(self):
        super(MailViewsTests, self).setUp()
        self.client.force_login(self.staff)

    def test_send_view(self, mock_mailgun_client, mock_prepare_exec_search):
        """
        Test that the email send view will accept and return expected values
        """
        email_results = ['a@example.com', 'b@example.com']
        mock_prepare_exec_search.return_value = email_results
        mock_mailgun_client.send_batch.return_value = [
            Mock(spec=Response, status_code=HTTP_200_OK, json=mocked_json())
        ]
        resp_post = self.client.post(self.mail_url, data=self.request_data, format='json')
        assert resp_post.status_code == HTTP_200_OK
        assert mock_prepare_exec_search.called
        assert mock_mailgun_client.send_batch.called
        _, called_kwargs = mock_mailgun_client.send_batch.call_args
        assert called_kwargs['subject'] == self.request_data['email_subject']
        assert called_kwargs['body'] == self.request_data['email_body']
        assert called_kwargs['recipients'] == email_results

    def test_view_response(self, mock_mailgun_client, mock_prepare_exec_search):
        """
        Test the structure of the response returned by the view
        """
        email_results = ['a@example.com', 'b@example.com']
        mock_prepare_exec_search.return_value = email_results
        mock_mailgun_client.send_batch.return_value = [
            Mock(spec=Response, status_code=HTTP_200_OK, json=mocked_json()),
            Mock(spec=Response, status_code=HTTP_400_BAD_REQUEST, json=mocked_json()),
        ]
        resp_post = self.client.post(self.mail_url, data=self.request_data, format='json')
        assert resp_post.status_code == HTTP_200_OK
        assert len(resp_post.data.keys()) == 2
        for num in range(2):
            batch = 'batch_{0}'.format(num)
            assert batch in resp_post.data
            assert 'status_code' in resp_post.data[batch]
            assert 'data' in resp_post.data[batch]
        assert resp_post.data['batch_0']['status_code'] == HTTP_200_OK
        assert resp_post.data['batch_1']['status_code'] == HTTP_400_BAD_REQUEST

    def test_no_program_user_response(self, *args):  # pylint: disable=unused-argument
        """
        Test that a 403 will be returned when a user with inadequate permissions attempts
        to send an email through the email send view
        """
        with mute_signals(post_save):
            no_permissions_profile = ProfileFactory.create()
        self.client.force_login(no_permissions_profile.user)
        resp_post = self.client.post(self.mail_url, data=self.request_data, format='json')
        assert resp_post.status_code == HTTP_403_FORBIDDEN


# -*- coding: utf-8 -*-
"""
Utility functions to convert the html body in e-mail friendly html
Actually it would be better to convert our html to an intermediate
structure (json) and template it. We'll do that later
"""
from bs4 import BeautifulSoup

from django.template import TemplateDoesNotExist
from django.template.loader import render_to_string

class HtmlConvert(object):
    def __init__(self, template_root):
        self.template_root = template_root

    def _clean(self, soup):
        empty_paras = soup.findAll(
            lambda tag: tag.name == 'p'
            and tag.find(True) is None
            and (tag.string is None or tag.string.strip() == '')
        )
        [empty_para.extract() for empty_para in empty_paras]

        # remove <br />
        # brs = soup.find_all('br')
        # [br.extract() for br in brs]

    def to_mail(self, body):
        soup = BeautifulSoup(body)
        self._clean(soup)
        return self._convert_html(soup).replace('\n', '')

    def _convert_html(self, soup_in):
        stack = ""
        try:
            if len(soup_in.find_all()):
                for child in soup_in.children:
                    stack += self._convert_html(child)
            return self._template(soup_in, stack)

        except AttributeError:
            return self._template(soup_in, stack)

    def _template(self, tag, stack):

        if not tag.name:
            return unicode(tag)

        string = stack if stack else tag.string
        try:
            context = {
                'tag': tag,
                'href': tag.get('href'),
                'title': tag.get('title', ''),
                'class': " ".join(tag.get('class', '')),
                'string': string,
            }
            template_name = "%s/%s.html" % (self.template_root, tag.name)
            return render_to_string(template_name, context).rstrip()

        except TemplateDoesNotExist:
            return unicode(string)


# Copyright (c) [2022] Huawei Technologies Co.,Ltd.ALL rights reserved.
# This program is licensed under Mulan PSL v2.
# You can use it according to the terms and conditions of the Mulan PSL v2.
#          http://license.coscl.org.cn/MulanPSL2
# THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
####################################
# @Author  :
# @email   :
# @Date    :
# @License : Mulan PSL v2
#####################################

from flask.json import jsonify
from flask import request
from flask_restful import Resource
from flask_pydantic import validate
from sqlalchemy import case as sql_case

from server.model import Product, Milestone, TestReport
from server.utils.auth_util import auth
from server.utils.db import Edit, Select
from server.utils.page_util import PageUtil

from server.schema.product import ProductBase, ProductUpdate, ProductQueryBase
from server.utils.permission_utils import GetAllByPermission
from server.utils.resource_utils import ResourceManager
from server import casbin_enforcer
from server.utils.response_util import RET, response_collect

class ProductEventItem(Resource):
    @auth.login_required
    @validate()
    @casbin_enforcer.enforcer
    @response_collect
    def delete(self, product_id):
        return ResourceManager("product").del_cascade_single(
            product_id, Milestone, [Milestone.product_id == product_id], False
        )

    @auth.login_required
    @validate()
    @casbin_enforcer.enforcer
    @response_collect
    def get(self, product_id):
        return Select(Product, {"id": product_id}).single()

    @auth.login_required
    @validate()
    @casbin_enforcer.enforcer
    @response_collect
    def put(self, product_id, body: ProductUpdate):
        product = Product.query.filter_by(id=product_id).first()
        if not product:
            return jsonify(
                error_code=RET.NO_DATA_ERR,
                error_msg="product does not exist.",
            )
        name = product.name
        version = product.version
        if body.name:
            name = body.name
        if body.version:
            version = body.version

        product = Product.query.filter_by(
            name=name, version=version
        ).first()
        if product and product.id != product_id:
            return jsonify(
                error_code=RET.NO_DATA_ERR,
                error_msg="The version of product has existed.",
            )
        _data = body.__dict__
        _data["id"] = product_id
        return Edit(Product, _data).single(Product, '/product')

class ProductEvent(Resource):
    @auth.login_required
    @validate()
    @response_collect
    def post(self, body: ProductBase):
        return ResourceManager("product").add("api_infos.yaml", body.__dict__)

    @auth.login_required
    @response_collect
    @validate()
    def get(self, query: ProductQueryBase):
        _g = GetAllByPermission(Product)
        if query.permission_type is not None:
            _g.set_filter(Product.permission_type == query.permission_type)
            ords = [Product.name.asc(), Product.create_time.asc()]
        else:
            _ord = sql_case(
                (Product.permission_type == 'org', 1),
                (Product.permission_type == 'public', 2),
                (Product.permission_type == 'group', 3),
                (Product.permission_type == 'person', 4)
            )
            ords = [_ord, Product.name.asc(), Product.create_time.asc()]
        query_filter = _g.fuzz(
            query.__dict__,
            ords,
            "query"
        )
        return PageUtil.get_data(query_filter, query)

class PreciseProductEvent(Resource):
    @auth.login_required
    @response_collect
    def get(self):
        body = dict()

        for key, value in request.args.to_dict().items():
            if value:
                body[key] = value

        return GetAllByPermission(Product).precise(body)

class UpdateProductIssueRate(Resource):
    @auth.login_required
    @validate()
    @response_collect
    def put(self, product_id):
        from celeryservice.lib.issuerate import UpdateIssueRate
        from server.apps.milestone.handler import IssueStatisticsHandlerV8

        product = Product.query.filter_by(id=product_id).first()
        if not product:
            return jsonify(
                error_code=RET.NO_DATA_ERR,
                error_msg="product does not exist.",
            )

        user_id = IssueStatisticsHandlerV8.get_user_id(product.org_id)
        if user_id:
            UpdateIssueRate.update_product_issue_resolved_rate(
                user_id,
                {"product_id": product_id, "org_id": product.org_id},
            )

        return jsonify(
            error_code=RET.OK,
            error_msg="OK",
        )

class ProductTestReportEvent(Resource):
    @auth.login_required()
    @response_collect
    def get(self, product_id):
        _product = Product.query.filter_by(id=product_id).first()
        if not _product:
            return jsonify(
                error_code=RET.NO_DATA_ERR,
                error_msg="product doesn't exist.",
            )

        _test_reports = TestReport.query.join(Milestone).filter(
            TestReport.milestone_id == Milestone.id,
            Milestone.product_id == product_id
        ).all()
        data = []
        if _test_reports:
            data = [tr.to_json() for tr in _test_reports]

        return jsonify(
            error_code=RET.OK,
            error_msg="OK",
            data=data
        )


from math import radians, cos, sin, asin, sqrt
import matplotlib.pyplot as plt
import numpy as np
from data.data_preprocess import df_stations

x = [long for long in df_stations['longitude'].values]
y = [lat for lat in df_stations['latitude'].values]

m = len(df_stations)        # Here m = 302 subway stations

'''=================== Implementation of distances between stations =================='''

def euc_distance(A,B):
    """Simply returns the euclidean distance between points A and B."""
    return(np.sqrt(((B[0]-A[0])**2)+((B[1]-A[1])**2)))

def sph_distance_station(station1, station2):
    global df_stations
    """More elaborated distance that takes into account Earth spherical nature, given two subway stations."""
    lon1, lat1 = df_stations.loc[df_stations['station']==station1][['longitude','latitude']].values[0].tolist()
    lon2, lat2 = df_stations.loc[df_stations['station']==station2][['longitude','latitude']].values[0].tolist()
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a))
    r = 6371
    return c * r

def sph_distance_coordinate(lon1, lat1, lon2, lat2):
    global df_stations
    """Same function than before except that longitude and latitude are already known."""
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a))
    r = 6371
    return c * r

'''=================== Construction of the real parisian network ======================'''

import ast

with open('data/real_network.txt', encoding="utf-8") as file:
    real_network_structure = ast.literal_eval(file.read())

def station_index(station,df):
    """Returns the index of 'station' in the DataFrame 'df'."""
    for index, row in df.iterrows():
        if row['station'] == station:
            return index

def build_real_network(structure_list):
    """Creates the adjacency matrix of Paris subway network."""
    global m, dist_matrix, df_stations
    adj_matrix = np.zeros((m, m))
    for k in range(len(structure_list) - 1):
        if structure_list[k] == 'END_OF_LINE':
            pass
        elif structure_list[k + 1] == 'END_OF_LINE':
            pass
        else:
            i = station_index(structure_list[k],df_stations)
            j = station_index(structure_list[k + 1],df_stations)
            adj_matrix[i][j] = sph_distance_station(structure_list[k], structure_list[k+1])
            adj_matrix[j][i] = adj_matrix[i][j]
    for i in range(m):
        for j in range(m):
            if adj_matrix[i][j] == 0.0:
                adj_matrix[i][j], adj_matrix[j][i] = -1.0, -1.0
    return adj_matrix

def matrix_to_dic(adj_matrix):
    """Transforms the adjacency matrix of a graph into its adjacency dictionary."""
    m = len(adj_matrix)
    adj_dic = {}
    for i in range(m):
        adj_dic[i] = [[j,adj_matrix[i][j]] for j in range(m) if adj_matrix[i][j] != -1]
    return(adj_dic)

def display_graph(adj_dic, plot_title='', figsize=(10,10), special_edges = []):
    """Plot a graph described by its adjacency dictionary 'adj_dic'."""
    global x,y
    plt.figure(figsize=figsize)
    plt.xlim(2.2, 2.5)
    plt.ylim(48.75, 49.0)
    plt.gca().set_aspect('equal', adjustable='box')
    plt.scatter(x,y,marker='.',c='g')
    for station_id in adj_dic:
        for connected_station in adj_dic[station_id]:
            if [station_id, connected_station[0], connected_station[1]] in special_edges:
                j = connected_station[0]
                plt.plot([x[station_id],x[j]],[y[station_id],y[j]],'r-',linewidth=0.5)
            else:
                j = connected_station[0]
                plt.plot([x[station_id], x[j]], [y[station_id], y[j]], 'g-', linewidth=0.5)
    plt.title(plot_title)
    plt.show()


"""ProtoTorch LGMLVQ example using 2D Iris data."""

import numpy as np
import torch
from matplotlib import pyplot as plt
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score

from prototorch.functions.competitions import stratified_min
from prototorch.functions.distances import lomega_distance
from prototorch.functions.init import eye_
from prototorch.modules.losses import GLVQLoss
from prototorch.modules.prototypes import Prototypes1D

# Prepare training data
x_train, y_train = load_iris(True)
x_train = x_train[:, [0, 2]]

# Define the model
class Model(torch.nn.Module):
    def __init__(self):
        """Local-GMLVQ model."""
        super().__init__()
        self.p1 = Prototypes1D(input_dim=2,
                               prototype_distribution=[1, 2, 2],
                               prototype_initializer="stratified_random",
                               data=[x_train, y_train])
        omegas = torch.zeros(5, 2, 2)
        self.omegas = torch.nn.Parameter(omegas)
        eye_(self.omegas)

    def forward(self, x):
        protos = self.p1.prototypes
        plabels = self.p1.prototype_labels
        omegas = self.omegas
        dis = lomega_distance(x, protos, omegas)
        return dis, plabels

# Build the model
model = Model()

# Optimize using Adam optimizer from `torch.optim`
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
criterion = GLVQLoss(squashing="sigmoid_beta", beta=10)

x_in = torch.Tensor(x_train)
y_in = torch.Tensor(y_train)

# Training loop
title = "Prototype Visualization"
fig = plt.figure(title)
for epoch in range(100):
    # Compute loss
    dis, plabels = model(x_in)
    loss = criterion([dis, plabels], y_in)
    y_pred = np.argmin(stratified_min(dis, plabels).detach().numpy(), axis=1)
    acc = accuracy_score(y_train, y_pred)
    log_string = f"Epoch: {epoch + 1:03d} Loss: {loss.item():05.02f} "
    log_string += f"Acc: {acc * 100:05.02f}%"
    print(log_string)

    # Take a gradient descent step
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # Get the prototypes form the model
    protos = model.p1.prototypes.data.numpy()

    # Visualize the data and the prototypes
    ax = fig.gca()
    ax.cla()
    ax.set_title(title)
    ax.set_xlabel("Data dimension 1")
    ax.set_ylabel("Data dimension 2")
    cmap = "viridis"
    ax.scatter(x_train[:, 0], x_train[:, 1], c=y_train, edgecolor='k')
    ax.scatter(protos[:, 0],
               protos[:, 1],
               c=plabels,
               cmap=cmap,
               edgecolor='k',
               marker='D',
               s=50)

    # Paint decision regions
    x = np.vstack((x_train, protos))
    x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
    y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, 1 / 50),
                         np.arange(y_min, y_max, 1 / 50))
    mesh_input = np.c_[xx.ravel(), yy.ravel()]

    d, plabels = model(torch.Tensor(mesh_input))
    y_pred = np.argmin(stratified_min(d, plabels).detach().numpy(), axis=1)
    y_pred = y_pred.reshape(xx.shape)

    # Plot voronoi regions
    ax.contourf(xx, yy, y_pred, cmap=cmap, alpha=0.35)

    ax.set_xlim(left=x_min + 0, right=x_max - 0)
    ax.set_ylim(bottom=y_min + 0, top=y_max - 0)

    plt.pause(0.1)


from datetime import datetime
import random
import importlib
from init import *
import pytz

def welcome(user, location, bot):
    hour = datetime.now(pytz.timezone('Europe/Moscow')).hour
    if hour > 20 or hour < 8:
        bot.send_message(user["chat_id"], "Администрация закрыта, приходите завтра. Вы перемещаетесь на улицу.")

        location = change_location_by_id(user, "street")
        try:
            location_module = importlib.import_module(location['file'])
            location_module.welcome(user, location, bot)
        except Exception as e:
            print(e)
    elif "dirty" in user['states']:
        bot.send_message(user["chat_id"], "Вы испачкались, в таком виде вас не пускают. Вы перемещаетесь на улицу.")

        location = change_location_by_id(user, "street")
        try:
            location_module = importlib.import_module(location['file'])
            location_module.welcome(user, location, bot)
        except Exception as e:
            print(e)
    else:
        bot.send_message(user['chat_id'], "👩💼 Вы в здании администрации.\n\n"
                                          "* /icecream - купить мороженое.")

def message(msg, user, location, neighbors, bot):
    hour = datetime.now(pytz.timezone('Europe/Moscow')).hour

    if "/icecream" in msg.text:
        if 'coin' in user['inventory']:
            bot.send_message(user["chat_id"], '🍦 В инвентарь добавлено одно мороженое.')
            user['inventory'].remove('coin')
            user['inventory'].append('icecream')
        else:
            bot.send_message(user["chat_id"], '👀 У вас нет монет, монет...')
    else:
        for neighbor in neighbors:
            if neighbor["chat_id"] != user["chat_id"]:
                bot.send_message(neighbor["chat_id"], "{}: {}".format(user["name"], msg.text))

def event(users, location, bot):
    hour = datetime.now(pytz.timezone('Europe/Moscow')).hour

    if hour > 20 or hour < 8:
        for user in users:
            bot.send_message(user['chat_id'], "🕜 Администрация закрывается, вас попросили выйти на улицу.")

            location = change_location_by_id(user, "street")
            try:
                location_module = importlib.import_module(location['file'])
                location_module.welcome(user, location, bot)
            except Exception as e:
                print(e)


"""
Common NLP tasks such as named_entities, noun_chunks, etc.
"""

import spacy
import pandas as pd

def named_entities(s, package="spacy"):
    """
    Return named-entities.

    Use Spacy named-entity-recognition.

        PERSON: People, including fictional.
        NORP: Nationalities or religious or political groups.
        FAC: Buildings, airports, highways, bridges, etc.
        ORG: Companies, agencies, institutions, etc.
        GPE: Countries, cities, states.
        LOC: Non-GPE locations, mountain ranges, bodies of water.
        PRODUCT: Objects, vehicles, foods, etc. (Not services.)
        EVENT: Named hurricanes, battles, wars, sports events, etc.
        WORK_OF_ART: Titles of books, songs, etc.
        LAW: Named documents made into laws.
        LANGUAGE: Any named language.
        DATE: Absolute or relative dates or periods.
        TIME: Times smaller than a day.
        PERCENT: Percentage, including ”%“.
        MONEY: Monetary values, including unit.
        QUANTITY: Measurements, as of weight or distance.
        ORDINAL: “first”, “second”, etc.
        CARDINAL:	Numerals that do not fall under another type.

    """
    entities = []

    nlp = spacy.load('en_core_web_sm', disable=["tagger", "parser"])
    # nlp.pipe is now 'ner'

    for doc in nlp.pipe(s.astype("unicode").values, batch_size=32):
        entities.append([(ent.text, ent.label_, ent.start_char, ent.end_char)
                         for ent in doc.ents])

    return pd.Series(entities, index=s.index)

def noun_chunks(s):
    """
    Return noun_chunks, flat phrases that have a noun as their head.

    """
    noun_chunks = []

    nlp = spacy.load('en_core_web_sm', disable=["ner"])
    # nlp.pipe is now "tagger", "parser"

    for doc in nlp.pipe(s.astype('unicode').values, batch_size=32):
        noun_chunks.append([(chunk.text, chunk.label_, chunk.start_char,
                             chunk.end_char) for chunk in doc.noun_chunks])

    return pd.Series(noun_chunks, index=s.index)

def dependency_parse(s):
    """
    Return the dependency parse

    """
    return NotImplemented


import numpy as np
import glob
import random
import cv2
import torch

def show_config(config):
    print("option".center(60, "-"))
    for k, v in vars(config).items():
        print(k.rjust(24), ":", v)
    print("-" * 60)

def setup_seed(seed):
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    np.random.seed(seed)
    random.seed(seed)
    torch.backends.cudnn.deterministic = True

class ImageLoader:
    def __init__(self, path, batch_size=64, image_shape=(1, 28, 28), label=False, pre_load=False, random_state=2021):
        self.paths = glob.glob(path)
        self.batch_size = batch_size
        self.label = label
        self.pre_load = pre_load
        self.channel = image_shape[0]
        self.height = image_shape[1]
        self.width = image_shape[2]
        self.label2idx_ = dict()
        self.idx2label_ = dict()
        self.random_state = random_state
        random.seed(random_state)

        self.images = None
        if self.pre_load:
            self.images = [cv2.imread(f) for f in self.paths]
        if self.label:
            labels = list(set(p.split("/")[-2] for p in self.paths))
            labels.sort(reverse=False)
            self.idx2label_ = dict(enumerate(labels))
            self.label2idx_ = dict((v, k) for k, v in self.idx2label_.items())

    def preprocess(self, img):
        img = cv2.resize(img, (self.height, self.width), interpolation=cv2.INTER_LINEAR)
        img = img.reshape((self.height, self.width, -1))
        img = img.transpose(2, 0, 1)  # cv2读入的数据为h,w,c，而pytorch需要c,h,w
        img = np.array(img).astype(np.float32) / 255 * 2 - 1
        return img

    def __len__(self):
        return len(self.paths) // self.batch_size

    def __iter__(self):
        data = list()
        labels = list()
        while True:
            if self.pre_load:
                random.seed(self.random_state)
                random.shuffle(self.images)
                random.seed(self.random_state)
                random.shuffle(self.paths)
            else:
                random.shuffle(self.paths)
            for idx in range(len(self.paths)):
                img = self.images[idx] if self.pre_load else cv2.imread(self.paths[idx])
                img = img if self.channel != 1 else cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                if self.label:
                    label = self.paths[idx].split("/")[-2]
                    label_idx = self.label2idx_[label]
                    labels.append(label_idx)
                data.append(self.preprocess(img))
                if len(data) == self.batch_size:
                    data = np.array(data)
                    if self.label:
                        labels = np.array(labels)
                        yield data, labels
                    else:
                        yield data
                    data = list()
                    labels = list()

if __name__ == "__main__":
    loader = ImageLoader(path="../data/mnist_png/training/*/*.png", batch_size=3)
    print(len(loader))
    for i in loader:
        print(i.shape)
        cv2.imwrite("test.png", (i[0].transpose(1, 2, 0) + 1) / 2 * 255)
        cv2.imwrite("test.png", (i[2].transpose(1, 2, 0) + 1) / 2 * 255)
        break


import os
import pygame

BACKGROUND_IMAGE = 'background.png'     # 792 x 480
IMAGES_DIRECTORY = 'images'

class Background:

    def __init__(self, rect):
        try:
            self.surface = pygame.image.load(os.path.join(IMAGES_DIRECTORY, BACKGROUND_IMAGE))
        except:
            print('Cannot load background image')

    def draw(self, target_surface, area_to_update = None):
        if area_to_update is None:
            target_surface.blit(self.surface, (0, 0))
        else:
            target_surface.blit(self.surface, area_to_update, area_to_update)


import warnings
import theano
import numpy

import theano.tensor as T

from layer import Layer
from utils.model.layer_utils import setupDefaultLayerOptions

__all__ = ["BatchStandardizeLayer"]

#-------------------------------------------------------------------------------
# Begin BatchNormLayer
class BatchStandardizeLayer(Layer):
    def __init__(self):
        super(BatchStandardizeLayer, self).__init__()
        self.layerType='BStandardLayer'

    def constructLayer(self, inputShape, initParams, name,
                       **layerSpecs):
        self.layerName = name

        self.inputShape = inputShape
        self.outputShape = inputShape

    def fprop(self, x, isTest=False):

        ret = x
        if not isTest:
            norm_axis = (1,)+tuple(range(2,len(self.inputShape)))
            x_avg = T.mean(x, axis=norm_axis, keepdims=True)
            x_std = T.std(x, axis=norm_axis, keepdims=True)
            ret = (x-x_avg)/(x_std+1e-4)

        return ret

# End BatchNormLayer
#-------------------------------------------------------------------------------


import tensorflow as tf
import os
import time
import datetime
from TextCNN import TextCNN
from DataPreprocess import data_preprocess

def train():
    # 指定样本文件
    data_file = "../data_preprocess/train_data.csv"

    # 设置训练参数
    num_steps = 2000
    display_every = 10
    checkpoint_every = 100
    save_file = 'textcnn'

    # 设置模型参数
    num_classes = 126
    dropout_keep_prob = 0.8
    l2_reg_lambda = 0.1
    filter_sizes = [3, 5, 7]
    num_filters = 256
    embedding_size = 128

    tf.reset_default_graph()

    # 预处理数据
    data, vocab_processor, max_document_length = data_preprocess(data_file)
    iterator = data.make_one_shot_iterator()
    next_element = iterator.get_next()

    # 定义cnn model
    cnn = TextCNN(
        sequence_length=max_document_length,
        num_classes=num_classes,
        vocab_size=len(vocab_processor.vocabulary_),
        embedding_size=embedding_size,
        filter_sizes=filter_sizes,
        num_filters=num_filters,
        l2_reg_lambda=l2_reg_lambda,
    )

    # 构建网络
    cnn.build_model()

    # 打开会话
    session_conf = tf.ConfigProto(
        allow_soft_placement=True, log_device_placement=False)
    with tf.Session(config=session_conf) as sess:
        sess.run(tf.global_variables_initializer())

        # 输出模型路径
        out_dir = os.path.abspath(os.path.join(os.path.curdir, save_file))
        print("Writing to {}\n".format(out_dir))

        # 设置输出摘要路径
        train_summary_dir = os.path.join(out_dir, "summaries")
        train_summary_writer = tf.summary.FileWriter(
            train_summary_dir, sess.graph)

        # 设置检查点文件名称
        checkpoint_dir = os.path.abspath(os.path.join(out_dir, "checkpoints"))
        checkpoint_prefix = os.path.join(checkpoint_dir, "model")

        if not os.path.exists(checkpoint_dir):
            os.makedirs(checkpoint_dir)

        # 定义操作检查点的Saver
        saver = tf.train.Saver(tf.global_variables(), max_to_keep=1)

        # # 保存字典
        # vocab_processor.save(os.path.join(out_dir,"vocab"))

        def train_step(x_batch, y_batch):
            feed_dict = {
                cnn.input_x: x_batch,
                cnn.input_y: y_batch,
                cnn.dropout_keep_prob: dropout_keep_prob
            }
            _, step, summaries, loss, accuracy = sess.run(
                [cnn.train_op, cnn.global_step, cnn.train_summary_op, cnn.loss, cnn.accuracy], feed_dict)

            time_str = datetime.datetime.now().isoformat()
            train_summary_writer.add_summary(summaries, step)

            return (time_str, step, loss, accuracy)

        i = 0
        while tf.train.global_step(sess, cnn.global_step) < num_steps:
            x_batch, y_batch = sess.run(next_element)
            i += 1
            time_str, step, loss, accuracy = train_step(x_batch, y_batch)

            current_step = tf.train.global_step(sess, cnn.global_step)
            if current_step % display_every == 0:
                print("{}:step {},loss {:g},acc {:g}".format(
                    time_str, step, loss, accuracy))

            if current_step % checkpoint_every == 0:
                path = saver.save(sess, checkpoint_prefix,
                                  global_step=current_step)
                print("Saved model checkpoint to {}\n".format(path))

# def main(argv=None):
# 	train()

# if __name__=='__main__':
# 	tf.app.run()

if __name__ == '__main__':
    train()


import bpy
from bpy.props import *
from ...nodes.BASE.node_tree import RenderStackNode

def poll_object(self, object):
    return object.type in {'MESH', 'CURVE', 'VOLUME'}

def update_slot_index(self, context):
    if self.object:
        if self.slot_index > len(self.object.material_slots) - 1:
            self.slot_index = len(self.object.material_slots) - 1
    self.update_parms()

def update_node(self, context):
    self.update_parms()

class RSNodeObjectMaterialNode(RenderStackNode):
    bl_idname = 'RSNodeObjectMaterialNode'
    bl_label = 'Object Material'

    object: PointerProperty(type=bpy.types.Object, poll=poll_object, name='Object', update=update_node)

    slot_index: IntProperty(min=0, default=0, name="Slot index", update=update_slot_index)
    new_material: PointerProperty(type=bpy.types.Material, name='New Mat', update=update_node)

    def init(self, context):
        self.outputs.new('RSNodeSocketTaskSettings', "Settings")

    def draw_buttons(self, context, layout):
        layout.use_property_split = 1
        layout.use_property_decorate = 0
        col = layout.column(align=1)

        row = col.row(align=1)
        row.prop(self, "object")
        if self.object:
            row.operator('rsn.select_object', icon='RESTRICT_SELECT_OFF', text='').name = self.object.name

        col.prop(self, 'slot_index', text='Slot')
        col.prop(self, 'new_material', text='Material')

    def get_data(self):
        task_data_obj = {}
        if self.object and self.new_material:
            task_data_obj[self.name] = {'object'      : f"bpy.data.objects['{self.object.name}']",
                                        'slot_index'  : self.slot_index,
                                        'new_material': self.new_material.name}
        return task_data_obj

def register():
    bpy.utils.register_class(RSNodeObjectMaterialNode)

def unregister():
    bpy.utils.unregister_class(RSNodeObjectMaterialNode)


import zipfile as ziph
from os import path
from tkinter import *
from tkinter import filedialog
from os import listdir, path
class Gui(Toplevel):
    def __init__(self, parent, title="Обработка файлов"):
        Toplevel.__init__(self, parent)
        parent.geometry("250x250+100+150")
        if title:
            self.title(title)
        parent.withdraw()
        self.parent = parent
        self.result = None
        dialog = Frame(self)
        self.initial_focus = self.dialog(dialog)
        self.protocol("WM_DELETE_WINDOW", self.on_exit)
        dialog.pack()

    def on_exit(self):
        self.quit()

    def text_3_on(self):
        if self.var_1.get():
            self.text_3["state"] = "normal"
            self.text_3.delete(0, END)
            self.text_3.insert(END, "address.jpg")
        else:
            self.text_3["state"] = "disabled"

    def text_5_on(self):
        if self.var_2.get():
            self.text_5["state"] = "normal"
            self.text_5.delete(0, END)
            self.text_5.insert(END, "Name_{{initial_image_name}}")
        else:
            self.text_5["state"] = "disabled"

    def search_folder_for_files(self):
        path_to = filedialog.askdirectory()
        print(path_to)
        self.text_1.delete(0, END)
        self.text_1.insert(END, path_to)

    def search_folder_for_images(self):
        path_to = filedialog.askdirectory()
        print(path_to)
        self.text_2.delete(0, END)
        self.text_2.insert(END, path_to)

    def search_folder_for_zip(self):
        path_to = filedialog.askdirectory()
        print(path_to)
        self.text_4.delete(0, END)
        self.text_4.insert(END, path_to)

    def start(self):
        print()
        print(listdir(self.text_1.get()))
        print(listdir(self.text_2.get()))
        print(listdir(self.text_4.get()))

    # Создадим массив имен архивов
        name = []
        for i in range(0, len(listdir(self.text_2.get()))):
            name.append(str(self.text_5.get())+"_"+str(i+1))

        for i in range(0,len(listdir(self.text_2.get()))):
            # Создает архив
            newzip = ziph.ZipFile(str(self.text_4.get().replace('/', '\\')) + '\\' + str(name[i]) + '.zip', 'w',
                                  ziph.ZIP_LZMA)
            # Берет все элементы
            for item in listdir(self.text_1.get()):
                newzip.write(str(self.text_1.get().replace('/', '\\')) + '\\' + str(item), str(item))

            # Берет по одному элементу
            if self.var_1.get():
                if ".jpg" in listdir(self.text_2.get())[i]:
                    newzip.write(str(self.text_2.get()).replace('/', '\\') + "\\" + str(listdir(self.text_2.get())[i]),
                                 str(self.text_3.get()))
                else:
                    newzip.write(str(self.text_2.get().replace('/', '\\')) + '\\' + str(listdir(self.text_2.get())[i]),
                                 str(listdir(self.text_2.get())[i]))
            else:
                newzip.write(str(self.text_2.get().replace('/', '\\'))+'\\'+str(listdir(self.text_2.get())[i]),
                         str(listdir(self.text_2.get())[i]))

        newzip.close()

        import ctypes
        message = 'Готово!'
        ctypes.windll.user32.MessageBoxW(0, message, 'Обработка файлов', 0)
        print('ok')

    def dialog(self, parent):
        self.parent = parent

        # Created main elements
        self.label_1 = Label(parent, text="Укажите папку, в которой лежат основные файлы")
        self.text_1 = Entry(parent, width=50)
        self.but_1 = Button(parent, text="Указать", command=self.search_folder_for_files)

        self.label_2 = Label(parent, text="Укажите папку, где лежат изображения, которые нужно разложить")
        self.text_2 = Entry(parent, width=50)
        self.but_2 = Button(parent, text="Указать", command=self.search_folder_for_images)

        self.var_1 = IntVar()
        self.var_2 = IntVar()
        self.text_3 = Entry(parent, width=50, state=DISABLED, disabledforeground=parent.cget('bg'))
        self.chk_1 = Checkbutton(parent, text="Переименовать изображения при копировании в:", variable=self.var_1, command=self.text_3_on)

        self.label_3 = Label(parent, text="Укажие папку, куда сложить финальные файлы zip")
        self.text_4 = Entry(parent, width=50)
        self.but_3 = Button(parent, text="Указать", command=self.search_folder_for_zip)

        self.chk_2 = Checkbutton(parent, text="Переименовать zip архивы по маске", variable=self.var_2, command=self.text_5_on)
        self.text_5 = Entry(parent, width=50, state=DISABLED, disabledforeground=parent.cget('bg'))

        self.label_1.pack()
        self.text_1.pack()
        self.but_1.pack()

        self.label_2.pack()
        self.text_2.pack()
        self.but_2.pack()

        self.chk_1.pack()
        self.text_3.pack()

        self.label_3.pack()
        self.text_4.pack()
        self.but_3.pack()

        self.chk_2.pack()
        self.text_5.pack()

        # start button
        self.but_start = Button(parent, text="Выполнить",command=self.start)
        self.but_start.pack()

if __name__ == "__main__":
    root = Tk()
    root.minsize(width=500, height=400)
    gui = Gui(root)
    root.mainloop()


from django.shortcuts import render
import requests
from django.http import HttpResponse, HttpResponseRedirect
import json

url = 'http://campaign-tracker.zyrl.us'

class FacebookImage(object):
	image = ""
	message = ""
	date = ""
	reactions = ""
	comments = ""

class InstagramImage(object):
	image = ""
	message = ""
	date = ""
	reactions = ""
	comments = ""

def tracker_index(request):
	context_dict = {}
	r = requests.get('http://zdash.zyrl.us/campaigns/')
	names = []
	for data in r.json():
		# print data['name']
		if data['name'] != '':
			names.append(data['name'])
	context_dict['names'] = names
	return render(request, 'campaign_index.html', context_dict)

def tracker_detail(request, name):
	context_dict = {}
	r = requests.get(url+'/campaign/'+name)
	users = {}
	users_ig = {}
	try:
		context_dict['campaignName'] = r.json()[0]['campaign_name']
	except Exception as e:
		return HttpResponse("no details yet. come again later.")
	context_dict['campaignName'] = r.json()[0]['campaign_name']
	# print r.json()
	redeemed = 0
	numberOfFbPosts = 0
	numberOfIgPosts = 0
	likes = 0
	comments = 0
	likes_ig = 0
	comments_ig = 0
	for data in r.json():
		if data['redeemed'] == 1:
			redeemed += 1
		if data['fb_post'] != "":
			numberOfFbPosts += 1
			if data['messenger_id'] in users:
				pass
			else:
				messenger_id_request = requests.get('http://zdash.zyrl.us/token/'+str(data['messenger_id'])+'/')
				if messenger_id_request.status_code == 200:
					facebook_access_token = messenger_id_request.json()['facebook_access_token']
					users[data['messenger_id']] = [data['fb_post'], facebook_access_token]

		if data['ig_post'] != "":
			numberOfIgPosts += 1
			if data['messenger_id'] in users_ig:
				pass
			else:
				messenger_id_request = requests.get('http://zdash.zyrl.us/token/'+str(data['messenger_id'])+'/')
				if messenger_id_request.status_code == 200:
					instagram_access_token = messenger_id_request.json()['instagram_access_token']
					users_ig[data['messenger_id']] = [data['ig_post'], instagram_access_token]

	fbimages = []
	for key, value in users.iteritems():
		image = FacebookImage()
		r = requests.get('https://graph.facebook.com/v2.9/'+str(value[0])+'?fields=full_picture%2Creactions.summary(total_count)%2Ccomments.summary(total_count)&access_token='+str(value[1]))
		# print r.json()
		try:
			image.image = r.json()['full_picture']
			image.reactions = r.json()['reactions']['summary']['total_count']
			likes += image.reactions
			image.comments = r.json()['comments']['summary']['total_count']
			comments += image.comments
		except Exception as e:
			pass

		fbimages.append(image)

	igimages = []
	for key, value in users_ig.iteritems():
		image = InstagramImage()
		r = requests.get('https://api.instagram.com/v1/users/self/media/recent?access_token='+str(value[1]))
		# hi.
		# print r.status_code
		for data in r.json()['data']:
			# print value[0]
			if data['id'] == value[0]:
				# print "matched."
				image.image = data['images']['standard_resolution']['url']
				image.reactions = data['likes']['count']
				likes_ig += image.reactions
				image.comments = data['comments']['count']
				comments_ig += image.comments

				igimages.append(image)
		# image.image = value[0]
		# igimages.append(image)

	context_dict['fbimages'] = fbimages
	context_dict['igimages'] = igimages
	context_dict['redeemed'] = redeemed
	context_dict['numberOfIgPosts'] = numberOfIgPosts
	context_dict['numberOfFbPosts'] = numberOfFbPosts
	context_dict['fbengagement'] = likes+comments
	context_dict['igengagement'] = likes_ig+comments_ig
	context_dict['totalPosts'] = numberOfFbPosts+numberOfIgPosts

	return render(request, "campaign_details.html", context_dict)


import numpy as np
import matplotlib.pyplot as plt

# numbers of dogs
greyhounds = 500
labradors = 500

# lists with weights
grey_height = 28 + 4 * np.random.randn(greyhounds)
lab_height = 24 + 4 * np.random.randn(labradors)

print("# of greyhounds: " + str(len(grey_height)))
print(grey_height)
print("# of labradors: " + str(len(lab_height)))
print(lab_height)

plt.hist([grey_height, lab_height], stacked=False, color=['r','b'])
plt.show()


# emacs: -*- mode: python-mode; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-
# -*- coding: utf-8 -*-
# ex: set sts=4 ts=4 sw=4 noet:
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the datalad package for the
#   copyright and license terms.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Some additional tests for search command (some are within test_base)"""

from mock import patch
from datalad import cfg
from datalad.api import Dataset, install
from nose.tools import assert_equal, assert_raises
from datalad.utils import chpwd
from datalad.tests.utils import assert_in
from datalad.tests.utils import assert_is_generator
from datalad.tests.utils import with_tempfile
from datalad.tests.utils import with_testsui
from datalad.tests.utils import SkipTest
from datalad.support.exceptions import NoDatasetArgumentFound

from datalad.api import search
from datalad.metadata import search as search_mod

from datalad.tests.utils import skip_if_no_network

@with_testsui(interactive=False)
@with_tempfile(mkdir=True)
def test_search_outside1_noninteractive_ui(tdir):
    # we should raise an informative exception
    with chpwd(tdir):
        with assert_raises(NoDatasetArgumentFound) as cme:
            list(search("bu"))
        assert_in('run interactively', str(cme.exception))

@with_tempfile(mkdir=True)
@with_tempfile(mkdir=True)
def test_search_outside1(tdir, newhome):
    with chpwd(tdir):
        # should fail since directory exists, but not a dataset
        # should not even waste our response ;)
        always_render = cfg.obtain('datalad.api.alwaysrender')
        with patch.object(search_mod, 'LOCAL_CENTRAL_PATH', newhome):
            if always_render:
                # we do try to render results which actually causes exception
                # to come right away
                assert_raises(NoDatasetArgumentFound, search, "bu")
            else:
                gen = search("bu")
                assert_is_generator(gen)
                assert_raises(NoDatasetArgumentFound, next, gen)

        # and if we point to some non-existing dataset -- the same in both cases
        # but might come before even next if always_render
        with assert_raises(ValueError):
            next(search("bu", dataset=newhome))

@with_testsui(responses='yes')
@with_tempfile(mkdir=True)
@with_tempfile()
def test_search_outside1_install_central_ds(tdir, central_dspath):
    with chpwd(tdir):
        # let's mock out even actual install/search calls
        with \
            patch.object(search_mod, 'LOCAL_CENTRAL_PATH', central_dspath), \
            patch('datalad.api.install',
                  return_value=Dataset(central_dspath)) as mock_install, \
            patch('datalad.distribution.dataset.Dataset.search',
                  new_callable=_mock_search):
            _check_mocked_install(central_dspath, mock_install)

            # now on subsequent run, we want to mock as if dataset already exists
            # at central location and then do search again
            from datalad.ui import ui
            ui.add_responses('yes')
            mock_install.reset_mock()
            with patch(
                    'datalad.distribution.dataset.Dataset.is_installed',
                    True):
                _check_mocked_install(central_dspath, mock_install)

            # and what if we say "no" to install?
            ui.add_responses('no')
            mock_install.reset_mock()
            with assert_raises(NoDatasetArgumentFound):
                list(search(".", regex=True))

            # and if path exists and is a valid dataset and we say "no"
            Dataset(central_dspath).create()
            ui.add_responses('no')
            mock_install.reset_mock()
            with assert_raises(NoDatasetArgumentFound):
                list(search(".", regex=True))

_mocked_search_results = [
    ('ds1', {'f': 'v'}),
    ('d2/ds2', {'f1': 'v1'})
]

class _mock_search(object):
    def __call__(*args, **kwargs):
        for loc, report in _mocked_search_results:
            yield loc, report

def _check_mocked_install(central_dspath, mock_install):
    gen = search(".", regex=True)
    assert_is_generator(gen)
    # we no longer do any custom path tune up from the one returned by search
    # so should match what search returns
    assert_equal(
        list(gen), [(loc, report)
                    for loc, report in _mocked_search_results])
    mock_install.assert_called_once_with(central_dspath, source='///')

@skip_if_no_network
@with_tempfile
def test_our_metadataset_search(tdir):
    # smoke test for basic search operations on our super-megadataset
    # expensive operation but ok
    ds = install(path=tdir, source="///")
    assert list(ds.search('.', report='*', regex=True))
    assert list(ds.search('.', report='*'))
    assert list(ds.search('.', report_matched=True))

    # and either we could provide output in different formats
    import simplejson
    from datalad.utils import swallow_outputs
    from datalad.api import search_
    with swallow_outputs() as cmo:
        assert list(search_('.', report='*', regex=True, format='json', dataset=ds))
        out = cmo.out
    # since this one is just absorbs all first, we can't go one by one
    assert simplejson.loads(out)

    try:
        import yaml
    except ImportError:
        raise SkipTest("no yaml module")
    with swallow_outputs() as cmo:
        assert list(search_('.', report='*', regex=True, format='yaml', dataset=ds))
        out = cmo.out
    assert yaml.load(out)

@with_tempfile
def test_search_non_dataset(tdir):
    from datalad.support.gitrepo import GitRepo
    GitRepo(tdir, create=True)
    with assert_raises(NoDatasetArgumentFound) as cme:
        list(search('smth', dataset=tdir))
    # Should instruct user how that repo could become a datalad dataset
    assert_in("datalad create --force", str(cme.exception))


from abc import ABC, abstractmethod
from typing import Dict, Tuple

import numpy as np
from jax.config import config
from jax_md import space
from ase.atoms import Atoms
from ase.calculators.abc import GetPropertiesMixin
from ase.calculators.calculator import compare_atoms, PropertyNotImplementedError
from asax import utils, jax_utils

class Calculator(GetPropertiesMixin, ABC):
    implemented_properties = ["energy", "forces"]

    displacement: space.DisplacementFn
    shift: space.ShiftFn
    potential: jax_utils.PotentialFn

    def __init__(self, x64=True):
        self.x64 = x64
        config.update("jax_enable_x64", self.x64)

        self.atoms: Atoms = None
        self.results = {}

    def update(self, atoms: Atoms):
        if atoms is None and self.atoms is None:
            raise RuntimeError("Need an Atoms object to do anything!")

        if self.atoms is None:
            self.atoms = atoms.copy()
            self.results = {}
            self.on_atoms_changed()
            self.setup()
            return

        changes = compare_atoms(self.atoms, atoms)
        if not changes:
            return

        # cache not empty and we got a new atom that has changes
        # => clear results, clear cache, re-run update function to write new atom to cache
        self.results = {}
        if "cell" in changes:
            # TODO: Does this include switches from bulk to molecules?
            # => displacement only requires re-initialization if this is the case
            self.atoms = None
            self.update(atoms)
            return

        if "positions" in changes:
            self.results = self.compute_properties()
            return

        # TODO: Detect changes in atom count/shape
        # => potential only requires re-initialization if this is the case

        # there are changes, but not within the cell.
        # => clear results, but write directly to the cache without copying.
        # TODO: why this?
        self.atoms = atoms
        self.on_atoms_changed()
        self.setup()

    @abstractmethod
    def on_atoms_changed(self):
        """Called whenever a new atoms object is passed so that child classes can react accordingly."""
        pass

    def setup(self):
        self.displacement, self.shift = self.get_displacement(self.atoms)
        self.potential = self.get_potential()

    def get_displacement(self, atoms: Atoms):
        if not all(atoms.get_pbc()):
            return space.free()

        box = atoms.get_cell().array
        return space.periodic_general(box, fractional_coordinates=False)

    @property
    def R(self):
        return self.atoms.get_positions()

    @property
    def box(self):
        return self.atoms.get_cell().array

    @abstractmethod
    def get_potential(self):
        pass

    @abstractmethod
    def compute_properties(self) -> Dict:
        """Expected to return a dictionary keyed on (a subset of) implemented_properties"""
        pass

    def calculate(self, atoms=None, **kwargs):
        self.update(atoms)
        self.results = self.compute_properties()

    # ase plumbing

    def get_property(self, name, atoms=None, allow_calculation=True):
        if name not in self.implemented_properties:
            raise PropertyNotImplementedError(f"{name} property not implemented")

        self.update(atoms)

        if name not in self.results:
            if not allow_calculation:
                return None
            self.calculate(atoms=atoms)

        if name not in self.results:
            # For some reason the calculator was not able to do what we want,
            # and that is OK.
            raise PropertyNotImplementedError(
                f"{name} property not present in results!"
            )

        result = self.results[name]
        if isinstance(result, np.ndarray):
            result = result.copy()
        return result

    def get_potential_energy(self, atoms=None):
        return self.get_property(name="energy", atoms=atoms)