import time
import pickle
import numpy as np

from matplotlib import pyplot as plt
from keras.datasets import mnist
from functions import *
from Classes import *
from A2C.a2c import A2C

from datetime import date

num_sets = 10

""" Import Data, Set Parameters"""

#debug_mode = False
input_mode = 'minimal' # options: minimal or autoencoder

if input_mode == 'autoencoder':
    filename = "autoencoder_mnist2019-07-11 12:34:09.098789.pickle"

    infile = open(filename,'rb')
    autoencoderModel, encoderModel = pickle.load(infile)

    # Import data
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    # Prepare Input: Normalizing, Flatten Images
    x_train = x_train.astype('float32') / 255.
    x_test = x_test.astype('float32') / 255.
    x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
    x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))

# Hyperparameters for training/testing
num_steps_unrolled = 20
num_steps_unrolled_array = [10, 20, 50, 100]
gamma = .9
gammas = [0.5, 0.8, 0.9, 0.95, 0.99]
a_size = 3 # stay, left, right
num_episode_train = 120000 # Wang: 120000
num_episode_test = 300
num_trial_per_episode = 10 # Should be 10
learning_rate = 7e-4
learning_rates = [5e-4, 7e-4, 1e-3, 2e-3]
num_lstm_units = 48 # Wang: 256
num_lstm_units_array = [16, 48, 256]

# LSTM parameters + Optimizer (currently hardcoded)
# activation = 'tanh'
# recurrent_activation = 'hard_sigmoid'
# use_bias = True
# optimizer = 'rmsprop' # currently rmsprop is hardcoded

# input shape
if input_mode == 'minimal':
    input_size = a_size * 1
elif input_mode == 'autoencoder':
    input_size = a_size * 128 # Todo: Encoder dimensionality is hardcoded
else:
    raise NameError("Input mode is not available, pick 'minimal or 'autoencoder'")

# environment parameters
maxtime_trial = 20
expected_fixation_time = 2
non_fixation_reward = - 0.01#*np.ones((1,1))
fixation_reward = 0.2#*np.ones((1,1))
non_selection_reward = -0.01#*np.ones((1,1))
wrong_selection_reward = -1#*np.ones((1,1))
target_fixation_time = 2

# Configuration parameters
save_variables = 1
save_figures = 0

""" RUN """

for idx_set in num_sets: # gammas, learning_rates, num_lstm_units_array:

    # define empty states as initial values
    empty_state_memory = np.zeros([num_steps_unrolled, input_size])  # for fixation period
    empty_state = np.zeros([1, input_size])
    shortempty_state = np.zeros([1, input_size / a_size])

    # create instance of Advantage Actor Critic
    algorithm = A2C(a_size, input_size, num_lstm_units, num_steps_unrolled, gamma, learning_rate, print_summary=True)

    # empty variables for storing actions, rewards, states and trial indices
    reward_pertrial_matrix = np.zeros([num_episode_train, num_trial_per_episode])
    trial_durations = np.zeros([num_episode_train, num_trial_per_episode])
    rewarded_image = np.zeros(num_episode_train)
    selected_image = np.zeros([num_episode_train, num_trial_per_episode])
    state_values = []
    run_duration = 0
    model = []
    # all_actions, all_states, all_rewards, all_trialIdx, all_hidden_reps, all_good_labels, all_labels\
    #     = [], [], [], [], [], [], []

    time_start = time.time()

    # run episodes
    for idx_episode in range(num_episode_train):

        # Load 2 hidden representations and the corresponding labels
        if input_mode == 'autoencoder':
            # sample hidden representations
            hidden_representations, labels \
                = create_sample_representation(encoderModel, x_train, y_train, is_training=1)
        elif input_mode == 'minimal':
            hidden_representations, labels = pick_digit_sample()

        # pick one of the representations to be the rewarded one
        q = np.random.random_sample()
        if q > 0.5:
            good_label = labels[1]
            rewarded_image[idx_episode] = 2
        else:
            good_label = labels[0]
            rewarded_image[idx_episode] = 1

        # Reset parameters at beginning of an episode
        state_values_episode = []
        episode_states, episode_actions, episode_actions_scalar, episode_rewards,  trialidx_observer = [], [], [], [], []
        state_memory = np.array(empty_state_memory)

        for idx_trial in range(num_trial_per_episode):

            # Reset trial variable dependant variables
            duration, reward,  one_hot_action = 0, 0, np.zeros((1, a_size))
            fixation_time = 0  # counts the fixation time
            fixation_isdone, image_selection_isdone, trial_is_finished = False, False, False
            trial_reward = 0
            second_2last_action = 0
            state_values_trial = []

            # Fixation Block
            while fixation_time < expected_fixation_time and duration < maxtime_trial:
                # select action
                a, action_probs = algorithm.select_action(state_memory)# Note for Debugging: Set a = 0
                current_state_value = algorithm.critic.predict(state_memory)
                state_values_trial.append(current_state_value)
                # reset one_hot_action
                one_hot_action = np.zeros((1, a_size))
                one_hot_action[0, a] = 1

                if a == 0:
                    fixation_time += 1
                    # Collect Fixation Reward if success
                    if fixation_time == expected_fixation_time:
                        reward = fixation_reward
                        # change the state to Left_rep, 0's, Right_rep
                        if input_mode == 'autoencoder':
                            left_state = hidden_representations[0, :]
                            left_state = np.asarray([left_state])
                            right_state = hidden_representations[1, :]
                            right_state = np.asarray([right_state])
                            new_state = np.concatenate([left_state, shortempty_state, right_state], 1)
                        elif input_mode == 'minimal':
                            left_state = hidden_representations[0]
                            left_state = np.asarray([left_state])
                            left_state = np.asarray([left_state])
                            right_state = hidden_representations[1]
                            right_state = np.asarray([right_state])
                            right_state = np.asarray([right_state])
                            new_state = np.concatenate([left_state, shortempty_state, right_state], 1)

                    else:
                        reward = 0
                        new_state = np.array([empty_state])
                else:
                    fixation_time = 0
                    reward = non_fixation_reward
                    new_state = np.array([empty_state])

                # Append state, one_hot_action, reward and log probs
                episode_states.append(np.array(state_memory))
                episode_actions.append(one_hot_action)
                # episode_actions_scalar.append(np.int(a))
                episode_rewards.append(np.float(reward))
                # trialidx_observer.append(idx_trial)
                trial_reward += reward
                duration += 1

                # reconfigure the state memory:
                last_states = np.array([state_memory[1:,:]])
                state_memory[0:num_steps_unrolled-1,:] = last_states
                state_memory[num_steps_unrolled-1,:] = new_state

            while duration < maxtime_trial and not trial_is_finished:

                # select action
                a, action_probs= algorithm.select_action(state_memory) # a = 1, a = 0
                current_state_value = algorithm.critic.predict(state_memory)
                state_values_trial.append(current_state_value)
                # reset one_hot_action
                one_hot_action = np.zeros((1, a_size))
                one_hot_action[0, a] = 1
                if not image_selection_isdone:
                    if a == 0:
                        reward = non_selection_reward
                        new_state = new_state # state remains the same for next trial
                    else:
                        reward = np.zeros((1, 1))
                        image_selection_isdone = True
                        rep_selected = np.int(a - 1)  # Shift by -1 because action 1 stands for 0 and action 2 for 1
                        if a == 1:
                            new_state = np.concatenate([shortempty_state, left_state, shortempty_state], 1)
                            second_2last_action = 1
                        else:
                            new_state = np.concatenate([shortempty_state, right_state, shortempty_state], 1)
                            second_2last_action = 2
                else:  # The selection is done, so we want confirmation or it falls back to selecting an image
                    if a == 0:
                        if good_label == labels[rep_selected]:
                            reward = 1
                        else:
                            reward = wrong_selection_reward
                        trial_is_finished = True
                        new_state = np.array(empty_state)
                    else:
                        reward = non_selection_reward
                        image_selection_isdone = False
                        new_state = np.concatenate([left_state, shortempty_state, right_state],
                                                   1)  # the next state is back to initial config

                # Append state, one_hot_action reward and trial idx
                episode_states.append(np.array(state_memory))
                episode_actions.append(one_hot_action)
                episode_rewards.append(np.float(reward))
                trial_reward += reward
                duration += 1

                # reconfigure the state memory:
                last_states = np.array(state_memory[1:,:])
                state_memory[0:num_steps_unrolled-1,:] = last_states
                state_memory[num_steps_unrolled-1,:] = new_state

                # Todo: create a switch to turn it on an off
                # # switch representation - action assignment with 50%
                # hidden_rep1 = hidden_representations[0, :]
                # hidden_rep2 = hidden_representations[1, :]
                # hidden_representations, labels = mix_up(hidden_rep1, hidden_rep2, labels)

            reward_pertrial_matrix[idx_episode, idx_trial] = trial_reward
            trial_durations[idx_episode, idx_trial] = duration
            selected_image[idx_episode, idx_trial] = second_2last_action
            state_values_episode.append(state_values_trial)

        # append all the critic values of the episode
        state_values.append(state_values_episode)

        # convert from lists into 3-dim array
        episode_states = np.array(episode_states)
        episode_actions = np.array(episode_actions)
        episode_rewards = np.array(episode_rewards)

        # if debug_mode == True:
        #     filename = 'sRa_forDebug.pickle'
        #     infile = open(filename, 'rb')
        #     episode_states, episode_actions, episode_rewards = pickle.load(infile)

        # train the network with data from the episode
        algorithm.train_models(episode_states, episode_actions, episode_rewards, num_steps_unrolled)

    time_loopend = time.time()
    print(["time passed in ",num_episode_train, " episodes:"])
    print(time_loopend - time_start)

    """ Variable Saving and Plotting """
    run_duration = time_loopend-time_start
    today = date.today()
    month = today.month
    day = today.day
    filename = '{0}{1}_nEpisode:{2}_nUnroll:{3}_gamma:{4}_lr:{5}_nLstm:{6}_set:{7}.pickle'.format(month, day, num_episode_train, num_steps_unrolled, gamma, learning_rate, num_lstm_units, num_sets)
    with open('data/{0}'.format(filename), "w") as f:
        pickle.dump([reward_pertrial_matrix, trial_durations, selected_image, rewarded_image, state_values, run_duration, non_selection_reward, non_fixation_reward, wrong_selection_reward], f)
    f.close()

    # #reward_pertrial_matrix = np.transpose(reward_pertrial_matrix)
    # fname = 'figures/RewardsPerTrial{0}{1}_nUnroll:{2}_gamma:{3}_lr:{4}_nLstm:{5}.png'.format(month, day, num_steps_unrolled, gamma, learning_rate, num_lstm_units)
    # plt.figure(1)
    # for idx in range (num_trial_per_episode):
    #     plt.subplot(2,5,idx+1)
    #     plt.plot(reward_pertrial_matrix[:, idx])
    #     if idx == 0:
    #         plt.xlabel('Episode')
    #         plt.ylabel('Reward')
    #         plt.title('Reward per Trial %s' %(idx+1))
    #     else:
    #         plt.title('Trial %s' %(idx+1))
    #     plt.xlim([-10, num_episode_train*1.1])
    #     plt.ylim([-0.4, 1.5])
    #     plt.grid(True)
    #     plt.show()
    # #plt.savefig(fname)
    #
    # # smooth rewards
    # smoothing_coeff = 0.99
    # smooth_reward_pertrial = np.zeros([num_episode_train, num_trial_per_episode])
    # smooth_reward_pertrial[0,:] = reward_pertrial_matrix[0,:]
    # for idx_episode in range(1,num_episode_train):
    #     smooth_reward_pertrial[idx_episode, :] = smoothing_coeff*smooth_reward_pertrial[idx_episode-1, :] \
    #                                              + (1-smoothing_coeff)*reward_pertrial_matrix[idx_episode, :]
    #
    # fname = 'figures/SmoothRewardsPerTrial{0}{1}_nUnroll:{2}_gamma:{3}_lr:{4}_nLstm:{5}.png'.format(month, day, num_steps_unrolled, gamma, learning_rate, num_lstm_units)
    # plt.figure(2)
    # for idx in range (num_trial_per_episode):
    #     plt.subplot(2,5,idx+1)
    #     plt.plot(smooth_reward_pertrial[:, idx])
    #     if idx == 0:
    #         plt.xlabel('Episode')
    #         plt.ylabel('Reward')
    #         plt.title('Smooth Reward per Trial %s' %(idx+1))
    #     else:
    #         plt.title('Trial %s' %(idx+1))
    #     plt.xlim([-10, num_episode_train*1.1])
    #     plt.ylim([-0.4, 1.5])
    #     plt.grid(True)
    #     plt.show()
    # #plt.savefig(fname)


