import bpy
from .camera import export_camera as export_camera
from .light import export_light as export_light
from .material import export_default_materials as export_default_materials
from .material import export_material as export_material
from .mesh import export_mesh as export_mesh
from .spectral import write_spectral_color
from .settings import export_settings

def is_renderable(scene, ob):
    return (not ob.hide_render)

def renderable_objects(scene):
    return [ob for ob in bpy.data.objects if is_renderable(scene, ob)]

def is_allowed_mesh(ob):
    return (not ob.type in {'META', 'FONT', 'ARMATURE', 'LATTICE', 'EMPTY', 'CAMERA', 'LAMP', 'SPEAKER'})

def write_scene(exporter, pr):
    w = exporter.w
    scene = exporter.scene

    res_x = exporter.render.resolution_x * exporter.render.resolution_percentage * 0.01
    res_y = exporter.render.resolution_y * exporter.render.resolution_percentage * 0.01

    # Exporters
    def export_scene():
        w.write(":name '_from_blender'")
        w.write(":renderWidth %i" % res_x)
        w.write(":renderHeight %i" % res_y)
        w.write(":camera '%s'" % scene.camera.name)

    def export_outputs():
        def start_output(str):
            w.write("(output")
            w.goIn()
            w.write(":name '%s'" % str)
            w.write("(channel")
            w.goIn()

        def end_output():
            w.goOut()
            w.write(")")
            w.goOut()
            w.write(")")

        def raw_output(str):
            start_output(str)
            w.write(":type '%s'" % str)
            end_output()

        rl = scene.render.layers.active
        if rl.use_pass_combined:
            start_output('image')
            w.write(":type 'rgb'")
            w.write(":gamma '%s'" % (scene.pearray.linear_rgb if 'none' else 'srgb'))
            w.write(":mapper 'none'")
            end_output()

        if rl.use_pass_z:
            raw_output('depth')
        if rl.use_pass_normal:
            raw_output('norm')
        if rl.use_pass_vector:
            raw_output('dpdt')
        if rl.use_pass_uv:
            raw_output('uv')
        if rl.use_pass_object_index:
            raw_output('id')
        if rl.use_pass_material_index:
            raw_output('mat')

        rl2 = scene.pearray_layer
        if rl2.aov_ng:
            raw_output('ng')
        if rl2.aov_nx:
            raw_output('nx')
        if rl2.aov_ny:
            raw_output('ny')
        if rl2.aov_p:
            raw_output('p')
        if rl2.aov_dpdu:
            raw_output('dpdu')
        if rl2.aov_dpdv:
            raw_output('dpdv')
        if rl2.aov_dpdw:
            raw_output('dpdw')
        if rl2.aov_dpdx:
            raw_output('dpdx')
        if rl2.aov_dpdy:
            raw_output('dpdy')
        if rl2.aov_dpdz:
            raw_output('dpdz')
        if rl2.aov_t:
            raw_output('t')
        if rl2.aov_q:
            raw_output('q')
        if rl2.aov_samples:
            raw_output('samples')

        if rl2.raw_spectral:
            w.write("(output_spectral")
            w.goIn()
            w.write(":name 'spectral'")
            w.goOut()
            w.write(")")

    def export_background():# TODO: Add texture support
        background_mat_n = exporter.register_unique_name('MATERIAL', '_blender_world_background')

        if exporter.world:
            color = exporter.world.horizon_color
            if color.r > 0 or color.g > 0 or color.b > 0:
                background_spec_n = write_spectral_color(exporter, "%s_spec" % background_mat_n, color)
                w.write("(material")
                w.goIn()

                w.write(":name '%s'" % background_mat_n)
                w.write(":type 'light'")
                w.write(":emission '%s'" % background_spec_n)

                w.goOut()
                w.write(")")

                w.write("(light")
                w.goIn()
                w.write(":type 'env'")
                w.write(":material '%s'" % background_mat_n)
                w.goOut()
                w.write(")")

    # Block
    objs = renderable_objects(scene)

    w.write("(scene")
    w.goIn()

    export_scene()
    w.write("; Settings")
    export_settings(exporter, pr,scene)
    w.write("; Outputs")
    export_outputs()
    w.write("; Default Materials")
    export_default_materials(exporter)
    w.write("; Camera")
    export_camera(exporter, scene.camera)
    w.write("; Background")
    export_background()
    w.write("; Lights")
    for light in objs:
        if light.type == 'LAMP':
            export_light(exporter, light)
    w.write("; Meshes")
    for obj in objs:
        if is_allowed_mesh(obj):
            export_mesh(exporter, obj)
    w.write("; Materials")
    for obj in objs:
        if is_allowed_mesh(obj):
            for m in obj.data.materials:
                export_material(exporter, m)

    w.goOut()
    w.write(")")


import ply.lex as lex

# list of token names
tokens = (
	'SUBJ',
	'CODE',
	'LPAREN',
	'RPAREN',
	'MIN',
	'NUMBER',
	'PERMISSION',
	'OR',
	'FROM',
	'OF',
	'CREDIT',
	'AND',
	'PERIOD',
	'PREREQ',
)

# regular expresion rules for simple tokens
t_SUBJ = r'[A-Z]{4}'
t_CODE = r'[0-9][FP][0-9][0-9]'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_OR = r'\sor\s'
t_FROM = r'\sfrom\s'
t_OF = r'\sof\s'
t_CREDIT = r'\scredits?'
t_AND = r'\sand\s'
t_PERIOD = r'\.'

def t_MIN(t):
	r'minimum\s[0-9][0-9]\spercent'
	t.value = int(t.value.split(' ')[1])
	return t

def t_PREREQ(t):
	r'Prerequisite\(s\)\: '

def t_PERMISSION(t):
	r'permission\sof\sthe\s[A-Za-z]+'
	t.value = t.value.split(' ')[3]
	return t

def t_NUMBER(t):
	r'one-half|one|two|three|four|five|six'
	t.value = ['one-half','one','two','three','four','five','six'].index(t.value)
	return t

# a string containing ignored characters
t_ignore = ','

def t_error(t):
	t.lexer.skip(1)

lexer = lex.lex()

#data = 'Prerequisite(s): MATH 1P12 or permission of the instructor.'
#print(data)

#lexer.input(data)

#for tok in lexer:
#	print(tok)


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

from . import log
from flask import request,render_template
from ..models import Log_host_monitor
from flask.ext.login import login_required

#客户端心跳日志
@log.route('/hosts')
@log.route('/hosts/<int:num>')
@login_required
def heartbeat_log(num = 1):
    site_url = '/log/hosts'

    project_list = [u'id',u'客户端ip',u'时间',u'状态']
    search_select_list = {'all':u'全部',
                          "200":u'在线',
                          "403":u'拒绝',
                          "404":u'ip 不存在',
                          "500":u'离线'}
    search_value = ""
    select_value = "all"
    if 'search' in request.args  and \
            'select' in request.args and \
            request.args.get('select'):
        select_value = request.args.get('select')
        search_value = request.args.get('search')
        if select_value == 'all':
            pagination = Log_host_monitor.query.\
                order_by(-Log_host_monitor.id).\
                filter(Log_host_monitor.client_ip.ilike('%'+search_value+'%'))\
                .order_by(-Log_host_monitor.id)\
                .paginate(num, 20, True)
        else:
            pagination = Log_host_monitor.query.\
                order_by(-Log_host_monitor.id).\
                filter(Log_host_monitor.client_ip.ilike('%'+search_value+'%'),
                       Log_host_monitor.status.ilike('%'+select_value+'%'))\
                .order_by(-Log_host_monitor.id)\
                .paginate(num, 20, True)

    else:
        pagination = Log_host_monitor.query.\
            order_by(-Log_host_monitor.id).\
            paginate(num, 20, True)
    posts = pagination.items
    return render_template('log/hosts.html',
                            site_url=site_url,
                            project_list=project_list,
                            search_select_list=search_select_list,
                            posts=posts,
                            pagination=pagination,
                            search_value=search_value,
                            select_value=select_value)


from PIL import Image, ImageOps
import os

# creates an image of the Mandelbrot set
res = 400

for iters in range(50):
    img = Image.new("L", (res, res), 255)
    for im in range(res):
        for re in range(res):
            z = 0
            # a scaling to show the "interesting" part of
            # the Mandelbrot fractal
            c = (re*2/res-1.5)+1j*(im*2/res-1)
            for k in range(iters):
                z = z**2+c
                if abs(z)>2:
                    img.putpixel((re, im), 255-k*255/iters)
                    break

    # create a uniform distribution of gray levels
    img = ImageOps.equalize(img)

    # save to file
    img.save('../images/mandelbrot_%04d.png' % iters, dpi=(150,150))

last_path = os.getcwd()

# handle Linux/Mac and Windows properly
os.chdir('../images')
if os.sys.platform.startswith('win'):
    mee = 'c:/mplayer/mencoder '
    mep = 'c:/mplayer/mplayer '
else:
    mee = 'mplayer '
    mec = 'c:/mplayer '

# encode the movie
os.system(mee+'mf://mandelbrot*.png -mf type=png -ovc lavc -o mandelbrot.avi')

# play the movie
os.system(mep+'mandelbrot.avi')
os.chdir(last_path)


import yaml
import pytest
from unittest import mock
from argparse import Namespace

from mlagents.trainers.upgrade_config import convert_behaviors, main, remove_nones
from mlagents.trainers.settings import (
    TrainerType,
    PPOSettings,
    SACSettings,
    RewardSignalType,
)

BRAIN_NAME = "testbehavior"

# Check one per category
BATCH_SIZE = 256
HIDDEN_UNITS = 32
SUMMARY_FREQ = 500

PPO_CONFIG = f"""
    default:
        trainer: ppo
        batch_size: 1024
        beta: 5.0e-3
        buffer_size: 10240
        epsilon: 0.2
        hidden_units: 128
        lambd: 0.95
        learning_rate: 3.0e-4
        learning_rate_schedule: linear
        max_steps: 5.0e5
        memory_size: 256
        normalize: false
        num_epoch: 3
        num_layers: 2
        time_horizon: 64
        sequence_length: 64
        summary_freq: 10000
        use_recurrent: false
        vis_encode_type: simple
        reward_signals:
            extrinsic:
                strength: 1.0
                gamma: 0.99

    {BRAIN_NAME}:
        trainer: ppo
        batch_size: {BATCH_SIZE}
        beta: 5.0e-3
        buffer_size: 64
        epsilon: 0.2
        hidden_units: {HIDDEN_UNITS}
        lambd: 0.95
        learning_rate: 5.0e-3
        max_steps: 2500
        memory_size: 256
        normalize: false
        num_epoch: 3
        num_layers: 2
        time_horizon: 64
        sequence_length: 64
        summary_freq: {SUMMARY_FREQ}
        use_recurrent: false
        reward_signals:
            curiosity:
                strength: 1.0
                gamma: 0.99
                encoding_size: 128
    """

SAC_CONFIG = f"""
    default:
        trainer: sac
        batch_size: 128
        buffer_size: 50000
        buffer_init_steps: 0
        hidden_units: 128
        init_entcoef: 1.0
        learning_rate: 3.0e-4
        learning_rate_schedule: constant
        max_steps: 5.0e5
        memory_size: 256
        normalize: false
        num_update: 1
        train_interval: 1
        num_layers: 2
        time_horizon: 64
        sequence_length: 64
        summary_freq: 10000
        tau: 0.005
        use_recurrent: false
        vis_encode_type: simple
        reward_signals:
            extrinsic:
                strength: 1.0
                gamma: 0.99

    {BRAIN_NAME}:
        trainer: sac
        batch_size: {BATCH_SIZE}
        buffer_size: 64
        buffer_init_steps: 100
        hidden_units: {HIDDEN_UNITS}
        init_entcoef: 0.01
        learning_rate: 3.0e-4
        max_steps: 1000
        memory_size: 256
        normalize: false
        num_update: 1
        train_interval: 1
        num_layers: 1
        time_horizon: 64
        sequence_length: 64
        summary_freq: {SUMMARY_FREQ}
        tau: 0.005
        use_recurrent: false
        curiosity_enc_size: 128
        demo_path: None
        vis_encode_type: simple
        reward_signals:
            curiosity:
                strength: 1.0
                gamma: 0.99
                encoding_size: 128
    """

