"""A class that provides methods used to properly format and display replay data"""

import copy
from immutabledict import immutabledict
from typing import Iterable, Optional
from . import game_ids
from replays import models

#   These table fields configure the display of the stage split columns
#   These may differ from whether the replay file actually has the field or not
#       depending on whether it is relevant to show that field
#   eg. life_pieces will almost always be False as displaying it is integrated into Lives

_table_fields_th06 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": False,
        "graze": False,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": True,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th07 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": True,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": True,
        "th07_cherrymax": True,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th08 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": True,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th09 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": False,
        "graze": False,
        "point_items": False,
        "power": False,
        "lives": True,
        "bombs": False,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": True,
        "th09_p2_score": True,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th09_PVP = immutabledict(
    {
        "stage": True,
        "score": False,
        "piv": False,
        "graze": False,
        "point_items": False,
        "power": False,
        "lives": False,
        "bombs": False,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": True,
        "th09_p2_cpu": True,
        "th09_p2_shot": True,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th10 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": False,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": False,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th11 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": False,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th12 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th13 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": True,
        "th16_season_power": False,
        "extends": True,
    }
)

_table_fields_th14 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th15 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th16 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": True,
        "extends": False,
    }
)

_table_fields_th17 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th18 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": True,
        "graze": True,
        "point_items": False,
        "power": True,
        "lives": True,
        "bombs": True,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": False,
        "th128_perfect_freeze": False,
        "th128_frozen_area": False,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_table_fields_th128 = immutabledict(
    {
        "stage": True,
        "score": True,
        "piv": False,
        "graze": True,
        "point_items": False,
        "power": False,
        "lives": False,
        "bombs": False,
        "th06_rank": False,
        "th07_cherry": False,
        "th07_cherrymax": False,
        "th09_p1_cpu": False,
        "th09_p2_cpu": False,
        "th09_p2_shot": False,
        "th09_p2_score": False,
        "th128_motivation": True,
        "th128_perfect_freeze": True,
        "th128_frozen_area": True,
        "th13_trance": False,
        "th16_season_power": False,
        "extends": False,
    }
)

_game_fields = immutabledict(
    {
        "th01": None,
        "th05": None,
        "th06": _table_fields_th06,
        "th07": _table_fields_th07,
        "th08": _table_fields_th08,
        "th09": _table_fields_th09,
        "th10": _table_fields_th10,
        "th11": _table_fields_th11,
        "th12": _table_fields_th12,
        "th128": _table_fields_th128,
        "th13": _table_fields_th13,
        "th14": _table_fields_th14,
        "th15": _table_fields_th15,
        "th16": _table_fields_th16,
        "th17": _table_fields_th17,
        "th18": _table_fields_th18,
    }
)

_game_fields_PVP = immutabledict(
    {
        "th01": None,
        "th05": None,
        "th06": None,
        "th07": None,
        "th08": None,
        "th09": _table_fields_th09_PVP,
        "th10": None,
        "th11": None,
        "th12": None,
        "th128": None,
        "th13": None,
        "th14": None,
        "th15": None,
        "th16": None,
        "th17": None,
        "th18": None,
    }
)

def GetFormatPower(
    game_id: str, power: Optional[int], shot: Optional[str] = None
) -> str:
    if power is None:
        return ""
    if game_id in (game_ids.GameIDs.TH06, game_ids.GameIDs.TH07, game_ids.GameIDs.TH08):
        return str(power)
    if game_id == game_ids.GameIDs.TH11 and shot == "MarisaA":
        return "%.2f" % round(float(power) / 12, ndigits=2)
    if game_id in (game_ids.GameIDs.TH10, game_ids.GameIDs.TH11):
        return "%.2f" % (float(power) * 0.05)
    if game_id in (
        game_ids.GameIDs.TH12,
        game_ids.GameIDs.TH13,
        game_ids.GameIDs.TH14,
        game_ids.GameIDs.TH15,
        game_ids.GameIDs.TH16,
        game_ids.GameIDs.TH17,
        game_ids.GameIDs.TH18,
    ):
        return "{:.2f}".format(power / 100)

    return str(power)

# used in GetFormatLives for string formatting the life/life piece counts
# if this is None, lives will be displayed standalone instead of including the life piece counts
# Technically the maximum life pieces for TH12 is 5, but the first piece you collect gives you 2, so functionally there are only 4
#   The parser for the game accounts for this discrepancy
_life_pieces = immutabledict(
    {
        "th01": None,
        "th02": None,
        "th03": None,
        "th04": None,
        "th05": None,
        "th06": None,
        "th07": None,
        "th08": None,
        "th09": None,
        "th10": None,
        "th11": 5,
        "th12": 4,
        "th128": None,
        "th13": None,  # this game has variable life pieces, so hardcoding it doesn't work
        "th14": 3,
        "th15": 3,
        "th16": None,
        "th17": 3,
        "th18": 3,
    }
)

# used in GetFormatBombs for string formatting the bomb/bomb piece counts
_bomb_pieces = immutabledict(
    {
        "th01": None,
        "th02": None,
        "th03": None,
        "th04": None,
        "th05": None,
        "th06": None,
        "th07": None,
        "th08": None,
        "th09": None,
        "th10": None,
        "th11": None,
        "th12": 3,
        "th128": None,
        "th13": 8,
        "th14": 8,
        "th15": 5,
        "th16": 5,
        "th17": 3,
        "th18": 3,
    }
)

# Takes the lives and life pieces and formats them accordingly for viewing in frontend
# A special case is made here for TH13, since it has a variable number of life pieces needed
#   so the amount is calculated off of the current extends
def GetFormatLives(
    game_id: str,
    lives: Optional[int],
    life_pieces: Optional[int],
    extends: Optional[int] = 0,
) -> str:
    if lives is None:
        return ""

    life_pieces_str = ""

    if game_id == "th13":
        threshholds = [8, 10, 12, 15, 18, 20, 25]
        if extends is None:
            life_pieces_str = ""
        else:
            if extends > 5:
                extends = 6
            if extends < 0:
                extends = 0
            life_pieces_str = f" ({life_pieces}/{threshholds[extends]})"
    else:
        total_life_pieces = _life_pieces[game_id]
        if total_life_pieces is None:
            life_pieces_str = ""
        else:
            if life_pieces is None:
                life_pieces = 0
            life_pieces_str = f" ({life_pieces}/{total_life_pieces})"
    return f"{lives}{life_pieces_str}"

def GetFormatBombs(
    game_id: str, bombs: Optional[int], bomb_pieces: Optional[int]
) -> str:
    if bombs is None:
        return ""
    total_bomb_pieces = _bomb_pieces[game_id]
    if total_bomb_pieces is None:
        return str(bombs)
    else:
        if bomb_pieces is None:
            bomb_pieces = 0
        return f"{bombs} ({bomb_pieces}/{total_bomb_pieces})"

def GetGameField(gameid: str, replay_type: game_ids.ReplayTypes):
    if replay_type is game_ids.ReplayTypes.PVP:
        if gameid in _game_fields_PVP:
            return _game_fields_PVP[gameid]
    else:
        if gameid in _game_fields:
            return _game_fields[gameid]
    return None

FORMAT_EXTRA = "Extra"
FORMAT_PHANTASM = "Phantasm"

def GetFormatStage(game_id: str, stage: Optional[int]) -> str:
    if stage is None:
        return ""
    if game_id == "th08":
        stages = {
            1: "1",
            2: "2",
            3: "3",
            4: "4A",
            5: "4B",
            6: "5",
            7: "6A",
            8: "6B",
            9: FORMAT_EXTRA,
        }
        return stages[stage]
    if game_id == "th09":
        if stage == 10:
            return FORMAT_EXTRA
    elif game_id == "th07" and stage == 8:
        return FORMAT_PHANTASM
    elif game_id == "th128":
        stages = {
            1: "A1-1",
            2: "A1-2",
            3: "A1-3",
            4: "A2-2",
            5: "A2-3",
            6: "B1-1",
            7: "B1-2",
            8: "B1-3",
            9: "B2-2",
            10: "B2-3",
            11: "C1-1",
            12: "C1-2",
            13: "C1-3",
            14: "C2-2",
            15: "C2-3",
            16: "Extra",
        }
        return stages[stage]
    elif stage == 7:
        return FORMAT_EXTRA
    return str(stage)