from ephysiopy.axona import axonaIO

class TetrodeDict(dict):
    def __init__(self, filename_root, *args, **kwargs):
        self.filename_root = filename_root
        self.valid_keys = range(1, 33)
        self.update(*args, **kwargs)

    def update(self, *args, **kwargs):
        for k, v in dict(*args, **kwargs).items():
            self[k] = v

    def __getitem__(self, key):
        if isinstance(key, int):
            try:
                val = dict.__getitem__(self, key)
                return val
            except KeyError:
                if key in self.valid_keys:
                    try:
                        val = axonaIO.Tetrode(
                            self.filename_root, key, volts=True)
                        self[key] = val
                        return val
                    except Exception:
                        raise KeyError(f"Tetrode {key} not available")
                else:
                    raise KeyError(f"Tetrode {key} not available")

    def get_spike_samples(self, tetrode, cluster):
        '''
        Returns spike times in pos samples for given cluster from given
        tetrode
        '''
        try:
            this_tet = self[tetrode]
            return this_tet.getClustIdx(cluster)
        except Exception:
            raise Exception(f'Could not get timestamps for cluster: {cluster}')


import logging
from contextvars import ContextVar
from aiohttp import web
from aiohttp.abc import BaseRequest, AbstractAccessLogger
from aiohttp.web import middleware
from aiohttp.web_app import Application
from aiohttp.web_request import Request
from aiohttp.web_response import StreamResponse

# https://docs.aiohttp.org/en/stable/web_advanced.html#contextvars-support
USER_ID_CONTEXT = ContextVar('VAR', default='default')

class CustomAccessLogger(AbstractAccessLogger):
    def log(self,
            request: BaseRequest,
            response: StreamResponse,
            time: float) -> None:
        self.logger.info(f'access_log: {request.remote} '
                         f'"{request.method} {request.path} '
                         f'done in {time}s: {response.status}')

@middleware
async def user_id_middleware(request: Request, handler) -> StreamResponse:
    if request.headers is not None and request.headers.get('x-user-id', '') != '':
        USER_ID_CONTEXT.set(request.headers.get('x-user-id'))
    return await handler(request)

async def handler(request: Request) -> StreamResponse:
    user_id: str = USER_ID_CONTEXT.get()
    return web.Response(text='previous user_id:' + user_id + '\n')

access_logger = logging.getLogger('aiohttp.access')
ch = logging.StreamHandler()
access_logger.setLevel(logging.INFO)
access_logger.addHandler(ch)

app: Application = web.Application()
app.middlewares.append(user_id_middleware)
app.router.add_get('/', handler)

web.run_app(app, port=33000, access_log_class=CustomAccessLogger)


# Q1. Tamanho de uma string

def recursiveLength(value: str):
    if value == "":
        return 0
    else:
        return 1 + recursiveLength(value[1:])

# print(recursiveLength('Pedro'))

# Q.2 Função que imprima na tela uma string (caractere a caractere na mesma linha)

def printStr(string: str):
    if string == "":
        print("")
    else:
        print(string[0], end="")
        printStr(string[1:])

# printStr('Rafael')

# Q.3 Inverter a string

def invertString(string: str):
    if string == "":
        return ""
    else:
        return string[-1] + str(invertString(string[:-1]))

# print(invertString('Rafael'))

# Q.4 Printar a string invertida

def printInverse(string: str):
    if string == "":
        print("")
    else:
        print(string[-1], end="")
        printInverse(string[:-1])

# printInverse('Milena')

# Q.5 Comparar duas strings -> 0: São iguais, 1: str1 > str2 ou -1: str2 > str1
def compareStr(str1, str2):
    if len(str1) == 0 or len(str2) == 0:
        if len(str1) == len(str2):
            return 0
        elif len(str1) > len(str2):
            return 1
        else:
            return -1
    return compareStr(str1[1:], str2[1:])

# print(compareStr("Rafa", "Milena"))

# Q6. Verifica se é palindromo

# O erro da primeira func é que eu não estava retornando a chamada da função

# def ispalindrome(value: str) -> bool:
#     if value[0] != value[-1]:
#         return False
#     # Quer  dizer que a primeira e a ultima letra sao iguais
#     else:
#         # se a string nao tiver vazia, a string passa a ser ela sem a primeira e a ultima letra
#         if len(value) == 0:
#             return True
#         # aqui tiro a primeira e a ultima letra
#         # value = value[1:-1]
#         # chamo novamente a funçao passando a nova string
#         ispalindrome(value[1:-1])

def ispalindrome(value: str) -> bool:
    if len(value) < 2:
        return True
    else:
        if value[0] != value[-1]:
            return False
        else:
            # Aqui :)
            return ispalindrome(value[1:-1])

# print(ispalindrome("ABBA"))

# Q.7 Func p/ retornar as somas até n
def somaAteN(num: int) -> int:
    if num == 0:
        return 0
    return num + somaAteN(num - 1)

# print(somaAteN(5))

# Q.8 recebe uma lista e um num, retorna quantos elementos da lista são menores que num
def menores_rec(lista: list, num: int) -> int:
    if len(lista) == 0:
        return 0
    else:
        if lista[0] < num:
            return 1 + menores_rec(lista[1:], num)
        else:
            return menores_rec(lista[1:], num)

# print(menores_rec([1, 2, 3], 3))