@pytest.mark.parametrize("use_recurrent", [True, False])
@pytest.mark.parametrize("trainer_type", [TrainerType.PPO, TrainerType.SAC])
def test_convert_behaviors(trainer_type, use_recurrent):
    if trainer_type == TrainerType.PPO:
        trainer_config = PPO_CONFIG
        trainer_settings_type = PPOSettings
    elif trainer_type == TrainerType.SAC:
        trainer_config = SAC_CONFIG
        trainer_settings_type = SACSettings

    old_config = yaml.load(trainer_config)
    old_config[BRAIN_NAME]["use_recurrent"] = use_recurrent
    new_config = convert_behaviors(old_config)

    # Test that the new config can be converted to TrainerSettings w/o exceptions
    trainer_settings = new_config[BRAIN_NAME]

    # Test that the trainer_settings contains the settings for BRAIN_NAME and
    # the defaults where specified
    assert trainer_settings.trainer_type == trainer_type
    assert isinstance(trainer_settings.hyperparameters, trainer_settings_type)
    assert trainer_settings.hyperparameters.batch_size == BATCH_SIZE
    assert trainer_settings.network_settings.hidden_units == HIDDEN_UNITS
    assert RewardSignalType.CURIOSITY in trainer_settings.reward_signals

@mock.patch("mlagents.trainers.upgrade_config.convert_behaviors")
@mock.patch("mlagents.trainers.upgrade_config.remove_nones")
@mock.patch("mlagents.trainers.upgrade_config.write_to_yaml_file")
@mock.patch("mlagents.trainers.upgrade_config.parse_args")
@mock.patch("mlagents.trainers.upgrade_config.load_config")
def test_main(mock_load, mock_parse, yaml_write_mock, remove_none_mock, mock_convert):
    test_output_file = "test.yaml"
    mock_load.side_effect = [
        yaml.safe_load(PPO_CONFIG),
        "test_curriculum_config",
        "test_sampler_config",
    ]
    mock_args = Namespace(
        trainer_config_path="mock",
        output_config_path=test_output_file,
        curriculum="test",
        sampler="test",
    )
    mock_parse.return_value = mock_args
    mock_convert.return_value = "test_converted_config"
    dict_without_nones = mock.Mock(name="nonones")
    remove_none_mock.return_value = dict_without_nones

    main()
    saved_dict = remove_none_mock.call_args[0][0]
    # Check that the output of the remove_none call is here
    yaml_write_mock.assert_called_with(dict_without_nones, test_output_file)
    assert saved_dict["behaviors"] == "test_converted_config"
    assert saved_dict["curriculum"] == "test_curriculum_config"
    assert saved_dict["parameter_randomization"] == "test_sampler_config"

def test_remove_nones():
    dict_with_nones = {"hello": {"hello2": 2, "hello3": None}, "hello4": None}
    dict_without_nones = {"hello": {"hello2": 2}}
    output = remove_nones(dict_with_nones)
    assert output == dict_without_nones


# David Dewhurst

from __future__ import print_function
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

def moving_average(array, order):
	"""moving_average(array, order):
	calculates a moving average of array
	to the specified order

    Args:
        array (1-d array): array of data of which you want the moving average
        order (int): the order of which you want a moving average

    Returns:
        ret: The moving average of the array calculated to the correct order

    """
	ret = np.cumsum(array, dtype=float)
	ret[order:] = ret[order:] - ret[:-order]
	return ret[order - 1:] / order

def historical_volatility(array, num_days=252):
	"""historical volatility(array, num_days=252):
	calculates the historical volatility of a security

	Args:
		array (1-d array): an array of security prices
		num_days (int, optional): the number of days over which you want to
		calculuate the historical volatility. Default is 252 (252 trading
		days in a year) but 360 and 365 are also common

	Returns:
		the historical volatility of the security

	"""
	log_daily_returns = [np.log(array[i] / array[i-1]) for i in range(1,
		len(array))]
	return np.sqrt(num_days * np.var(log_daily_returns))

class time_series_viz(object):
	"""time_series_viz(object)
	A time series visualization class that provides limited methods by which
	to visualize multiple time series of similar time scale on the same axis

	Initialization:

		arrays (numpy array): should be a timesteps x number_of_series nd
		array. Use numpy.column_stack((array1, array2, array3)) to create

	Methods:

		standalone_display
		Displays visualization in a standalone manner without assuming
		other axes are present.

		Args:
			labels (array, optional): ['x-axis', 'y-axis']
			save (boolean, optional): True saves the figure, False does not
			save. Default is not to save the figure and instead show it on
			screen
			savename (string, optional): string to save the plot as.
			Should include the file type, e.g., 'picture.png'

		append_to_plot
		Appends the visualization to an already-created figure

		Args:
			axes (matplotlib.pyplot axes object): a set of axes to which to
			append the plot
			labels (array, optional): ['x-axis', 'y-axis']
	"""

	def __init__(self, arrays):
		self.ts = arrays

	def standalone_display(self, labels=None, save=False, savename=None):
		fig = plt.figure()
		ax = fig.add_subplot(1, 1, 1)
		try:
			ax.hold(True)
			[ax.plot(range(self.ts.shape[0]),
			 self.ts[:, i]) for i in range(self.ts.shape[-1])]
		except IndexError:
			ax.plot(range(self.ts.shape[0]), self.ts,
				'k-')

		ax.set_xticks([])

		if labels is not None:
			try:
				ax.set_xlabel(labels[0])
				ax.set_ylabel(labels[1])
			except:
				raise(IOError, 'labels specified incorrectly')

		if save is False:
			plt.show()
		elif save is True:
			assert(type(savename) is str)
			plt.savefig(savename)

	def append_to_plot(self, axes, labels=None):
		try:
			axes.hold(True)
			[axes.plot(range(self.ts.shape[0]),
			 self.ts[:, i]) for i in range(self.ts.shape[-1])]
		except IndexError:
			axes.plot(range(self.ts.shape[0]), self.ts,
				'k-')

		if labels is not None:
			try:
				axes.set_xlabel(labels[0])
				axes.set_ylabel(labels[1])
			except:
				raise(IOError, 'labels specified incorrectly')

def high_low_strike_prices(array, prop=0.1):
	""" calculates a "high" and "low" strike price for an option
	on an asset for heuristic use in genetic programming

	Args:
		array (np array): array of security price data
		prop (float, optional): proportion up (down) the high (low) price
		should be

	Returns:
		high (np array): array of high strike prices
		low (np array): array of low strike prices
	"""
	high = [(1. + prop) * price for price in array]
	low = [(1. - prop) * price for price in array]
	return np.asarray(high), np.asarray(low)

def jensen_shannon_divergence(p, q):
	""" calculates the jensen-shannon divergence of two distributions

	Args:
		p (array): probability distribution
		q (array): probability distribution

	Returns:
		jensen shannon divergence of the distributions
	"""
	p = np.asarray(p)
	q = np.asarray(q)
	m = 0.5 * (p + q)
	return 0.5 * (stats.entropy(p, m) + stats.entropy(q, m))


import OpenSSL
import base64
import json
import hashlib

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

key = OpenSSL.crypto.PKey()
key.generate_key(type=OpenSSL.crypto.TYPE_RSA,bits=2048)
priv = key.to_cryptography_key()
pub = priv.public_key()

header = {
    "alg":"RS256",
    "jwk":  {
            "kty":"RSA",
            "kid":"bilbo.baggins@hobbiton.example",
            "use":"sig"#,
            # "n":"n4EPtAOCc9Alke...........rNP5zw",
            # "e":"AQAB"
            }
}

e = pub.public_numbers().e
n = pub.public_numbers().n