def FormatStages(game_id: str, replay_stages: Iterable[models.ReplayStage], shot: str):
    """This function formats the stage values to be displayed in the front end"""
    new_stages = copy.deepcopy(replay_stages)

    for stage in new_stages:
        stage.power = GetFormatPower(game_id, stage.power, shot)
        stage.stage = GetFormatStage(game_id, stage.stage)
        stage.lives = GetFormatLives(
            game_id, stage.lives, stage.life_pieces, stage.extends
        )
        stage.bombs = GetFormatBombs(game_id, stage.bombs, stage.bomb_pieces)
        if game_id == game_ids.GameIDs.TH09:
            stage.th09_p2_shotFormat = stage.th09_p2_shot.GetName()

        if stage.th128_motivation is None:
            stage.th128_motivation = ""
        else:
            stage.th128_motivation = f"{stage.th128_motivation//100}%"

        if stage.th128_perfect_freeze is None:
            stage.th128_perfect_freeze = ""
        else:
            stage.th128_perfect_freeze = f"{stage.th128_perfect_freeze//100}%"

        if stage.th128_frozen_area is None:
            stage.th128_frozen_area = ""
        else:
            stage.th128_frozen_area = f"{int(stage.th128_frozen_area)}%"

        if stage.stage is None:
            stage.stage = ""
        if stage.score is None:
            stage.score = ""
        if stage.piv is None:
            stage.piv = ""
        if stage.graze is None:
            stage.graze = ""
        if stage.point_items is None:
            stage.point_items = ""
        if stage.power is None:
            stage.power = ""
        if stage.lives is None:
            stage.lives = ""
        if stage.bombs is None:
            stage.bombs = ""
        if stage.th06_rank is None:
            stage.th06_rank = ""
        if stage.th07_cherry is None:
            stage.th07_cherry = ""
        if stage.th07_cherrymax is None:
            stage.th07_cherrymax = ""
        if stage.th09_p1_cpu is None:
            stage.th09_p1_cpu = ""
        if stage.th09_p2_cpu is None:
            stage.th09_p2_cpu = ""
        if stage.th09_p2_score is None:
            stage.th09_p2_score = ""
        if stage.th13_trance is None:
            stage.th13_trance = ""
        if stage.th16_season_power is None:
            stage.th16_season_power = ""
        if stage.extends is None:
            stage.extends = ""

    return new_stages

_games_with_pvp = ["th03", "th09"]

def game_has_pvp(game_id: str) -> bool:
    return game_id in _games_with_pvp


from PyQt5.QtGui import (
    QKeySequence,
)
from PyQt5.QtWidgets import (
    QMainWindow,
)

class MainWindowGuiUserAction(QMainWindow):
    page_idx = 0

    def setup_signal_connections_for_user_actions(self):
        self.buttons_bot_type[0].clicked.connect(self.play_mouse_click_sound)
        self.buttons_bot_type[1].clicked.connect(self.play_mouse_click_sound)
        self.buttons_bot_type[2].clicked.connect(self.play_mouse_click_sound)
        self.buttons_bot_type[3].clicked.connect(self.play_mouse_click_sound)
        self.button_exit.clicked.connect(self.play_mouse_click_sound)
        self.button_help.clicked.connect(self.play_mouse_click_sound)
        self.button_back.clicked.connect(self.play_mouse_click_sound)
        self.inputbox.returnPressed.connect(self.play_key_press_sound)

        self.buttons_bot_type[0].clicked.connect(self.change_bot_type_to_0)
        self.buttons_bot_type[1].clicked.connect(self.change_bot_type_to_1)
        self.buttons_bot_type[2].clicked.connect(self.change_bot_type_to_2)
        self.buttons_bot_type[3].clicked.connect(self.change_bot_type_to_3)
        self.button_exit.clicked.connect(self.close_app)
        self.button_help.clicked.connect(self.switch_page_from_button_help)
        self.button_back.clicked.connect(self.switch_page_from_button_back)
        self.inputbox.returnPressed.connect(self.show_msg)

class MainWindowKeybind(QMainWindow):
    def keyPressEvent(self, evt):
        keycode_key = evt.key()

        token_key = QKeySequence(keycode_key).toString()
        try:
            token_key.encode('utf-8')
        except UnicodeEncodeError:
            token_key = 'UnicodeEncodeError'

        msg = f'current page, pressed key: {self.page_idx} "{token_key}"'
        self.logger.i(msg)

        if token_key == '':
            pass
        elif token_key == 'F1':
            self.play_key_press_sound()
            self.page_idx = 1 if self.page_idx == 0 else 0
            self.switch_page_widget(self.page_idx)
        elif token_key == 'F11':
            self.play_key_press_sound()
            self.clear_inputbox()
        elif token_key == 'F12':
            self.play_key_press_sound()
            self.initialize_window_size()
        elif token_key == 'Up':
            if self.page_idx != 0:
                return
            self.play_key_press_sound()
            type_bot = self.type_bot + 1
            self.change_bot(type_bot)
        elif token_key == 'Down':
            if self.page_idx != 0:
                return
            self.play_key_press_sound()
            type_bot = self.type_bot - 1
            self.change_bot(type_bot)
        elif token_key == 'Esc':
            if self.page_idx != 0:
                return
            self.play_key_press_sound()
            self.close_app()

if __name__ == '__main__':
    from gui_talkbot import MainWindow
    TestClass = MainWindow

    import sys
    from PyQt5.QtWidgets import QApplication
    qapp = QApplication(sys.argv)
    window = TestClass()
    window.show()
    code = qapp.exec()
    sys.exit(code)


import numpy as np
from numpy.random import default_rng
import h5py

import numpy as np
import numpy.linalg as la
#import cppimport.import_hook
#import cpp_ext.tensor_kernels as tensor_kernels

class SparseTensor:
    '''
    For single-node testing purposes only (in Jupyter). Does not have
    an MPI component.
    '''
    def __init__(self, tensor_file):
        self.type = "SPARSE_TENSOR"

        f = h5py.File(tensor_file, 'r')
        self.max_idxs = f['MAX_MODE_SET'][:]
        self.min_idxs = f['MIN_MODE_SET'][:]
        self.dim = len(self.max_idxs)

        # The tensor must have at least one mode
        self.nnz = len(f['MODE_0'])

        self.tensor_idxs = []
        for i in range(self.dim):
            self.tensor_idxs.append(f[f'MODE_{i}'][:] - 1)

        self.values = f['VALUES'][:]
        self.tensor_norm = la.norm(self.values)

    def random_permute(self, seed=42):
        '''
        Applies a random permutation to the indices of the sparse
        tensor. We could definitely make this more efficient, but meh
        '''
        rng = np.random.default_rng(seed)
        for i in range(self.dim):
            idxs = np.array(list(range(self.max_idxs[i])), dtype=np.ulonglong)
            perm = rng.permutation(idxs)
            self.tensor_idxs[i] = perm[self.tensor_idxs[i]]


lista = []
soma = 0

while True:

    listaObj = str(input('Digite nomes para popular a lista e deixe em branco para parar: '))
    if listaObj == '':
        break
    else:
        lista.append(listaObj)

remover = str(input('Digite um nome para ser removido: '))

for obj in range(len(lista)-1):

    if lista[obj] == remover:
        soma += 1
        lista.remove(remover)

print('Foi(ram) removido(s) ', soma, 'ocorrência(s) de ', remover)

print('A lista atual é ', lista)


# 昇順をスライドさせてできた数列の中で最小値を見つける。
# 4 5 1 2 3