# Q.9 Decimal para binário recursivamente - Como fazer: [https://embarcados.com.br/conversao-entre-sistemas-de-numeracao/]
def dectobin(num: int) -> str:
    if num == 1:
        return "1"
    else:
        return str(dectobin(num // 2)) + str(num % 2)

# print(dectobin(12))

# Q.10 Elemento radioativo que tem meia vida de 50segundo, receber massa em gramas e calcular qto tempo leva p decair até 0.8

def invictusRec(massa: float) -> int:
    if massa < 0.8:
        return massa, 0
    else:
        t = invictusRec(massa / 2)
        return t[0], t[1] + 50

# Apenas para correção

def invictusIterativo(massa):
    tempo = 0
    while massa >= 0.8:
        tempo += 50
        massa = massa / 2
    return massa, tempo

# print(invictusIterativo(10))
# print(invictusRec(10))

# Q.11 Calcular 1/1 ... 1/n até n
def seqTermos1(num):
    if num == 1:
        return 1
    else:
        return 1 / num + seqTermos1(num - 1)

# print(seqTermos1(3))

# Q.12 (nˆ2 + 1)/(n+3) até 1
def seqTermos2(num):
    if num == 1:
        return 2 / 4
    else:
        return (num**2 + 1) / (num + 3) + seqTermos2(num - 1)

# print(seqTermos2(2))

# Q.13 Soma de um vetor de num reais
def somaVec(lista: list) -> float:
    if len(lista) == 1:
        return lista[0]
    else:
        return lista[0] + somaVec(lista[1:])

# print(somaVec([1.5, 2.5, 3]))

# Q.14 Encontrar o maior valor em um vetor
def maior(lista: list):
    if len(lista) == 1:
        return lista[0]
    else:
        if lista[0] < lista[-1]:
            lista = lista[1:]
        else:
            lista = lista[:-1]
        return maior(lista)

# print(maior([1, 50, 50, 4]))

# Q.15 Verificar se o vetor está em ordem crescente
def ordenado(lista: list):
    if len(lista) < 2:
        return True
    else:
        if lista[0] < lista[1]:
            return ordenado(lista[1:])
        else:
            return False

# print(ordenado([1, 2, 3]))
# print(ordenado([1, 4, 3]))


from itertools import product

def solution(users, emoticons):
    answer = []
    for rates in list(product([10, 20, 30, 40], repeat=len(emoticons))):
        cnt, cost = 0, 0
        for rate, price in users:
            total = 0
            for e, r in zip(emoticons, rates):
                if r >= rate:
                    total += e * (1 - r / 100)
            if total >= price:
                cnt += 1
            else:
                cost += total
        answer.append((cnt, cost))
    return sorted(answer)[-1]

프로그래머스/level2/이모티콘 할인행사.py

이모티콘 할인행사.py


from django.conf.urls import patterns, include, url
from blog.views import blog_detail, blog_list

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',

    url(r'^admin/', include(admin.site.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^$', blog_list),
    url(r'^blog/(?P<pk>[0-9]+)/$', blog_detail),
)


from collections import deque

def solution(rectangle, characterX, characterY, itemX, itemY):
    matrix = [[False] * 102 for _ in range(102)]

    for x1, y1, x2, y2 in rectangle:
        for i in range(x1 * 2, x2 * 2 + 1):
            for j in range(y1 * 2, y2 * 2 + 1):
                matrix[i][j] = True

    for x1, y1, x2, y2 in rectangle:
        for i in range(x1 * 2 + 1, x2 * 2):
            for j in range(y1 * 2 + 1, y2 * 2):
                matrix[i][j] = False

    q = deque([(characterX * 2, characterY * 2, 0)])
    directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
    matrix[characterX * 2][characterY * 2] = False

    while q:
        x, y, count = q.popleft()
        if (x, y) == (itemX * 2, itemY * 2):
            return count // 2

        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if matrix[nx][ny]:
                matrix[nx][ny] = False
                q.append((nx, ny, count + 1))

프로그래머스/level3/아이템 줍기.py


import cloudstorage as gcs
import logging
import math
from db import YonderDb
from random import randint

my_default_retry_params = gcs.RetryParams(initial_delay=0.2,
                                          max_delay=5.0,
                                          backoff_factor=2,
                                          max_retry_period=15)
gcs.set_default_retry_params(my_default_retry_params)

class Upload(object):

	def add_video(self, video, thumbnail, caption, user_id, channel, college):
		file_name = "/yander/" + video.filename
		logging.info("Adding new video %s" % video.filename[:-4])
		logging.debug("Caption '%s' User %s Channel %s" % (caption, user_id, channel))
		write_retry_params = gcs.RetryParams(backoff_factor=1.1)
		gcs_file = gcs.open(file_name,
		                    "w",
		                    content_type="video/mp4",
		                    options={"x-goog-acl": "public-read"},
		                    retry_params=write_retry_params)
		file_content = video.file.read()
		gcs_file.write(file_content)
		gcs_file.close()

		file_name = "/yander/" + thumbnail.filename
		logging.info("Adding new thumbnail %s" % thumbnail.filename[:-4])
		write_retry_params = gcs.RetryParams(backoff_factor=1.1)
		gcs_file = gcs.open(file_name,
		                    "w",
		                    content_type="image/jpg",
		                    options={"x-goog-acl": "public-read"},
		                    retry_params=write_retry_params)
		file_content = thumbnail.file.read()
		gcs_file.write(file_content)

		gcs_file.close()
		yonderdb = YonderDb()
		yonderdb.add_video(video.filename[:-4], caption, user_id, channel, college)

class Story(object):

	def get_videos(self, user_id, channel, channel_sort):
		yonderdb = YonderDb()
		video_ids = yonderdb.get_videos(user_id, channel, channel_sort)
		videos_info = []
		if len(video_ids) > 0:
			videos_info = yonderdb.get_video_info(video_ids, user_id)
		yonderdb.add_seen(user_id, video_ids)
		return videos_info

	def get_video(self, user_id, video):
		yonderdb = YonderDb()
		video_ids = [video]
		videos_info = yonderdb.get_video_info(video_ids, user_id)
		return videos_info

	def get_videos_info(self, video_ids):
		yonderdb = YonderDb()
		videos_info = []
		if len(video_ids) > 0:
			videos_info = yonderdb.get_video_info(video_ids, user_id)
		return videos_info

class Video(object):
	def add_rating(self, video_id, rating, user_id):
		yonderdb = YonderDb()
		yonderdb.rate_video(video_id, int(rating), user_id)

	def add_flag(self, video_id, user_id):
		yonderdb = YonderDb()
		yonderdb.report_video(video_id, user_id)

class Feed(object):

	def get_videos(self, user_id, type):
		yonderdb = YonderDb()
		videos = yonderdb.get_feed_videos(user_id, type)
		return videos


import typing as t

from itertools import count

from pca.data.errors import QueryErrors
from pca.interfaces.dao import (
    BatchOfDto,
    BatchOfKwargs,
    Dto,
    Id,
    Ids,
    Kwargs,
)
from pca.utils.dependency_injection import (
    Scopes,
    scope,
)

from .abstract import (
    AbstractDao,
    QueryChain,
)

@scope(Scopes.SINGLETON)
class InMemoryDao(AbstractDao[int]):
    def __init__(self, initial_content: BatchOfKwargs = None):
        self._register: t.Dict[int, Dto] = {}
        self._id_generator = count(1)
        if initial_content:
            self.batch_insert(initial_content)

    def _get_id(self) -> int:
        return next(self._id_generator)

    def _resolve_filter(self, query_chain: QueryChain) -> BatchOfDto:
        if query_chain._filters:
            filter_ = query_chain._reduced_filter
            filtered: BatchOfDto = (dto for dto in self._register.values() if filter_(dto))
        else:
            filtered = self._register.values()
        if query_chain._ids:
            filtered = (dto for dto in filtered if dto.id in query_chain._ids)
        return [dto for dto in filtered if dto]

    def _resolve_get(self, dtos: BatchOfDto, id_: Id, nullable: bool = False) -> t.Optional[Dto]:
        result = next((dto for dto in dtos if dto.id == id_), None)
        if result is not None:
            return result
        elif nullable:
            return
        raise QueryErrors.NOT_FOUND.with_params(id=id_)

    def _resolve_exists(self, query_chain: QueryChain) -> bool:
        filtered = self._resolve_filter(query_chain)
        return bool(filtered)

    def _resolve_count(self, query_chain: QueryChain) -> int:
        filtered = self._resolve_filter(query_chain)
        return len(filtered)

    def _resolve_update(self, query_chain: QueryChain, update: Kwargs) -> Ids:
        updated_dtos = ((dto.update(update), dto.id) for dto in self._resolve_filter(query_chain))
        return [id_ for _, id_ in updated_dtos]

    def _resolve_remove(self, query_chain: QueryChain) -> Ids:
        if query_chain._is_trivial:
            raise QueryErrors.UNRESTRICTED_REMOVE
        dtos_to_remove = (self._register.pop(dto.id) for dto in self._resolve_filter(query_chain))
        return [dto.id for dto in dtos_to_remove]

    def insert(self, **kwargs) -> Id:
        id_ = self._get_id()
        dto = Dto(kwargs)
        dto.__id__ = id_
        self._register[id_] = dto
        return id_

    def batch_insert(self, batch_kwargs: BatchOfKwargs) -> Ids:
        return tuple(self.insert(**kwargs) for kwargs in batch_kwargs)

    def clear(self) -> None:
        self._register.clear()


from Graph import Graph
from Graph import bfs_paths
from Gerador import GeradorCidades
import time

g = Graph()
while True:
    print("1 - Gerar e Carregar Mapa")
    print("2 - Calcular caminho mais curto")
    print("3 - Imprimir Grafo")
    print("0 - Sair")
    opcao = input("Opção: ")

    if opcao == "1":
        #nome = input("Nome do ficheiro: ")
        tarefa = input("Tarefa numero: ")
        if  tarefa == "1":
            numcidade = input("Numero de Cidades: ")
            nome = "tarefa_"+ tarefa +"_"+ numcidade +".txt"

            GeradorCidades(nome, numcidade,tarefa)
            with open(nome) as f:
                first_line = f.readline()

                start = first_line.split()[2]
                g.addVertex(start)

                for line in f:
                    linha = line.rstrip('\n').split(',')  # rstrip para ignorar o \n, split para ignorar as virgulas
                    g.addEdge(linha[0], linha[1], int(linha[2]))
                    last = linha[1]
            print("Mapa carregado")

        # Tenho de alterar algumas coisas ainda
        if tarefa == "2":
            numCidade = input("Numero de Cidades: ")
            nome = "tarefa_"+ tarefa +"_"+ numCidade +".txt"

            GeradorCidades(nome, numCidade,tarefa)
            with open(nome) as f:
                first_line = f.readline()

                start = first_line.split()[2]
                g.addVertex(start)

                for line in f:
                    linha = line.rstrip('\n').split(',')  # rstrip para ignorar o \n, split para ignorar as virgulas
                    g.addEdge2(linha[0], linha[1], int(linha[2]))
                    last = linha[1]
            print("Mapa carregado")

        if tarefa == "3":
            nome = "tarefa_" + tarefa + "_11.txt"

            GeradorCidades(nome, 11,tarefa)
            with open(nome) as f:
                first_line = f.readline()

                start = first_line.split()[2]
                g.addVertex(start)

                for line in f:
                    linha = line.rstrip('\n').split(',')  # rstrip para ignorar o \n, split para ignorar as virgulas
                    g.addEdge(linha[0], linha[1], int(linha[2]))
                    last = linha[1]
            print("Mapa carregado")

    if opcao == "2":
        init = time.time()
        lista = list(bfs_paths(g, start, last))

        n = g.getNumVertices()
        dist = 9999999999
        listtmp = {}
        for i in range(len(lista)):
            if len(lista[int(-i)]) == n:
                if dist > g.calcDist(lista[int(-i)]):
                    dist = g.calcDist(lista[int(-i)])
                    listtmp = lista[int(-i)]
                    # print("Path: " + str(lista[int(-i)]) + " -> Distance: " + str(g.calcDist(lista[int(-i)])))
        print("Caminho mais curto = " + str(listtmp) + ' -> Distância: ' + str(dist))
        end = time.time()
        print("Tempo: " + str(end-init) + " s")

    if opcao == "3":
        for i in g.getVertices():
            print(g.getVertex(i))

    if opcao == "0":
        break


"""
Classes containing the Target config parameters for the high-level interface and
also the functions involving Models generation and assignment to datasets.
"""

from enum import Enum
from typing import List

import astropy.units as u
import numpy as np
from gammapy.modeling import Parameter
from gammapy.modeling.models import (
    SPATIAL_MODEL_REGISTRY,
    SPECTRAL_MODEL_REGISTRY,
    DatasetModels,
    EBLAbsorptionNormSpectralModel,
    FoVBackgroundModel,
    Models,
    SkyModel,
    SpectralModel,
    create_fermi_isotropic_diffuse_model,
)

from asgardpy.base.base import AngleType, BaseConfig, FrameEnum, PathType
from asgardpy.base.geom import SkyPositionConfig
from asgardpy.gammapy.interoperate_models import (
    get_gammapy_spectral_model,
    xml_spatial_model_to_gammapy,
    xml_spectral_model_to_gammapy,
)

__all__ = [
    "BrokenPowerLaw2SpectralModel",
    "EBLAbsorptionModel",
    "ExpCutoffLogParabolaSpectralModel",
    "ModelTypeEnum",
    "RoISelectionConfig",
    "SpatialModelConfig",
    "SpectralModelConfig",
    "Target",
    "apply_selection_mask_to_models",
    "config_to_dict",
    "create_gal_diffuse_skymodel",
    "create_iso_diffuse_skymodel",
    "create_source_skymodel",
    "read_models_from_asgardpy_config",
    "set_models",
]

# Basic components to define the Target Config and any Models Config
class ModelTypeEnum(str, Enum):
    """
    Config section for Different Gammapy Model type.
    """

    skymodel = "SkyModel"
    fovbkgmodel = "FoVBackgroundModel"

class EBLAbsorptionModel(BaseConfig):
    """
    Config section for parameters to use for EBLAbsorptionNormSpectralModel.
    """

    filename: PathType = PathType("None")
    reference: str = ""
    type: str = "EBLAbsorptionNormSpectralModel"
    redshift: float = 0.0
    alpha_norm: float = 1.0

class ModelParams(BaseConfig):
    """Config section for parameters to use for a basic Parameter object."""

    name: str = ""
    value: float = 1
    unit: str = " "
    error: float = 0.1
    min: float = 0.1
    max: float = 10
    frozen: bool = True

class SpectralModelConfig(BaseConfig):
    """
    Config section for parameters to use for creating a SpectralModel object.
    """

    type: str = ""
    parameters: List[ModelParams] = [ModelParams()]
    ebl_abs: EBLAbsorptionModel = EBLAbsorptionModel()

class SpatialModelConfig(BaseConfig):
    """
    Config section for parameters to use for creating a SpatialModel object.
    """

    type: str = ""
    frame: FrameEnum = FrameEnum.icrs
    parameters: List[ModelParams] = [ModelParams()]

class ModelComponent(BaseConfig):
    """Config section for parameters to use for creating a SkyModel object."""

    name: str = ""
    type: ModelTypeEnum = ModelTypeEnum.skymodel
    datasets_names: List[str] = [""]
    spectral: SpectralModelConfig = SpectralModelConfig()
    spatial: SpatialModelConfig = SpatialModelConfig()

class RoISelectionConfig(BaseConfig):
    """
    Config section for parameters to perform some selection on FoV source
    models.
    """

    roi_radius: AngleType = 0 * u.deg
    free_sources: List[str] = []

class CatalogConfig(BaseConfig):
    """Config section for parameters to use information from Catalog."""

    name: str = ""
    selection_radius: AngleType = 0 * u.deg
    exclusion_radius: AngleType = 0 * u.deg

class Target(BaseConfig):
    """Config section for main information on creating various Models."""

    source_name: str = ""
    sky_position: SkyPositionConfig = SkyPositionConfig()
    use_uniform_position: bool = True
    models_file: PathType = PathType("None")
    datasets_with_fov_bkg_model: List[str] = []
    use_catalog: CatalogConfig = CatalogConfig()
    components: List[ModelComponent] = [ModelComponent()]
    covariance: str = ""
    from_3d: bool = False
    roi_selection: RoISelectionConfig = RoISelectionConfig()

class ExpCutoffLogParabolaSpectralModel(SpectralModel):
    r"""Spectral Exponential Cutoff Log Parabola model.

    Using a simple template from Gammapy.

    .. math::
        \phi(E) = \phi_0 \left( \frac{E}{E_0} \right) ^ {
          - \alpha_1 - \beta \log{ \left( \frac{E}{E_0} \right) }} \cdot
          \exp(- {(\lambda E})^{\alpha_2})

    Parameters
    ----------
    amplitude : `~astropy.units.Quantity`
        :math:`\phi_0`
    reference : `~astropy.units.Quantity`
        :math:`E_0`
    alpha_1 : `~astropy.units.Quantity`
        :math:`\alpha_1`
    beta : `~astropy.units.Quantity`
        :math:`\beta`
    lambda_ : `~astropy.units.Quantity`
        :math:`\lambda`
    alpha_2 : `~astropy.units.Quantity`
        :math:`\alpha_2`
    """
    tag = ["ExpCutoffLogParabolaSpectralModel", "ECLP"]

    amplitude = Parameter(
        "amplitude",
        "1e-12 cm-2 s-1 TeV-1",
        scale_method="scale10",
        interp="log",
        is_norm=True,
    )
    reference = Parameter("reference", "1 TeV", frozen=True)
    alpha_1 = Parameter("alpha_1", -2)
    alpha_2 = Parameter("alpha_2", 1, frozen=True)
    beta = Parameter("beta", 1)
    lambda_ = Parameter("lambda_", "0.1 TeV-1")

    @staticmethod
    def evaluate(energy, amplitude, reference, alpha_1, beta, lambda_, alpha_2):
        """Evaluate the model (static function)."""
        en_ref = energy / reference
        exponent = -alpha_1 - beta * np.log(en_ref)
        cutoff = np.exp(-np.power(energy * lambda_, alpha_2))

        return amplitude * np.power(en_ref, exponent) * cutoff

class BrokenPowerLaw2SpectralModel(SpectralModel):
    r"""Spectral broken power-law 2 model.

    In this slightly modified Broken Power Law, instead of having the second index
    as a distinct parameter, the difference in the spectral indices around the
    Break Energy is used, to try for some assumptions on the different physical
    processes that define the full spectrum, where the second process is dependent
    on the first process.

    For more information see :ref:`broken-powerlaw-spectral-model`.

    .. math::
        \phi(E) = \phi_0 \cdot \begin{cases}
                \left( \frac{E}{E_{break}} \right)^{-\Gamma_1} & \text{if } E < E_{break} \\
                \left( \frac{E}{E_{break}} \right)^{-(\Gamma_1 + \Delta\Gamma)} & \text{otherwise}
            \end{cases}

    Parameters
    ----------
    index1 : `~astropy.units.Quantity`
        :math:`\Gamma_1`
    index_diff : `~astropy.units.Quantity`
        :math:`\Delta\Gamma`
    amplitude : `~astropy.units.Quantity`
        :math:`\phi_0`
    ebreak : `~astropy.units.Quantity`
        :math:`E_{break}`

    See Also
    --------
    SmoothBrokenPowerLawSpectralModel
    """

    tag = ["BrokenPowerLaw2SpectralModel", "bpl2"]
    index1 = Parameter("index1", 2.0)
    index_diff = Parameter("index_diff", 1.0)
    amplitude = Parameter(
        name="amplitude",
        value="1e-12 cm-2 s-1 TeV-1",
        scale_method="scale10",
        interp="log",
        is_norm=True,
    )
    ebreak = Parameter("ebreak", "1 TeV")

    @staticmethod
    def evaluate(energy, index1, index_diff, amplitude, ebreak):
        """Evaluate the model (static function)."""
        energy = np.atleast_1d(energy)
        cond = energy < ebreak
        bpwl2 = amplitude * np.ones(energy.shape)

        index2 = index1 + index_diff
        bpwl2[cond] *= (energy[cond] / ebreak) ** (-index1)
        bpwl2[~cond] *= (energy[~cond] / ebreak) ** (-index2)

        return bpwl2

SPECTRAL_MODEL_REGISTRY.append(ExpCutoffLogParabolaSpectralModel)
SPECTRAL_MODEL_REGISTRY.append(BrokenPowerLaw2SpectralModel)

# Function for Models assignment
def set_models(
    config_target,
    datasets,
    datasets_name_list=None,
    models=None,
):
    """
    Set models on given Datasets.

    Parameters
    ----------
    config_target: `AsgardpyConfig.target`
        AsgardpyConfig containing target information.
    datasets: `gammapy.datasets.Datasets`
        Datasets object
    dataset_name_list: List
        List of datasets_names to be used on the Models, before assigning them
        to the given datasets.
    models : `~gammapy.modeling.models.Models` or str of file location or None
        Models object or YAML models string

    Returns
    -------
    datasets: `gammapy.datasets.Datasets`
        Datasets object with Models assigned.
    """
    # Have some checks on argument types
    if isinstance(models, (DatasetModels, list)):
        models = Models(models)
    elif isinstance(models, PathType):
        models = Models.read(models)
    elif models is None:
        models = Models(models)
    else:
        raise TypeError(f"Invalid type: {type(models)}")

    if len(models) == 0:
        if config_target.components[0].name != "":
            models = read_models_from_asgardpy_config(config_target)
        else:
            raise Exception("No input for Models provided for the Target source!")
    else:
        models = apply_selection_mask_to_models(
            list_sources=models,
            target_source=config_target.source_name,
            roi_radius=config_target.roi_selection.roi_radius,
            free_sources=config_target.roi_selection.free_sources,
        )

    if len(config_target.datasets_with_fov_bkg_model) > 0:
        # For extending a Background Model for a given 3D dataset name
        bkg_models = []

        for dataset in datasets:
            if dataset.name in config_target.datasets_with_fov_bkg_model:
                # Check if it is of MapDataset or MapDatasetOnOff type and
                # no associated background model exists already.
                if "MapDataset" in dataset.tag and dataset.background_model is None:
                    bkg_models.append(FoVBackgroundModel(dataset_name=f"{dataset.name}-bkg"))

        models.extend(bkg_models)

    if datasets_name_list is None:
        datasets_name_list = datasets.names

    if len(models) > 1:
        models[config_target.source_name].datasets_names = datasets_name_list

        # Check if FoVBackgroundModel is provided
        bkg_model_name = [m_name for m_name in models.names if "bkg" in m_name]

        if len(bkg_model_name) > 0:
            # Remove the -bkg part of the name of the FoVBackgroundModel to get
            # the appropriate datasets name.
            for bkg_name in bkg_model_name:
                models[bkg_name].datasets_names = [bkg_name[:-4]]
    else:
        models.datasets_names = datasets_name_list

    datasets.models = models

    return datasets, models

def apply_selection_mask_to_models(
    list_sources, target_source=None, selection_mask=None, roi_radius=0 * u.deg, free_sources=[]
):
    """
    For a given list of source models, with a given target source, apply various
    selection masks on the Region of Interest in the sky. This will lead to
    complete exclusion of models or freezing some or all spectral parameters.
    These selections excludes the diffuse background models in the given list.

    First priority is given if a distinct selection mask is provided, with a
    list of excluded regions to return only the source models within the selected
    ROI.

    Second priority is on creating a Circular ROI as per the given radius, and
    freeze all the spectral parameters of the models of the sources.

    Third priority is when a list of free_sources is provided, then the
    spectral amplitude of models of those sources, if present in the given list
    of models, will be unfrozen, and hence, allowed to be variable for fitting.

    Parameters
    ----------
    list_sources: '~gammapy.modeling.models.Models'
        Models object containing a list of source models.
    target_source: 'str'
        Name of the target source, whose position is used as the center of ROI.
    selection_mask: 'WcsNDMap'
        Map containing a boolean mask to apply to Models object.
    roi_radius: 'astropy.units.Quantity' or 'asgardpy.data.base.AngleType'
        Radius for a circular region around ROI (deg)
    free_sources: 'list'
        List of source names for which the spectral amplitude is to be kept free.

    Returns
    -------
    list_sources: '~gammapy.modeling.models.Models'
        Selected Models object.
    """
    list_sources_excluded = []
    list_diffuse = []

    # Separate the list of sources and diffuse background
    for model_ in list_sources:
        if "diffuse" in model_.name or "bkg" in model_.name:
            list_diffuse.append(model_)
        else:
            list_sources_excluded.append(model_)

    list_sources_excluded = Models(list_sources_excluded)

    # Get the target source position as the center of RoI
    if not target_source:
        target_source = list_sources_excluded[0].name
        target_source_pos = target_source.spatial_model.position
    else:
        target_source_pos = list_sources_excluded[target_source].spatial_model.position

    # If a distinct selection mask is provided
    if selection_mask:
        list_sources_excluded = list_sources_excluded.select_mask(selection_mask)

    # If RoI radius is provided and is not default
    if roi_radius.to_value("deg") != 0:
        for model_ in list_sources_excluded:
            model_pos = model_.spatial_model.position
            separation = target_source_pos.separation(model_pos).deg
            if separation >= roi_radius.deg:
                model_.spectral_model.freeze()
    else:
        # For a given list of non free sources, unfreeze the spectral amplitude
        if len(free_sources) > 0:
            for model_ in list_sources_excluded:
                # Freeze all spectral parameters for other models
                if model_.name != target_source:
                    model_.spectral_model.freeze()
                # and now unfreeze the amplitude of selected models
                if model_.name in free_sources:
                    model_.spectral_model.parameters["amplitude"].frozen = False

    # Add the diffuse background models back
    for diff_ in list_diffuse:
        list_sources_excluded.append(diff_)

    # Re-assign to the main variable
    list_sources = list_sources_excluded

    return list_sources

# Functions for Models generation
def read_models_from_asgardpy_config(config):
    """
    Reading Models information from AsgardpyConfig and return Models object.
    If a FoVBackgroundModel information is provided, it will also be added.

    Parameter
    ---------
    config: `AsgardpyConfig`
        Config section containing Target source information

    Returns
    -------
    models: `gammapy.modeling.models.Models`
        Full gammapy Models object.
    """
    models = Models()

    for model_config in config.components:
        if model_config.type == "SkyModel":
            # Spectral Model
            if model_config.spectral.ebl_abs.reference != "":
                model1 = SPECTRAL_MODEL_REGISTRY.get_cls(model_config.spectral.type)().from_dict(
                    {"spectral": config_to_dict(model_config.spectral)}
                )

                ebl_model = model_config.spectral.ebl_abs

                # First check for filename of a custom EBL model
                if ebl_model.filename.is_file():
                    model2 = EBLAbsorptionNormSpectralModel.read(
                        str(ebl_model.filename), redshift=ebl_model.redshift
                    )
                    # Update the reference name when using the custom EBL model for logging
                    ebl_model.reference = ebl_model.filename.name[:-8].replace("-", "_")
                else:
                    model2 = EBLAbsorptionNormSpectralModel.read_builtin(
                        ebl_model.reference, redshift=ebl_model.redshift
                    )
                if ebl_model.alpha_norm:
                    model2.alpha_norm.value = ebl_model.alpha_norm
                spectral_model = model1 * model2
            else:
                if model_config.spectral.type == "ExpCutoffLogParabolaSpectralModel":
                    spectral_model = ExpCutoffLogParabolaSpectralModel().from_dict(
                        {"spectral": config_to_dict(model_config.spectral)}
                    )
                elif model_config.spectral.type == "BrokenPowerLaw2SpectralModel":
                    spectral_model = BrokenPowerLaw2SpectralModel().from_dict(
                        {"spectral": config_to_dict(model_config.spectral)}
                    )
                else:
                    spectral_model = SPECTRAL_MODEL_REGISTRY.get_cls(model_config.spectral.type)().from_dict(
                        {"spectral": config_to_dict(model_config.spectral)}
                    )
            spectral_model.name = config.source_name

            # Spatial model if provided
            if model_config.spatial.type != "":
                spatial_model = SPATIAL_MODEL_REGISTRY.get_cls(model_config.spatial.type)().from_dict(
                    {"spatial": config_to_dict(model_config.spatial)}
                )
            else:
                spatial_model = None

            models.append(
                SkyModel(
                    spectral_model=spectral_model,
                    spatial_model=spatial_model,
                    name=config.source_name,
                )
            )

        # FoVBackgroundModel is the second component
        if model_config.type == "FoVBackgroundModel":
            # Spectral Model. At least this has to be provided for distinct
            # parameter values
            spectral_model_fov = SPECTRAL_MODEL_REGISTRY.get_cls(model_config.spectral.type)().from_dict(
                {"spectral": config_to_dict(model_config.spectral)}
            )

            # Spatial model if provided
            if model_config.spatial.type != "":
                spatial_model_fov = SPATIAL_MODEL_REGISTRY.get_cls(model_config.spatial.type)().from_dict(
                    {"spatial": config_to_dict(model_config.spatial)}
                )
            else:
                spatial_model_fov = None

            models.append(
                FoVBackgroundModel(
                    spectral_model=spectral_model_fov,
                    spatial_model=spatial_model_fov,
                    dataset_name=model_config.datasets_names[0],
                )
            )

    return models

def config_to_dict(model_config):
    """
    Convert the Spectral/Spatial models into dict.
    Probably an extra step and maybe removed later.

    Parameter
    ---------
    model_config: `AsgardpyConfig`
        Config section containing Target Model SkyModel components only.

    Returns
    -------
    model_dict: dict
        dictionary of the particular model.
    """
    model_dict = {}
    model_dict["type"] = str(model_config.type)
    model_dict["parameters"] = []

    for par in model_config.parameters:
        par_dict = {}
        par_dict["name"] = par.name
        par_dict["value"] = par.value
        par_dict["unit"] = par.unit
        par_dict["error"] = par.error
        par_dict["min"] = par.min
        par_dict["max"] = par.max
        par_dict["frozen"] = par.frozen
        model_dict["parameters"].append(par_dict)

    # For spatial model, include frame info
    try:
        getattr(model_dict, "frame")
    except AttributeError:
        pass

    return model_dict

def create_source_skymodel(config_target, source, aux_path, base_model_type="Fermi-XML"):
    """
    Build SkyModels from a given AsgardpyConfig section of the target
    source information, list of XML file and other relevant information.

    Parameters
    ----------
    config_target: `AsgardpyConfig`
        Config section containing the Target source information.
    source: dict
        Dictionary containing the source models information from XML file.
    aux_path: str
        Path location of the DL3 auxiliary files.
    base_model_type: str
        Name indicating the XML format used to read the skymodels from.

    Returns
    -------
    source_sky_model: `gammapy.modeling.SkyModel`
        SkyModels object for the given source information.
    is_source_target: bool
        Boolean to check if the Models belong to the target source.
    """
    # Following a general XML format, taking Fermi-LAT as reference.
    source_name = source["@name"]
    spectrum_type = source["spectrum"]["@type"]
    spectrum = source["spectrum"]["parameter"]

    source_name_check = source_name.replace("_", "").replace(" ", "")
    target_check = config_target.source_name.replace("_", "").replace(" ", "")

    # initialized to check for the case if target spectral model information
    # is to be taken from the Config
    spectral_model = None

    # Check if target_source file exists
    is_source_target = False
    ebl_atten = False

    # If Target source model's spectral component is to be taken from Config
    # and not from 3D dataset.
    if source_name_check == target_check:
        source_name = config_target.source_name
        is_source_target = True

        # Only taking the spectral model information right now.
        if not config_target.from_3d:
            models_ = read_models_from_asgardpy_config(config_target)
            spectral_model = models_[0].spectral_model

    if spectral_model is None:
        # Define the Spectral Model type for Gammapy
        spectral_model, ebl_atten = get_gammapy_spectral_model(
            spectrum_type,
            ebl_atten,
            base_model_type,
        )
        spectrum_type = spectrum_type.split("EblAtten::")[-1]

        # Read the parameter values from XML file to create SpectralModel
        params_list = xml_spectral_model_to_gammapy(
            spectrum,
            spectrum_type,
            is_target=is_source_target,
            keep_sign=ebl_atten,
            base_model_type=base_model_type,
        )

        for param_ in params_list:
            setattr(spectral_model, param_.name, param_)
        config_spectral = config_target.components[0].spectral
        ebl_absorption_included = config_spectral.ebl_abs.reference != ""

        if is_source_target and ebl_absorption_included:
            ebl_model = config_spectral.ebl_abs

            if ebl_model.filename.is_file():
                ebl_spectral_model = EBLAbsorptionNormSpectralModel.read(
                    str(ebl_model.filename), redshift=ebl_model.redshift
                )
                ebl_model.reference = ebl_model.filename.name[:-8].replace("-", "_")
            else:
                ebl_spectral_model = EBLAbsorptionNormSpectralModel.read_builtin(
                    ebl_model.reference, redshift=ebl_model.redshift
                )
            spectral_model = spectral_model * ebl_spectral_model

    # Reading Spatial model from the XML file
    spatial_model = xml_spatial_model_to_gammapy(aux_path, source["spatialModel"], base_model_type)

    spatial_model.freeze()
    source_sky_model = SkyModel(
        spectral_model=spectral_model,
        spatial_model=spatial_model,
        name=source_name,
    )

    return source_sky_model, is_source_target

def create_iso_diffuse_skymodel(iso_file, key):
    """
    Create a SkyModel of the Fermi Isotropic Diffuse Model and assigning
    name as per the observation key. If there are no distinct key types of
    files, the value is None.
    """
    diff_iso = create_fermi_isotropic_diffuse_model(filename=iso_file, interp_kwargs={"fill_value": None})
    if key:
        diff_iso._name = f"{diff_iso.name}-{key}"

    # Parameters' limits
    diff_iso.spectral_model.model1.parameters[0].min = 0.001
    diff_iso.spectral_model.model1.parameters[0].max = 10
    diff_iso.spectral_model.model2.parameters[0].min = 0
    diff_iso.spectral_model.model2.parameters[0].max = 10

    return diff_iso

def create_gal_diffuse_skymodel(diff_gal):
    """
    Create SkyModel of the Diffuse Galactic sources.
    """
    template_diffuse = SPATIAL_MODEL_REGISTRY.get_cls("TemplateSpatialModel")(
        diff_gal, normalize=False, filename=diff_gal.meta["filename"]
    )
    source = SkyModel(
        spectral_model=SPECTRAL_MODEL_REGISTRY.get_cls("PowerLawNormSpectralModel")(),
        spatial_model=template_diffuse,
        name="diffuse-iem",
    )
    source.parameters["norm"].min = 0
    source.parameters["norm"].max = 10
    source.parameters["norm"].frozen = False

    return source


import numpy as np

stars = opinions.stars.value_counts().reindex(np.arange(0,5.5,0.5), fill_value = 0)

stars.plot.bar(color = "red")
plt.title("Gwiazdki")
plt.xlabel("Liczba gwiazdek")
plt.ylabel("Liczba opinii")
plt.savefig("plots/{}.png".format(product_id))
plt.show()
plt.close()

recomm = opinions.recomm.value_counts(dropna = False).sort_index()
recomm.plot.pie(colors = ["red", "green", "blue"])

plt.show()


import contextlib
import ctypes
import sdl2
import sys
import threading
from scope.simple_rpc import rpc_client
from scope import scope_client

SDL_SUBSYSTEMS = sdl2.SDL_INIT_JOYSTICK | sdl2.SDL_INIT_GAMECONTROLLER | sdl2.SDL_INIT_TIMER
SDL_INITED = False
SDL_EVENT_LOOP_IS_RUNNING = False
SDL_TIMER_CALLBACK_TYPE = ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_uint32, ctypes.c_void_p)
DEFAULT_MAX_AXIS_COMMAND_WALLCLOCK_TIME_PORTION = 0.3333
DEFAULT_MAX_AXIS_COMMAND_COOL_OFF = 500
# AXES_THROTTLE_DELAY_EXPIRED_EVENT: Sent by the timer thread to wake up the main
# SDL thread and cause it to update the scope state in response to any axis position changes
# that have occurred since last updating the scope for an axis position change.
AXES_THROTTLE_DELAY_EXPIRED_EVENT = sdl2.SDL_RegisterEvents(1)
COARSE_DEMAND_FACTOR = 20
FINE_DEMAND_FACTOR = 1
Z_DEMAND_FACTOR = 0.5
AXES_MAP = {
    sdl2.SDL_CONTROLLER_AXIS_LEFTX : lambda self, demand: self.scope.stage.move_along_x(-demand * COARSE_DEMAND_FACTOR),
    sdl2.SDL_CONTROLLER_AXIS_LEFTY : lambda self, demand: self.scope.stage.move_along_y(demand * COARSE_DEMAND_FACTOR),
    sdl2.SDL_CONTROLLER_AXIS_RIGHTX : lambda self, demand: self.scope.stage.move_along_x(-demand * FINE_DEMAND_FACTOR),
    sdl2.SDL_CONTROLLER_AXIS_RIGHTY : lambda self, demand: self.scope.stage.move_along_y(demand * FINE_DEMAND_FACTOR),
    sdl2.SDL_CONTROLLER_AXIS_TRIGGERLEFT : lambda self, demand: self.scope.stage.move_along_z(-demand * Z_DEMAND_FACTOR),
    sdl2.SDL_CONTROLLER_AXIS_TRIGGERRIGHT : lambda self, demand: self.scope.stage.move_along_z(demand * Z_DEMAND_FACTOR)
}

def init_sdl():
    global SDL_INITED
    if SDL_INITED:
        sdl2.SDL_SetHint(sdl2.SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, b"1")
    else:
        if sdl2.SDL_Init(SDL_SUBSYSTEMS) < 0:
            sdl_e = sdl2.SDL_GetError()
            sdl_e = sdl_e.decode('utf-8') if sdl_e else 'UNKNOWN ERROR'
            sdl2.SDL_Quit()
            raise RuntimeError('Failed to initialize SDL ("{}").'.format(sdl_e))
        # The following SDL_SetHint call causes SDL2 to process joystick (and game controller, as the
        # game controller subsystem is built on the joystick subsystem) events without a window created
        # and owned by SDL2 focused or even extant.  In our case, we have no SDL2 window, and
        # we do not even initialize the SDL2 video subsystem.
        sdl2.SDL_SetHint(sdl2.SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, b"1")
        if sdl2.SDL_JoystickEventState(sdl2.SDL_QUERY) != sdl2.SDL_ENABLE:
            sdl2.SDL_JoystickEventState(sdl2.SDL_ENABLE)
        if sdl2.SDL_GameControllerEventState(sdl2.SDL_QUERY) != sdl2.SDL_ENABLE:
            sdl2.SDL_GameControllerEventState(sdl2.SDL_ENABLE)
        SDL_INITED = True
        def deinit_sdl():
            sdl2.SDL_QuitSubSystem(SDL_SUBSYSTEMS)
            sdl2.SDL_Quit()
        import atexit
        atexit.register(deinit_sdl)

def enumerate_devices():
    with contextlib.ExitStack() as estack:
        # We may be called from a different thread than the one that will run the SDL event loop.  In case that
        # will happen, if SDL is not already initialized, we do not leave it initialized (if we did, it would be
        # bound to our current thread, which may not be desired).
        if not SDL_INITED:
            if sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK | sdl2.SDL_INIT_GAMECONTROLLER) < 0:
                sdl_e = sdl2.SDL_GetError()
                sdl_e = sdl_e.decode('utf-8') if sdl_e else 'UNKNOWN ERROR'
                sdl2.SDL_Quit()
                raise RuntimeError('Failed to initialize SDL ("{}").'.format(sdl_e))
            estack.callback(lambda: sdl2.SDL_QuitSubSystem(sdl2.SDL_INIT_JOYSTICK | sdl2.SDL_INIT_GAMECONTROLLER))
            estack.callback(sdl2.SDL_Quit)
        rows = []
        for sdl_dev_idx in range(sdl2.SDL_NumJoysticks()):
            device_is_game_controller = bool(sdl2.SDL_IsGameController(sdl_dev_idx))
            device_type = 'game controller' if device_is_game_controller else 'joystick'
            cols = [sdl_dev_idx, device_type, sdl2.SDL_JoystickNameForIndex(sdl_dev_idx).decode('utf-8')]
            if device_is_game_controller:
                cols.append(sdl2.SDL_GameControllerNameForIndex(sdl_dev_idx).decode('utf-8'))
            rows.append(cols)
    return rows

def open_device(input_device_index=0, input_device_name=None, _used_idx_and_name=None):
    if input_device_name is None and int(input_device_index) != input_device_index:
        raise ValueError('If input_device_name is not specified, the value supplied for input_device_index must be an integer.')
    input_device_count = sdl2.SDL_NumJoysticks()
    if input_device_count == 0:
        raise RuntimeError('According to SDL, there are no joysticks/game controllers attached.')
    if input_device_name is None:
        if not 0 <= input_device_index < input_device_count:
            isare, ssuffix = ('is', '') if input_device_count == 1 else ('are', 's')
            e = ('According to SDL, there {0} {1} joystick{2}/game controller{2} attached.  Therefore, input_device_index must be '
                 'an integer in the closed interval [0, {3}], which the supplied value, {4}, is not.')
            raise ValueError(e.format(isare, input_device_count, ssuffix, input_device_count - 1, input_device_index))
        input_device_name = sdl2.SDL_JoystickNameForIndex(input_device_index)
    else:
        if isinstance(input_device_name, str):
            input_device_name = input_device_name.encode('utf-8')
        else:
            input_device_name = bytes(input_device_name)
        for sdl_dev_idx in range(sdl2.SDL_NumJoysticks()):
            if sdl2.SDL_JoystickNameForIndex(sdl_dev_idx) == input_device_name:
                input_device_index = sdl_dev_idx
                break
        else:
            raise ValueError('No connected joystick or game controller device recognized by SDL has the name "{}".'.format(input_device_name.decode('utf-8')))
    device_is_game_controller = bool(sdl2.SDL_IsGameController(input_device_index))
    device = (sdl2.SDL_GameControllerOpen if device_is_game_controller else sdl2.SDL_JoystickOpen)(input_device_index)
    if not device:
        raise RuntimeError('Failed to open {} at device index {} with name "{}".'.format(
            'game controller' if device_is_game_controller else 'joystick',
            input_device_index,
            input_device_name.decode('utf-8'))
        )
    if _used_idx_and_name is not None:
        _used_idx_and_name[0] = input_device_index
        _used_idx_and_name[1] = input_device_name
    return device, device_is_game_controller

def dump_input(input_device_index=0, input_device_name=None):
    init_sdl()
    used_idx_and_name = [None, None]
    device, device_is_game_controller = open_device(input_device_index, input_device_name, used_idx_and_name)
    device_id = sdl2.SDL_JoystickInstanceID(sdl2.SDL_GameControllerGetJoystick(device) if device_is_game_controller else device)
    if device_is_game_controller:
        s = 'Opened game controller, c_name "{}", j_name "{}", idx {}, j_id {}'.format(
            sdl2.SDL_GameControllerName(device).decode('utf-8'),
            used_idx_and_name[1].decode('utf-8'),
            used_idx_and_name[0],
            device_id
        )
    else:
        s = 'Opened joystick, j_name "{}", idx {}, j_id {}'.format(
            used_idx_and_name[1].decode('utf-8'),
            used_idx_and_name[0],
            device_id
        )
    print(s)
    def on_joydeviceaddedevent(event):
        return 'idx: {} j_name: {}'.format(event.jdevice.which, sdl2.SDL_JoystickNameForIndex(event.jdevice.which).decode('utf-8'))
    def on_joydeviceremovedevent(event):
        return 'j_id: {}'.format(event.jdevice.which)
    def on_joyaxismotionevent(event):
        return 'j_id: {} axis: {} pos: {}'.format(event.jaxis.which, event.jaxis.axis, event.jaxis.value)
    def on_joyballmotionevent(event):
        return 'j_id: {} ball: {} xdelta: {} ydelta: {}'.format(event.jball.which, event.jball.ball, event.jball.xrel, event.jball.yrel)
    def on_joyhatmotionevent(event):
        return 'j_id: {} hat: {} pos: {}'.format(event.jhat.which, event.jhat.hat, SDL_HAT_DIRECTION_NAMES.get(event.jhat.value, event.jhat.value))
    def on_joybuttonevent(event):
        return 'j_id: {} button: {} state: {}'.format(
            event.jbutton.which,
            event.jbutton.button,
            'is_pressed' if bool(event.jbutton.state) else 'is_not_pressed'
        )
    def on_controllerdeviceaddedevent(event):
        return 'idx: {} c_name: {}'.format(event.cdevice.which, sdl2.SDL_GameControllerNameForIndex(event.cdevice.which).decode('utf-8'))
    def on_controllerdeviceremovedevent(event):
        return 'c_id: {}'.format(event.cdevice.which)
    def on_controlleraxismotionevent(event):
        return 'c_id: {} axis: {} pos: {}'.format(
            event.caxis.which,
            SDL_CONTROLLER_AXIS_NAMES.get(event.caxis.axis, event.caxis.axis),
            event.caxis.value
        )
    def on_controllerbuttonevent(event):
        return 'c_id: {} button: {} state: {}'.format(
            event.cbutton.which,
            SDL_CONTROLLER_BUTTON_NAMES.get(event.cbutton.button, event.cbutton.button),
            'is_pressed' if bool(event.cbutton.state) else 'is_not_pressed'
        )
    event_handlers = {
        sdl2.SDL_JOYDEVICEADDED : on_joydeviceaddedevent,
        sdl2.SDL_JOYDEVICEREMOVED : on_joydeviceremovedevent,
        sdl2.SDL_JOYAXISMOTION : on_joyaxismotionevent,
        sdl2.SDL_JOYBALLMOTION : on_joyballmotionevent,
        sdl2.SDL_JOYHATMOTION : on_joyhatmotionevent,
        sdl2.SDL_JOYBUTTONDOWN : on_joybuttonevent,
        sdl2.SDL_JOYBUTTONUP : on_joybuttonevent,
        sdl2.SDL_CONTROLLERDEVICEADDED : on_controllerdeviceaddedevent,
        sdl2.SDL_CONTROLLERDEVICEREMOVED : on_controllerdeviceremovedevent,
        sdl2.SDL_CONTROLLERAXISMOTION : on_controlleraxismotionevent,
        sdl2.SDL_CONTROLLERBUTTONDOWN : on_controllerbuttonevent,
        sdl2.SDL_CONTROLLERBUTTONUP : on_controllerbuttonevent
    }
    print('# milliseconds since SDL initialization, SDL_EventType, some event-type-specific information (not necessarily exhaustive)')
    try:
        while 1:
            event = sdl2.SDL_Event()
            # If there is no event for an entire second, we iterate, giving CPython an opportunity to
            # raise KeyboardInterrupt.
            if sdl2.SDL_WaitEventTimeout(ctypes.byref(event), 1000):
                s = '{}, {}'.format(event.generic.timestamp, SDL_EVENT_NAMES.get(event.type, "UNKNOWN"))
                try:
                    s += ', {}'.format(event_handlers[event.type](event))
                except KeyError:
                    pass
                print(s)
                if event.type == sdl2.SDL_QUIT:
                    print('# SDL_QUIT received.  Exiting...')
                    break
                if event.type == sdl2.SDL_JOYDEVICEREMOVED and event.jdevice.which == device_id:
                    print('# Our SDL input device has been disconnected.  Exiting...')
                    break
    except KeyboardInterrupt:
        print('\n# ctrl-c received.  Exiting...')

def only_for_our_device(handler):
    def f(self, event):
        try:
            event_device_id = event.jdevice.which
        except:
            return
        if event_device_id == self.device_id:
            return handler(self, event)
    return f

class SDLControl:
    def __init__(
            self,
            input_device_index=0,
            input_device_name=None,
            scope_server_host='127.0.0.1',
            zmq_context=None,
            maximum_portion_of_wallclock_time_allowed_for_axis_commands=DEFAULT_MAX_AXIS_COMMAND_WALLCLOCK_TIME_PORTION,
            maximum_axis_command_cool_off=DEFAULT_MAX_AXIS_COMMAND_COOL_OFF):
        '''* input_device_index: The argument passed to SDL_JoystickOpen(index) or SDL_GameControllerOpen(index).
        Ignored if the value of input_device_name is not None.
        * input_device_name: If specified, input_device_name should be the exact string or UTF8-encoded bytearray
        by which SDL identifies the controller you wish to use, as reported by SDL_JoystickName(..).  For USB devices,
        this is USB iManufacturer + ' ' + iProduct.  (See example below.)
        * scope_server_host: IP address or hostname of scope server.
        * zmq_context: If None, one is created.
        * maximum_portion_of_wallclock_time_allowed_for_axis_commands: Limit the rate at which commands are sent to the scope
        in response to controller axis motion such that the scope such that the scope is busy processing those commands no more
        than this fraction of the time.
        * maximum_axis_command_cool_off: The maximum number of milliseconds to defer issuance of scope commands in response
        to controller axis motion (in order to enforce maximum_portion_of_wallclock_time_allowed_for_axis_commands).

        For example, a Sony PS4 controller with the following lsusb -v output would be known to SDL as 'Sony Computer
        Entertainment Wireless Controller':

        Bus 003 Device 041: ID 054c:05c4 Sony Corp.
        Device Descriptor:
          bLength                18
          bDescriptorType         1
          bcdUSB               2.00
          bDeviceClass            0
          bDeviceSubClass         0
          bDeviceProtocol         0
          bMaxPacketSize0        64
          idVendor           0x054c Sony Corp.
          idProduct          0x05c4
          bcdDevice            1.00
          iManufacturer           1 Sony Computer Entertainment
          iProduct                2 Wireless Controller
          iSerial                 0
          bNumConfigurations      1
        ...

        Additionally, sdl_control.enumerate_devices(), a module function, returns a list of the currently available
        SDL joystick and game controller input devices, in the order by which SDL knows them.  So, if you know that
        your input device is a Logilech something-or-other, and sdl_control.enumerate_devices() returns the following:
        [
            'Nintenbo Olympic Sport Mat v3.5',
            'MANUFACTURER NAME HERE. DONT FORGET TO SET THIS!!     Many Product Ltd. 1132 Guangzhou    $  !*llSN9_Q   ',
            'Duckhunt Defender Scanline-Detecting Plastic Gun That Sadly Does Not Work With LCDs',
            'Macrosoft ZBox-720 Controller Colossal-Hands Mondo Edition',
            'Logilech SixThousandAxis KiloButtonPad With Haptic Feedback Explosion',
            'Gametech Gameseries MegaGamer Excel Spreadsheet 3D-Orb For Executives, Doom3D Edition',
            'Gametech Gameseries MegaGamer Excel Spreadsheet 3D-Orb For Light Rail Transport, Doom3D Edition'
        ]
        You will therefore want to specify input_device_index=4 or
        input_device_name='Logilech SixThousandAxis KiloButtonPad With Haptic Feedback Explosion'
        '''
        assert 0 < maximum_portion_of_wallclock_time_allowed_for_axis_commands <= 1
        init_sdl()
        self.device, self.device_is_game_controller = open_device(input_device_index, input_device_name)
        if self.device_is_game_controller:
            self.jdevice = sdl2.SDL_GameControllerGetJoystick(self.device)
        else:
            self.jdevice = self.device
        self.device_id = sdl2.SDL_JoystickInstanceID(self.jdevice)
        self.num_axes = sdl2.SDL_JoystickNumAxes(self.jdevice)
        self.num_buttons = sdl2.SDL_JoystickNumButtons(self.jdevice)
        self.num_hats = sdl2.SDL_JoystickNumHats(self.jdevice)
        print('SDLControl is connecting to scope server...', file=sys.stderr)
        self.scope, self.scope_properties = scope_client.client_main(scope_server_host, zmq_context)
        print('SDLControl successfully connected to scope server.', file=sys.stderr)
        self.event_loop_is_running = False
        self.warnings_enabled = False
        self.quit_event_posted = False
        self.throttle_delay_command_time_ratio = 1 - maximum_portion_of_wallclock_time_allowed_for_axis_commands
        self.throttle_delay_command_time_ratio /= maximum_portion_of_wallclock_time_allowed_for_axis_commands
        self.maximum_axis_command_cool_off = maximum_axis_command_cool_off
        self._axes_throttle_delay_lock = threading.Lock()
        self._c_on_axes_throttle_delay_expired_timer_callback = SDL_TIMER_CALLBACK_TYPE(self._on_axes_throttle_delay_expired_timer_callback)

    def _init_handlers(self):
        self._event_handlers = {
            sdl2.SDL_QUIT : self._on_quit,
            AXES_THROTTLE_DELAY_EXPIRED_EVENT : self._on_axes_throttle_delay_expired_event
        }
        if self.device_is_game_controller:
            self._event_handlers.update({
                sdl2.SDL_CONTROLLERDEVICEREMOVED : self._on_device_removed,
                sdl2.SDL_CONTROLLERAXISMOTION : self._on_axis_motion,
                sdl2.SDL_CONTROLLERBUTTONDOWN : self._on_button,
                sdl2.SDL_CONTROLLERBUTTONUP : self._on_button
            })
        else:
            self._event_handlers.update({
                sdl2.SDL_JOYDEVICEREMOVED : self._on_device_removed,
                sdl2.SDL_JOYAXISMOTION : self._on_axis_motion,
                sdl2.SDL_JOYBUTTONDOWN : self._on_button,
                sdl2.SDL_JOYBUTTONUP : self._on_button
            })

    def event_loop(self):
        global SDL_EVENT_LOOP_IS_RUNNING
        assert not SDL_EVENT_LOOP_IS_RUNNING
        self._next_axes_tick = 0
        self._axes_throttle_delay_timer_set = False
        self._last_axes_positions = {axis_idx : None for axis_idx in AXES_MAP.keys()}
        self._get_axis_pos = sdl2.SDL_GameControllerGetAxis if self.device_is_game_controller else sdl2.SDL_JoystickGetAxis
        SDL_EVENT_LOOP_IS_RUNNING = True
        def on_loop_end():
            global SDL_EVENT_LOOP_IS_RUNNING
            SDL_EVENT_LOOP_IS_RUNNING = False
        with contextlib.ExitStack() as estack:
            estack.callback(on_loop_end)
            assert SDL_INITED
            assert self.device
            self._init_handlers()
            try:
                while not self.quit_event_posted:
                    event = sdl2.SDL_Event()
                    # If there is no event for an entire second, we iterate, giving CPython an opportunity to
                    # raise KeyboardInterrupt.
                    if sdl2.SDL_WaitEventTimeout(ctypes.byref(event), 1000):
                        self._event_handlers.get(event.type, self._on_unhandled_event)(event)
            except KeyboardInterrupt:
                pass

    def exit_event_loop(self):
        '''The exit_event_loop method is thread safe and is safe to call even if the event loop is not running.
        Calling exit_event_loop pushes a quit request onto the SDL event queue, causing self.event_loop() to
        exit gracefully (IE, return) if it is running.'''
        event = sdl2.SDL_Event()
        event.type = sdl2.SDL_QUIT
        sdl2.SDL_PushEvent(ctypes.byref(event))

    def _on_quit(self, event):
        self.quit_event_posted = True

    def _on_unhandled_event(self, event):
        if self.warnings_enabled:
            print('Received unhandled SDL event: ' + SDL_EVENT_NAMES.get(event.type, "UNKNOWN"), file=sys.stderr)

    @only_for_our_device
    def _on_device_removed(self, event):
        print('Our SDL input device has been disconnected.  Exiting event loop...', sys.stderr)
        self.exit_event_loop()

    @only_for_our_device
    def _on_button(self, event):
        if self.device_is_game_controller:
            idx = event.cbutton.button
            state = bool(event.cbutton.state)
        else:
            idx = event.jbutton.button
            state = bool(event.jbutton.state)
        if idx == sdl2.SDL_CONTROLLER_BUTTON_A:
            # Hardcode ps4 X button to stop all stage movement
            self.scope.stage.stop_x()
            self.scope.stage.stop_y()
            self.scope.stage.stop_z()

    @only_for_our_device
    def _on_axis_motion(self, event):
        # A subtle point: we need to set the axes throttle delay timer only when cooldown has not expired and
        # no timer is set.  That is, if the joystick moves, SDL tells us about it.  When SDL tells us, if we
        # have too recently handled an axis move event, we defer handling the event by setting a timer that wakes
        # us up when the cooldown has expired.  There is never a need to set a new axes throttle delay timer
        # in response to timer expiration.
        curr_ticks = sdl2.SDL_GetTicks()
        if curr_ticks >= self._next_axes_tick:
            self._handle_axes_motion()
        else:
            with self._axes_throttle_delay_lock:
                if not self._axes_throttle_delay_timer_set:
                    defer_ticks = round(max(1, self._next_axes_tick - curr_ticks))
                    if not sdl2.SDL_AddTimer(defer_ticks, self._c_on_axes_throttle_delay_expired_timer_callback, ctypes.c_void_p(0)):
                        sdl_e = sdl2.SDL_GetError()
                        sdl_e = sdl_e.decode('utf-8') if sdl_e else 'UNKNOWN ERROR'
                        raise RuntimeError('Failed to set timer: {}'.format(sdl_e))
                    self._axes_throttle_delay_timer_set = True

    def _on_axes_throttle_delay_expired_timer_callback(self, interval, _):
        # NB: SDL timer callbacks execute on a special thread that is not the main thread
        if not SDL_EVENT_LOOP_IS_RUNNING:
            return
        with self._axes_throttle_delay_lock:
            self._axes_throttle_delay_timer_set = False
            if sdl2.SDL_GetTicks() < self._next_axes_tick:
                if self.warnings_enabled:
                    print('Axes throttling delay expiration callback pre-empted.', sys.stderr)
                return 0
        event = sdl2.SDL_Event()
        event.type = AXES_THROTTLE_DELAY_EXPIRED_EVENT
        sdl2.SDL_PushEvent(event)
        # Returning 0 tells SDL to not recycle this timer.  _handle_axes_motion, in the main SDL thread, will
        # ultimately be caused to set a new timer by the event we just pushed.
        return 0

    def _on_axes_throttle_delay_expired_event(self, event):
        if sdl2.SDL_GetTicks() < self._next_axes_tick:
            if self.warnings_enabled:
                print('Axes throttling delay expiration event pre-empted.', sys.stderr)
            return
        self._handle_axes_motion()

    def _handle_axes_motion(self):
        command_ticks = 0
        for axis, cmd in AXES_MAP.items():
            pos = self._get_axis_pos(self.device, axis)
            if pos != self._last_axes_positions[axis]:
                demand = pos / (32768 if pos <= 0 else 32767)
                t0 = sdl2.SDL_GetTicks()
                cmd(self, demand)
                t1 = sdl2.SDL_GetTicks()
                self._last_axes_positions[axis] = pos
                command_ticks += t1 - t0
        self._next_axes_tick = sdl2.SDL_GetTicks() + int(min(
            command_ticks * self.throttle_delay_command_time_ratio,
            self.maximum_axis_command_cool_off
        ))

SDL_EVENT_NAMES = {
    sdl2.SDL_APP_DIDENTERBACKGROUND : 'SDL_APP_DIDENTERBACKGROUND',
    sdl2.SDL_APP_DIDENTERFOREGROUND : 'SDL_APP_DIDENTERFOREGROUND',
    sdl2.SDL_APP_LOWMEMORY : 'SDL_APP_LOWMEMORY',
    sdl2.SDL_APP_TERMINATING : 'SDL_APP_TERMINATING',
    sdl2.SDL_APP_WILLENTERBACKGROUND : 'SDL_APP_WILLENTERBACKGROUND',
    sdl2.SDL_APP_WILLENTERFOREGROUND : 'SDL_APP_WILLENTERFOREGROUND',
    sdl2.SDL_CLIPBOARDUPDATE : 'SDL_CLIPBOARDUPDATE',
    sdl2.SDL_CONTROLLERAXISMOTION : 'SDL_CONTROLLERAXISMOTION',
    sdl2.SDL_CONTROLLERBUTTONDOWN : 'SDL_CONTROLLERBUTTONDOWN',
    sdl2.SDL_CONTROLLERBUTTONUP : 'SDL_CONTROLLERBUTTONUP',
    sdl2.SDL_CONTROLLERDEVICEADDED : 'SDL_CONTROLLERDEVICEADDED',
    sdl2.SDL_CONTROLLERDEVICEREMAPPED : 'SDL_CONTROLLERDEVICEREMAPPED',
    sdl2.SDL_CONTROLLERDEVICEREMOVED : 'SDL_CONTROLLERDEVICEREMOVED',
    sdl2.SDL_DOLLARGESTURE : 'SDL_DOLLARGESTURE',
    sdl2.SDL_DOLLARRECORD : 'SDL_DOLLARRECORD',
    sdl2.SDL_DROPFILE : 'SDL_DROPFILE',
    sdl2.SDL_FINGERDOWN : 'SDL_FINGERDOWN',
    sdl2.SDL_FINGERMOTION : 'SDL_FINGERMOTION',
    sdl2.SDL_FINGERUP : 'SDL_FINGERUP',
    sdl2.SDL_FIRSTEVENT : 'SDL_FIRSTEVENT',
    sdl2.SDL_JOYAXISMOTION : 'SDL_JOYAXISMOTION',
    sdl2.SDL_JOYBALLMOTION : 'SDL_JOYBALLMOTION',
    sdl2.SDL_JOYBUTTONDOWN : 'SDL_JOYBUTTONDOWN',
    sdl2.SDL_JOYBUTTONUP : 'SDL_JOYBUTTONUP',
    sdl2.SDL_JOYDEVICEADDED : 'SDL_JOYDEVICEADDED',
    sdl2.SDL_JOYDEVICEREMOVED : 'SDL_JOYDEVICEREMOVED',
    sdl2.SDL_JOYHATMOTION : 'SDL_JOYHATMOTION',
    sdl2.SDL_KEYDOWN : 'SDL_KEYDOWN',
    sdl2.SDL_KEYUP : 'SDL_KEYUP',
    sdl2.SDL_LASTEVENT : 'SDL_LASTEVENT',
    sdl2.SDL_MOUSEBUTTONDOWN : 'SDL_MOUSEBUTTONDOWN',
    sdl2.SDL_MOUSEBUTTONUP : 'SDL_MOUSEBUTTONUP',
    sdl2.SDL_MOUSEMOTION : 'SDL_MOUSEMOTION',
    sdl2.SDL_MOUSEWHEEL : 'SDL_MOUSEWHEEL',
    sdl2.SDL_MULTIGESTURE : 'SDL_MULTIGESTURE',
    sdl2.SDL_QUIT : 'SDL_QUIT',
    sdl2.SDL_RENDER_DEVICE_RESET : 'SDL_RENDER_DEVICE_RESET',
    sdl2.SDL_RENDER_TARGETS_RESET : 'SDL_RENDER_TARGETS_RESET',
    sdl2.SDL_SYSWMEVENT : 'SDL_SYSWMEVENT',
    sdl2.SDL_TEXTEDITING : 'SDL_TEXTEDITING',
    sdl2.SDL_TEXTINPUT : 'SDL_TEXTINPUT',
    sdl2.SDL_WINDOWEVENT : 'SDL_WINDOWEVENT'
}

SDL_CONTROLLER_AXIS_NAMES = {
    sdl2.SDL_CONTROLLER_AXIS_INVALID : 'SDL_CONTROLLER_AXIS_INVALID',
    sdl2.SDL_CONTROLLER_AXIS_LEFTX : 'SDL_CONTROLLER_AXIS_LEFTX',
    sdl2.SDL_CONTROLLER_AXIS_LEFTY : 'SDL_CONTROLLER_AXIS_LEFTY',
    sdl2.SDL_CONTROLLER_AXIS_RIGHTX : 'SDL_CONTROLLER_AXIS_RIGHTX',
    sdl2.SDL_CONTROLLER_AXIS_RIGHTY : 'SDL_CONTROLLER_AXIS_RIGHTY',
    sdl2.SDL_CONTROLLER_AXIS_TRIGGERLEFT : 'SDL_CONTROLLER_AXIS_TRIGGERLEFT',
    sdl2.SDL_CONTROLLER_AXIS_TRIGGERRIGHT : 'SDL_CONTROLLER_AXIS_TRIGGERRIGHT',
    sdl2.SDL_CONTROLLER_AXIS_MAX : 'SDL_CONTROLLER_AXIS_MAX'
}

SDL_CONTROLLER_BUTTON_NAMES = {
    sdl2.SDL_CONTROLLER_BUTTON_INVALID : 'SDL_CONTROLLER_BUTTON_INVALID',
    sdl2.SDL_CONTROLLER_BUTTON_A : 'SDL_CONTROLLER_BUTTON_A',
    sdl2.SDL_CONTROLLER_BUTTON_B : 'SDL_CONTROLLER_BUTTON_B',
    sdl2.SDL_CONTROLLER_BUTTON_X : 'SDL_CONTROLLER_BUTTON_X',
    sdl2.SDL_CONTROLLER_BUTTON_Y : 'SDL_CONTROLLER_BUTTON_Y',
    sdl2.SDL_CONTROLLER_BUTTON_BACK : 'SDL_CONTROLLER_BUTTON_BACK',
    sdl2.SDL_CONTROLLER_BUTTON_GUIDE : 'SDL_CONTROLLER_BUTTON_GUIDE',
    sdl2.SDL_CONTROLLER_BUTTON_START : 'SDL_CONTROLLER_BUTTON_START',
    sdl2.SDL_CONTROLLER_BUTTON_LEFTSTICK : 'SDL_CONTROLLER_BUTTON_LEFTSTICK',
    sdl2.SDL_CONTROLLER_BUTTON_RIGHTSTICK : 'SDL_CONTROLLER_BUTTON_RIGHTSTICK',
    sdl2.SDL_CONTROLLER_BUTTON_LEFTSHOULDER : 'SDL_CONTROLLER_BUTTON_LEFTSHOULDER',
    sdl2.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER : 'SDL_CONTROLLER_BUTTON_RIGHTSHOULDER',
    sdl2.SDL_CONTROLLER_BUTTON_DPAD_UP : 'SDL_CONTROLLER_BUTTON_DPAD_UP',
    sdl2.SDL_CONTROLLER_BUTTON_DPAD_DOWN : 'SDL_CONTROLLER_BUTTON_DPAD_DOWN',
    sdl2.SDL_CONTROLLER_BUTTON_DPAD_LEFT : 'SDL_CONTROLLER_BUTTON_DPAD_LEFT',
    sdl2.SDL_CONTROLLER_BUTTON_DPAD_RIGHT : 'SDL_CONTROLLER_BUTTON_DPAD_RIGHT',
    sdl2.SDL_CONTROLLER_BUTTON_MAX : 'SDL_CONTROLLER_BUTTON_MAX'
}

SDL_HAT_DIRECTION_NAMES = {
    sdl2.SDL_HAT_LEFTUP : 'SDL_HAT_LEFTUP',
    sdl2.SDL_HAT_UP : 'SDL_HAT_UP',
    sdl2.SDL_HAT_RIGHTUP : 'SDL_HAT_RIGHTUP',
    sdl2.SDL_HAT_LEFT : 'SDL_HAT_LEFT',
    sdl2.SDL_HAT_CENTERED : 'SDL_HAT_CENTERED',
    sdl2.SDL_HAT_RIGHT : 'SDL_HAT_RIGHT',
    sdl2.SDL_HAT_LEFTDOWN : 'SDL_HAT_LEFTDOWN',
    sdl2.SDL_HAT_DOWN : 'SDL_HAT_DOWN',
    sdl2.SDL_HAT_RIGHTDOWN : 'SDL_HAT_RIGHTDOWN'
}

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(epilog='Note: Either device_name/index, --list (-l), or --dump-sdl-input (-d) device_name/index must be supplied.')
    parser.add_argument('--scope', '-s', default='127.0.0.1', help='Hostname or IP address of the scope server.  Defaults to "127.0.0.1".')
    parser.add_argument(
        '--enable-warnings',
        '-w',
        action='store_true',
        help='Print warnings to stderr when unhandled events are received.')
    parserg = parser.add_mutually_exclusive_group(required=True)
    parserg.add_argument(
        '--list',
        '-l',
        action='store_true',
        help='For each detected SDL joystick and game controller, print a line containing "index, type, joystick name, game controller name".  '
             'The game controller name field is omitted for joysticks that are not also game controllers (all game controllers are joysticks, but '
             'the reverse is not always true).  Then exit.  No connection to the scope server is established.'
    )
    parserg.add_argument(
        '--dump-sdl-input',
        '-d',
        metavar='DEVICE_NAME_OR_INDEX',
        help='Print SDL input from the specified device, formatted for human consumption, to stdout.  Exit gracefully upon '
             'ctrl-c.  Nothing is done with the input aside from printing it to stdout, and no connection to the scope server '
             'is established.'
    )
    parserg.add_argument('device', metavar='DEVICE_NAME_OR_INDEX', nargs='?', help='SDL input device name or index.')
    args = parser.parse_args()
    if args.list:
        for cols in enumerate_devices():
            print(', '.join(str(col) for col in cols))
    elif args.dump_sdl_input is not None:
        if args.dump_sdl_input.isdigit():
            dump_input(input_device_index=int(args.dump_sdl_input))
        else:
            dump_input(input_device_name=args.dump_sdl_input)
    else:
        if args.device.isdigit():
            sdlc = SDLControl(input_device_index=int(args.device), scope_server_host=args.scope)
        else:
            sdlc = SDLControl(input_device_name=args.device, scope_server_host=args.scope)
        sdlc.warnings_enabled = args.enable_warnings
        sdlc.event_loop()


import json
import nltk
from nltk.corpus import stopwords
import nltk
from sklearn import linear_model, svm
import pickle
from gensim.models import Word2Vec
import math
import heapq
import statistics
import numpy

# dictionary of 22 most common POS tags
pos_tags = {
    "CC": 0, "CD": 1, "DT": 2, "IN": 3, "JJ": 4, "JJS": 5, "MD": 6, "NN": 7, "NNS": 8, "NNP": 9, "POS": 10, "PRP": 11,
    "PRP$": 12, "RB": 13, "RP": 14, "TO": 15, "VB": 16, "VBD": 17, "VBG": 18, "VBP": 19, "VBZ": 20, "WRB": 21
}

# function to remove stop words (eg. 'a', 'the')
def remove_stopwords(text):
    stop_words = set(stopwords.words('english'))
    word_tokens = nltk.tokenize.word_tokenize(text)
    filtered_sentence = [w for w in word_tokens if not w in stop_words]
    return filtered_sentence

# returns tags given a sentence
def pos_tagging(sentence):
    tokens = nltk.word_tokenize(sentence.lower())
    tags = nltk.pos_tag(tokens)
    return tags

# after being tagged, create feature vector of the part-of-speech counts
# this vector will be used to train the model
def vectorize_sentence(sentence):
    pos_count = [0]*(len(pos_tags)*(len(pos_tags) + 1))
    pos = pos_tagging(sentence)
    for word in pos:
        if word[1] in pos_tags.keys():
            pos_count[pos_tags[word[1]]] += 1

    # now we do squared part
    for i in range(len(pos) - 1):
        if pos[i][1] in pos_tags.keys():
            if pos[i+1][1] in pos_tags.keys():
                position_index = len(pos_tags) + len(pos_tags) * pos_tags[pos[i][1]] + pos_tags[pos[i+1][1]]
                pos_count[position_index] += 1
    # print(pos_count)
    return pos_count

# testing word2vec
def run_word2vec():
    with open('data.txt') as json_file:
        data = json.load(json_file)

    sentences = []
    for video in data:
        sentences.append(data[video][0])

    # print(sentences)
    word2vec = Word2Vec(sentences)
    vocabulary = word2vec.wv.vocab
    print(word2vec.wv['artificial'])

# take text and turn it into a usable format
# remove non ascii characters, chunking (NER), lemmatization, stopwords
def preprocess_data():
    with open('data/video_data.txt') as json_file:
        data = json.load(json_file)

    features = []
    labels = []

    for video in data:
        video_title = data[video][0]
        features.append(vectorize_sentence(video_title))
        # features.append(video_title)
        ratio = math.sqrt(int(data[video][3]) / int(data[video][1]))
        labels.append(ratio)
    return features, labels

# classifying based on extracted features (vector of pos tags)
def train_model(features, labels):
    regr = svm.SVR()
    regr.fit(features, labels)
    pickle.dump(regr, open('nlp_model.sav', 'wb'))

# run to train the model
def main():
    features, labels = preprocess_data()
    train_model(features, labels)
    # run_word2vec()

if __name__ == "__main__":
    main()


def dpll(cnf_formula, assignment={}):
    # Check for empty clauses
    if any(len(clause) == 0 for clause in cnf_formula):
        return False, {}  # Unsolvable

    # Check for all clauses being satisfied
    if all(any(lit in assignment and assignment[lit] for lit in clause) for clause in cnf_formula):
        return True, assignment  # Satisfiable

    # Unit propagation
    unit_clauses = [clause[0] for clause in cnf_formula if len(clause) == 1]
    for lit in unit_clauses:
        assignment[lit] = True

    # Pure literal elimination
    pure_literals = set()
    for clause in cnf_formula:
        for lit in clause:
            if -lit not in pure_literals:
                pure_literals.add(lit)
    for lit in pure_literals:
        assignment[lit] = True

    # Find an unassigned literal (naive approach)
    chosen_lit = None
    for clause in cnf_formula:
        for lit in clause:
            if lit not in assignment and -lit not in assignment:
                chosen_lit = lit
                break
        if chosen_lit is not None:
            break

    if chosen_lit is None:
        # If no unassigned literals are found, the assignment is complete
        return True, assignment

    # Branching: Try both assignments
    result, new_assignment = dpll(cnf_formula, {**assignment, chosen_lit: True})
    if result:
        return True, new_assignment

    result, new_assignment = dpll(cnf_formula, {**assignment, -chosen_lit: True})
    if result:
        return True, new_assignment

    # Backtrack
    return False, {}

# Example usage:
if __name__ == "__main__":
    cnf_formula = [[1, 2, -3], [-1, 3, 4], [-2, -4, 5]]
    is_satisfiable, assignment = dpll(cnf_formula)
    if is_satisfiable:
        print("Satisfiable. Assignment:", assignment)
    else:
        print("Unsatisfiable.")


import numpy as np
import matplotlib.pyplot as plt
import cv2
import config as p

def debug(array):
    plt.imshow(array)
    plt.show()

def CA_1d(U,w,A,B):
    CA = np.zeros((w))
    for i in range(1,w-1):
        Ujk_n = np.max((U[i-1],U[i+1]))
        CA[i] = calc_value(Ujk_n,A,B)

    return CA

def calc_value(Ujk_n,A,B):
    if Ujk_n < B/2:
        return 0
    if ((Ujk_n >= B/2) and (Ujk_n < (A + B)/2)):
        return 2 * Ujk_n - B
    if Ujk_n >= (A + B)/2:
        return A

def main():

    w =  13
    A = 5
    B = 0
    data = []
    U = np.zeros((w))

    if p.mode == "erosion":
        for i in range(w):
            x_ = abs(i-int(w/2))
            U[i]= x_
    else:
        for i in range(w):
            x_ = abs(i-int(w/2))
            U[i] = x_
        in_value = np.max(U)
        U = abs(in_value - U)-1

    print(U[1:w-1])
    data.append(U[1:w-1])
    CA = CA_1d(U,w,A,B)
    print(CA[1:w-1])
    data.append(CA[1:w-1])
    for i in range(12):
        CA = CA_1d(CA,w,A,B)
        print(CA[1:w-1])
        data.append(CA[1:w-1])

    plt.imshow(np.array(data))
    plt.xlabel("空間 j ")
    plt.xticks(range(w-2))
    plt.ylabel("時間経過 n ")
    plt.yticks(range(12))
    plt.colorbar()
    # plt.grid(c='white', zorder=50)
    plt.show()

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""
Created on Sat Mar 28 23:37:56 2015

@author: n4p
"""

import time
from src.httpServer import http_request
from src.httpServer import http_server
from src.config import Config

conf = Config(filename="sandbagger.conf")

Handler = http_request.HttpRequest
HTTPD = http_server.HttpServer(Handler, int(conf.value("Server/port")))
HTTPD.set_cert(conf.value("Server/cert"), conf.value("Server/key"))
HTTPD.start()
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("Server shutting down")
HTTPD.stop()