header["jwk"]["e"] = base64.urlsafe_b64encode((e).to_bytes((e).bit_length()//8+1,byteorder='big')).decode('utf8').rstrip("=")
header["jwk"]["n"] = base64.urlsafe_b64encode((n).to_bytes((n).bit_length()//8+1,byteorder='big')).decode('utf8').rstrip("=")
payload = "YWRtaW4"

str = base64.urlsafe_b64encode(bytes(json.dumps(header), encoding='utf8')).decode('utf8').rstrip("=")+"."+payload

sig = priv.sign(bytes(str, encoding='utf8'), algorithm=hashes.SHA256(), padding=padding.PKCS1v15())

print(str+"."+base64.urlsafe_b64encode(sig).decode('utf8').rstrip("="))


# -*- coding: utf-8 -*-
from django import forms
from .models import *
from tinymce.widgets import TinyMCE

class SendMessageForm(forms.ModelForm):
    class Meta:
        model = Message
        exclude = [
            'read',
            'read_at',
            'sender',
            'receiver',
        ]
        widgets = {
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'body': TinyMCE(attrs={'class': 'form-control'})
        }

class MessageAttachmentsForm(forms.ModelForm):
    class Meta:
        model = Attachments
        fields = ['attachment']
        widgets = {
            'attachment': forms.FileInput(attrs={'class': 'form-control', 'multiple': 'multiple'})
        }

class ReplyMessageForm(forms.ModelForm):
    class Meta:
        model = Message
        exclude = [
            'read',
            'read_at',
            'sender',
            'receiver',
            'title',
        ]
        widgets = {
            'body': TinyMCE(attrs={'class': 'form-control'})
        }

class ForwardMessageForm(forms.ModelForm):
    class Meta:
        model = Message
        exclude = [
            'read',
            'read_at',
            'sender',
            'receiver',
            'title',
        ]
        widgets = {
            'body': TinyMCE(attrs={'class': 'form-control'})
        }


#! /usr/bin/env python3

__all__ = [
    'track_and_calc_colors'
]

from typing import List, Optional, Tuple

import cv2
import numpy as np

from corners import (CornerStorage, FrameCorners)
from data3d import CameraParameters, PointCloud, Pose
import frameseq
from _camtrack import (
    PointCloudBuilder,
    create_cli,
    calc_point_cloud_colors,
    to_opencv_camera_mat3x3,
    view_mat3x4_to_pose,
    triangulate_correspondences,
    TriangulationParameters,
    build_correspondences,
    pose_to_view_mat3x4,
    calc_inlier_indices,
    rodrigues_and_translation_to_view_mat3x4,
    eye3x4,
    check_baseline,
    get_baseline,
    _remove_correspondences_with_ids)

class TrackingError(Exception):
    pass

class CameraTracker:
    def __init__(self, intrinsic_mat, corner_storage, known_view_1, known_view_2):
        self.intrinsic_mat = intrinsic_mat
        self.corner_storage = corner_storage
        frame_num_1 = known_view_1[0]
        frame_num_2 = known_view_2[0]
        self.pc_builder = PointCloudBuilder()
        view_matr_1 = pose_to_view_mat3x4(known_view_1[1])
        view_matr_2 = pose_to_view_mat3x4(known_view_2[1])

        self.tracked_views = [eye3x4()] * len(self.corner_storage)
        self.tracked_views[frame_num_1] = view_matr_1
        self.tracked_views[frame_num_2] = view_matr_2
        self.initial_baseline = get_baseline(view_matr_1, view_matr_2)
        print("initial baseline =", self.initial_baseline)

        self._add_points_from_frame(frame_num_1, frame_num_2, initial_triangulation=True)
        self.min_init_frame = min(frame_num_1, frame_num_2)
        self.max_init_frame = max(frame_num_1, frame_num_2)
        self.outliers = set()

    def _get_pos(self, frame_number) -> np.ndarray:
        corners = self.corner_storage[frame_number]
        _, pts_ids, corners_ids = np.intersect1d(self.pc_builder.ids, corners.ids, assume_unique=True,
                                                 return_indices=True)

        common_pts_3d = self.pc_builder.points[pts_ids]
        common_ids = self.pc_builder.ids[pts_ids]
        common_corners = corners.points[corners_ids]
        inlier_mask = np.zeros_like(common_pts_3d, dtype=np.bool)
        inlier_counter = 0
        for common_id, mask_elem in zip(common_ids[:, 0], inlier_mask):
            if common_id not in self.outliers:
                mask_elem[:] = True
                inlier_counter += 1
        if inlier_counter > 7:
            common_pts_3d = common_pts_3d[inlier_mask].reshape(-1, 3)
            common_ids = common_ids[inlier_mask[:, :1]].reshape(-1, 1)
            common_corners = common_corners[inlier_mask[:, :2]].reshape(-1, 2)
        max_reproj_error = 3.0
        if len(common_pts_3d) < 4:
            raise TrackingError('Not enough points to solve RANSAC on frame ' + str(frame_number))
        _, rot_vec, tr_vec, inliers = cv2.solvePnPRansac(common_pts_3d,
                                                         common_corners,
                                                         self.intrinsic_mat,
                                                         None,
                                                         reprojectionError=max_reproj_error,
                                                         flags=cv2.SOLVEPNP_EPNP)
        extrinsic_mat = rodrigues_and_translation_to_view_mat3x4(rot_vec, tr_vec)
        proj_matr = self.intrinsic_mat @ extrinsic_mat
        if inliers is None:
            raise TrackingError('Failed to solve PnP on frame' + str(frame_number))

        while len(inliers) < 8 and max_reproj_error < 50:
            max_reproj_error *= 1.2
            inliers = calc_inlier_indices(common_pts_3d, common_corners, proj_matr, max_reproj_error)
        inlier_pts = common_pts_3d[inliers]
        inlier_corners = common_corners[inliers]
        outlier_ids = np.setdiff1d(common_ids, common_ids[inliers], assume_unique=True)
        self.outliers.update(outlier_ids)
        if len(inliers) < 4:
            inlier_pts = common_pts_3d
            inlier_corners = common_corners
        print('Found position on', len(inlier_corners), 'inliers')
        _, rot_vec, tr_vec, inliers = cv2.solvePnPRansac(inlier_pts, inlier_corners, self.intrinsic_mat, None,
                                                         rot_vec, tr_vec, useExtrinsicGuess=True)
        return rodrigues_and_translation_to_view_mat3x4(rot_vec, tr_vec)

    def _add_points_from_frame(self,
                               frame_num_1: int,
                               frame_num_2: int,
                               initial_triangulation: bool = False) -> int:
        corners_1 = self.corner_storage[frame_num_1]
        corners_2 = self.corner_storage[frame_num_2]
        correspondences = build_correspondences(corners_1, corners_2, ids_to_remove=self.pc_builder.ids)
        if len(correspondences.ids) > 0:
            max_reproj_error = 1.0
            min_angle = 1.0
            view_1 = self.tracked_views[frame_num_1]
            view_2 = self.tracked_views[frame_num_2]
            triangulation_params = TriangulationParameters(max_reproj_error, min_angle, 0)
            pts_3d, triangulated_ids, med_cos = triangulate_correspondences(correspondences, view_1,
                                                                            view_2, self.intrinsic_mat,
                                                                            triangulation_params)
            if initial_triangulation:
                num_iter = 0
                while len(pts_3d) < 8 and len(correspondences.ids) > 7 and num_iter < 100:
                    max_reproj_error *= 1.2
                    min_angle *= 0.8
                    triangulation_params = TriangulationParameters(max_reproj_error, min_angle, 0)
                    pts_3d, triangulated_ids, med_cos = triangulate_correspondences(correspondences, view_1,
                                                                                view_2, self.intrinsic_mat,
                                                                                triangulation_params)
                    num_iter += 1

                if num_iter >= 100 and len(pts_3d) < 4:
                    raise TrackingError('Failed to triangulate enough points')
            self.pc_builder.add_points(triangulated_ids, pts_3d)

            return len(pts_3d)
        elif initial_triangulation:
            raise TrackingError('Not found correspondences on image pair')
        else:
            return 0

    def track(self):
        curr_frame = self.min_init_frame + 1
        seq_size = len(self.corner_storage)
        for _ in range(2, seq_size):
            if curr_frame == self.max_init_frame:
                curr_frame += 1
            if curr_frame >= seq_size:
                curr_frame = self.min_init_frame - 1
                self.outliers = set()
            print('Frame', curr_frame)
            try:
                self.tracked_views[curr_frame] = self._get_pos(curr_frame)
            except TrackingError as error:
                print(error)
                print('Stopping tracking')
                break
            prev_curr_diff = 5
            num_pairs = 0
            num_added = 0
            while num_pairs < 5:
                prev_frame = \
                    curr_frame - prev_curr_diff if curr_frame > self.min_init_frame else curr_frame + prev_curr_diff
                prev_curr_diff += 1
                if prev_frame < seq_size and (self.min_init_frame <= prev_frame or curr_frame < self.min_init_frame):
                    if check_baseline(self.tracked_views[prev_frame], self.tracked_views[curr_frame],
                                      self.initial_baseline * 0.15):
                        num_added += self._add_points_from_frame(prev_frame, curr_frame)
                        num_pairs += 1
                else:
                    break
            print('Added', num_added, 'points')
            print('Point cloud size = ', len(self.pc_builder.ids))
            if curr_frame > self.min_init_frame:
                curr_frame += 1
            else:
                curr_frame -= 1

        return self.tracked_views, self.pc_builder

def _test_frame_pair(intrinsic_mat: np.ndarray,
                     corners_1: FrameCorners,
                     corners_2: FrameCorners,
                     param_koeff: float = 1) -> Tuple[int, Optional[Pose]]:
    correspondences = build_correspondences(corners_1, corners_2)
    if len(correspondences.ids) < 6:
        return 0, None
    points2d_1 = correspondences.points_1
    points2d_2 = correspondences.points_2

    essential, essential_inliers = cv2.findEssentialMat(points2d_1, points2d_2, intrinsic_mat, threshold=param_koeff)
    homography, homography_inliers = cv2.findHomography(points2d_1, points2d_2, method=cv2.RANSAC)
    if len(np.where(homography_inliers > 0)[0]) > len(np.where(essential_inliers > 0)[0]):
        return 0, None
    if essential.shape != (3, 3):
        return 0, None
    num_passed, rot, t, mask = cv2.recoverPose(essential, points2d_1, points2d_2,
                                               intrinsic_mat, mask=essential_inliers)

    outlier_ids = np.array(
        [pt_id for pt_id, mask_elem in zip(correspondences.ids, mask) if mask_elem[0] == 0],
        dtype=correspondences.ids.dtype)
    inlier_correspondences = _remove_correspondences_with_ids(correspondences, outlier_ids)
    if len(inlier_correspondences.ids) < 4:
        return 0, None
    view_matr_1 = eye3x4()
    view_matr_2 = np.hstack((rot, t))
    triangulation_params = TriangulationParameters(param_koeff, 1.0 / param_koeff, 0.0)
    pts_3d, trianulated_ids, med_cos = triangulate_correspondences(inlier_correspondences, view_matr_1, view_matr_2,
                                                                   intrinsic_mat, triangulation_params)
    if len(pts_3d) < 4:
        return 0, None
    print(len(inlier_correspondences.ids), len(pts_3d))
    return len(pts_3d), view_mat3x4_to_pose(view_matr_2)

def _find_pos_pair(intrinsic_mat: np.ndarray,
                   corner_storage: CornerStorage,
                   param_koeff: float = 1) -> Tuple[Tuple[int, Pose], Tuple[int, Pose]]:
    best_num_pts = 0
    best_frame = 1
    best_pose = None
    for frame_number in range(1, len(corner_storage)):
        print(frame_number)
        num_pts, pose = _test_frame_pair(intrinsic_mat, corner_storage[0], corner_storage[frame_number])
        if num_pts > best_num_pts:
            best_num_pts = num_pts
            best_pose = pose
            best_frame = frame_number
    if best_pose is None:
        if param_koeff < 4:
            return _find_pos_pair(intrinsic_mat, corner_storage, param_koeff * 2)
        raise TrackingError("Failed to initialize tracking")
    return (0, view_mat3x4_to_pose(eye3x4())), (best_frame, best_pose)

def track_and_calc_colors(camera_parameters: CameraParameters,
                          corner_storage: CornerStorage,
                          frame_sequence_path: str,
                          known_view_1: Optional[Tuple[int, Pose]] = None,
                          known_view_2: Optional[Tuple[int, Pose]] = None) \
        -> Tuple[List[Pose], PointCloud]:
    rgb_sequence = frameseq.read_rgb_f32(frame_sequence_path)
    intrinsic_mat = to_opencv_camera_mat3x3(
        camera_parameters,
        rgb_sequence[0].shape[0]
    )
    view_mats, point_cloud_builder = [eye3x4()] * len(corner_storage), PointCloudBuilder()

    try:
        known_view_1, known_view_2 = _find_pos_pair(intrinsic_mat, corner_storage)
        tracker = CameraTracker(intrinsic_mat, corner_storage, known_view_1, known_view_2)
        view_mats, point_cloud_builder = tracker.track()
    except TrackingError as error:
        print(error)
        print('Poses and point cloud are not calculated')

    calc_point_cloud_colors(
        point_cloud_builder,
        rgb_sequence,
        view_mats,
        intrinsic_mat,
        corner_storage,
        5.0
    )
    point_cloud = point_cloud_builder.build_point_cloud()
    poses = list(map(view_mat3x4_to_pose, view_mats))
    return poses, point_cloud

if __name__ == '__main__':
    # pylint:disable=no-value-for-parameter
    create_cli(track_and_calc_colors)()


import torch
import torch.nn as nn
from torch_geometric.nn import MessagePassing
from torch_geometric.utils import degree

class HeterogeneousAggregationLayer(MessagePassing):
    def __init__(self, user_dim, event_dim, user_out_dim, event_out_dim, num_user, num_event, device):
        super(HeterogeneousAggregationLayer, self).__init__(aggr='add', )
        self.user_linear = nn.Linear(user_dim, user_out_dim)
        self.event_linear = nn.Linear(event_dim, event_out_dim)
        self.num_user = num_user
        self.user_norm = nn.LayerNorm(user_out_dim)
        self.event_norm = nn.LayerNorm(user_out_dim)
        self.num_event = num_event
        self.device = device
        self.to(device)

    def forward(self, x, edge_index):
        x['event'] = self.event_linear(x['event'])
        x['user'] = self.user_linear(x['user'])

        x['user'], x['event'] = self.propagate(edge_index=edge_index, x=(x['event'], x['user']), size=(self.num_event, self.num_user)) + x[
            'user'], self.propagate(edge_index=edge_index[[1, 0]], x=(x['user'], x['event']), size=(self.num_user, self.num_event)) + x['event']
        x['event'], x['user'] = x['event'] / (degree(edge_index[0], num_nodes=self.num_event) + 1).unsqueeze(1),\
                                x['user'] / (degree(edge_index[1], num_nodes=self.num_user) + 1).unsqueeze(1)

        return x

class HeterogeneousAggregationLayers(nn.Module):
    def __init__(self, in_dim_dic, mid_dim_dic, out_dim_dic, num_user, num_event, device):
        super(HeterogeneousAggregationLayers, self).__init__()
        self.hal0 = HeterogeneousAggregationLayer(in_dim_dic['user'], in_dim_dic['event'], mid_dim_dic['user'],
                                                  mid_dim_dic['event'], num_user, num_event, device)
        self.hal1 = HeterogeneousAggregationLayer(mid_dim_dic['user'], mid_dim_dic['event'], out_dim_dic['user'],
                                                  out_dim_dic['event'], num_user, num_event, device)

    def forward(self, x, edge_index):

        x = self.hal0(x,edge_index)

        x = self.hal1(x, edge_index)
        return x

class SequenceMaskedSoftmax(nn.Module):
    def __init__(self,device):
        super(SequenceMaskedSoftmax, self).__init__()
        self.eps = 1e-45
        self.softmax = nn.Softmax(dim=-1)
        self.device = device

    def forward(self, inputs, seq):
        for i in range(seq.shape[1] -1):
            mask = torch.zeros((inputs.shape[0], inputs.shape[-1]), dtype=torch.float).to(self.device).scatter_(-1, seq[:, i:].sort()[0], 1)
            inputs[:, i, :] = inputs[:, i, :] + (mask + self.eps).log()
        inputs = self.softmax(inputs)
        return inputs

class SequencePredictionLayer(nn.Module):
    def __init__(self, num_user, num_event, input_size, hidden_size, num_layers,device,use_softmax=False):
        super(SequencePredictionLayer, self).__init__()
        self.use_softmax = use_softmax
        self.gru = nn.GRU(input_size, hidden_size, num_layers)
        self.linear = nn.Linear(hidden_size, num_user)
        if use_softmax:
            self.softmax = nn.Softmax(dim=-1)
        else:
            self.softmax = SequenceMaskedSoftmax(device)
        self.num_layers = num_layers
        self.start = nn.Parameter(torch.randn((1,input_size), dtype=torch.float))
        self.to(device)

    def forward(self, x, ids, sequence):
        hx = nn.functional.embedding(ids,x['event']).unsqueeze(0).repeat(self.num_layers,1,1)
        start = self.start.unsqueeze(0).repeat(1,sequence.shape[0],1)
        x = nn.functional.embedding(sequence, x['user']).transpose(0,1)
        x = torch.cat([start,x], dim=0)
        x, _ = self.gru(x,hx)
        x = self.linear(x).transpose(0,1)
        if self.use_softmax:
            x = self.softmax(x)
        else:
            x = self.softmax(x,sequence)

        return x

    def test(self, feature_dic, ids, sequence):

        hx = nn.functional.embedding(ids, feature_dic['event']).unsqueeze(0).repeat(self.num_layers, 1, 1)
        x = self.start.unsqueeze(0).repeat(1, sequence.shape[0], 1)
        x, hx = self.gru(x, hx)
        x = self.linear(x).squeeze(0)
        x = x.gather(dim=-1, index=sequence).sort(descending=True)[1]
        sequence = sequence.gather(dim=-1, index=x)
        for i in range(0, sequence.shape[1]-1):
            x = nn.functional.embedding(sequence[:,i:i+1], feature_dic['user']).transpose(0, 1)
            x, hx = self.gru(x, hx)
            x = self.linear(x).squeeze(0)
            x = x.gather(dim=-1, index=sequence[:,i+1:]).sort(descending=True)[1]
            sequence[:,i+1:] = sequence[:,i+1:].gather(dim=-1,index=x)
        return sequence

class EPSGF(nn.Module):
    def __init__(self, num_node_dic,num_feature_dic, mid_size, out_size,input_size,device):

        super(EPSGF, self).__init__()

        self.in_dim_dic = num_feature_dic
        self.mid_dim_dic = {'event': mid_size, 'user': mid_size}
        self.out_dim_dic = {'event': out_size, 'user': out_size}

        self.hals = HeterogeneousAggregationLayers(self.in_dim_dic, self.mid_dim_dic, self.out_dim_dic, num_node_dic['user'],
                                                       num_node_dic['event'], device)
        self.sequence_prediction_layer = SequencePredictionLayer(num_node_dic['user'], num_node_dic['event'], out_size,
                                                                 out_size, 1, device)

        self.user_embedding =  nn.Parameter(torch.randn((num_node_dic['user'], input_size), dtype=torch.float).to(device))
        self.device =device
        self.to(device)

    def forward(self, raw_feature,batch_size,edge_index, ids, sequence):
        raw_feature = self.hals(raw_feature, edge_index)
        raw_feature['user'] = self.user_embedding

        raw_feature = self.sequence_prediction_layer(raw_feature, ids, sequence)
        return raw_feature

    @torch.no_grad()
    def test(self, raw_feature,batch_size,edge_index, ids, sequence):
        raw_feature = self.hals(raw_feature, edge_index)
        raw_feature['user'] = self.user_embedding
        return self.sequence_prediction_layer.test(raw_feature,ids,sequence)

    @torch.no_grad()
    def get_embedding(self, raw_feature, edge_index):

        raw_feature = self.hals(raw_feature, edge_index)
        return raw_feature['event']

class EPSGF_MLP(EPSGF):
    def __init__(self,num_node_dic,num_feature_dic, mid_size, out_size,input_size,device):

        super(EPSGF_MLP, self).__init__(num_node_dic,num_feature_dic, mid_size, out_size,input_size,device)
        self.linear = nn.Linear(num_feature_dic['event'], out_size)
        self.activation = nn.ReLU()
        self.hals = None
        self.to(device)

    def forward(self, raw_feature,batch_size,edge_index, ids, sequence):
        raw_feature = {'user': self.user_embedding, 'event': self.activation(self.linear(raw_feature['event']))}
        raw_feature = self.sequence_prediction_layer(raw_feature, ids, sequence)
        return raw_feature

    @torch.no_grad()
    def test(self, raw_feature, batch_size, edge_index, ids, sequence):
        raw_feature = {'user': self.user_embedding, 'event': self.activation(self.linear(raw_feature['event']))}
        return self.sequence_prediction_layer.test(raw_feature, ids, sequence)

class EPSGF_RAND(EPSGF):
    def __init__(self, num_node_dic, num_feature_dic, mid_size, out_size, input_size, device):
        super(EPSGF_RAND, self).__init__(num_node_dic, num_feature_dic, mid_size, out_size, input_size, device)
        self.linear = nn.Linear(num_feature_dic['event'], out_size)
        self.event_embedding = torch.randn((num_node_dic['event'], out_size), dtype=torch.float).to(device)
        self.hals = None
        self.to(device)

    def forward(self, raw_feature, batch_size, edge_index, ids, sequence):
        raw_feature = {'user':self.user_embedding,'event':self.event_embedding}
        raw_feature = self.sequence_prediction_layer(raw_feature, ids, sequence)
        return raw_feature

    @torch.no_grad()
    def test(self, raw_feature, batch_size, edge_index, ids, sequence):
        raw_feature = {'user': self.user_embedding, 'event': self.event_embedding}
        return self.sequence_prediction_layer.test(raw_feature, ids, sequence)

class EPSGF_SOFTMAX(EPSGF):
    def __init__(self, num_node_dic, num_feature_dic, mid_size, out_size, input_size, device):
        super(EPSGF_SOFTMAX, self).__init__(num_node_dic, num_feature_dic, mid_size, out_size, input_size, device)
        self.sequence_prediction_layer = SequencePredictionLayer(num_node_dic['user'], num_node_dic['event'],
                                                                 out_size, out_size, 1, device, True)
        self.to(device)


#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2018 yakumo <yakumo@yakumo-pc>
#
# Distributed under terms of the MIT license.

import json
import sys

from flask import Flask, request, g
from github_webhook import Webhook
import zmq

from consumer import zmq_address, Consumer
from store import store

def create_app():

    app = Flask(__name__)
    webhook = Webhook(app)
    context = zmq.Context()
    zmq_sock = context.socket(zmq.PUSH)
    zmq_sock.bind(zmq_address)

    @webhook.hook('release')
    def on_release(data):
        guid = request.headers['X-Github-Delivery']
        zmq_sock.send_pyobj((guid, data))

    @webhook.hook('status')
    def on_status(data):
        guid = request.headers['X-Github-Delivery']
        zmq_sock.send_pyobj((guid, data))

    @app.route('/')
    def hello_world():
        return 'Hello, World!'

    @app.route('/deployments/<guid>')
    def get_deployment(guid):
        return json.dumps(store.get(guid) or {'op': 'null'})

    @app.route('/ops', methods=['POST'])
    def ops():
        print(json.loads(request.form['payload']))
        payload = json.loads(request.form['payload'])
        guid = payload['callback_id']
        action = payload['actions'][0]
        user = payload['user']['name']
        if action['value'] == 'deploy':
            store.set(guid, {'op': 'deploy', 'user': user})
        elif action['value'] == 'abort':
            store.set(guid, {'op': 'abort', 'user': user})
        # return json.dumps(payload['original_message'])
        return '', 204

    return app

def create_consumer():
    instance = Consumer()
    instance.run()

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print('Usage: python main.py [webhook|consumer]')
    if sys.argv[1] == 'webhook':
        create_app().run(host="0.0.0.0", port=8080)
    if sys.argv[1] == 'consumer':
        create_consumer()


# basic lib
import os,sys
import time
import math
import random
# plot
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
# self define file
import rbfn
parent = os.path.dirname(os.getcwd())

def dist2line_intersection(line1Car, line1p2, line2p1, line2p2):
    xdiff = (line1Car[0] - line1p2[0], line2p1[0] - line2p2[0])
    ydiff = (line1Car[1] - line1p2[1], line2p1[1] - line2p2[1])

    def det(a, b):
        return a[0] * b[1] - a[1] * b[0]

    div = det(xdiff, ydiff)
    if div == 0:
       return math.inf
    # no intersection

    d = (det(line1Car, line1p2), det(line2p1, line2p2))
    x = det(d, xdiff) / div
    y = det(d, ydiff) / div

    if (line1Car[0]-x) * (line1Car[0]-line1p2[0]) < 0 or (line1Car[1]-y) * (line1Car[1]-line1p2[1]) < 0:
        return math.inf
    # opposite direction
    right, left, up, down = 0, 0, 0, 0
    if line2p1[0] > line2p2[0]:
        right, left = line2p1[0], line2p2[0]
    else:
        right, left = line2p2[0], line2p1[0]
    if line2p1[1] > line2p2[1]:
        up, down = line2p1[1], line2p2[1]
    else:
        up, down = line2p2[1], line2p1[1]
    if not(((right+1>=x)) and ((x>=left-1)) and ((up+1>=y)) and ((y>=down-1))):
        return math.inf
    # not reach the line segment
    ret = math.sqrt((line1Car[0]-x)*(line1Car[0]-x)+(line1Car[1]-y)*(line1Car[1]-y))
    if ret < 3:
        return math.inf
    # car reach something (wall or endline)
    return ret

class Car():
    def __init__(self):
        super(Car, self).__init__()
        # init params
        self.turn_deg = 45
        self.rad_car = 3.0
        self.deg_dir = 0.0
        self.x_rec, self.y_rec, self.f_rec, self.r_rec, self.l_rec, self.dir_rec = [], [], [], [], [], []
        # init map, engine
        self.loadMap()
        self.engine = rbfn.RBFN(3, 12)

    def loadMap(self, path='case01.txt'):
        with open(path, 'r') as f:
            lines = f.readlines()
            lines = [line.replace('\n', '').split(',') for line in lines]
            lines = [[int(j) for j in line] for line in lines]
            self.x_car, self.y_car, self.deg_x_axis= lines[0][0], lines[0][1], float(lines[0][2])
            self.end1, self.end2 = lines[1], lines[2]
            self.walls = lines[3:]

    def loadRecord(self, path=os.path.dirname(os.getcwd()) + '/outputs/train6D.txt'):
        with open(path, 'r') as f:
            lines = f.readlines()
            lines = [line.replace('\n', '').split() for line in lines]
            lines = [[float(j) for j in line] for line in lines]
            for i in range(len(lines)):
                self.x_rec.append(lines[i][0])
                self.y_rec.append(lines[i][1])
                self.f_rec.append(lines[i][2])
                self.r_rec.append(lines[i][3])
                self.l_rec.append(lines[i][4])
                self.dir_rec.append(lines[i][5])

    def draw(self):
        fig = plt.figure()

        # start point
        plt.scatter(0, 0, s = 300, color = 'c')
        # end
        end = list(zip(self.end1, self.end2))
        plt.plot(end[0], end[1], color = 'r')
        # start
        start = list(zip(self.walls[-1], self.walls[-2]))
        plt.plot(start[0], start[1], color = 'k')
        # walls
        for i in range(len(self.walls)-2):
            wall = list(zip(self.walls[i], self.walls[i+1]))
            plt.plot(wall[0], wall[1], color = 'b')

        # animation
        ims = []
        moves = len(self.x_rec)-1 if len(self.x_rec) != 0 else 0
        for i in range(moves):
            move = list(zip([self.x_rec[i],self.y_rec[i]], [self.x_rec[i+1],self.y_rec[i+1]]))
            if self.dir_rec[i] > 0:
                im = plt.plot(move[0], move[1], marker='o', markersize=20, color = 'c')
            else:
                im = plt.plot(move[0], move[1], marker='o', markersize=20, color = 'b')
            ims.append(im)
        self.ani = animation.ArtistAnimation(fig, ims, interval=100, repeat_delay=1000)
        plt.gca().set_aspect('equal', adjustable='box')
        # plt.show()
        return fig

    def saveDraw(self):
        assert isinstance(self.ani, animation.ArtistAnimation)
        # t = time.strftime('_%Y%m%d_%H%M%S')
        self.ani.save('autoCar.gif',writer='pillow')

    def saveResult(self):
        parent = os.path.dirname(os.getcwd())
        with open(parent + '/outputs/train4D.txt', 'w') as train4D, open(parent + '/outputs/train6D.txt', 'w') as train6D:
            for i in range(len(self.x_rec)):
                a = self.x_rec[i]
                b = self.y_rec[i]
                c = self.f_rec[i]
                d = self.r_rec[i]
                e = self.l_rec[i]
                f = self.dir_rec[i]
                str4 = '{:8.2f} {:8.2f} {:8.2f} {:8.2f}'.format(c, d, e, f)
                str6 = '{:8.2f} {:8.2f} {:8.2f} {:8.2f} {:8.2f} {:8.2f}'.format(a, b, c, d, e, f)

                train4D.write(str4+'\n')
                train6D.write(str6+'\n')

    def setEngine(self, engine):
        self.engine = engine

    def getDeg(self, inp):
        lower, upper = 0, 80
        assert isinstance(self.engine, rbfn.RBFN)
        inp = [rbfn.normalization(i, lower, upper) for i in inp]
        deg = self.engine.output(inp)
        lower, upper = -40, 40
        deg = rbfn.denormalization(deg, lower, upper)
        if deg > 40:
            deg = 40
        elif deg < -40:
            deg = -40
        return deg

    def run(self):
        # 0 not see end, 1 see end, 2 near end
        flag = 0
        for _ in range(100):
            # print(j)
            dist_f, dist_r, dist_l = math.inf, math.inf, math.inf
            for i in range(len(self.walls)-2):
                l1p1, l1p2 = [self.x_car,self. y_car], [self.x_car+1*math.cos(math.radians(self.deg_x_axis+self.turn_deg)), self.y_car+1*math.sin(math.radians(self.deg_x_axis+self.turn_deg))]
                dist = dist2line_intersection(l1p1, l1p2, self.walls[i], self.walls[i+1])
                if dist < dist_l:
                    dist_l = dist

                l1p1, l1p2 = [self.x_car, self.y_car], [self.x_car+1*math.cos(math.radians(self.deg_x_axis)), self.y_car+1*math.sin(math.radians(self.deg_x_axis))]
                dist = dist2line_intersection(l1p1, l1p2, self.walls[i], self.walls[i+1])
                if dist < dist_f:
                    dist_f = dist

                l1p1, l1p2 = [self.x_car, self.y_car], [self.x_car+1*math.cos(math.radians(self.deg_x_axis-self.turn_deg)), self.y_car+1*math.sin(math.radians(self.deg_x_axis-self.turn_deg))]
                dist = dist2line_intersection(l1p1, l1p2, self.walls[i], self.walls[i+1])
                if dist < dist_r:
                    dist_r = dist
            # use x_car, y_car, deg_x_axis
            # to calculate dist_f, dist_r, dist_l

            self.x_rec.append(self.x_car)
            self.y_rec.append(self.y_car)
            self.f_rec.append(dist_f)
            self.r_rec.append(dist_r)
            self.l_rec.append(dist_l)
            self.dir_rec.append(self.deg_dir)
            # record

            # 0 not see end, 1 see end, 2 near end
            l1p1, l1p2 = [self.x_car, self.y_car], [self.x_car+1*math.cos(math.radians(self.deg_x_axis)), self.y_car+1*math.sin(math.radians(self.deg_x_axis))]
            dist = dist2line_intersection(l1p1, l1p2, self.end1, self.end2)
            if flag == 0 and dist_f > dist:
                flag = 1
            elif flag == 1 and dist == math.inf:
                flag = 2
            elif flag == 2:
                if (l1p1[0]-self.end1[0]) * (l1p1[0]-l1p2[0]) < 0 or (l1p1[1]-self.end1[1]) * (l1p1[1]-l1p2[1]) < 0:
                    flag = 0
                    break
            if dist_f==math.inf or dist_r==math.inf or dist_l==math.inf:
                break
            # ending

            ################################################################################################
            ##################################           engine           ##################################
            ##################################      set self.deg_dir      ##################################
            ################################################################################################
            inp = []
            if self.engine.num_inp == 3:
                inp = dist_f, dist_r, dist_l
            elif self.engine.num_inp == 5:
                inp = [self.x_car, self.y_car, dist_f, dist_r, dist_l]
            else:
                print('engine input error')
            self.deg_dir = self.getDeg(inp)
            ################################################################################################
            ##################################           engine           ##################################
            ################################################################################################

            # move the car (get new point and deg)
            x_next = self.x_car + (math.cos(math.radians(self.deg_dir+self.deg_x_axis)) + math.sin(math.radians(self.deg_dir)) * math.sin(math.radians(self.deg_x_axis)))
            y_next = self.y_car + (math.sin(math.radians(self.deg_dir+self.deg_x_axis)) - math.sin(math.radians(self.deg_dir)) * math.cos(math.radians(self.deg_x_axis)))
            deg_x_axis_next  = self.deg_x_axis - (math.degrees(math.asin(2*math.sin(math.radians(self.deg_dir))/self.rad_car)))
            self.x_car, self.y_car, self.deg_x_axis = x_next, y_next, deg_x_axis_next

if __name__ == "__main__":
    pass

    # c = Car()
    # '''
    # # c.engine.loadParams('RBFN_params_3_12_w.txt')
    # # c.run()
    # # c.saveResult()
    # '''
    # c.loadRecord()
    # # c.run()
    # c.draw()


import time
from urllib.request import urlretrieve
import subprocess
from selenium import webdriver

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By

driver = webdriver.Firefox()
driver.get(
    "https://www.amazon.com/Programming-Rust-Fast-Systems-Development/dp/1491927283")

time.sleep(2)
#push the button of preview of the book

driver.find_element_by_id("sitbLogoImg").click()
#driver.find_element_by_id("sitbLogoImg").send_keys(Keys.RETURN)

imageList = set()

#wait for loading the page
time.sleep(5)
#turn the page as long as right arrow can be clicked on

while "pointer" in driver.find_element_by_id("sitbReaderRightPageTurner"
                                            ).get_attribute("style"):
    driver.find_element_by_id("sitbReaderRightPageTurner").click()
    time.sleep(2)
    # get a loaded new page(multiple pages can be loaded together but dont add
    # duplicated pages to the set)
    pages = driver.find_elements_by_xpath("//div[@class='pageImage']/div/img")
    for page in pages:
        image = page.get_attribute("src")
        imageList.add(image)

driver.quit()

#start processing image with the URL by tesseract
for image in sorted(imageList):
    urlretrieve(image, "page.jpg")
    p = subprocess.Popen(["tesseract", "page.jpg", "page"],
                        stdout = subprocess.PIPE, stderr=subprocess.PIPE)
    p.wait()
    f = open("page.txt", "r", encoding='UTF-8')
    print(f.read())


import sys
import numpy as np

import matplotlib.pyplot as plt
import scipy.io as sio

from fealpy.mesh.TriangleMesh import TriangleMesh
from fealpy.functionspace.tools import function_space

inputName = sys.argv[1]
degree = int(sys.argv[2])
outputName = sys.argv[3]

data = sio.loadmat(inputName)

point = data['point']
cell = data['cell'] - 1

mesh = TriangleMesh(point, cell)
edge = mesh.ds.edge
cell2edge = mesh.ds.cell_to_edge()
cell2edgeSign = mesh.ds.cell_to_edge_sign()
V = function_space(mesh, 'Lagrange', degree)

ipoint = V.interpolation_points()
edge2dof = V.edge_to_dof()
cell2dof = V.cell_to_dof()

data = {
        'point':point,
        'cell':cell + 1,
        'edge':edge + 1,
        'cell2edge':cell2edge + 1,
        'cell2edgeSign':cell2edgeSign,
        'dofPoint':ipoint,
        'edge2dof':edge2dof + 1,
        'cell2dof':cell2dof + 1
        }
sio.matlab.savemat(outputName, data)


from numpy.lib.recfunctions import unstructured_to_structured as struct
from numpy.lib.recfunctions import structured_to_unstructured as unstruct
import numpy as np
import pricer
import utils
import query

np.seterr(divide='ignore')
np.warnings.filterwarnings('ignore')
base = 253

def surface(symbol,qdate,qtime=None,errors=False,post=True,loc=0,scale=None):
    q = f"select * from dbo.{symbol} where Date = convert(datetime,'{qdate}',103) order by Time,Tenor,Strike"
    df = query.get("Vols",q)
    if qtime is not None: df = df[df["Time"]==qtime]
    st = utils.pack(df)
    del df;

    #----------------------------------------------------------------------------------
    f = lambda LST: pricer.norm_weights(LST,loc,scale)
    wgt = utils.apply(f,1,st,["Time","Tenor"],["LogStrike"])

    sv = pricer.SSVI(errors)
    f = lambda LST,VAR,TNR,VOL: sv.calibrate(LST,VAR,TNR,VOL,wgt)

    if errors == True:
        prm = utils.apply(f,6,st,["Time"],["LogStrike","TotAtmfVar","Tenor","SmtVol"],diff=True,fill=False)
        errors = prm[-1]
        prm = np.asarray(prm[:-1]).T
    else:
        prm = utils.apply(f,5,st,["Time"],["LogStrike","TotAtmfVar","Tenor","SmtVol"],fill=False)

    #----------------------------------------------------------------------------------
    reduced = ["Time","Tenor","SpotMid","Forward","CumDivDays","Div","ImpBor",
               "Rate","CallH0","CallH1","CallKh","PutH0","PutH1","PutKh","TotAtmfVar"]
    st = utils.unique_nosort(st[reduced])

    prm = utils.restack(prm,st["TotAtmfVar"],tile=False)

    rho = sv.correlation(st["TotAtmfVar"], prm[:,0], prm[:,1], prm[:,2])
    phi = sv.power_law(st["TotAtmfVar"], prm[:,3], prm[:,4])
    atm,skw,krt = sv.raw2jw(st["Tenor"]/base,st["TotAtmfVar"],phi,rho)

    arr = unstruct(st)
    arr = np.column_stack([arr,atm,skw,krt,phi,rho])
    df = utils.unpack(arr,qdate,False,symbol)

    if post == True:
        query.post(df,"Params","main","replace")

    return df

# symbol = "JPM"
# qdate = "16/10/2020"
# qtime = 2040
# errors = True
# df = surface(symbol,qdate,qtime=None,errors=False,post=False)


import concurrent.futures
from typing import List

import numpy as np
from rasterio import features
from rasterio.transform import Affine, from_bounds
from shapely.geometry import Polygon

from raster_analysis.data_environment import DataEnvironment, SourceLayer
from raster_analysis.geodesy import get_area
from raster_analysis.globals import LOGGER, BasePolygon
from raster_analysis.query import Query
from raster_analysis.window import DerivedWindow, SourceWindow

class DataCube:
    def __init__(self, geom: BasePolygon, tile: Polygon, query: Query):
        self.grid = query.get_minimum_grid()
        self.mean_area = get_area(tile.centroid.y, self.grid.get_pixel_width()) / 10000

        source_layers = query.get_source_layers()
        layer_names = query.get_layer_names()
        self.windows = self._get_windows(source_layers, tile, query.data_environment)

        for layer in query.get_derived_layers():
            self.windows[layer.name] = DerivedWindow(
                layer, self.windows[layer.source_layer], self.mean_area
            )

        for layer in source_layers:
            if layer.name not in layer_names and layer.name in self.windows:
                # free up memory, since this means the source layer was only required
                # for a derived layer
                del self.windows[layer.name]

        tile_width = self.grid.get_tile_width()
        self.shifted_affine: Affine = from_bounds(*tile.bounds, tile_width, tile_width)

        self.mask = self._mask_geom_on_raster(
            np.ones((tile_width, tile_width)), self.shifted_affine, geom
        )

    def _get_windows(
        self,
        layers: List[SourceLayer],
        tile: BasePolygon,
        data_environment: DataEnvironment,
    ):
        with concurrent.futures.ThreadPoolExecutor() as executor:
            # Start the load operations and mark each future with its URL
            futures = {
                executor.submit(
                    SourceWindow, layer, tile, self.grid, data_environment
                ): layer
                for layer in layers
            }

            return self._get_window_results(futures)

    @staticmethod
    def _get_window_results(futures):
        windows = {}
        for future in concurrent.futures.as_completed(futures):
            layer = futures[future]

            try:
                windows[layer.name] = future.result()
            except Exception as e:
                LOGGER.exception(f"Exception while reading window for layer {layer}")
                raise e

        return windows

    @staticmethod
    def _mask_geom_on_raster(
        raster_data: np.ndarray, shifted_affine: Affine, geom: BasePolygon
    ) -> np.ndarray:
        """For a given polygon, returns a numpy masked array with the
        intersecting values of the raster_data, all non- intersecting cells are
        masked.  This assumes that the input geometry is in the same SRS as the
        raster.

        Args:
            raster_data (ndarray): ndarray of raster data to be masked onto
            shifted_affine (Affine): the transform used to map the vector geometry to the raster
            geom (Shapely Geometry): A polygon in the same SRS as `raster_path`
                which will define the area of the raster to mask.

        Returns
           Numpy masked array of source raster, cropped to the extent of the
           input geometry, with any modifications applied. Areas where the
           supplied geometry does not intersect are masked.
        """

        if raster_data.size > 0:
            # Create a numpy array to mask cells which don't intersect with the
            # polygon. Cells that intersect will have value of 1 (unmasked), the
            # rest are filled with 0s (masked)
            geom_mask = features.geometry_mask(
                [geom],
                out_shape=raster_data.shape,
                transform=shifted_affine,
                invert=True,
            )

            # Mask the data array, with modifications applied, by the query polygon
            return geom_mask
        else:
            return np.array([])


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import itertools
import numpy as np
from atlas_db.inputs.nc4 import AtlasNc4Input
from atlas_db.ingestors.mongodb import AtlasMongoIngestor
from atlas_db.constants import SCALE

class AtlasPsims(AtlasNc4Input):
    """Ingestion object for PSIMS.

    """
    def __init__(self, backend, *args, **kwargs):
        super(AtlasPsims, self).__init__(*args, **kwargs)
        self.name = ''.join(self.nc_file.split('/')[-1].split('.')[:-1])
        params = ['agricultural_model', 'climate_model', None, 'harms',
                  'irrigation', 'variable', 'crop']
        self.parameters = {
            params[i]: v for i, v in enumerate(self.name.split('_'))
            if i in [0, 1, 2, 3, 4, 5, 6]}
        # self.name = '_'.join(self.name.split('_')[3:5])
        self.human_name = 'pSIMS: {0} {1} {2}'.format(
            self.parameters['agricultural_model'],
            self.parameters['climate_model'],
            self.parameters['irrigation'])
        self.backend = backend

    def ingest(self):
        self.backend.ingest_metadata(self.metadata)
        for variable in self.variables:
            self.ingest_variable(variable)

    def ingest_variable(self, variable):

        print(variable)

        values = self.nc_dataset[variable][:]

        lons_lats = itertools.product(
            enumerate(self.lats), enumerate(self.lons))

        values = np.swapaxes(
            values, self.nc_dataset.variables[variable].dimensions.index(
                self.lat_var), 0)

        values = np.swapaxes(
            values, self.nc_dataset.variables[variable].dimensions.index(
                self.lon_var), 1)

        self.backend.ingest(values, lons_lats, self.metadata['name'], variable)

if __name__ == '__main__':
    import os
    from atlas_db.constants import BASE_DIR
    _filename = '{}_{}_{}_{}_{}_{}_{}_{}_{}.nc4'.format(
        'papsim', 'wfdei.cru', 'hist', 'default', 'firr', 'whe',
        'annual', 1979, 2012)
    NC_FILE = os.path.join(BASE_DIR, 'data', 'netcdf', 'psims', _filename)
    p = AtlasPsims(AtlasMongoIngestor(SCALE), NC_FILE, SCALE)
    p.ingest()


import xml.etree.ElementTree as ET
from shutil import copy2

import sys, os.path
datapath = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..") + '/OA Data Files')
sys.path.append(datapath)

import app_config

import Base_Manage_Data
import Food
import List_Object
import GUI_Equipment_Controller

class Manage_food(Base_Manage_Data.Manage_data):
    def save_one(self,item,filename=None,backup_filename=None):
        if type(item) == Food.Food and not(item.isempty()):
            super().save_one(item,filename,backup_filename)
        else:
            raise ValueError('expected Food object, instead got ' + str(type(item)))

    def remove_item(self,item):
        if type(item) == Food.Food and not(item.isempty()):
            super().remove_item(item)
        else:
            raise ValueError('expected Food object, instead got ' + str(type(item)))

    def save_all(self,filename=None,backup_filename=None):
        if not self.current_set == self.loaded_set:
            data=ET.Element('food')
            for mfood in self.current_set.all_items:
                l=ET.SubElement(data,'foodType')
                ET.SubElement(l,'name').text = mfood.name
                ET.SubElement(l,'shortDescription').text = mfood.short_description
                ET.SubElement(l,'description').text = mfood.description
                ET.SubElement(l,'value').text = mfood.value
                ET.SubElement(l,'weight').text = mfood.weight
                ET.SubElement(l,'health').text = mfood.health
                ET.SubElement(l,'capacity').text = mfood.capacity
                ET.SubElement(l,'special').text = mfood.special
            if filename == None:
                filename = app_config.file_path + app_config.food_filename
            if backup_filename == None:
                backup_filename = app_config.backup_file_path + app_config.backup_food_filename
            copy2(filename,backup_filename)
            f = open(filename,'w')
            f.write(ET.tostring(data, encoding="unicode"))
            f.close()

    def set_controller(self,parent=None):
        self.edit_controller = GUI_Equipment_Controller.GUI_equipment_controller(parent)

    def launch_edit(self,name,parent=None):
        self.edit_controller.create_form(parent)
        if len(name) > 0:
            food = self.current_set.get_item(name)
        else:
            food = Food.Food('','')
        self.edit_controller.load_data('Food',food,self.save_one,self.close_edit_item)

    def load_set(self,filename=None):
        self.current_set = Food.Foods()
        if filename == None:
            filename = app_config.file_path + app_config.food_filename
        tree = ET.parse(filename)
        data_root = tree.getroot()
        for food in data_root:
            new_food_name = food.find('name').text or 'UNKNOWN'
            new_food_short_description = food.find('shortDescription').text or 'UNKNOWN'
            new_food = Food.Food(new_food_name,new_food_short_description)
            new_food.description = food.find('description').text or 'UNKNOWN'
            new_food.value = food.find('value').text or 0
            new_food.weight = food.find('weight').text or 0
            new_food.health = food.find('health').text or 0
            new_food.capacity = food.find('capacity').text or 0
            new_food.special = food.find('special').text or 'UNK'
            self.current_set.add_new(new_food)
        self.loaded_set = self.current_set.clone()

    def __init__(self):
        self.name = 'Food'
        Base_Manage_Data.Manage_data.__init__(self)

if __name__ == '__main__':
    manager = Manage_food()
    manager.load_food()
    manager.launch_food_list()


"""
This module is starting point for task 4.1 from Coding Campus 2018 Python course
(Dungeon Game)
"""

import logging
import threading
from .dungeon_map import DungeonMap
from .player import Player
import dungeon_game.utils as utils
import dungeon_game.log as log
from dungeon_game.decorators import log_decorator, debug_log_decorator
from dungeon_game.exceptions import InputError, MapInitError
from dungeon_game.enemy import ThreadEnemyWrapper
import dungeon_game.config as config

SAVE_PATH = "save.dat"
logger = logging.getLogger(log.LOGGER_NAME)

active_map = None
active_player = None
thread_enemy = None

def validator_map_size(string):
    """
    Validator for map size input
    Raises InputError with error description if string is not valid
    :param string: String to check
    :return: Bool, if success
    """
    result = False

    if string.isdigit():

        size = int(string)
        if 5 <= size <= 100:
            result = True
        else:
            raise InputError("Unacceptable map size! Try again")
    else:
        raise InputError("Input is not integer! Try again")

    return result

def validator_movement_string(string):
    """
    Validator for player move direction input
    Raises InputError with error description if string is not valid
    :param string: String to check
    :return: Bool, if success
    """
    result = False

    if string.lower() == "u":
        result = True
    elif string.lower() == "l":
        result = True
    elif string.lower() == "r":
        result = True
    elif string.lower() == "d":
        result = True
    else:
        raise InputError("Incorrect movement direction!\nPlayer can move up [U], left [L], right [R] or down [D]\n")

    return result

def validator_response(string):
    """
    Validator for yes/no response input
    Raises InputError with error description if string is not valid
    :param string: String to check
    :return: Bool, if success
    """
    result = False

    if string.lower() == "n" or string.lower() == "y":
        result = True
    else:
        raise InputError("Incorrect answer!")

    return result

def validator_command(string):
    """
    Validator for command input
    Raises InputError with error description if string is not valid
    :param string: String to check
    :return: Bool, if success
    """
    result = False

    if string.lower() == "move" or string.lower() == "save":
        result = True
    else:
        raise InputError("Incorrect command!")

    return result

@log_decorator
@debug_log_decorator
def play_game():
    """
    Plays single game of Dungeon Game
    :return: None
    """

    while True:

        player_hitpoints = active_player.get_hitpoints()
        is_trap_nearby, is_treasure_nearby = active_map.check_nearby_tiles(active_player.position)

        print("\n\n")

        if active_player.is_dead():

            logger.info("Player is killed")
            print("You grow weak and fall to the cold floor, dropping your bag beside you. You feel you can't go anymore further.")
            print("Dungeon consumes you!")
            break

        if is_trap_nearby:
            print("Your senses detect a trap in nearby tile. Watch your step!")
        if is_treasure_nearby:
            print("Radiant glow gives away treasure's location in nearby tile. Target is close!")

        logger.info(f"Player position {active_player.position}")
        print(f"Your position is ({active_player.position[1]}, {active_player.position[0]})")
        print(f"Your health is {player_hitpoints} HP")
        print(f"Your bag has space for {config.PLAYER_BAG_SIZE - active_player.bag } more chests.\n")

        command = utils.get_input(validator_command, "Input command [Save] or [Move]: ")
        if command.lower() == "save":

            if utils.save_game(SAVE_PATH, active_map, active_player):
                print("Game saved!")
            else:
                print("Save failed!")

            continue

        while True:

            move_direction = utils.get_input(validator_movement_string, "Input direction to move in: ")
            if active_player.move(move_direction.lower(), active_map):

                logger.info(f"Player moves {active_player.position[1]}, {active_player.position[0]}")
                break
            else:
                print("You can't move there! Try again\n")

        is_trap, is_treasure = active_map.check_current_tile(active_player.position)

        if is_trap:

            logger.info(f"Player is damaged by 1 hitpoint. Hitpoints left: {player_hitpoints - 1}")
            print("You spring the trap and it firmly clenches around your leg.")
            active_player.decrease_hitpoints()

            if active_player.is_dead():

                logger.info("Player is killed")
                print("You loose too much blood trying to remove it and give in to darkness.")
                print("Dungeon consumes you!")
                break

            else:

                print("You manage to remove the trap suffering minor wounds.")
                active_map.game_map[active_player.position[0]][active_player.position[1]] = DungeonMap.SYMBOL_PLAYER

        if is_treasure:

            logger.info(f"Player found the treasure. Current bag size: {active_player.bag + 1}")
            print("Shimmering glow and warmth leads you to open chest filled with gold. You fill your bag with contents of the chest.")
            active_player.bag += 1

            if active_player.is_bag_full():

                logger.info("Player filled the bag")
                print("Feeling you can't carry anymore, you backtrack to dungeon exit with the bag full of gold.")
                print("You escaped the dungeon!")
                break

            else:

                print("Your bag feels a little heavier, but there is still space for more. You continue your journey.")
                active_map.game_map[active_player.position[0]][active_player.position[1]] = DungeonMap.SYMBOL_PLAYER

    active_player.mark_last_pos(active_map)
    logger.info("Game over")

@log_decorator
@debug_log_decorator
def init_game():
    """
    Initializes game map and player position
    :return: None
    """

    global active_map
    global active_player

    while True:

        map_size = utils.get_input(validator_map_size, "Input map size [5 - 100]: ")

        try:
            active_map = DungeonMap(int(map_size))
        except MapInitError as exc:
            print(f"Failed to create map! Error: f{str(exc)}")
        else:
            break

    active_player = Player(active_map)

@log_decorator
@debug_log_decorator
def start_game():
    """
    Start game dialog
    :return: None
    """

    global active_map
    global active_player
    global thread_enemy

    active_map = DungeonMap(0, False)
    active_player = Player(active_map)

    response = utils.get_input(validator_response, "Do you wish to load last saved game? [Y\\N]: ")

    if response.lower() == 'y':

        if not utils.load_game(SAVE_PATH, active_map, active_player):

            print("Failed to load saved game! Starting new game")
            init_game()

    else:

        logger.info("Starting new game.")
        init_game()

    thread_enemy = ThreadEnemyWrapper(active_map, active_player)
    thread_enemy.start()

def run():
    """
    Runs game
    Package link: https://test.pypi.org/project/dungeon-game-yeremenko/
    :return: None
    """

    print("Welcome to Dungeon Game!")
    log.init_logger()

    while True:

        start_game()
        play_game()

        print("\nGAME OVER\n")
        active_map.print_map()

        thread_enemy.join()

        response = utils.get_input(validator_response, "Try again? [Y\\N]: ")

        if response.lower() == 'n':
            break
        else:
            logger.info("User is restarting the game")

    logger.info("User quit the game")
    print("\nQuitting game...")


# -*- coding: utf-8 -*-
"""
Created on Thu May 28 20:39:35 2020

@author: omars
"""
#############################################################################
# Load Libraries
import pandas as pd
import sir_ode
import sir_cost
import datetime
from copy import deepcopy
from scipy.integrate import odeint as ode
import scipy.optimize as optimize
import numpy as np
from mdp_model import MDP_model
from knn_utils import (get_best_parameters, match_to_real_growth, transpose_case_df)
#############################################################################

#############################################################################
# Helper variables
models = ['sir', 'knn', 'mdp', 'agg']
metrics = ['prediction', 'lower', 'upper']
cols_to_keep = ['state',
                'date',
                'cases',
                'prevalence'] + [model + '_' + metric for model in models for metric in metrics]

# Fit Predict fucntions for SIR and KNN
def sir_fit_predict(df_train, #dataset has columns state, date, cases
                    pop_dic,
                    pred_out=100,
                    nmin=100):
    dataset = deepcopy(df_train)
    dataset.set_index(['date'])
    output = pd.DataFrame()
    states = dataset.state.unique()
    for i in range(len(states)):
        state = states[i]
        train_set = dataset.query('state == @state').query('cases >= @nmin')
        if train_set.shape[0] > 10:
            timer = [j for j in range(len(train_set))]
            actual_time = [k for k in range(len(train_set) + pred_out)]
            data = train_set.loc[:, 'cases'].values
            times = timer
            params = [0.4, 0.06, pop_dic[state]]
            #paramnames = ['beta', 'gamma', 'k']
            ini = sir_ode.x0fcn(params,data)

    	    #Simulate and plot the model
            res = ode(sir_ode.model, ini, times, args=(params,))
            #sim_measure = sir_ode.yfcn(res, params)

    	    #Parameter estimation
            optimizer = optimize.minimize(sir_cost.NLL, params, args=(data,times), method='Nelder-Mead')
            paramests = np.abs(optimizer.x)
            iniests = sir_ode.x0fcn(paramests, data)
            xest = ode(sir_ode.model, iniests, times, args=(paramests,))
            est_measure = sir_ode.yfcn(xest, paramests)

            est_measure = np.array(est_measure)

            params = paramests
            ini1 = sir_ode.x0fcn(params,data)

    	    #Simulate and plot the model
            res = ode(sir_ode.model, ini1, actual_time, args=(params,))

            preds_test = sir_ode.yfcn(res, params)
            preds_test = np.delete(preds_test,times)
            pred_train = pd.DataFrame(est_measure)
            pred_test = pd.DataFrame(preds_test)
            df_fin = pred_train.append(pred_test, ignore_index = True)
            df_fin.columns = ["prediction"]

            last_date = train_set.date.tail(1)
            date_list = [last_date + datetime.timedelta(days=x) for x in range(pred_out)]
            df_fin["date"] = train_set.date.append(date_list, ignore_index = True)

            df_fin["state"] = states[i]
            output = output.append(df_fin, ignore_index = True) #df5 stores the output for all states together
    return output

def knn_fit_predict(df,
                    memory=7,
                    forward_days=7,
                    split_date='2020-05-01',
                    day_0='2020-05-01',
                    real_GR=False,
                    deterministic=True):
    '''
    everything before split_date is train

    '''
    #This section of code creates the forward and back features

    df0 = df.copy(deep=True) # deep copy might not be needed, just for security

    #remove some states/territories with late or small number of cases
    #CHANGE TO KEEPING STATES - hard copy in this code maybe global variable
    df0 = df0.loc[~df0['state'].isin(['West Virginia','District of Columbia','Puerto Rico','American Samoa', 'Diamond Princess','Grand Princess','Guam','Northern Mariana Islands','Virgin Islands'])]

    df0 = df0.sort_values(by=['state', 'date']) #has to be sorted by days to create growth rates
    df0['GrowthRate'] = (df0.groupby('state')['cases'].shift(0) / df0['cases'].shift(1) - 1) #group by state so that consecutive rows are consecutive days in a single state

    #create the t-1 to t-memory growth rates
    for i in range(memory):
        df0['GrowthRate_t-' + str(i+1)] = df0.groupby('state')['GrowthRate'].shift(i+1)

    df0['cases_t-1'] = df0['cases'].shift(1)

    #this is used only if we are using the alternate method where we run nearest neighbors on predictions in the train set
    if real_GR:
        for i in range(forward_days):
            df0['GrowthRate_t+' + str(i)] = df0.groupby('state')['GrowthRate'].shift(-i)

        for i in range(forward_days):
            df0['actual_growth_for_next_{}days'.format(i+1)] = (df0['cases'].shift(-i)/df0['cases'].shift(1)) - 1
    '''
    threshold: multiplier on the nearest distance that we cut off at when assigning weights, e.g. a point outside the threshold gets a weight of 0
    n: maximum number of nearest neighbors
    p: either L1 norm (manhattan) or L2 norm
    func: get_weights or get_weights_sq, whether the distance norm will be squared or not
    '''
    df0 = df0.dropna()
    threshold, n, p, func = get_best_parameters(df0, memory, split_date)

    #we run the method using the best parameters according to the split date
    predictions = match_to_real_growth(df0, threshold, n, p, func, memory, forward_days, day_0, split_date, deterministic)

    #we have finished producing predictions, and move on to converting predicted growth rates into predicted cases

    #convert growth rates to cumulative growth rates -- here we need to add 1 to each predicted growth rate so that when multiplied they represent growth rate over multiple days
    #the cumulative growth rate over n days starting today = (1+ GR_0) * (1+GR_1) * ... * (1+ GR_n-1)
    predictions['pred_growth_for_next_1days'] = predictions['pred_forward_day_0'] + 1
    predictions['pred_high_growth_for_next_1days'] = predictions['pred_high_day_0'] + 1
    predictions['pred_low_growth_for_next_1days'] = predictions['pred_low_day_0'] + 1

    for i in range(1,forward_days):
        predictions['pred_growth_for_next_{}days'.format(i+1)] = predictions['pred_growth_for_next_{}days'.format(i)]*(predictions['pred_forward_day_'+ str(i)] + 1)
        predictions['pred_high_growth_for_next_{}days'.format(i+1)] = predictions['pred_growth_for_next_{}days'.format(i)]*(predictions['pred_high_day_'+ str(i)] + 1)
        predictions['pred_low_growth_for_next_{}days'.format(i+1)] = predictions['pred_growth_for_next_{}days'.format(i)]*(predictions['pred_low_day_'+ str(i)] + 1)
    for i in range(forward_days):
        predictions['pred_growth_for_next_{}days'.format(i+1)] = predictions['pred_growth_for_next_{}days'.format(i+1)] - 1
        predictions['pred_high_growth_for_next_{}days'.format(i+1)] = predictions['pred_high_growth_for_next_{}days'.format(i+1)] - 1
        predictions['pred_low_growth_for_next_{}days'.format(i+1)] = predictions['pred_low_growth_for_next_{}days'.format(i+1)] - 1

    #convert cumulative growth rates to cases
    for i in range(forward_days):
        predictions['cases_predicted_day_' + str(i)] = np.round(predictions['cases_t-1']*(predictions['pred_growth_for_next_{}days'.format(i+1)]+1))
        predictions['cases_high_predicted_day_' + str(i)] = np.round(predictions['cases_t-1']*(predictions['pred_high_growth_for_next_{}days'.format(i+1)]+1))
        predictions['cases_low_predicted_day_' + str(i)] = np.round(predictions['cases_t-1']*(predictions['pred_low_growth_for_next_{}days'.format(i+1)]+1))

    columns_to_keep = ['state', 'date', 'cases'] + ['cases_predicted_day_' + str(i) for i in range(forward_days)] + ['cases_low_predicted_day_' + str(i) for i in range(forward_days)] + ['cases_high_predicted_day_' + str(i) for i in range(forward_days)]
    simple_output = predictions[columns_to_keep]

    #transpose simple output to have forward_days*50 rows
    transposed_simple_output = transpose_case_df(simple_output, forward_days, day_0)

    return transposed_simple_output, predictions
#############################################################################

#############################################################################
# Helper Functions
def mean_absolute_percentage_error(y_true, y_pred):
    y_true, y_pred = np.array(y_true), np.array(y_pred)
    return np.mean(np.abs((y_true - y_pred) / y_true))

def alpha(percentage_tested, p=0.1, q=0.2):
    beta1 = (1-q)/(1-p)
    beta0 = 1 - beta1
    return((beta1 * percentage_tested) + beta0)
#############################################################################

#############################################################################
# Wrapper
def wrapper(df_orig,
            df_input,
            training_cutoff,
            pop_dic,
            weights,
            nmin=20,
            n_iter_mdp=20,
            deterministic=True,
            run_mdp=False):

    df = deepcopy(df_input)
    df_train = df[df['date'] <= training_cutoff]
    df_test = df[df['date'] > training_cutoff]

    pred_out = len(set(df_test.date))
    day_0 = str(df_test.date.min())[:10]
    ###
    sir_output = sir_fit_predict(df_train, pop_dic, pred_out, nmin)
    sir_output = sir_output.rename(
        columns={'prediction':'sir_prediction'}).loc[:, ['state','date', 'sir_prediction']]

    df = df.merge(sir_output, how='left', on=['state', 'date'])
    ###

    ###

    knn_output, _ = knn_fit_predict(
        df=df, memory=7, forward_days=pred_out, split_date =training_cutoff,
        day_0 = day_0, real_GR=True, deterministic=deterministic)

    knn_output = knn_output.rename(
        columns={'pred_cases':'knn_prediction'}).loc[:, ['state','date', 'knn_prediction']]
    knn_output['date'] = knn_output['date'].apply(lambda x: datetime.datetime.strptime(x,'%Y-%m-%d'))

    df = df.merge(knn_output, how='left', on=['state', 'date'])
    df.knn_prediction = np.where([a and b for a, b in zip(df.knn_prediction.isnull(), df.date <= training_cutoff)], df.cases, df.knn_prediction)
    ####

    ###
    if run_mdp:
        df_train = df_orig[df_orig['date'] <= training_cutoff].drop(columns='people_tested').dropna(axis=0)

        mdp = MDP_model()
        mdp.fit(df_train,
                h=5,
                n_iter=n_iter_mdp,
                d_avg=3,
                distance_threshold = 0.05)

        mdp_output = pd.DataFrame()
        for i in range(pred_out):
            mdp_output = mdp_output.append(mdp.predict_all(n_days=i))

        mdp_output = mdp_output.rename(columns={'TIME': 'date', 'cases':'mdp_prediction'}).loc[:, ['state','date', 'mdp_prediction']]

        df = df.merge(mdp_output, how='left', on=['state', 'date'])
        df.mdp_prediction = np.where([a and b for a, b in zip(df.mdp_prediction.isnull(), df.date <= training_cutoff)], df.cases, df.mdp_prediction)
    ###

    ###

    df = df.reset_index()
    if run_mdp:
        df['agg_prediction'] = [weights[df.state[i]][0]*df.sir_prediction[i] + weights[df.state[i]][1]*df.knn_prediction[i] + weights[df.state[i]][2]*df.mdp_prediction[i] if df.state[i] in weights.keys() else df.knn_prediction[i] for i in range(len(df))]
    else:
         df['agg_prediction'] = [weights[df.state[i]][0]*df.sir_prediction[i] + weights[df.state[i]][1]*df.knn_prediction[i] if df.state[i] in weights.keys() else df.knn_prediction[i] for i in range(len(df))]
         df['mdp_prediction'] = 0

    df = df.sort_values(by=['state','date'])

    return (np.array(df['sir_prediction']),
            np.array(df['knn_prediction']),
            np.array(df['mdp_prediction']),
            np.array(df['agg_prediction']))

    # return(df)
#############################################################################


import math
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
import numpy as np
import sys

import os
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, parent_dir)
import linegraph
import scatterplot

def main(figureSaveLocation):
    """Create an image that demonstrates the difference between the step boundary of a decision tree and the boundary induced by an SVM.
    """

    # Define the image size.
    maxX = 20
    minX = 0
    maxY = 20
    minY = 0

    # Define the good hyperplanes.
    goodShift = 1.75
    goodDividingPlaneMinY = goodHyperlpaneDividing(x=minX)
    goodDividingPlaneMaxY = goodHyperlpaneDividing(x=maxX)
    goodDividingPlaneXCoords = [minX, maxX]
    goodDividingPlaneYCoords = [goodDividingPlaneMinY, goodDividingPlaneMaxY]

    # Determine support vectors.
    class1SupportVectorsX = np.array([8.5])
    class1SupportVectorsY = np.array([goodHyperlpaneDividing(x=class1SupportVectorsX[0] + goodShift)])
    class2SupportVectorsX = np.array([6.5, 13.0])
    class2SupportVectorsY = np.array([goodHyperlpaneDividing(x=class2SupportVectorsX[0] - goodShift), goodHyperlpaneDividing(x=class2SupportVectorsX[1] - goodShift)])

    # Define plane appearances.
    planeStyles = ['-', '--', '--']
    planeWidths = [2.0, 1.0, 1.0]

    # Class 1 data and control variables.
    class1X = np.concatenate([class1SupportVectorsX, np.array([
        1.0, 1.3, 1.5, 1.7,
        2.0, 2.2, 2.5, 2.9,
        3.0, 3.5, 3.7,
        4.0, 4.3, 4.8,
        5.1, 5.4, 5.8,
        6.5, 6.9,
        7.3, 7.6, 7.9,
        8.2, 8.5,
        9.1, 9.5,
        10.6, 10.9,
        13.3, 13.6,
        14.0])])
    class1Y = np.concatenate([class1SupportVectorsY, np.array([
        4.0, 7.9, 12.5, 16.3,
        6.7, 8.1, 17.9, 10.3,
        5.8, 13.2, 19.0,
        9.3, 17.6, 12.0,
        14.5, 8.3, 12.3,
        10.1, 17.1,
        11.7, 16.2, 19.1,
        13.7, 18.3,
        12.3, 16.7,
        15.7, 18.2,
        19.8, 17.9,
        19.0])])
    class1Color = '#0000FF'  # Blue
    class1Size = 30

    # Class 2 data and control variables.
    class2X = np.concatenate([class2SupportVectorsX, np.array([
        4.0,
        5.3, 5.7,
        6.2, 6.6, 6.9,
        7.5,
        8.1, 8.3, 8.7,
        9.2, 9.6,
        10.1, 10.5, 10.9,
        11.4, 11.7,
        12.2, 12.5, 12.9,
        13.1, 13.7,
        14.1, 14.5, 14.6,
        15.0, 15.3, 15.7, 15.9,
        16.1, 16.3, 16.5, 16.9,
        17.0, 17.5, 17.7,
        18.2, 18.3, 18.7,
        19.0, 19.3, 19.7])])
    class2Y = np.concatenate([class2SupportVectorsY, np.array([
        0.6,
        2.2, 1.2,
        0.3, 3.2, 1.7,
        2.4,
        2.3, 5.4, 3.1,
        0.7, 4.3,
        3.2, 5.6, 1.3,
        6.2, 3.4,
        7.8, 1.2, 4.3,
        2.3, 10.0,
        6.8, 11.5, 8.9,
        4.5, 7.5, 13.2, 8.3,
        2.1, 12.0, 5.7, 9.3,
        1.2, 14.4, 4.5,
        3.4, 6.7, 12.3,
        14.3, 10.1, 15.8])])
    class2Color = '#FF0000'  # Red
    class2Size = 30

    # Aggregate all class information.
    scatterXValues = [class1X, class2X]  # The X values for the classes.
    scatterXAllValues = [j for i in scatterXValues for j in i]  # A list of the X values for all the datapoints.
    scatterYValues = [class1Y, class2Y]  # The Y values for the classes.
    scatterYAllValues = [j for i in scatterYValues for j in i]  # A list of the Y values for all the datapoints.
    colors = [class1Color, class2Color]  # The colors for the classes.
    sizes = [class1Size, class2Size]  # The size of the markers for the scatterplots.

    # Define the decision tree boundary.
    decisionBoundarySegmentsXCoords = [[0.0, 0.0], [0.0, 6.0], [6.0, 6.0], [6.0, 11.0], [11.0, 11.0], [11.0, 17.0], [17.0, 17.0], [17.0, 20.0]]
    decisionBoundarySegmentsYCoords = [[0.0, 3.0], [3.0, 3.0], [3.0, 7.0], [7.0, 7.0], [7.0, 15.0], [15.0, 15.0], [15.0, 20.0], [20.0, 20.0]]

    # Create the plot.
    currentFigure = plt.figure()
    gs = gridspec.GridSpec(10, 10)
    gs.update(left=0, right=1, bottom=0, top=1, wspace=0.05)#, hspace=0.05)
    plot = plt.subplot(gs[1:-1, 1:-1])
    plot.set_xlim(left=minX, right=maxX)
    plot.set_ylim(bottom=minY, top=maxY)
    scatterplot.graphGeneration(scatterXValues, scatterYValues, currentFigure=currentFigure, colors=colors, sizes=sizes)
    linegraph.graphGeneration([goodDividingPlaneXCoords], [goodDividingPlaneYCoords], currentFigure=currentFigure, markerSizes=[0], lineWidths=[1], lineStyles=['--'])

    # Create the decision tree boundary.
    for i, j in zip(decisionBoundarySegmentsXCoords, decisionBoundarySegmentsYCoords):
        linegraph.graphGeneration([i], [j], currentFigure=currentFigure, markerSizes=[0], lineWidths=[2])
        if i[0] == i[1]:
            plt.fill_betweenx(j, i, [goodHyperlpaneDividing(y=j[0]), goodHyperlpaneDividing(y=j[1])], color='green', alpha=0.2)
        else:
            plt.fill_between(i, j, [goodHyperlpaneDividing(x=i[0]), goodHyperlpaneDividing(x=i[1])], color='green', alpha=0.2)

    # Make all the tick marks invisible.
    for ax in currentFigure.get_axes():
        removeTickMarks(ax, xAxis=True, yAxis=True)

    plt.savefig(figureSaveLocation, bbox_inches='tight', transparent=True)
    plt.show()

def goodHyperlpaneDividing(x=None, y=None):
    if x != None:
        return x
    if y != None:
        return y

def removeTickMarks(axes, xAxis=False, yAxis=False):
    """Removes all tick marks.
    """

    if xAxis:
        axes.set_xticks([])
    if yAxis:
        axes.set_yticks([])

if __name__ == '__main__':
    main(sys.argv[1])