# 入力のサイズが10**8以下だったら、O(N)の方法で行ける。
# nums = list(map(int, input().split()))

# for i in range(len(nums)-1):
#     if nums[i] < nums[i+1]:
#         continue
#     else:
#         print(nums[i+1])
#         break
# else:
#     print(nums[0])

# 入力のサイズが10**8以上だったら、O(log(N))の方法で行ける。

# nums = list(map(int, input().split()))
# left = 0
# right = len(nums) - 1

# if nums[0] < nums[-1]:
#     print(nums[0])
#     exit()

# while right - left > 1:
#     mid = (right + left) // 2
#     if nums[left] < nums[mid]:
#         left = mid
#     else:
#         right = mid

# print(nums[right])

# 練習するぜ
# 昇順をスライドさせてできた数列の中で最小値を見つける。
# 4 5 1 2 3

import sys
from typing import List

def main(lines: List):
    numbers = list(map(int, lines[0].split()))
    left = 0
    right = len(numbers) - 1

    if numbers[left] < numbers[right]:
        print(numbers[left])
        exit()

    while right - left > 1:
        mid = (left + right) // 2
        if numbers[left] < numbers[mid]:
            left = mid
        else:
            right = mid

    print(numbers[right])

if __name__ == '__main__':
    lines = []
    for l in sys.stdin:
        lines.append(l.rstrip('\r\n'))
    main(lines)


#!/usr/bin/python -u
# -*- coding: latin-1 -*-
#
# Who killed agatha? (The Dreadsbury Mansion Murder Mystery) in Z3
#
# http://www.lsv.ens-cachan.fr/~goubault/H1.dist/H1.1/Doc/h1003.html
#
# """
# Someone in Dreadsbury Mansion killed Aunt Agatha.
# Agatha, the butler, and Charles live in Dreadsbury Mansion, and
# are the only ones to live there. A killer always hates, and is no
# richer than his victim. Charles hates noone that Agatha hates. Agatha
# hates everybody except the butler. The butler hates everyone not richer
# than Aunt Agatha. The butler hates everyone whom Agatha hates.
# Noone hates everyone. Who killed Agatha?
# """
#
# Originally from
# F. J. Pelletier: Seventy-five problems for testing automatic theorem provers.
# Journal of Automated Reasoning, 2: 191-216, 1986.
#
# As usual, this model yields 8 solutions, all indicating that Agatha is the killer.
# For a detailed discussion on this, see
# http://www.hakank.org/minizinc/who_killed_agatha_dmcommunity_challenge.html
#
# This is version is an alternative to who_killed_agatha.py:
# it use Function instead of Array for the two matrices hates and richer.
# This makes it possible to use a "natural" matrix element constraint such as:
#    hates(the_killer,the_victim)  == True
#
# This Z3 model was written by Hakan Kjellerstrand (hakank@gmail.com)
# See also my Z3 page: http://hakank.org/z3/
#
from z3_utils_hakank import *

sol = SimpleSolver()

n = 3
agatha = 0
butler = 1
charles = 2

who = ["agatha","butler","charles"]

the_killer = Int("the_killer")
sol.add(the_killer >= agatha, the_killer <= charles)
the_victim = agatha

hates = Function("hates", IntSort(), IntSort(), BoolSort())
richer = Function("richer", IntSort(), IntSort(), BoolSort())

# Agatha, the butler, and Charles live in Dreadsbury Mansion, and
# are the only ones to live there.
sol.add(hates(the_killer,the_victim)  == True)

# A killer always hates, and is no richer than his victim.
sol.add(hates(the_killer,the_victim) == True)
sol.add(richer(the_killer,the_victim) == False)

# # define the concept of richer: no one is richer than him-/herself
for i in range(n):
    sol.add(richer(i,i) == False)

# (contd...) if i is richer than j then j is not richer than i
for i in range(n):
    for j in range(n):
        if i != j:
            sol.add( (richer(i,j) == True) == (richer(j,i) == False))

# Charles hates noone that Agatha hates.
for i in range(n):
    sol.add(Implies(hates(agatha,i) == True, hates(charles,i) == False))

# Agatha hates everybody except the butler.
sol.add(hates(agatha,charles) == True)
sol.add(hates(agatha,agatha) == True)
sol.add(hates(agatha,butler) == False)

# The butler hates everyone not richer than Aunt Agatha.
for i in range(n):
    sol.add(Implies(richer(i,agatha) == False, hates(butler,i) == True ))

# The butler hates everyone whom Agatha hates.
for i in range(n):
    sol.add(Implies(hates(agatha,i) == True, hates(butler,i) == True ))

# Noone hates everyone.
for i in range(n):
    sol.add(Sum([If(hates(i,j) == True,1,0) for j in range(n)]) <= 2)

# Who killed Agatha?

num_solutions = 0
while sol.check() == sat:
    mod = sol.model()
    # print(mod)
    num_solutions += 1
    killer = mod.eval(the_killer)
    print("the_killer:", who[killer.as_long()])
    sol.add(
        Or(killer != the_killer,
           Or([hates(i,j) != mod.eval(hates(i,j)) for i in range(n) for j in range(n)]),
           Or([richer(i,j) != mod.eval(richer(i,j)) for i in range(n) for j in range(n)])
          )
        )

print("num_solutions:", num_solutions)


# from pudb import set_trace; set_trace()
from typing import List
import heapq

class Solution1:
    def scheduleCourse(self, courses: List[List[int]]) -> int:
        """LeetCode 630

        This solution is based on hint, although I have basically the same
        idea as the hint. Yet, I was not sure to pursue the idea illustrated in
        the hint.

        The first task is to sort courses. We sort based on last day. It can be
        proven that having large last day after small last day is a better
        strategy than the other way around. This is because, if cur_time + dur
        fits in both the small and large last day, then their order doesn't
        matter. Similarly, if cur_time + dur does not fit in either the small or
        large last day, their order doesn't matter. It only matters, if one
        of the last day fits. Apparently, it can only be the large last day that
        fits, and the small last day doesn't fit. In this scenario, if we do
        the large last day first, then we are guaranteed to only fit one course.
        However, if we do the small last day first, then it is guaranteed that
        we can fit both courses. Therefore, it is always better to sort the
        courses based on their last day.

        If the last day is the same, we want to have the smaller duration first,
        because that can produce larger gaps between the end of the class and
        the last day, which provides higher chance of fitting another class.

        The key idea from the hint is to iterate through the sorted courses, and
        when a course cannot fit, we check whether it is a good deal to drop
        the course with the largest duration so far. The check is based on
        whether the drop can fit the new last day and whether the drop leads to
        bigger gap between the end of the current course and the last day. If
        both conditions are satisfied, we do the drop.

        To obtain the largest duration so far, we use a heapq.

        O(Nlog(N)) 732 ms, 31% ranking.
        """
        courses.sort(key=lambda tup: (tup[1], tup[0]))
        heap = []
        cur_time = 0
        for dur, last in courses:
            if cur_time + dur <= last:
                heapq.heappush(heap, -dur)
                cur_time += dur
            else:
                if heap:
                    max_dur = -heapq.heappop(heap)
                    if cur_time + dur - max_dur <= last and cur_time + dur - max_dur < cur_time:
                        cur_time = cur_time - max_dur + dur
                        heapq.heappush(heap, -dur)
                    else:
                        heapq.heappush(heap, -max_dur)
        return len(heap)

class Solution2:
    def scheduleCourse(self, courses: List[List[int]]) -> int:
        """This is according to the solution. The key idea is to pop the max
        duration encountered so far if and only if it is larger than the current
        duration. This is because if the max duration is larger than the current
        duration, we can guarantee that the swap results in larger gap between
        the current time and the last day. In other words, we don't have to
        check for it separately.
        """
        courses.sort(key=lambda tup: (tup[1], tup[0]))
        heap = []
        cur_time = 0
        for dur, last in courses:
            if cur_time + dur <= last:
                heapq.heappush(heap, -dur)
                cur_time += dur
            elif heap and -heap[0] > dur:
                cur_time = cur_time + dur + heapq.heappop(heap)
                heapq.heappush(heap, -dur)
        return len(heap)

sol = Solution2()
tests = [
    ([[100, 200], [200, 1300], [1000, 1250], [2000, 3200]], 3),
    ([[1, 2]], 1),
    ([[3, 2], [4, 3]], 0),
    ([[5, 5], [4, 6], [2, 6]], 2),
]
for i, (courses, ans) in enumerate(tests):
    res = sol.scheduleCourse(courses)
    if res == ans:
        print(f'Test {i}: PASS')
    else:
        print(f'Test {i}; Fail. Ans: {ans}, Res: {res}')


import config
from graphdatascience import GraphDataScience

gds = GraphDataScience(
    config.host, auth=(config.user, config.password), database="neo4j"
)

bham = gds.find_node_id(["Station"], {"name": "Birmingham New Street"})
eboro = gds.find_node_id(["Station"], {"name": "Edinburgh"})

shortest_path = gds.shortestPath.dijkstra.stream(
    gds.graph.get("trains"),
    sourceNode=bham,
    targetNode=eboro,
    relationshipWeightProperty="distance",
)

# Extract nodeIds and costs from the shortest_path result
nodeIds = shortest_path.get("nodeIds").get(0)
costs = shortest_path.get("costs").get(0)

# Fetch station names and print stations and costs for each stop along the route
stations = [gds.util.asNode(nodeId).get("name") for nodeId in nodeIds]
for station, cost in zip(stations, costs):
    print(f"Station: {station} (Cost: {'{:.2f}'.format(cost)})")

# Print starting and ending stations
print("\nStarting Station:", stations[0])
print("Ending Station:", stations[-1])

print(
    "\nShortest distance from {} to {} involves visiting {} station(s) for a total distance of {}\n".format(
        stations[0], stations[-1], len(stations), "{:.2f}".format(costs[-1])
    )
)

"""
// VERIFY: Cypher code to display the shortest path between BHM and EDB

MATCH (bhm:Station {crs:"BHM"}), (edb:Station {crs:"EDB"})
CALL gds.shortestPath.dijkstra.stream('trains', {sourceNode:bhm, targetNode:edb, relationshipWeightProperty:'distance'})
YIELD index, sourceNode, targetNode, totalCost, nodeIds, costs, path
RETURN index,
    gds.util.asNode(sourceNode).name AS sourceNodeName,
    gds.util.asNode(targetNode).name AS targetNodeName,
    totalCost,
    [nodeId IN nodeIds | gds.util.asNode(nodeId).name] AS nodeNames,
    costs,
    nodes(path) as path
"""

gds.close()


import re
import json
from tabulate import tabulate
from pprint import PrettyPrinter
import requests as req

def conll2clusters(inp, out):
    pp = PrettyPrinter()
    lines = out.strip().split("\n")
    clusters = {}
    tokens = []
    resolved = ""
    tok_nr = 0
    print("conlltoclusters")
    print(inp)
    print(out)
    print(lines)
    for line in lines:
        line = line.strip().split("\t")
        if len(line) > 1:
            token = line[1]
            coref_info = line[9]
            print(coref_info, token, line)
            tokens.append(token)
            if coref_info != "-":
                cluster_ids = coref_info.split("|")
                for cluster_id in cluster_ids:
                    openm = re.match("^\((\d+)$", cluster_id)
                    closem = re.match("^(\d+)\)$", cluster_id)
                    singlem = re.match("^\((\d+)\)$", cluster_id)
                    if openm:
                        # start of a cluster
                        cid = int(openm.group(1))
                        if cid not in clusters:
                            clusters[cid] = []
                        clusters[cid].append([tok_nr, None])
                    elif closem:
                        cid = int(closem.group(1))
                        assert(cid in clusters)
                        clusters[cid][-1][1] = tok_nr+1
                    elif singlem:
                        cid = int(singlem.group(1))
                        if cid not in clusters:
                            clusters[cid] = []
                        clusters[cid].append([tok_nr, tok_nr+1])

            tok_nr += 1
    pp.pprint(tokens)
    pp.pprint(clusters)

    tok2char = tokpos2charpos(inp, tokens)
    pp.pprint(tok2char)

    outclusters = []
    for k, v in clusters.items():
        # print(v)
        outcluster = {"main": {}, "mentions": []}
        tokstart = v[0][0]
        tokend = v[0][1]
        toktext = " ".join(tokens[tokstart:tokend])
        chrstart = tok2char[tokstart][0]
        chrend = tok2char[tokend-1][1]
        chrtext = inp[chrstart:chrend]
        assert(toktext.replace(" ", "") == chrtext.replace(" ", ""))
        outcluster["main"] = {"start": tokstart,
                              "end":   tokend,
                              "start_char": chrstart,
                              "end_char": chrend,
                              "text":  chrtext}
        del v[0]
        for ve in v:
            # print(v)
            tokstart = ve[0]
            tokend = ve[1]
            toktext = " ".join(tokens[tokstart:tokend])
            chrstart = tok2char[tokstart][0]
            chrend = tok2char[tokend-1][1]
            chrtext = inp[chrstart:chrend]
            assert(toktext.replace(" ", "") == chrtext.replace(" ", ""))
            mention = {"start": tokstart,
                       "end":   tokend,
                       "start_char": chrstart,
                       "end_char": chrend,
                       "text":  chrtext}
            outcluster["mentions"].append(mention)
        outclusters.append(outcluster)
    pp.pprint(outclusters)
    return outclusters, tokens

def tokpos2charpos(text, tokens):
    if re.sub("\s+", "", text) != " ".join(tokens).replace(" ", ""):
        print(text)
        print(tokens)
        raise Exception("sum ting wong: {}, {}".format(str(text), str(tokens)))
    text_ = text + ""
    tokpos2charpos = {}
    acc = 0
    for i, token in enumerate(tokens):
        startchar = text_.find(token)
        endchar = startchar + len(token)
        assert(len(re.sub("\s+", "", text_[:startchar])) == 0)
        tokpos2charpos[i] = (acc + startchar, acc + endchar)
        text_ = text_[endchar:]
        acc += endchar
    return tokpos2charpos

if __name__ == '__main__':
    p = "sampleout.conll"
    inp = "Mein Schwester hat einen  Hund. Sie liebt ihn . Aber nicht mich."
    with open(p, "r") as f:
        out = f.read()
        clusters, tokens = conll2clusters(inp, out)


from flask import Flask, render_template, request, redirect, Response, jsonify
import pandas as pd
import json
from sklearn.cluster import KMeans
from sklearn import metrics
from sklearn.decomposition import PCA
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import StandardScaler
from sklearn.manifold import MDS

app = Flask(__name__)

@app.route("/", methods = ['GET', 'POST'])
def index():
    return render_template("index.html", data = "")

@app.route("/elbow-k-means", methods = ['POST'])
def get_elbow():
    global elbow_vals
    return jsonify(elbow_vals)

@app.route("/screeplot_full_data", methods = ['POST'])
def scree_plot_full_data():
    global df1
    data, list_intrinsic_dimensions, count_2 = calculate_intrinsic_dimensionality(df1)
    return jsonify(data)

@app.route("/screeplot_random_sample_data", methods = ['POST'])
def scree_plot_random_data():
    global df2
    data, list_intrinsic_dimensions, count_2 = calculate_intrinsic_dimensionality(df2)
    return jsonify(data)

@app.route("/screeplot_stratified_sample_data", methods = ['POST'])
def scree_plot_stratified_data():
    global df3
    data, list_intrinsic_dimensions, count_2 = calculate_intrinsic_dimensionality(df3)
    return jsonify(data)

@app.route("/scatter_plot_full_data_pc_values", methods = ['POST'])
def scatter_plot_full_data_pc_values():
    global df1
    data = calculate_top_PC_Vals(df1)
    return jsonify(data)

@app.route("/scatter_plot_random_sampled_data_pc_values", methods = ['POST'])
def scatter_plot_random_sampled_data_pc_values():
    global df2
    data = calculate_top_PC_Vals(df2)
    return jsonify(data)

@app.route("/scatter_plot_stratified_sampled_data_pc_values", methods = ['POST'])
def scatter_plot_stratified_sampled_data_pc_values():
    global df3
    data = calculate_top_PC_Vals(df3)
    return jsonify(data)

@app.route("/scatter_matrix_full_data", methods = ['POST'])
def scatter_matrix_full_data():
    global df1
    data_temp, list_intrinsic_dimensions, count_2 = calculate_intrinsic_dimensionality(df1)
    data = calculate_top_attributes(df1, list_intrinsic_dimensions,count_2)
    return jsonify(data)

@app.route("/scatter_matrix_random_sampled_data", methods = ['POST'])
def scatter_matrix_random_sampled_data():
    global df2
    data_temp, list_intrinsic_dimensions, count_2 = calculate_intrinsic_dimensionality(df2)
    data = calculate_top_attributes(df2, list_intrinsic_dimensions,count_2)
    return jsonify(data)

@app.route("/scatter_matrix_stratified_sampled_data", methods = ['POST'])
def scatter_matrix_stratified_sampled_data():
    global df3
    data_temp, list_intrinsic_dimensions, count_2 = calculate_intrinsic_dimensionality(df1)
    data = calculate_top_attributes(df3, list_intrinsic_dimensions, count_2)
    return jsonify(data)

@app.route("/mds_euclidean_full_data", methods = ['POST'])
def mds_euclidean_full_data():
    global df1
    data = calculate_mds(df1, 'euclidean')
    return jsonify(data)

@app.route("/mds_euclidean_random_data", methods = ['POST'])
def mds_euclidean_random_data():
    global df2
    data = calculate_mds(df2, 'euclidean')
    return jsonify(data)

@app.route("/mds_euclidean_stratified_data", methods = ['POST'])
def mds_euclidean_stratified_data():
    global df3
    data = calculate_mds(df3, 'euclidean')
    return jsonify(data)

@app.route("/mds_correlation_full_data", methods = ['POST'])
def mds_correlation_full_data():
    global df1
    data = calculate_mds(df1, 'correlation')
    return jsonify(data)

@app.route("/mds_correlation_random_data", methods = ['POST'])
def mds_correlation_random_data():
    global df2
    data = calculate_mds(df2, 'correlation')
    return jsonify(data)

@app.route("/mds_correlation_stratified_data", methods = ['POST'])
def mds_correlation_stratified_data():
    global df3
    data = calculate_mds(df3, 'correlation')
    return jsonify(data)

def calculate_intrinsic_dimensionality(df):
    #variables to obtain required values to send to front-end. Count_2 holds the intrinsic dimensionality
    count = 0
    count_2 = 0
    sum = 0
    sum_2 = 0
    ptg_data = []
    list_intrinsic_dimensions = []

    #performing PCA = 13
    pca = PCA(n_components=13)

    #scaling the data using standardscalar()
    x = StandardScaler().fit_transform(df.loc[:, :'Overall_Ranking'])
    principal_components = pca.fit_transform(x)
    data = pca.explained_variance_ratio_
    data = data.tolist()

    #identifying the PC components contributing < 80% and storing them to send to front end
    for i in data:
        sum += i
        if sum<0.80:
            count_2 +=1
            list_intrinsic_dimensions.append("PC" + str(count_2))

        ptg_data.append(sum)

    list_pca = []
    for i in data:
        count += 1
        list_pca.append("PC" + str(count))

    flag = 0
    list_pc_vector = []
    for i in range(len(data)):
        sum_2 += data[i]
        if sum_2 < 0.80:
            list_pc_vector.append("True")
        else:
            list_pc_vector.append("False")

    for i in range(len(list_pc_vector)):
        if list_pc_vector[i+1] == 'False':
            for j in range(i):
                list_pc_vector[j] = 'False'
            break

    #convering the data to json to send it to front end.
    mapping = {"PC": list_pca, "Value": data, "Percent_data": ptg_data, "PC_T_F": list_pc_vector}
    df_combined = pd.DataFrame(mapping)
    mapping = df_combined.to_dict(orient="records")
    chart_data = json.dumps(mapping, indent=2)
    data = {'chart_data': chart_data}
    return data, list_intrinsic_dimensions, count_2

def calculate_top_PC_Vals(df):

    #Performing PCA for n=2
    pca = PCA(n_components=2)

    #Scaling data using Standard Scalar and appending the University, Country and Rank
    x = StandardScaler().fit_transform(df.loc[:, :'Overall_Ranking'])
    pc = pca.fit_transform(x)
    data = pca.explained_variance_ratio_
    principal_Df = pd.DataFrame(data=pc, columns=['PC1', 'PC2'])
    principal_Df['University'] = df['University']
    principal_Df['Country'] = df['Country']
    principal_Df['Rank'] = df['Rank']

    #Formatting the data to send to the front end
    mapping = principal_Df.to_dict(orient="records")
    chart_data = json.dumps(mapping, indent=2)
    data = {'chart_data': chart_data}
    return data

def calculate_top_attributes(df, list_intrinsic_dimensions, count):
    df_temp = df.loc[:, :'Overall_Ranking']
    list_country = df['Country'].tolist()
    list_uni = df['University'].tolist()
    list_rank = df['Rank'].tolist()

    #running PCA for the intrinsic dimensionality
    pca = PCA(n_components=count)

    #transforming the values using standardscalar()
    x = StandardScaler().fit_transform(df_temp)
    pc1 = pca.fit_transform(x)
    data = pca.explained_variance_ratio_
    data = data.tolist()

    #obtaining the loadings per column and storing them in a dataframe
    loadings = pd.DataFrame(pca.components_.T, columns= list_intrinsic_dimensions,
                            index=df_temp.columns)

    #calculating the values with the highest PCA loadings
    for i in loadings:
        loadings[i] = loadings[i] ** 2
    loadings['sum'] = loadings.sum(axis=1)
    df_final = df_temp.loc[:, loadings.nlargest(3, ['sum']).index.tolist()]
    df_final['Country'] = list_country
    df_final['University'] = list_uni
    df_final['Rank'] = list_rank

    #formatting data to send to front end
    mapping = df_final.to_dict(orient="records")
    chart_data = json.dumps(mapping, indent=2)
    data = {'chart_data': chart_data}
    return data

def calculate_mds(df, distance):
    df_temp = df.loc[:, :'Overall_Ranking']

    #Scale data
    df_scaled = StandardScaler().fit_transform(df_temp)
    df_scaled_final = pd.DataFrame(df_scaled)

    #compute required pairwise distance
    matrix = metrics.pairwise.pairwise_distances(df_scaled_final, metric=distance)
    list_country = df['Country'].tolist()
    list_uni = df['University'].tolist()
    list_rank = df['Rank'].tolist()

    #perform MDS
    mds = MDS(n_components=2, dissimilarity='precomputed', n_jobs=-1)

    values = mds.fit_transform(matrix)

    df_final = pd.DataFrame(values, columns= ['MDS1', 'MDS2'])
    df_final['Country'] = list_country
    df_final['University'] = list_uni
    df_final['Rank'] = list_rank

    mapping = df_final.to_dict(orient="records")
    chart_data = json.dumps(mapping, indent=2)
    data = {'chart_data': chart_data}
    return data

def create_random_samples():
    global df1
    df_random = df1.sample(frac=0.25)
    df_random.to_csv("random_sample.csv", index=False)

def create_random_stratified_samples():

    global df1

    #array to store sum of squared distances
    sum_of_squared_distances = []
    #array to store k values
    k_vals = []
    #array to store elbow values
    elbow_values = []

    #performing k-means for k = 1 to k = 17
    for k in range(1,18):
        #appending k value in k_vals array
        k_vals.append(k)
        #running k-means function
        k_means = KMeans(n_clusters=k)
        #fitting the values and appending them to sum_of_squared_distances array
        model = k_means.fit(df1.loc[:, :'Overall_Ranking'])
        sum_of_squared_distances.append(k_means.inertia_ * 10**-12)

    #transforming the data to be able to send it to front end
    elbow_values.append(k_vals)
    elbow_values.append(sum_of_squared_distances)
    final_elbow_vals = pd.DataFrame(elbow_values)
    final_elbow_values = final_elbow_vals.T
    final_elbow_values.columns = ['K', 'Value']
    mapping = final_elbow_values.to_dict(orient="records")
    chart_data = json.dumps(mapping, indent=2)
    data = {'chart_data': chart_data}

    #performing k-means for k=4 based on elbow point
    k_means = KMeans(n_clusters=4)
    model = k_means.fit(df1.loc[:, :'Overall_Ranking'])
    y = k_means.predict(df1.loc[:, :'Overall_Ranking'])
    df1['Cluster'] = y

    #sampling 25% of each cluster
    df_c0 = df1.loc[df1['Cluster'] == 0]
    df_c0_sample = df_c0.sample(frac=0.25)

    df_c1 = df1.loc[df1['Cluster'] == 1]
    df_c1_sample = df_c1.sample(frac=0.25)

    df_c2 = df1.loc[df1['Cluster'] == 2]
    df_c2_sample = df_c2.sample(frac=0.25)

    df_c3 = df1.loc[df1['Cluster'] == 3]
    df_c3_sample = df_c3.sample(frac=0.25)

    #appending the sampled data into a single dataframe and dropping the cluser column
    df_strat_samples = df_c0_sample.append(df_c1_sample.append(df_c2_sample.append(df_c3_sample)))
    df_strat_final = df_strat_samples.drop(columns='Cluster')

    #storing the data into a .csv file
    df_strat_final.to_csv("random_stratified.csv", index=False)

    #returning the k-values for plotting elbow curve
    return data

if __name__ == "__main__":
    df1 = pd.read_csv("data_full.csv")
    create_random_samples()
    df2 = pd.read_csv("random_sample.csv")
    elbow_vals = create_random_stratified_samples()
    df3 = pd.read_csv("random_stratified.csv")
    app.run(debug=True)


import numpy as np
import nengo
from nengo.dists import Uniform
from nengo.solvers import NoSolver
from nengo.utils.numpy import rmse
from nengolib import Lowpass, DoubleExp
from nengolib.signal import s
from utils import decodeNoF, WNode, learnEncoders, setWeights, decode, plotState, plotActivity
from neurons import LIF, ALIF, Wilson, Bio, reset_neuron, NMDA
import neuron
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(context='paper', style='whitegrid')

def makeSignal(t, fPre, fNMDA, dt=0.001, value=1.0, freq=1, seed=0, c=None):
    if not c: c = t
    stim = nengo.processes.WhiteSignal(period=t/2, high=freq, rms=0.5, seed=seed)
    with nengo.Network() as model:
        u = nengo.Node(stim)
        pU = nengo.Probe(u, synapse=None)
        pX = nengo.Probe(u, synapse=1/s)
    with nengo.Simulator(model, progress_bar=False) as sim:
        sim.run(t/2, progress_bar=False)
    u = fNMDA.filt(fPre.filt(sim.data[pU]))
    x = fNMDA.filt(fPre.filt(sim.data[pX]))
    norm = value / np.max(np.abs(u))
    # norm = value / np.max(np.abs(x))
    mirrored = np.concatenate(([[0]], sim.data[pU]*norm, -sim.data[pU]*norm))
    func = lambda t: mirrored[int(t/dt)] if t<c else 0
    return func

# def ideal(N=100, t=10, c=7, f=DoubleExp(10e-3, 2.85e-1)):
#     stim = nengo.processes.WhiteSignal(period=t, high=0.5, rms=0.3, seed=0)
#     cutoff = lambda t: 0 if t<c else 1
#     with nengo.Network() as network:
#         inpt = nengo.Node(stim)
#         cut = nengo.Node(cutoff)
#         diff = nengo.Ensemble(N, 1, max_rates=Uniform(30, 30), intercepts=Uniform(-0.8, 0.8), seed=0)
#         ens = nengo.Ensemble(N, 1, max_rates=Uniform(30, 30), intercepts=Uniform(-0.8, 0.8), seed=0)
#         nengo.Connection(inpt, diff, synapse=None)
#         nengo.Connection(cut, diff.neurons, synapse=None, transform=-1e2*np.ones((N, 1)))
#         nengo.Connection(diff, ens, synapse=f)
#         nengo.Connection(ens, ens, synapse=f)
#         nengo.Connection(ens, diff, synapse=f, transform=-1)
#         pInpt = nengo.Probe(inpt, synapse=f)
#         pDiff = nengo.Probe(diff, synapse=f)
#         pEns = nengo.Probe(ens, synapse=f)
#     with nengo.Simulator(network, progress_bar=False) as sim:
#         sim.run(t, progress_bar=True)
#     fig, ax = plt.subplots()
#     ax.plot(sim.trange(), sim.data[pInpt], label='inpt')
#     ax.plot(sim.trange(), sim.data[pDiff], label='diff')
#     ax.plot(sim.trange(), sim.data[pEns], label='ens')
#     ax.legend()
#     fig.savefig("plots/diffMemory_ideal.pdf")

def go(NPre=100, N=100, t=10, c=None, dt=0.001, m=Uniform(30, 30), i=Uniform(-0.8, 0.8), seed=0, neuron_type=LIF(),
    fPre=None, fNMDA=None, dPre=None, dDiff=None, dEns=None, dNeg=None, Tff=1.0, stim=lambda t: 0, train=False):

    if not c: c = t
    dFF = dDiff*Tff if np.any(dDiff) else None
    with nengo.Network(seed=seed) as model:
        inpt = nengo.Node(stim)
        intg = nengo.Ensemble(1, 1, neuron_type=nengo.Direct())
        cut = nengo.Node(lambda t: 0 if t<c else 1)
        pre = nengo.Ensemble(NPre, 1, max_rates=m, seed=seed)
        pre2 = nengo.Ensemble(NPre, 1, max_rates=m, seed=seed)
        diff = nengo.Ensemble(N, 1, max_rates=m, intercepts=i, neuron_type=neuron_type, seed=seed)
        ens = nengo.Ensemble(N, 1, max_rates=m, intercepts=i, neuron_type=neuron_type, seed=seed)
        nengo.Connection(inpt, intg, synapse=1/s)
        nengo.Connection(inpt, pre, synapse=None, seed=seed)
        nengo.Connection(intg, pre2, synapse=fNMDA, seed=seed)
        c1 = nengo.Connection(pre, diff, synapse=fPre, solver=NoSolver(dPre), seed=seed)
        c2 = nengo.Connection(diff, ens, synapse=fNMDA, solver=NoSolver(dFF), seed=seed)
        c3 = nengo.Connection(ens, ens, synapse=fNMDA, solver=NoSolver(dEns), seed=seed)
        c4 = nengo.Connection(ens, diff, synapse=fNMDA, solver=NoSolver(dNeg), seed=seed)
        c5 = nengo.Connection(cut, diff.neurons, synapse=None, transform=-1e2*np.ones((N, 1)))
        if train: nengo.Connection(pre2, ens, synapse=fPre, solver=NoSolver(dPre), seed=seed)
        pInpt = nengo.Probe(inpt, synapse=None)
        pIntg = nengo.Probe(intg, synapse=None)
        pPre = nengo.Probe(pre.neurons, synapse=None)
        pDiff = nengo.Probe(diff.neurons, synapse=None)
        pEns = nengo.Probe(ens.neurons, synapse=None)

    with nengo.Simulator(model, seed=seed, dt=dt, progress_bar=False) as sim:
        sim.run(t, progress_bar=True)

    return dict(
        times=sim.trange(),
        inpt=sim.data[pInpt],
        intg=sim.data[pIntg],
        pre=sim.data[pPre],
        diff=sim.data[pDiff],
        ens=sim.data[pEns],
    )

def run(NPre=100, N=100, t=10, c=None, nTrain=10, nTest=5, dt=0.001, neuron_type=LIF(),
    fPre=DoubleExp(1e-3, 1e-1), fNMDA=DoubleExp(10.6e-3, 285e-3),
    reg=1e-2, load=[], file=None, neg=True):

    if not c: c = t
    if 0 in load:
        dPre = np.load(file)['dPre']
    else:
        print('readout decoders for pre')
        spikesInpt = np.zeros((nTrain, int(t/dt), NPre))
        targetsInpt = np.zeros((nTrain, int(t/dt), 1))
        for n in range(nTrain):
            stim = makeSignal(t, fPre, fNMDA, seed=n)
            data = go(NPre=NPre, N=N, t=t, fPre=fPre, fNMDA=fNMDA, neuron_type=neuron_type, stim=stim)
            spikesInpt[n] = data['pre']
            targetsInpt[n] = fPre.filt(data['inpt'], dt=dt)
        dPre, X, Y, error = decodeNoF(spikesInpt, targetsInpt, nTrain, fPre, reg=reg)
        np.savez("data/diffMemory_%s.npz"%neuron_type, dPre=dPre)
        times = np.arange(0, t*nTrain, 0.001)
        plotState(times, X, Y, error, "diffMemory_%s"%neuron_type, "pre", t*nTrain)

    if 1 in load:
        dDiff = np.load(file)['dDiff']
    else:
        print('readout decoders for diff')
        spikes = np.zeros((nTrain, int(t/dt), N))
        targets = np.zeros((nTrain, int(t/dt), 1))
        for n in range(nTrain):
            stim = makeSignal(t, fPre, fNMDA, seed=n)
            data = go(NPre=NPre, N=N, t=t, fPre=fPre, fNMDA=fNMDA, neuron_type=neuron_type, stim=stim, dPre=dPre)
            spikes[n] = data['diff']
            targets[n] = fNMDA.filt(fPre.filt(data['inpt'], dt=dt), dt=dt)
        dDiff, X, Y, error = decodeNoF(spikes, targets, nTrain, fNMDA, reg=reg)
        np.savez("data/diffMemory_%s.npz"%neuron_type, dPre=dPre, dDiff=dDiff)
        times = np.arange(0, t*nTrain, dt)
        plotState(times, X, Y, error, "diffMemory_%s"%neuron_type, "diff", t*nTrain)

    if 2 in load:
        dEns = np.load(file)['dEns']
        dNeg = np.load(file)['dNeg']
    else:
        print('readout decoders for ens')
        spikes = np.zeros((nTrain, int(t/dt), N))
        targets = np.zeros((nTrain, int(t/dt), 1))
        for n in range(nTrain):
            stim = makeSignal(t, fPre, fNMDA, seed=n)
            # data = go(NPre=NPre, N=N, t=t, fPre=fPre, fNMDA=fNMDA, neuron_type=neuron_type, stim=stim, dPre=dPre, dDiff=dDiff)
            data = go(NPre=NPre, N=N, t=t, fPre=fPre, fNMDA=fNMDA, neuron_type=neuron_type, stim=stim, dPre=dPre, dDiff=dDiff, train=True, Tff=0.3)
            spikes[n] = data['ens']
            # targets[n] = fNMDA.filt(fNMDA.filt(fPre.filt(data['inpt'], dt=dt), dt=dt), dt=dt)
            targets[n] = fNMDA.filt(fPre.filt(data['intg'], dt=dt), dt=dt)
        dEns, X, Y, error = decodeNoF(spikes, targets, nTrain, fNMDA, reg=reg)
        dNeg = -np.array(dEns)
        np.savez("data/diffMemory_%s.npz"%neuron_type, dPre=dPre, dDiff=dDiff, dEns=dEns, dNeg=dNeg)
        times = np.arange(0, t*nTrain, dt)
        plotState(times, X, Y, error, "diffMemory_%s"%neuron_type, "ens", t*nTrain)

    print('testing')
    vals = np.linspace(-1, 1, nTest)
    for test in range(nTest):
        if neg:
            stim = lambda t: vals[test] if t<c else 0
            data = go(NPre=NPre, N=N, t=t, fPre=fPre, fNMDA=fNMDA, neuron_type=neuron_type,
                stim=stim, dPre=dPre, dDiff=dDiff, dEns=dEns, dNeg=dNeg, c=c)
        else:
            stim = makeSignal(t, fPre, fNMDA, seed=test)
            data = go(NPre=NPre, N=N, t=t, fPre=fPre, fNMDA=fNMDA, neuron_type=neuron_type,
                stim=stim, dPre=dPre, dDiff=dDiff, dEns=dEns, dNeg=None, c=None, Tff=0.3)
        aDiff = fNMDA.filt(fPre.filt(data['diff'], dt=dt), dt=dt)
        aEns = fNMDA.filt(fNMDA.filt(fPre.filt(data['ens'], dt=dt), dt=dt), dt=dt)
        xhatDiff = np.dot(aDiff, dDiff)
        xhatEns = np.dot(aEns, dEns)
        u = fNMDA.filt(fPre.filt(data['inpt'], dt=dt), dt=dt)
        u2 = fNMDA.filt(fNMDA.filt(fPre.filt(data['inpt'], dt=dt), dt=dt), dt=dt)
        x = fNMDA.filt(fNMDA.filt(fPre.filt(data['intg'], dt=dt), dt=dt), dt=dt)
        error = rmse(xhatEns, x)
        fig, ax = plt.subplots()
        if neg:
            ax.plot(data['times'], u2, alpha=0.5, label="input (delayed)")
            ax.axvline(c, label="cutoff")
        else:
            # ax.plot(data['times'], 0.3*u2, alpha=0.5, label="input")
            ax.plot(data['times'], x, alpha=0.5, label="integral")
        # ax.plot(data['times'], xhatDiff, label="diff")
        ax.plot(data['times'], xhatEns, label="ens")
        ax.set(xlabel='time', ylabel='state', title="rmse=%.3f"%error, xlim=((0, t)), ylim=((-1, 1)))
        ax.legend(loc='upper left')
        sns.despine()
        fig.savefig("plots/diffMemory_%s_test%s.pdf"%(neuron_type, test))

# ideal()
# run(N=100, t=10, c=5, nTrain=3, load=[0,1,2], neg=True, neuron_type=LIF(), file="data/diffMemory_LIF().npz")
run(N=30, t=10, c=5, nTrain=3, load=[0,1,2], neg=False, neuron_type=ALIF(), file="data/diffMemory_ALIF().npz")


#########################################################
## Stat 413 - Homework 3
## Author: Luxi Li
## Date : 2/18/2018
## Description: This script implements an adaboost classifier
#########################################################

#############################################################
## INSTRUCTIONS: Please fill in the missing lines of code
## only where specified. Do not change function names,
## function inputs or outputs. You can add examples at the
## end of the script (in the "Optional examples" section) to
## double-check your work, but MAKE SURE TO COMMENT OUT ALL
## OF YOUR EXAMPLES BEFORE SUBMITTING.
##
## Very important: Do not use the function "os.chdir" anywhere
## in your code. If you do, I will be unable to grade your
## work since Python will attempt to change my working directory
## to one that does not exist.
#############################################################

import math
import numpy as np
import sklearn.datasets as ds
from sklearn.model_selection import train_test_split

def prepare_data(valid_digits = np.array((6, 5))):

    ## valid_digits is a vector containing the digits
    ## we wish to classify.
    ## Do not change anything inside of this function
    if len(valid_digits) != 2:
        raise Exception("Error: you must specify exactly 2 digits for classification!")

    data = ds.load_digits()
    labels = data['target']
    features = data['data']

    X = features[(labels == valid_digits[0]) | (labels == valid_digits[1]), :]
    Y = labels[(labels == valid_digits[0]) | (labels == valid_digits[1]),]

    X = np.asarray(list(map(lambda k: X[k,:]/X[k,:].max(), range(0,len(X)))))

    Y[Y == valid_digits[0]] = 0
    Y[Y == valid_digits[1]] = 1

    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.25, random_state=10)
    Y_train = Y_train.reshape((len(Y_train), 1))
    Y_test = Y_test.reshape((len(Y_test), 1))

    return X_train, Y_train, X_test, Y_test

##########################
## Function 1: Adaboost ##
##########################

## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ##
## Use Adaboost to classify the digits data ##
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ##

def my_Adaboost(X_train, Y_train, X_test, Y_test, num_iterations=200):
    ## X_train: Training set of features
    ## Y_train: Training set of labels corresponding to X_train
    ## X_test: Testing set of features
    ## Y_test: Testing set of labels correspdonding to X_test
    ## num_iterations: Number of iterations.

    ## Function should learn the parameters of an Adaboost classifier.

    n = X_train.shape[0]
    p = X_train.shape[1]
    threshold = 0.8

    X_train1 = 2 * (X_train > threshold) - 1
    Y_train = 2 * Y_train - 1

    X_test1 = 2 * (X_test > threshold) - 1
    Y_test = 2 * Y_test - 1

    beta = np.repeat(0., p).reshape((p, 1))
    w = np.repeat(1. / n, n).reshape((n, 1))

    weak_results = np.multiply(Y_train, X_train1) > 0

    acc_train = np.repeat(0., num_iterations, axis=0)
    acc_test = np.repeat(0., num_iterations, axis=0)

    #######################
    ## FILL IN CODE HERE ##
    #######################

    for it in range(num_iterations):
        weighted_weak_results = np.multiply(w, weak_results)
        weighted_accuracy = np.sum(weighted_weak_results, axis = 0)
        e = 1 - weighted_accuracy
        j = np.argmin(e)
        dbeta = 0.5* math.log((1 - e[j]) / e[j])
        beta[j] = beta[j] + dbeta
        w = np.multiply(w, np.exp(-np.multiply(np.multiply(Y_train, X_train1[:, j:(j+1)]), dbeta)))
        w = w/np.sum(w)
        acc_train[it] = np.mean(np.multiply(np.sign(np.dot(X_train1, beta)), Y_train) >0)
        #print acc_train[it]
        #acc_test[it] = np.mean(np.sign(np.dot(X_test1, beta)) == Y_test)
        acc_test[it] = np.mean(np.multiply(np.sign(np.dot(X_test1, beta)), Y_test) > 0 )

    ## Function should output 3 things:
    ## 1. The learned parameters of the adaboost classifier, beta
    ## 2. The accuracy over the training set, acc_train (a "num_iterations" dimensional vector).
    ## 3. The accuracy over the testing set, acc_test (a "num_iterations" dimensional vector).
    return beta, acc_train, acc_test

############################################################################
## Testing your functions and visualize the results here##
############################################################################

X_train, Y_train, X_test, Y_test = prepare_data()

beta, acc_train, acc_test = my_Adaboost(X_train, Y_train, X_test, Y_test, num_iterations = 300)
#print(beta)
#print(acc_train)
#print(acc_test)
print('median accuracy when number of iterations is 300:')
print('test accuracy:')
print(np.median(acc_test))
print('train accuracy:')
print(np.median(acc_train))

beta, acc_train, acc_test = my_Adaboost(X_train, Y_train, X_test, Y_test, num_iterations = 100)
print('accuracy in iterations of 1000:')
print('maximum accuracy in testing data:')
print(np.max(acc_test))
print('maximum accuracy in training data:')
print(np.max(acc_train))
print('median accuracy in testing data:')
print(np.median(acc_test))
print('median accuracy in training data:')
print(np.median(acc_train))

print(acc_train)
print(acc_test)

####################################################
## Optional examples (comment out your examples!) ##
####################################################


'''
   Author: Rohith Kumar Punithavel
   Email: rohithkumar@asu.edu
   Problem Statement: https://leetcode.com/problems/count-negative-numbers-in-a-sorted-matrix/
'''
class Solution:
    def countNegatives(self, grid: List[List[int]]) -> int:
        count = 0
        for ele in grid:
            ele.sort()
            for ele1 in ele:
                if  ele1>=0:
                    break
                else:
                    count+=1
        return count


# {
# 	"national":
# 		[
# 			"THW force all news organizations to be non profit(i.e. NHK, BBC, PBS)",
# 			"THR the romanticization of success stories about educational achievement(e.g Biri Gal, Dragon Zakura)",
# 		],
# 	"international":
# 		""
# 		[

# 		],
# }

import json
from collections import OrderedDict
import pprint

json_dict = {}
json_dict["national"] = []
json_dict["international"] = []

input_file_name = "./data/datastructure/datastructure.json"

with open(input_file_name, "r") as f:
	datas = json.loads(f.read())
	for i in range(len(datas["national"])):
		for j in range(len(datas["national"][i]["rounds"])):
			json_dict["national"].append(datas["national"][i]["rounds"][j]["motion"])

	for i in range(len(datas["international"])):
		for j in range(len(datas["international"][i]["rounds"])):
			json_dict["international"].append(datas["international"][i]["rounds"][j]["motion"])

print(len(json_dict["national"]))

class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, numpy.integer):
            return int(obj)
        elif isinstance(obj, numpy.floating):
            return float(obj)
        elif isinstance(obj, numpy.ndarray):
            return obj.tolist()
        else:
            return super(MyEncoder, self).default(obj)

output_file_name = "./data/datastructure/motions.json"
with open(output_file_name, 'w', encoding='utf-8') as fw:
    fw.write(json.dumps(json_dict, indent=4, cls=MyEncoder))


from uuid import UUID

from crm_pilates.command.command_bus import CommandBus
from crm_pilates.command.response import Response
from crm_pilates.command.saga_handler import SagaHandler
from crm_pilates.domain.attending.session import ConfirmedSession
from crm_pilates.domain.commands import SessionCreationCommand
from crm_pilates.domain.sagas import SessionCheckinSaga
from crm_pilates.domain.scheduling.attendee import Attendee
from crm_pilates.event.event_store import Event, EventSourced
from crm_pilates.infrastructure.repository_provider import RepositoryProvider

@EventSourced
class SessionCheckedIn(Event):
    def __init__(self, root_id: UUID, attendee: Attendee) -> None:
        self.checked_in_attendee = attendee
        super().__init__(root_id)

    def __map_attendee(self, attendee: Attendee) -> dict:
        return {"id": attendee.id, "attendance": attendee.attendance.value}

    def _to_payload(self):
        return {
            "session_id": self.root_id,
            "attendee": self.__map_attendee(self.checked_in_attendee),
        }

class SessionCheckinSagaHandler(SagaHandler):
    def __init__(self, command_bus: CommandBus) -> None:
        super().__init__(command_bus)

    def execute(self, saga: SessionCheckinSaga) -> SessionCheckedIn:
        session = (
            RepositoryProvider.write_repositories.session.get_by_classroom_id_and_date(
                saga.classroom_id, saga.session_date
            )
        )
        if session:
            session_id = session.id
        else:
            confirmed_session_event: Response = self._command_bus.send(
                SessionCreationCommand(saga.classroom_id, saga.session_date)
            )
            session_id = confirmed_session_event.event.root_id

        confirmed_session: ConfirmedSession = (
            RepositoryProvider.write_repositories.session.get_by_id(session_id)
        )
        checked_in_attendee: Attendee = confirmed_session.checkin(
            Attendee.create(saga.attendee)
        )
        return SessionCheckedIn(confirmed_session.id, checked_in_attendee)