from typing import List, Dict
from enum import IntEnum
import logging

from PyQt5 import QtGui, QtWidgets, QtCore

from irspy.qt.custom_widgets.QTableDelegates import TransparentPainterForWidget
from irspy.qt.qt_settings_ini_parser import QtSettings
from irspy.qt import qt_utils
from irspy import utils

from ui.py.graphs_edit_dialog import Ui_graphs_edit_dialog as GraphsEditForm

class GraphsEditDialog(QtWidgets.QDialog):

    class Column(IntEnum):
        NAME = 0,
        COLOR = 1,
        BOLD = 2,
        SHOW = 3,
        DELETE = 4,
        PATH = 5,
        COUNT = 6

    class PropertiesItem(IntEnum):
        COLOR = 0,
        BOLD = 1,
        SHOW = 2,
        PATH = 3

    DEFAULT_PEN_WIDTH = 2
    BOLD_PEN_WIDTH = 4

    enable_graph = QtCore.pyqtSignal(str, bool)
    change_graph_color = QtCore.pyqtSignal(str, QtGui.QColor)
    bold_graph_enable = QtCore.pyqtSignal(str, bool)
    remove_graph = QtCore.pyqtSignal(str)
    rename_graph = QtCore.pyqtSignal(str, str)

    def __init__(self, a_graph_properties: Dict[str, List], a_lock_changes,
                 a_settings: QtSettings, a_parent=None):
        super().__init__(a_parent)

        self.ui = GraphsEditForm()
        self.ui.setupUi(self)

        self.settings = a_settings
        self.settings.restore_qwidget_state(self)
        self.settings.restore_qwidget_state(self.ui.graphs_table)

        self.ui.graphs_table.setItemDelegate(TransparentPainterForWidget(self.ui.graphs_table, "#d4d4ff"))
        self.ui.graphs_table.cellDoubleClicked.connect(self.cell_double_clicked)

        self.graph_properties = a_graph_properties

        for name, style in self.graph_properties.items():
            self.add_graph_to_table(name, *style, a_lock_changes)

        self.measure_name_before_rename = ""

        self.ui.show_all_button.clicked.connect(self.show_all_button_clicked)
        self.ui.hide_all_button.clicked.connect(self.hide_all_button_clicked)
        self.ui.delete_all_button.clicked.connect(self.delete_all_button_clicked)
        self.ui.graphs_table.itemChanged.connect(self.measure_renamed)

        self.show()

    @staticmethod
    def __add_non_editable_item(a_table_widget, a_row, a_column, a_text=""):
        item = QtWidgets.QTableWidgetItem(a_text)
        item.setFlags(item.flags() & ~QtCore.Qt.ItemIsEditable)
        a_table_widget.setItem(a_row, a_column, item)

    def add_graph_to_table(self, a_name, a_color, a_bold, a_show, a_graph_filepath, a_lock_changes):
        row_idx = self.ui.graphs_table.rowCount()
        self.ui.graphs_table.insertRow(row_idx)

        if a_lock_changes:
            self.__add_non_editable_item(self.ui.graphs_table, row_idx, GraphsEditDialog.Column.NAME, a_name)
        else:
            self.ui.graphs_table.setItem(row_idx, GraphsEditDialog.Column.NAME, QtWidgets.QTableWidgetItem(a_name))

        self.__add_non_editable_item(self.ui.graphs_table, row_idx, GraphsEditDialog.Column.COLOR)
        self.__add_non_editable_item(self.ui.graphs_table, row_idx, GraphsEditDialog.Column.BOLD)
        self.__add_non_editable_item(self.ui.graphs_table, row_idx, GraphsEditDialog.Column.SHOW)
        self.__add_non_editable_item(self.ui.graphs_table, row_idx, GraphsEditDialog.Column.DELETE)
        self.__add_non_editable_item(self.ui.graphs_table, row_idx, GraphsEditDialog.Column.PATH)

        self.ui.graphs_table.item(row_idx, GraphsEditDialog.Column.COLOR).setBackground(QtGui.QColor(a_color))

        cb = QtWidgets.QCheckBox()
        self.ui.graphs_table.setCellWidget(row_idx, GraphsEditDialog.Column.BOLD, qt_utils.wrap_in_layout(cb))
        cb.setChecked(a_bold)
        cb.toggled.connect(self.bold_graph_checkbox_toggled)

        cb = QtWidgets.QCheckBox()
        self.ui.graphs_table.setCellWidget(row_idx, GraphsEditDialog.Column.SHOW, qt_utils.wrap_in_layout(cb))
        cb.setChecked(a_show)
        cb.toggled.connect(self.show_graph_checkbox_toggled)

        button = QtWidgets.QPushButton("Удалить")
        self.ui.graphs_table.setCellWidget(row_idx, GraphsEditDialog.Column.DELETE, qt_utils.wrap_in_layout(button))
        button.clicked.connect(self.delete_graph_button_clicked)

        self.ui.graphs_table.item(row_idx, GraphsEditDialog.Column.PATH).setText(a_graph_filepath)

    def __get_name_by_row(self, a_row):
        return self.ui.graphs_table.item(a_row, GraphsEditDialog.Column.NAME).text()

    def cell_double_clicked(self, a_row, a_column):
        name = self.__get_name_by_row(a_row)

        if a_column == GraphsEditDialog.Column.COLOR:
            color = self.graph_properties[name][GraphsEditDialog.PropertiesItem.COLOR]
            new_color = QtWidgets.QColorDialog.getColor(QtGui.QColor(color))
            if new_color.isValid():
                self.ui.graphs_table.item(a_row, GraphsEditDialog.Column.COLOR).setBackground(new_color)

                self.change_graph_color.emit(name, new_color)

        elif a_column == GraphsEditDialog.Column.NAME:
            self.measure_name_before_rename = name
            assert(self.measure_name_before_rename != "")

    def measure_renamed(self, a_item: QtWidgets.QTableWidgetItem):
        if a_item.column() == GraphsEditDialog.Column.NAME:
            if self.measure_name_before_rename:
                new_name = a_item.text()
                if new_name:
                    new_name = utils.get_allowable_name(self.graph_properties.keys(), new_name)

                    properties = self.graph_properties[self.measure_name_before_rename]
                    del self.graph_properties[self.measure_name_before_rename]
                    self.graph_properties[new_name] = properties

                    self.rename_graph.emit(self.measure_name_before_rename, new_name)

                    if a_item.text() != new_name:
                        # Если заданное имя уже существует и new_name подправлено в get_allowable_name
                        self.measure_name_before_rename = ""
                        a_item.setText(new_name)
                else:
                    old_name = self.measure_name_before_rename
                    self.measure_name_before_rename = ""
                    a_item.setText(old_name)

                self.measure_name_before_rename = ""

    def __get_row_by_sender_widget(self, a_sender, a_sender_column):
        for row in range(self.ui.graphs_table.rowCount()):
            cell_widget = self.ui.graphs_table.cellWidget(row, a_sender_column)
            widget = qt_utils.unwrap_from_layout(cell_widget)

            if a_sender == widget:
                selected_row = row
                break
        else:
            assert False, "Не найдена строка таблицы с виджетом-отправителем сигнала"

        return selected_row

    def show_graph_checkbox_toggled(self, a_state):
        sender_checkbox = self.sender()
        graph_row = self.__get_row_by_sender_widget(sender_checkbox, GraphsEditDialog.Column.SHOW)
        name = self.__get_name_by_row(graph_row)

        self.enable_graph.emit(name, a_state)

    def bold_graph_checkbox_toggled(self, a_state):
        sender_checkbox = self.sender()
        graph_row = self.__get_row_by_sender_widget(sender_checkbox, GraphsEditDialog.Column.BOLD)
        name = self.__get_name_by_row(graph_row)

        self.bold_graph_enable.emit(name, a_state)

    def delete_graph_button_clicked(self):
        delete_button = self.sender()
        deleted_row = self.__get_row_by_sender_widget(delete_button, GraphsEditDialog.Column.DELETE)
        graph_name = self.__get_name_by_row(deleted_row)

        self.ui.graphs_table.removeRow(deleted_row)
        self.remove_graph.emit(graph_name)

    def show_all_button_clicked(self):
        for row in range(self.ui.graphs_table.rowCount()):
            widget = self.ui.graphs_table.cellWidget(row, GraphsEditDialog.Column.SHOW)
            show_checkbox = qt_utils.unwrap_from_layout(widget)
            show_checkbox.setChecked(True)

    def hide_all_button_clicked(self):
        for row in range(self.ui.graphs_table.rowCount()):
            widget = self.ui.graphs_table.cellWidget(row, GraphsEditDialog.Column.SHOW)
            show_checkbox = qt_utils.unwrap_from_layout(widget)
            show_checkbox.setChecked(False)

    def delete_all_button_clicked(self):
        res = QtWidgets.QMessageBox.question(self, "Подтвердите действие", "Вы действительно хотите удалить все графики?",
                                             QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                             QtWidgets.QMessageBox.Yes)
        if res == QtWidgets.QMessageBox.Yes:
            for row in reversed(range(self.ui.graphs_table.rowCount())):
                widget = self.ui.graphs_table.cellWidget(row, GraphsEditDialog.Column.DELETE)
                delete_button = qt_utils.unwrap_from_layout(widget)
                delete_button.click()

    def ok_button_clicked(self):
        self.accept()

    def __del__(self):
        self.settings.save_qwidget_state(self.ui.graphs_table)
        self.settings.save_qwidget_state(self)
        print("GraphsEditDialog deleted")


"""
def mul(a,b):
    if a==0:
        return 0
    if a%2:
        return b+mul(a//2,b*2)
    else:
        return mul(a//2,b*2)

a,b=map(int,input().split())
print(mul(a,b))

 """

"""
def fib(a,b,d,num):
    if d>num:
        return
    if d==1:
        print(a,end=" ")
    if d==2:
        print(b,end=" ")
        d+=1
    print(a+b,end=" ")
    fib(b,a+b,d+1,num)

num=int(input())
fib(0,1,1,num-1)

"""

def fib(a,b,i,num):
    if i>num:
        return
    if i==1 and i<=num:
        print(a,end=" ")
        i+=1
    if i==2 and i<=num:
        print(b,end=" ")
        i+=1
    #if i<=num:
    print(a+b,end=" ")
    fib(b,a+b,i+1,num)

num=int(input())
fib(0,1,1,num)


import os

from PIL import Image

from tools.reader import BinaryReader

def dcr_decode():
    files = ['BEHOLDER.DCR', 'CLERIC1.DCR', 'CLERIC2.DCR', 'CLERIC3.DCR', 'DRAGON.DCR', 'GUARD1.DCR', 'GUARD2.DCR', 'MAGE.DCR', 'MANTIS.DCR']
    dcr = {}

    for file in files:
        dcr[file] = []
        with BinaryReader('data/{file}'.format(file=file)) as reader:
            count = reader.read_ushort()
            for i in range(count):
                sides = []
                for j in range(6):
                    side = {
                        "cps_x":    reader.read_ubyte() * 8,
                        "cps_y":    reader.read_ubyte(),
                        "width":    reader.read_ubyte() * 8,
                        "height":   reader.read_ubyte(),
                        "screen_x": reader.read_ubyte(),
                        "screen_y": reader.read_ubyte()
                    }

                    sides.append(side)
                dcr[file].append(sides)

            i = 1
    return dcr

def dcr_draw(assets):
    files = ['BEHOLDER', 'CLERIC1', 'CLERIC2', 'CLERIC3', 'DRAGON', 'GUARD1', 'GUARD2', 'MAGE', 'MANTIS']
    input_path = './data/'
    output_path = './build/dcr/'

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

    for file in files:
        dcr = assets['dcr'][file + '.DCR']

        for id in range(len(dcr)):
            data = dcr[id]
            img = Image.open("{path}{file}.PNG".format(path=input_path, file=file), 'r')
            # img.convert('RGBA')

            for face in range(6):
                d = data[face]

                x = d['cps_x']
                y = d['cps_y']
                right = x + d['width']
                lower = y + d['height']

                bg = Image.new('RGBA', (320, 200), (255, 0, 0, 0))
                bg.paste(img, (0, 0))

                crop = bg.crop((x, y, right, lower))
                # crop.convert('RGBA')

                x = d['screen_x']
                y = d['screen_y']
                bg.paste(crop, (x, y), )

                bg = bg.resize((640, 400))
                bg.save("{path}{file}_{id}_{face}.PNG".format(path=output_path, file=file, id=id, face=face), format='png')

            i = 1


"""
https://leetcode.com/problems/minimum-distance-between-bst-nodes/
bst에서 두 노드 간 값의 차이가 가장 작은 노드 계산
"""
import sys

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:
    prev = -sys.maxsize
    result = sys.maxsize

    # 재귀 구조 중위 순회 비교 결과
    def minDiffInBST(self, root: TreeNode) -> int:
        if root.left:
            self.minDiffInBST(root.left)

        self.result = min(self.result, root.val - self.prev)
        self.prev = root.val

        if root.right:
            self.minDiffInBST(root.right)
        return self.result

    # 반복 구조로 중위 순회, 스택 사용
    def minDiffInBST_dfs(self, root: TreeNode) -> int:
        prev = -sys.maxsize
        result = sys.maxsize

        stack = []
        node = root

        while stack or node:
            while node:
                stack.append(node)
                node = node.left

            node = stack.pop()

            result = min(result, node.val - prev)
            prev = node.val

            node = node.right

        return result


map = {
    "size_x": 10,
    "size_y": 7
}

player = { "x":3, "y":4}

boxes = [
    {"x": 1,"y": 1},
    {"x": 2,"y": 2},
    {"x": 3,"y": 3}
]

destination = [
    {"x": 2,"y": 1},
    {"x": 3,"y": 2},
    {"x": 4,"y": 3}
]

walls = [
    {"x": 8,"y": 2},
    {"x": 8,"y": 5},
    {"x": 3,"y": 5}
]
playing = True
count = 0   # tao bien dem de kiem tra undo 1 lan
while playing:
    # print map
    for y in range(map['size_y']):
        for x in range(map['size_x']):

            player_is_here = False
            if y == player['y'] and x == player['x']:
                player_is_here = True

            box_is_here = False
            for box in boxes:
                if y == box['y'] and x == box['x']:
                    box_is_here = True

            destination_is_here = False
            for des in destination:
                if y == des['y'] and x == des['x']:
                    destination_is_here = True

            wall_is_here = False
            for wall in walls:
                if y == wall['y'] and x == wall['x']:
                    wall_is_here = True

            if player_is_here:
                print("P ", end='')
            elif box_is_here:
                print("B ", end='')
            elif destination_is_here:
                print("D ", end='')
            elif wall_is_here:
                print("O ", end='')
            else:
                print("_ ", end='')
        print()
    # end of print map

    # checkwin
    win = True
    for box in boxes:
        if box not in destination:
            win = False

    if win:
        print("YOU WIN!!")
        break

    dx = 0
    dy = 0

    move = input("What is your next move? W/A/S/D Or (Undo - Z - You can Undo only 1 time after a move) ").upper()
    if move == "W":
        dy = -1
        dx1 = 0
        dy1 = 1
        count = 0
    elif move == "S":
        dy = 1
        dx1 = 0
        dy1 = -1
        count = 0
    elif move == "A":
        dx = -1
        dx1 = 1
        dy1 = 0
        count = 0
    elif move == "D":
        dx = 1
        dx1 = -1
        dy1 = 0
        count = 0
    elif move == "Z":
        if count == 0:
            player['x'] += dx1
            player['y'] += dy1
            print("Undo Action!")
            count += 1
        else:
            print("You can Undo only 1 time after a move! Keep moving pleasee!")
    else:
        playing = False

    if 0 <= player['x'] + dx < map['size_x'] and 0 <= player['y'] + dy < map['size_y']:
        player['x'] += dx
        player['y'] += dy

    for box in boxes:
        # check box trung nhau
        if box['y'] == player['y'] and box['x'] == player['x'] and 0 <= box['x'] + dx < map['size_x'] and 0 <= box['y'] + dy < map['size_y']:
            box['x'] += dx
            box['y'] += dy
            # khong cho phep day 2 box
            if boxes[0] == boxes[1] or boxes[0] == boxes[2] or boxes[2] == boxes[1]:
                player['x'] -= dx
                player['y'] -= dy
                box['x'] -= dx
                box['y'] -= dy
            # khong cho phep day box vao wall
            elif box['y'] == wall['y'] and box['x'] == wall['x']:
                player['x'] -= dx
                player['y'] -= dy
                box['x'] -= dx
                box['y'] -= dy
                print("Oop, walll! :<")
        elif box['y'] == player['y'] and box['x'] == player['x']:
            player['x'] -= dx
            player['y'] -= dy


import math
from collections import Counter

import BWT
import MTF
from huffman import make_tree, huffman_code_tree

BLOCK_SIZES = {
    1: 1024,
    2: 2048,
    3: 4096,
    4: 8192,
    5: 16384,
    6: 32768,  # ОПАСНО - ПОЖИРАТЕЛЬ ПАМЯТИ ~ 8 Гб
    7: 65536,  # ОПАСНО - ПОЖИРАТЕЛЬ ПАМЯТИ ~10 Гб
}

def main(size_level, file_in, file_out):
    block_size = BLOCK_SIZES[size_level]
    length = 0
    encoded = []
    with open(file_in, 'rb') as f:
        alphabet = []
        for i in f.read():
            length += 1
            if i not in alphabet:
                alphabet.append(i)
        alphabet.sort()
        f.seek(0)
        blocks_count = math.ceil(length / block_size)
        packet_num = 0
        bwt_codes = []
        while True:
            print(f'Progress: {packet_num} \\ {blocks_count}')
            packet = f.read(block_size)
            if packet == b'':
                break

            bwt_step = BWT.encode(packet)
            bwt_codes.append(bwt_step[1])

            mtf_step = MTF.encode(bwt_step[0], alphabet)
            encoded.extend(mtf_step)
            packet_num += 1

    frequency = dict(Counter(encoded))
    frequency = sorted(frequency.items(), key=lambda x: x[1], reverse=True)
    tree = make_tree(frequency)
    encoded_tree = huffman_code_tree(tree)
    encoded_text = [encoded_tree[i] for i in encoded]

    with open(file_out, 'wb') as f:
        for i in encoded_text:
            ch = str(i)[2:-1]
            f.write(int(ch, 2).to_bytes(math.ceil(len(ch) / 8), 'big'))

if __name__ == '__main__':
    filename = 'Rick.mp3'

    main(size_level=1, file_in=filename, file_out=f'{filename}.bin')


# Main program
from DictionaryData import dict_search

Condition = "y"

while Condition == "y":
    keyword = input("Type in the word you want to look up: ")
    print(f"You searched for '{keyword}':")
    result = dict_search(keyword)

    for key in result:
        for item in result[key]:
            print(f"{key} : {item}")

    Condition = input("Press 'y' to continue and look up another word or press any key to stop.")


import numpy as np

from interaction_components import *

class TraceGenerator:

    def __init__(self, TS):
        self.TS = TS
        print(self.TS)

        self.prob_ready = 0.2

    def get_trajectories(self, n):
        trajs = []

        # behavioral rules:
        # 1) probability of ignoring robot is initially high
        # 2) after every remark, probability decreases

        # experience rules:
        # 1) if multiple announcements in a row, experience
        # 2) if the person misses the announcement, then bad

        for i in range(n):
            traj = []
            traj_score = -1
            traj.append((HumanInput("Ready"), Microinteraction(self.TS.init.micros[0]["name"], 0)))

            curr_state = self.TS.init
            curr_prob_ready = 0.2
            speech_1 = False
            speech_2 = False

            missed_announcement = False
            made_up_missed_announcement = False
            while True:
                if curr_state.name == "Greet" or curr_state.name == "Announcement":
                    curr_prob_ready = min(1.0, curr_prob_ready + np.random.uniform(0.1,0.3))

                    if speech_1:
                        speech_2 = True
                    speech_1 = True
                else:
                    speech_1 = False

                options = curr_state.out_trans

                if len(options) == 0:
                    break
                conditions = ["Ready", "Ignore"]

                selection = np.random.choice(conditions, p=[curr_prob_ready, 1-curr_prob_ready])
                if curr_state.name == "Announcement" and selection == "Ignore":
                    missed_announcement = True
                if missed_announcement and curr_state.name == "Announcement" and selection == "Ready":
                    made_up_missed_announcement = True
                trans = None
                for option in options:
                    if option.condition == selection:
                        trans = option
                        curr_state = option.target
                        break

                if trans is not None:
                    traj.append((HumanInput(selection), Microinteraction(trans.target.micros[0]["name"], 0)))

            if not speech_2 and not (missed_announcement and not made_up_missed_announcement):
                score = np.random.random()*2 - 1
            else:
                score = np.random.random()-1

            trajs.append(Trajectory(traj,score,False,False))
        return trajs


from odoo.tests import tagged
from odoo.tools import mute_logger

from odoo.addons.payment import utils as payment_utils
from odoo.addons.payment_aps.controllers.main import APSController
from odoo.addons.payment_aps.tests.common import APSCommon

@tagged('post_install', '-at_install')
class TestPaymentTransaction(APSCommon):

    def test_reference_contains_only_valid_characters(self):
        """ Test that transaction references are made of only alphanumerics and/or '-' and '_'. """
        for prefix in (None, '', 'S0001', 'INV/20222/001', 'dummy ref'):
            reference = self.env['payment.transaction']._compute_reference('aps', prefix=prefix)
            self.assertRegex(reference, r'^[\w-]+$')

    def test_no_item_missing_from_rendering_values(self):
        """ Test that the rendered values are conform to the transaction fields. """
        tx = self._create_transaction(flow='redirect')

        converted_amount = payment_utils.to_minor_currency_units(self.amount, self.currency)
        expected_values = {
            'command': 'PURCHASE',
            'access_code': self.provider.aps_access_code,
            'merchant_identifier': self.provider.aps_merchant_identifier,
            'merchant_reference': tx.reference,
            'payment_option': 'UNKNOWN',
            'amount': str(converted_amount),
            'currency': self.currency.name,
            'language': tx.partner_lang[:2],
            'customer_email': tx.partner_id.email_normalized,
            'return_url': self._build_url(APSController._return_url),
            'signature': 'c9b9f35a607606c045f8882e762a4a4a35572cf230fe1cd45fa18d7c8681aeb9',
            'api_url': self.provider._aps_get_api_url(),
        }
        self.assertDictEqual(tx._get_specific_rendering_values(None), expected_values)

    @mute_logger('odoo.addons.payment.models.payment_transaction')
    def test_no_input_missing_from_redirect_form(self):
        """ Test that the no key is not omitted from the rendering values. """
        tx = self._create_transaction(flow='redirect')
        expected_input_keys = [
            'command',
            'access_code',
            'merchant_identifier',
            'merchant_reference',
            'amount',
            'currency',
            'language',
            'customer_email',
            'signature',
            'payment_option',
            'return_url',
        ]
        processing_values = tx._get_processing_values()
        form_info = self._extract_values_from_html_form(processing_values['redirect_form_html'])
        self.assertEqual(form_info['action'], 'https://sbcheckout.payfort.com/FortAPI/paymentPage')
        self.assertEqual(form_info['method'], 'post')
        self.assertListEqual(list(form_info['inputs'].keys()), expected_input_keys)

    def test_processing_notification_data_confirms_transaction(self):
        """ Test that the transaction state is set to 'done' when the notification data indicate a
        successful payment. """
        tx = self._create_transaction(flow='redirect')
        tx._process_notification_data(self.notification_data)
        self.assertEqual(tx.state, 'done')


# Licensed under a 3-clause BSD style license - see LICENSE.rst

from datetime import datetime
import os
import re

from astropy import log, units
from astropy.io import fits
from astropy.time import Time
import bottleneck as bn
import numpy as np
import pandas

from sofia_redux.instruments import fifi_ls
from sofia_redux.toolkit.utilities \
    import (robust_bool, valid_num, goodfile,
            natural_sort, date2seconds, hdinsert)

__all__ = ['create_requirements_table', 'clear_requirements_table',
           'get_keyword_comments', 'get_keyword_table',
           'get_keyword_comments_table', 'update_basehead',
           'order_headers', 'make_header']

__requirements_table = None
__requirements_file = None
__keyword_comments_file = None
__quick_comments = None

def create_requirements_table(default_file=None, comment_file=None,
                              reload=False):
    """
    Create the header keyword requirements definition table.

    Parameters
    ----------
    default_file : str, optional
        File path to the keyword definition file.  The default is
        fifi_ls/data/header_info/headerdef.dat
    comment_file : str, optional
        File path to the keyword comments file.  The default is
        fifi_ls/data/header_info/headercomment.dat.
    reload : bool, optional
        If set, data in cache will be ignored and files will be
        reloaded.
    """

    global __requirements_table
    global __requirements_file
    global __keyword_comments_file
    global __quick_comments

    create_table = (reload
                    or __requirements_table is None
                    or __requirements_file != default_file
                    or __keyword_comments_file != comment_file)

    if not create_table:
        return

    log.debug("Creating FIFI-LS keyword requirements table")
    clear_requirements_table()

    try:
        __requirements_table = get_keyword_table(filename=default_file).join(
            get_keyword_comments_table(filename=comment_file))
        __requirements_file = default_file
        __keyword_comments_file = comment_file
        __quick_comments = __requirements_table['comment'].to_dict()
        __requirements_table = __requirements_table.to_dict('index')
    except Exception as err:
        log.error(err)
        raise ValueError("Could not create requirements table")

def clear_requirements_table():
    """
    Clear all data from the requirements cache.
    """
    global __requirements_table
    global __requirements_file
    global __keyword_comments_file
    global __quick_comments

    __requirements_table = None
    __requirements_file = None
    __keyword_comments_file = None
    __quick_comments = None

def get_keyword_comments():
    """
    Get the keyword comments table from the cache.
    """
    global __quick_comments
    return __quick_comments

def get_keyword_table(filename=None):
    """
    Returns a dataframe containing the header requirements.

    Parameters
    ----------
    filename : str, optional
        File path to the keyword definition file.  The default is
        fifi_ls/data/header_info/headerdef.dat

    Returns
    -------
    pandas.DataFrame
    """
    if filename is None:
        filename = os.path.join(os.path.dirname(fifi_ls.__file__),
                                'data', 'header_info', 'headerdef.dat')
    if not goodfile(filename, verbose=True, read=True):
        raise ValueError("invalid header definition file: %s" % filename)

    log.debug('Using keyword file: %s' % filename)

    columns = ['required', 'default', 'type', 'combine',
               'min', 'max', 'enum']
    types = {'int': int, 'integer': int, 'float': float, 'bool': robust_bool,
             'str': str, 'string': str, 'complex': complex}
    converters = {
        'required': robust_bool,
        'default': lambda x: None if x == '.' else x,
        'type': lambda x: types.get(x),
        'combine': lambda x: '' if x == '.' else x,
        'min': lambda x: float(x) if x != '.' else None,
        'max': lambda x: float(x) if x != '.' else None,
        'enum': lambda x: x.split('|') if x != '.' else []
    }
    table = pandas.read_csv(
        filename, delim_whitespace=True, comment='#',
        index_col=0, names=columns, converters=converters)
    table.index = table.index.str.upper().str.strip()
    table.enum = table.apply(
        lambda row: [row.type(x) for x in row.enum], axis=1)
    table.default = table.apply(lambda row: row.type(row.default), axis=1)
    table['key'] = table.index

    return table

def get_keyword_comments_table(filename=None):
    """
    Returns a dictionary containing header keyword comments.

    Parameters
    ----------
    filename : str, optional
        File path to the keyword comments file.  The default is
        fifi_ls/data/header_info/headercomment.dat.

    Returns
    -------
    pandas.DataFrame
    """
    if filename is None:
        filename = os.path.join(os.path.dirname(fifi_ls.__file__),
                                'data', 'header_info', 'headercomment.dat')
    if not goodfile(filename, verbose=True, read=True):
        raise ValueError("invalid header comment file: %s" % filename)

    log.debug("Using keyword comment file %s" % filename)
    table = pandas.read_csv(
        filename, comment='#', index_col=0, names=['comment'],
        converters={'comment': str.strip}, skipinitialspace=True)
    table.index = table.index.str.upper().str.strip()
    return table

def clear_values(table):
    if table is None:
        return
    for row in table.values():
        row['value'] = None

def set_defaults(table):
    for row in table.values():
        if row.get('value') is None:
            row['value'] = row['default']

def get_keyword_values(basehead, headers,
                       default_file=None, comment_file=None):

    create_requirements_table(
        default_file=default_file,
        comment_file=comment_file,
        reload=False)

    global __requirements_table
    table = __requirements_table
    clear_values(table)

    if table is None:
        raise ValueError("Could not create requirements table")

    for key, row in table.items():
        table[key]['value'] = aggregate_key_value(basehead, headers, row)

    return table

def aggregate_key_value(basehead, headers, row):

    combine = row['combine']

    if combine == 'first' or len(headers) == 1:
        return value_from_header(basehead, row)

    elif combine == 'last':
        return value_from_header(headers[-1], row)

    elif combine == 'default':
        return row['default']

    elif combine == 'and':
        for header in headers:
            if not value_from_header(header, row):
                return False
        else:
            return True

    elif combine == 'or':
        for header in headers:
            if value_from_header(header, row):
                return True
        else:
            return False

    elif combine == 'concatenate':
        result = set()
        for header in headers:
            string_value = value_from_header(header, row)
            if not string_value:
                continue
            values = [x.upper().strip() for x in str(string_value).split(',')]
            for value in values:
                result.add(value)

        return ','.join(natural_sort(list(result)))

    elif combine == 'mean':
        result = []
        for header in headers:
            value = value_from_header(header, row)
            if value is not None:
                result.append(value)
        result = bn.nanmean(result)
        if not np.isfinite(result):
            result = row['default']
        else:
            result = row['type'](result)

        return result

    elif combine == 'sum':
        result = []
        for header in headers:
            value = value_from_header(header, row)
            if value is not None:
                result.append(value)
        result = bn.nansum(result)
        if not np.isfinite(result):
            result = row['default']
        else:
            result = row['type'](result)
        return result

    else:
        # return basehead value again
        return value_from_header(basehead, row)

def value_from_header(header, row, default=None):
    value = header.get(row['key'])
    if value is None:
        if default is not None:
            return default
        else:
            return None
    else:
        dtype = row['type']
        try:
            value = dtype(value)
        except (ValueError, TypeError, AttributeError):
            pass

    return value

def check_key(table, key):

    row = table.get(key)
    if row is None:
        log.warning("%s key is not in the keyword definitions" % key)
        # let it through
        return True

    value = row.get('value')

    if not row['required']:
        return True

    elif value is None:
        log.error('Required keyword %s not found' % key)
        return False

    dtype = row['type']
    if dtype is robust_bool:
        dtype = bool

    if not isinstance(value, dtype):
        log.error(
            "Required keyword %s has wrong type (value: %s). Should be %s" %
            (key, value, dtype))
        return False

    elif key == 'DATE-OBS':
        # special check for UTC 0 date (a common FIFI-LS glitch)
        try:
            mjd = Time(value).mjd
        except (ValueError, AttributeError, TypeError):
            mjd = 40587
        if int(mjd) == 40587:
            log.error("Required keyword DATE-OBS has wrong value (%s)"
                      % value)
            return False
        return True

    enum = row['enum']
    if len(enum) > 0:
        if value not in enum:
            log.error(
                "Required keyword %s has value (%s). Should be within [%s]"
                % (key, repr(value), ','.join(str(x) for x in enum)))
            return False

    if not np.isnan(row['min']) and value < row['min']:
        log.error("Required keyword %s has wrong value. Should be >= %s" %
                  (key, row['min']))
        return False

    if not np.isnan(row['max']) and value > row['max']:
        log.error("Required keyword %s has wrong value. Should be <= %s" %
                  (key, row['max']))
        return False

    # If we got here it's all good
    return True

def update_basehead(basehead, table, headers):
    """
    Update the base header with values that may be missing.

    Parameters
    ----------
    basehead : fits.Header
        FITS header to update
    headers : array_like of fits.Header
        List of headers from which to compile values
    table : dict
        Table of keywords and values

    Returns
    -------
    fits.Header
        Updated basehead
    """
    set_defaults(table)
    for key, row in table.items():
        hdinsert(basehead, key, row['value'], comment=row['comment'])

    comments = get_keyword_comments()

    # Add some FITS standard keys
    hdinsert(basehead, 'EQUINOX', 2000.0,
             comment='Equinox of celestial CS')
    hdinsert(basehead, 'RADESYS', 'FK5',
             comment='Celestial CS convention')
    hdinsert(basehead, 'TIMESYS', 'UTC',
             comment='Time system')
    hdinsert(basehead, 'TIMEUNIT', 's',
             comment='Time unit')
    hdinsert(basehead, 'XPOSURE', basehead.get('EXPTIME', 0),
             comment='Exposure time [s]')

    dateobs = basehead.get('DATE-OBS', 'UNKNOWN')
    utcstart = basehead.get('UTCSTART', '00:00:00')
    utcend = basehead.get('UTCEND', '00:00:00')
    datestr = str(dateobs).split('T')[0].strip()
    datebeg = '%sT%s' % (datestr, utcstart)
    dateend = '%sT%s' % (datestr, utcend)

    try:
        # Elapsed time in seconds
        telapse = (Time(dateend) - Time(datebeg)).to(units.s).value
    except ValueError:
        log.warning("Could not determine TELAPSE")
        telapse = 0.0

    hdinsert(basehead, 'DATE-BEG', datebeg)
    hdinsert(basehead, 'DATE-END', dateend)
    # format necessary for floating point annoyances
    hdinsert(basehead, 'TELAPSE', float("{:.5f}".format(telapse)))

    # copy aor to assc_aor and missn-id to assc_msn if single header
    if len(headers) == 1:
        aor = str(basehead.get('AOR_ID', 'UNKNOWN')).strip().upper()
        assc_aor = str(basehead.get('ASSC_AOR', 'UNKNOWN')).strip().upper()
        if assc_aor == 'UNKNOWN' and aor != 'UNKNOWN':
            hdinsert(basehead, 'ASSC_AOR', aor,
                     comment=comments['ASSC_AOR'])
        msn = str(basehead.get('MISSN-ID', 'UNKNOWN')).strip().upper()
        assc_msn = str(basehead.get('ASSC_MSN', 'UNKNOWN')).strip().upper()
        if assc_msn == 'UNKNOWN' and msn != 'UNKNOWN':
            hdinsert(basehead, 'ASSC_MSN', msn,
                     comment=comments['ASSC_MSN'])

    # add the current date/time
    utctime = Time(datetime.utcnow(), format='datetime').isot
    hdinsert(basehead, 'DATE', utctime.split('.')[0],
             comment=comments['DATE'])

    # set processing level to 2
    procstat = str(basehead.get('PROCSTAT', 'UNKNOWN')).strip().upper()
    if procstat not in ['LEVEL_3', 'LEVEL_4']:
        hdinsert(basehead, 'PROCSTAT', 'LEVEL_2',
                 comment='Processing status')

    # add raw file number
    filenum = str(basehead.get('FILENUM', 'UNKNOWN'))
    filename = str(basehead.get('FILENAME', 'UNKNOWN'))
    obsid = str(basehead.get('OBS_ID', 'UNKNOWN'))
    pattern = re.compile(r'[BR]([0-9]+)')
    match = pattern.findall(obsid)
    if filenum == 'UNKNOWN':
        if match and valid_num(match[-1]):
            filenum = match[-1].strip()
        else:
            if len(filename) >= 5:
                test = filename[:5].strip()
                if valid_num(test):
                    filenum = test
    if len(headers) > 1:
        filenums = [filenum]
        for h in headers:
            filenums.extend(str(h.get('FILENUM', 'UNKNOWN')).split('-'))
        filenums = natural_sort(list(np.unique(filenums)))
        filenums = [f for f in filenums if valid_num(f)]
        if len(filenums) > 1:
            filenum = filenums[0].strip() + '-' + filenums[-1].strip()
        elif len(filenums) == 1:
            filenum = filenums[0].strip()
        else:
            filenum = 'UNKNOWN'

    hdinsert(basehead, 'FILENUM', filenum,
             comment=comments['FILENUM'])

    # Modify the obsid
    obs = str(basehead.get('OBS_ID', 'UNKNOWN')).strip().upper()
    if not obs.startswith('P_'):
        assc_obs = str(basehead.get('ASSC_OBS', 'UNKNOWN')).strip().upper()
        if assc_obs == 'UNKNOWN' and obs != 'UNKNOWN':
            hdinsert(basehead, 'ASSC_OBS', obs,
                     comment=comments['ASSC_OBS'])
        hdinsert(basehead, 'OBS_ID', 'P_' + obs,
                 comment=comments['OBS_ID'])

    # Set the pipeline name and version
    hdinsert(basehead, 'PIPELINE', 'FIFI_LS_REDUX',
             comment=comments['PIPELINE'])
    hdinsert(basehead, 'PIPEVERS', fifi_ls.__version__.replace('.', '_'),
             comment=comments['PIPEVERS'])

def order_headers(headers):
    """
    Order headers based on contents.

    Return the earliest and the header list sorted by date

    Parameters
    ----------
    headers : array_like of fits.Header

    Returns
    -------
    2-tuple
       fits.Header : earliest header
       list of fits.Header : ordered headers
    """
    nhead = len(headers)
    if nhead == 1:
        return headers[0].copy(), [headers[0]]
    nodstyle = None
    dateobs, nodbeam = [], []
    for header in headers:

        if nodstyle is None:
            nodstyle = str(header.get('NODSTYLE'))
        dateobs.append(
            date2seconds(
                str(header.get('DATE-OBS', default='3000-01-01T00:00:00'))))
        nodbeam.append(str(header.get('NODBEAM', 'UNKNOWN')))

    # If C2NC2, get the earliest A header as the basehead
    # Otherwise, just use the earliest header
    index = np.argsort(dateobs)
    if nodstyle in ['C2NC2', 'ASYMMETRIC'] and 'A' in nodbeam:
        earliest_a = np.where(np.array(nodbeam)[index] == 'A')[0]
        earliest_a = 0 if earliest_a.size == 0 else earliest_a[0]
    else:
        earliest_a = 0

    earliest_idx = index[earliest_a]
    basehead = headers[earliest_idx].copy()

    # sort all headers by date-obs, including the basehead
    # This is used for C2NC2 mode, to get 'last' values, whether
    # in A or B nod
    sorted_headers = [headers[i] for i in index]

    return basehead, sorted_headers

def make_header(headers=None, checkheader=False, default_file=None,
                comment_file=None, check_all=False):
    """
    Standardize and combine input headers.

    Generates output headers for pipeline data products.

    The procedure is:

        1. Read the header keyword defaults and requirements from
           data/headerdef.dat and their associated default comments from
           data/headercomment.dat.
        2. Copy the earliest header for symmetric mode, or earliest A
           header for C2NC2 mode.  "Earliest" is defined by DATE-OBS.
        3. Loop through all keywords defined in headerdef.dat
            a. Get the value from the header as defined in the configuration
               algorithm.  The combination options are: and (for booleans),
               concatendate unique values with commas (for string values),
               use default value, use last value (i.e. latest according to
               DATE-OBS), or (for booleans), sum (for numerical values),
               mean (for numerical values), use the first value.  The default
               and most common case is to use the first value.  The
               combined keyword value is written to the output header.
            b. Check the value against requirements if desired.  Required
               keywords are checked for presence, checked against a
               specified data type (float, int, long, string, bool), and
               may additionally be checked against an enumerated value or
               min/max value range.  If requirements are not met, or if a
               defined keyword is not found in the input header, it is set
               to the default value in the output header.
        4. Some additional values are added or modified in the output
           header:

               - ASSC_AOR is copied from AOR_ID if not present
               - ASSC_MSN is copied from MISSN-ID if not present
               - DATE is set to the current date/time
               - PROCSTAT is set to LEVEL_2 (unless it is already LEVEL_3
                 or LEVEL_4
               - FILENUM is set from the raw filename if not present, or
                 from the range of input file numbers (first-last)
               - ASSC_OBS is copied from OBS_ID if not present
               - OBS_ID is prepended with P\\_ if not already done

    Parameters
    ----------
    headers : array_like of fits.Header, optional
        array of input FITS headers
    checkheader : bool, optional
        If True, will check keywords against SOFIA requirements.  If
        set, the return value will be a 2-tuple rather than a FITS
        header (see Return values).
    default_file : str, optional
        Path to the header keyword default file
    comment_file : str, optional
        Path to the header keyword comment file
    check_all : bool, optional
        If `checkheader` is True and a failure was encountered, keep
        checking the remainder of the keyword values and output warning
        messages.  Otherwise, the default is to return failure at the
        first bad keyword/value.

    Returns
    -------
    fits.Header
        a combined, standardized FITS header
        if checkheader is True then the return value will be a 2-tuple.
        The first element will be the header, and the second will be
        a boolean value indicating whether the header was created
        without any errors (False = errors were encountered).
    """
    if headers is None:
        headers = [fits.Header()]
    elif isinstance(headers, fits.Header):
        headers = [headers]
    elif not hasattr(headers, '__len__'):
        log.error("Invalid header")
        return (None, False) if checkheader else None
    elif len(headers) == 0:
        log.error("Empty list of headers")
        return (None, False) if checkheader else None

    for header in headers:
        if not isinstance(header, fits.Header):
            log.error("Invalid header in header list")
            return (None, False) if checkheader else None

    basehead, headers = order_headers(headers)
    table = get_keyword_values(basehead, headers,
                               default_file=default_file,
                               comment_file=comment_file)
    success = True
    if checkheader:
        for key in table.keys():
            if not check_key(table, key):
                success = False
                if not check_all:
                    break

    update_basehead(basehead, table, headers)

    return (basehead, success) if checkheader else basehead


"""tf.nn.bias_add(value, bias, name = None)
解释：这个函数的作用是将偏差项 bias 加到 value 上面。
这个操作你可以看做是 tf.add 的一个特例，其中 bias 必须是一维的。该API支持广播形式，因此 value 可以有任何维度。
但是，该API又不像 tf.add ，可以让 bias 的维度和 value 的最后一维不同。具体看使用例子。"""

import tensorflow as tf

a = tf.constant([[1.0, 2.0], [1.0, 2.0], [1.0, 2.0]])
b = tf.constant([2.0, 1.0])
c = tf.constant([1.0])
sess = tf.Session()
print(sess.run(tf.nn.bias_add(a, b)))
# 因为 a 最后一维的维度是 2 ，但是 c 的维度是 1，所以以下语句将发生错误
# print (sess.run(tf.nn.bias_add(a, c)))
# ValueError: Dimensions must be equal, but are 2 and 1 for 'BiasAdd_1' (op: 'BiasAdd') with input shapes: [3,2], [1].
# 但是 tf.add() 可以正确运行
print(sess.run(tf.add(a, c)))
"""输入参数：
  ● value: 一个Tensor。数据类型必须是float，double，int64，int32，uint8，int16，int8或者complex64。
  ● bias: 一个一维的Tensor，数据维度和 value 的最后一维相同。数据类型必须和value相同。
  ● name: （可选）为这个操作取一个名字。
输出参数：
  ● 一个Tensor，数据类型和value相同。"""


import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
import sklearn.metrics as metrics
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.preprocessing import StandardScaler
import sklearn.preprocessing as preprocessing
from sklearn.preprocessing import LabelEncoder
from keras.models import Sequential
from keras.layers import Dense, Dropout

import scipy.stats
from sklearn.cluster import KMeans
import pickle
from random import *
from scipy.spatial import distance
import seaborn as sns
from imblearn.over_sampling import RandomOverSampler
from imblearn.over_sampling import SMOTE, ADASYN
from sklearn import svm
from sklearn.neighbors import KNeighborsClassifier
import tensorflow as tf
from sklearn.svm import SVC
from sklearn.neural_network import MLPClassifier

#Change Dataset when needed
df_all_t =pd.read_csv('../datasets/DoS_all.csv')

#For pre processing if needed
# le = preprocessing.LabelEncoder()
# le.fit(df_all_t['state'])
# df_all_t['state']=le.transform(df_all_t['state'])
# df_all_t=df_all_t.drop(['state'],axis=1)
#df_all_t=df_all_t.drop(['ltime'],axis=1)

X2=df_all_t.iloc[:,0:39]
y2=df_all_t.iloc[:,39]
y2=y2.replace(-1,0)
weighted_acc_t_RF=[]
bal_acc_t_RF=[]
weighted_bal_acc_t_RF=[]
acc_t_RF=[]
f1_score_t_RF=[]
weighted_f1score_RF=[]

weighted_acc_t_KNN=[]
bal_acc_t_KNN=[]
weighted_bal_acc_t_KNN=[]
acc_t_KNN=[]
f1_score_t_KNN=[]
weighted_f1score_KNN=[]

weighted_acc_t_SVM=[]
bal_acc_t_SVM=[]
weighted_bal_acc_t_SVM=[]
acc_t_SVM=[]
f1_score_t_SVM=[]
weighted_f1score_SVM=[]

weighted_acc_t_DT=[]
bal_acc_t_DT=[]
weighted_bal_acc_t_DT=[]
acc_t_DT=[]
f1_score_t_DT=[]
weighted_f1score_DT=[]

runs=1
for i in range (0,runs):
    X_train, X_test, y_train, y_test = train_test_split(X2, y2, test_size=0.2)
    #Scaling
    ss=StandardScaler()
    ss.fit(X_train)
    X_train=ss.transform(X_train)
    X_test=ss.transform(X_test)
    #Smote oversampling
    X_train, y_train = SMOTE().fit_resample(X_train, y_train)
    # Random Forest
    model_RF_t = RandomForestClassifier()
    model_RF_t.fit(X_train, y_train)
    y_probs_RF_t= model_RF_t.predict_proba(X_test)
    y_predicted_RF_t = model_RF_t.predict(X_test)
    # Performance of RF
    acc_t_RF.append(metrics.accuracy_score(y_test, y_predicted_RF_t))
    bal_acc_t_RF.append(metrics.balanced_accuracy_score(y_test, y_predicted_RF_t))
    f1_score_t_RF.append(metrics.f1_score(y_test, y_predicted_RF_t))
    weights=np.where(np.logical_and(y_test==1,y_predicted_RF_t==0),10, np.where(np.logical_and(y_test==0,y_predicted_RF_t==1),1, np.where(np.logical_and(y_test==1,y_predicted_RF_t==1),0.2,0.1)))
    weights=weights/sum(weights)
    weighted_acc_t_RF.append(metrics.accuracy_score(y_test, y_predicted_RF_t,True,weights))
    weighted_bal_acc_t_RF.append(metrics.balanced_accuracy_score(y_test, y_predicted_RF_t,weights))
    weighted_f1score_RF.append(metrics.f1_score(y_test, y_predicted_RF_t,sample_weight=weights))
    # #KNN
    model_KNN = KNeighborsClassifier(n_jobs=-1).fit(X_train, y_train) #class_weight='balanced'
    y_predicted_KNN= model_KNN.predict(X_test)
    y_prob_KNN = model_KNN.predict_proba(X_test)
    #Performance of KNN
    acc_t_KNN.append(metrics.accuracy_score(y_test, y_predicted_KNN))
    bal_acc_t_KNN.append(metrics.balanced_accuracy_score(y_test, y_predicted_KNN))
    f1_score_t_KNN.append(metrics.f1_score(y_test, y_predicted_KNN))
    weights=np.where(np.logical_and(y_test==1,y_predicted_KNN==0),10, np.where(np.logical_and(y_test==0,y_predicted_KNN==1),1, np.where(np.logical_and(y_test==1,y_predicted_KNN==1),0.2,0.1)))
    weights=weights/sum(weights)
    weighted_acc_t_KNN.append(metrics.accuracy_score(y_test, y_predicted_KNN,True,weights))
    weighted_bal_acc_t_KNN.append(metrics.balanced_accuracy_score(y_test, y_predicted_KNN,weights))
    weighted_f1score_KNN.append(metrics.f1_score(y_test, y_predicted_KNN,sample_weight=weights))
    # #SVM
    # model_SVM = SVC(gamma='scale', random_state=0, probability=True).fit(X_train, y_train) #class_weight='balanced'
    # y_predicted_SVM = model_SVM.predict(X_test)
    # y_prob_SVM = model_SVM.predict_proba(X_test)
    # #Performance of SVM
    # acc_t_SVM.append(metrics.accuracy_score(y_test, y_predicted_SVM))
    # bal_acc_t_SVM.append(metrics.balanced_accuracy_score(y_test, y_predicted_SVM))
    # f1_score_t_SVM.append(metrics.f1_score(y_test, y_predicted_SVM))
    # weights=np.where(np.logical_and(y_test==1,y_predicted_SVM==0),10, np.where(np.logical_and(y_test==0,y_predicted_SVM==1),1, np.where(np.logical_and(y_test==1,y_predicted_SVM==1),0.2,0.1)))
    # weights=weights/sum(weights)
    # weighted_acc_t_SVM.append(metrics.accuracy_score(y_test, y_predicted_SVM,True,weights))
    # weighted_bal_acc_t_SVM.append(metrics.balanced_accuracy_score(y_test, y_predicted_SVM,weights))
    # weighted_f1score_SVM.append(metrics.f1_score(y_test, y_predicted_SVM,sample_weight=weights))

    # #NN
    # model_NN = MLPClassifier()
    # model_NN.fit(X_train, y_train)
    # y_probs_NN=model_NN.predict_proba(X_test)
    # y_predicted_NN = model_NN.predict(X_test)
    # #Performance of ANN
    # acc_t_NN.append(metrics.accuracy_score(y_test, y_predicted_NN))
    # bal_acc_t_NN.append(metrics.balanced_accuracy_score(y_test, y_predicted_NN))
    # f1_score_t_NN.append(metrics.f1_score(y_test, y_predicted_NN))
    # weights=np.where(np.logical_and(y_test==1,y_predicted_NN==0),10, np.where(np.logical_and(y_test==0,y_predicted_NN==1),1, np.where(np.logical_and(y_test==1,y_predicted_NN==1),0.2,0.1)))
    # weights=weights/sum(weights)
    # weighted_acc_t_NN.append(metrics.accuracy_score(y_test, y_predicted_NN,True,weights))
    # weighted_bal_acc_t_NN.append(metrics.balanced_accuracy_score(y_test, y_predicted_NN,weights))
    # weighted_f1score_NN.append(metrics.f1_score(y_test, y_predicted_NN,sample_weight=weights))

    # #Decision Tree
    model_DT = DecisionTreeClassifier(max_depth=15)
    model_DT.fit(X_train, y_train)
    y_probs_DT= model_DT.predict_proba(X_test)
    y_predicted_DT= model_DT.predict(X_test)
    #Performance of Decision Tree
    acc_t_DT.append(metrics.accuracy_score(y_test, y_predicted_DT))
    bal_acc_t_DT.append(metrics.balanced_accuracy_score(y_test, y_predicted_DT))
    f1_score_t_DT.append(metrics.f1_score(y_test, y_predicted_DT))
    weights=np.where(np.logical_and(y_test==1,y_predicted_DT==0),10, np.where(np.logical_and(y_test==0,y_predicted_DT==1),1, np.where(np.logical_and(y_test==1,y_predicted_DT==1),0.2,0.1)))
    weights=weights/sum(weights)
    weighted_acc_t_DT.append(metrics.accuracy_score(y_test, y_predicted_DT,True,weights))
    weighted_bal_acc_t_DT.append(metrics.balanced_accuracy_score(y_test, y_predicted_DT,weights))
    weighted_f1score_DT.append(metrics.f1_score(y_test, y_predicted_DT,sample_weight=weights))

x_axis=list(range(0,runs))
print(np.mean(acc_t_RF)*100)
print(np.mean(weighted_acc_t_RF)*100)
print(np.mean(f1_score_t_RF)*100)
print(np.mean(weighted_f1score_RF)*100)
print(np.mean(bal_acc_t_RF)*100)
print(np.mean(weighted_bal_acc_t_RF)*100)

print(np.mean(acc_t_KNN)*100)
print(np.mean(weighted_acc_t_KNN)*100)
print(np.mean(f1_score_t_KNN)*100)
print(np.mean(weighted_f1score_KNN)*100)
print(np.mean(bal_acc_t_KNN)*100)
print(np.mean(weighted_bal_acc_t_KNN)*100)

# print(np.mean(acc_t_SVM)*100)
# print(np.mean(weighted_acc_t_SVM)*100)
# print(np.mean(f1_score_t_SVM)*100)
# print(np.mean(weighted_f1score_SVM)*100)
# print(np.mean(bal_acc_t_SVM)*100)
# print(np.mean(weighted_bal_acc_t_SVM)*100)

print(np.mean(acc_t_DT)*100)
print(np.mean(weighted_acc_t_DT)*100)
print(np.mean(f1_score_t_DT)*100)
print(np.mean(weighted_f1score_DT)*100)
print(np.mean(bal_acc_t_DT)*100)
print(np.mean(weighted_bal_acc_t_DT)*100)


#Corey Henry                                 #Date Assigned:
#                                            #
#Course CSE 1384 Sec 06                      #Date Due:
#File name: Lab
#
#Program description-

class ListNode(object):
    def __init__(self, item = None, link = None):

        self.__item = item

        self.__link = link
        return

    def set_item(self, item):
        self.__item = item
        return

    def get_item(self):
        return(self.__item)

    def set_link(self,link):
        self.__link = link
        return

    def get_link(self):
        return(self.__link)

def main():
    #start the linked list head
    head = ListNode(3)
    #insert a new node containing 5 at the beggining
    #create new node
    temp = ListNode(5)
    #store address of the old first node in our new node
    temp.set_link(head)
    #make hold the address of the new first node
    head = temp
    #house keeping
    temp = None

    # OR...

    temp = ListNode(7,head)
    head = temp
    temp = None

    #OR
    head = ListNode(9,head)

    #traverse the list
    #start at the beggining of the list
    temp = head
    #loop until none is found
    while temp != None:
        print(temp.get_item())
        #move to the next node
        temp = temp.get_link()

    print('\n')
    current = head
    while current.get_item() != 7:
        current = current.get_link()

    temp = ListNode(5,current.get_link())

    current.set_link(temp)

    temp = head
    #loop until none is found
    while temp != None:
        print(temp.get_item())
        #move to the next node
        temp = temp.get_link()

    print('\n')

    #inserting at the end
    current = head
    temp = ListNode(4)

    while current.get_link() != None:
        current = current.get_link()

    current.set_link(temp)

    #previous and current links

    current = head

    while current.get_item() != 5:
        previous = current
        current = current.get_link()

    previous.set_link(current.get_link())

    #start at the beggining of the list
    temp = head
    #loop until none is found
    while temp != None:
        print(temp.get_item())
        #move to the next node
        temp = temp.get_link()

    print('\n')

    # deleting the last node
    current = head

    while current.get_link() != None:
        previous = current
        current = current.get_link()

    previous.set_link(None)

     #start at the beggining of the list
    temp = head
    #loop until none is found
    while temp != None:
        print(temp.get_item())
        #move to the next node
        temp = temp.get_link()

    return

main()


from DatabaseClass import Database

class AddTaskCommand:

    regex_tanggal = [
        r"\d"
    ]

    def __init__(self, matkul, jenis, deskripsi, tahun, bulan, tanggal):
        self.matkul = matkul
        self.jenis = jenis
        self.deskripsi = deskripsi
        self.tahun = tahun
        self.bulan = bulan
        self.tanggal = tanggal
        self.tempResult = ""

    def execute(self):
        database = Database()

        # matkul tidak boleh kosong
        if self.matkul.strip() != "":
            # mengecek keberadaan jenis
            valid_jenis = database.GetCursor().execute("""
                SELECT jenis FROM Prioritas
            """).fetchall()
            valid_jenis = list(map(lambda row: row[0], valid_jenis))

            if self.jenis in valid_jenis:
                # Generate ID
                database.GetCursor().execute("""
                    SELECT ID FROM Task
                """)

                id_result = database.GetCursor().fetchall()

                new_id = ""
                if len(id_result) == 0:
                    new_id = "1"
                else:
                    print(str(max(list(map(lambda row: int(row[0]), id_result))) + 1))
                    new_id = str(max(list(map(lambda row: int(row[0]), id_result))) + 1)

                print(new_id)
                new_id = int(new_id)

                #(self,id, matkul, jenis, deskripsi, tanggal):
                database.InsertTask(
                    str(new_id),
                    self.matkul,
                    self.jenis,
                    self.deskripsi,
                    "{:0>4}-{:0>2}-{:0>2}".format(self.tahun, self.bulan, self.tanggal));

                database.GetConnection().commit()

                self.tempResult = "Task berhasil ditambahkan! ^o^\n"
                self.tempResult += "(ID: {}) {} - {} - {} - {}".format(new_id, self.matkul, self.jenis, self.deskripsi, "{:0>4}-{:0>2}-{:0>2}".format(self.tahun, self.bulan, self.tanggal))

            else:
                self.tempResult = "Saya tidak mengenal jenis \"{}\" ... .-.".format(self.jenis)

        else:
            self.tempResult = "Saya bingung apa yang perlu diingatkan. .-."

    def getResult(self):
        return self.tempResult


__author__ = 'Sean Lip'

from core.domain import exp_domain
from core.domain import exp_services
from core.domain import feedback_services
from core.domain import rights_manager
from core.domain import subscription_services
from core.platform import models
(user_models,) = models.Registry.import_models([
    models.NAMES.user
])
from core.tests import test_utils

class SubscriptionsTest(test_utils.GenericTestBase):
    """Tests for subscription management."""

    OWNER_2_EMAIL = 'owner2@example.com'
    OWNER2_USERNAME = 'owner2'

    def setUp(self):
        super(SubscriptionsTest, self).setUp()
        self.signup(self.OWNER_EMAIL, self.OWNER_USERNAME)
        self.signup(self.EDITOR_EMAIL, self.EDITOR_USERNAME)
        self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME)
        self.signup(self.OWNER_2_EMAIL, self.OWNER2_USERNAME)

        self.owner_id = self.get_user_id_from_email(self.OWNER_EMAIL)
        self.editor_id = self.get_user_id_from_email(self.EDITOR_EMAIL)
        self.viewer_id = self.get_user_id_from_email(self.VIEWER_EMAIL)
        self.owner_2_id = self.get_user_id_from_email(self.OWNER_2_EMAIL)

    def _get_thread_ids_subscribed_to(self, user_id):
        subscriptions_model = user_models.UserSubscriptionsModel.get(
            user_id, strict=False)
        return (
            subscriptions_model.feedback_thread_ids
            if subscriptions_model else [])

    def _get_activity_ids_subscribed_to(self, user_id):
        subscriptions_model = user_models.UserSubscriptionsModel.get(
            user_id, strict=False)
        return (
            subscriptions_model.activity_ids
            if subscriptions_model else [])

    def test_subscribe_to_feedback_thread(self):
        USER_ID = 'user_id'
        self.assertEqual(self._get_thread_ids_subscribed_to(USER_ID), [])

        FEEDBACK_THREAD_ID = 'fthread_id'
        subscription_services.subscribe_to_thread(USER_ID, FEEDBACK_THREAD_ID)
        self.assertEqual(
            self._get_thread_ids_subscribed_to(USER_ID), [FEEDBACK_THREAD_ID])

        # Repeated subscriptions to the same thread have no effect.
        subscription_services.subscribe_to_thread(USER_ID, FEEDBACK_THREAD_ID)
        self.assertEqual(
            self._get_thread_ids_subscribed_to(USER_ID), [FEEDBACK_THREAD_ID])

        FEEDBACK_THREAD_2_ID = 'fthread_id_2'
        subscription_services.subscribe_to_thread(
            USER_ID, FEEDBACK_THREAD_2_ID)
        self.assertEqual(
            self._get_thread_ids_subscribed_to(USER_ID),
            [FEEDBACK_THREAD_ID, FEEDBACK_THREAD_2_ID])

    def test_subscribe_to_activity(self):
        USER_ID = 'user_id'
        self.assertEqual(self._get_activity_ids_subscribed_to(USER_ID), [])

        ACTIVITY_ID = 'activity_id'
        subscription_services.subscribe_to_activity(USER_ID, ACTIVITY_ID)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(USER_ID), [ACTIVITY_ID])

        # Repeated subscriptions to the same activity have no effect.
        subscription_services.subscribe_to_activity(USER_ID, ACTIVITY_ID)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(USER_ID), [ACTIVITY_ID])

        ACTIVITY_2_ID = 'activity_id_2'
        subscription_services.subscribe_to_activity(USER_ID, ACTIVITY_2_ID)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(USER_ID),
            [ACTIVITY_ID, ACTIVITY_2_ID])

    def test_thread_and_activity_subscriptions_are_tracked_individually(self):
        USER_ID = 'user_id'
        FEEDBACK_THREAD_ID = 'fthread_id'
        ACTIVITY_ID = 'activity_id'
        self.assertEqual(self._get_thread_ids_subscribed_to(USER_ID), [])

        subscription_services.subscribe_to_thread(USER_ID, FEEDBACK_THREAD_ID)
        subscription_services.subscribe_to_activity(USER_ID, ACTIVITY_ID)
        self.assertEqual(
            self._get_thread_ids_subscribed_to(USER_ID), [FEEDBACK_THREAD_ID])
        self.assertEqual(
            self._get_activity_ids_subscribed_to(USER_ID), [ACTIVITY_ID])

    def test_posting_to_feedback_thread_results_in_subscription(self):
        # The viewer posts a message to the thread.
        MESSAGE_TEXT = 'text'
        feedback_services.create_thread(
            'exp_id', 'state_name', self.viewer_id, 'subject', MESSAGE_TEXT)

        thread_ids_subscribed_to = self._get_thread_ids_subscribed_to(
            self.viewer_id)
        self.assertEqual(len(thread_ids_subscribed_to), 1)
        thread_id = thread_ids_subscribed_to[0]
        self.assertEqual(
            feedback_services.get_messages(thread_id)[0]['text'], MESSAGE_TEXT)

        # The editor posts a follow-up message to the thread.
        NEW_MESSAGE_TEXT = 'new text'
        feedback_services.create_message(
            thread_id, self.editor_id, '', '', NEW_MESSAGE_TEXT)

        # The viewer and editor are now both subscribed to the thread.
        self.assertEqual(
            self._get_thread_ids_subscribed_to(self.viewer_id), [thread_id])
        self.assertEqual(
            self._get_thread_ids_subscribed_to(self.editor_id), [thread_id])

    def test_creating_exploration_results_in_subscription(self):
        EXP_ID = 'exp_id'
        USER_ID = 'user_id'

        self.assertEqual(
            self._get_activity_ids_subscribed_to(USER_ID), [])
        exp_services.save_new_exploration(
            USER_ID,
            exp_domain.Exploration.create_default_exploration(
                EXP_ID, 'Title', 'Category'))
        self.assertEqual(
            self._get_activity_ids_subscribed_to(USER_ID), [EXP_ID])

    def test_adding_new_owner_or_editor_role_results_in_subscription(self):
        EXP_ID = 'exp_id'
        exploration = exp_domain.Exploration.create_default_exploration(
            EXP_ID, 'Title', 'Category')
        exp_services.save_new_exploration(self.owner_id, exploration)

        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.owner_2_id), [])
        rights_manager.assign_role(
            self.owner_id, EXP_ID, self.owner_2_id, rights_manager.ROLE_OWNER)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.owner_2_id), [EXP_ID])

        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.editor_id), [])
        rights_manager.assign_role(
            self.owner_id, EXP_ID, self.editor_id, rights_manager.ROLE_EDITOR)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.editor_id), [EXP_ID])

    def test_adding_new_viewer_role_does_not_result_in_subscription(self):
        EXP_ID = 'exp_id'
        exploration = exp_domain.Exploration.create_default_exploration(
            EXP_ID, 'Title', 'Category')
        exp_services.save_new_exploration(self.owner_id, exploration)

        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.viewer_id), [])
        rights_manager.assign_role(
            self.owner_id, EXP_ID, self.viewer_id, rights_manager.ROLE_VIEWER)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.viewer_id), [])

    def test_deleting_activity_does_not_delete_subscription(self):
        EXP_ID = 'exp_id'
        exploration = exp_domain.Exploration.create_default_exploration(
            EXP_ID, 'Title', 'Category')
        exp_services.save_new_exploration(self.owner_id, exploration)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.owner_id), [EXP_ID])

        exp_services.delete_exploration(self.owner_id, EXP_ID)
        self.assertEqual(
            self._get_activity_ids_subscribed_to(self.owner_id), [EXP_ID])


__author__ = 'Lucas Moeskops'

def solution(A):
    # Keep the three highest values and replace the lower ones if we find higher ones
    triplet_max = A[:3]
    # To account for the possibility of two negative values outmatching similar positive
    # values, also keep track of the two lowest numbers
    duo_min = A[:2]
    worst_best = min(triplet_max)
    best_worst = max(duo_min)
    for index, value in enumerate(A[2:], start=2):
        if value > worst_best and index > 2:
            triplet_max[triplet_max.index(worst_best)] = value
            worst_best = min(triplet_max)
        if value < best_worst:
            duo_min[duo_min.index(best_worst)] = value
            best_worst = max(duo_min)
    # Either the three best values or the two worst values and the best value produce
    # the highest triplet.
    return max(
        triplet_max[0] * triplet_max[1] * triplet_max[2],
        max(triplet_max) * duo_min[0] * duo_min[1]
    )


from modules.OsmoseTranslation import T_
from plugins.Plugin import Plugin
from modules.Stablehash import stablehash64

class Highway_Parking_Lane(Plugin):

    def init(self, logger):
        Plugin.init(self, logger)

        self.parkingLaneValues = ["parallel", "diagonal", "perpendicular", "marked", "yes", "no", "separate"]
        self.parkingConditionValues = ["free", "ticket", "disc", "residents", "customers", "private", "disabled", "loading", "no_parking", "no_standing", "no_stopping", "no"] # or custom
        self.parkingConditionReasonValues = ["bus_stop", "crossing", "driveway", "dual_carriage", "fire_lane", "junction", "loading_zone", "narrow", "passenger_loading_zone", "priority_road", "street_cleaning", "turnaround", "turn_lane"] # or custom

        self.errors[31611] = self.def_class(item = 3161, level = 2, tags = ['highway', 'parking', 'fix:imagery'],
            title = T_('Bad parking:lane:[side]'),
            detail = T_(
'''The side was not recognized, see
[`parking:lane=*`](https://wiki.openstreetmap.org/wiki/Key:parking:lane).'''),
            fix = T_(
'''Use `parking:lane:left`, `parking:lane:right` or `parking:lane:both`.'''))
        self.errors[31614] = self.def_class(item = 3161, level = 3, tags = ['highway', 'parking', 'fix:imagery'],
            title = T_('Too many parking:lane:[side]'),
            detail = T_(
'''The key `parking:lane:both` was used together with `parking:lane:left` and/or `parking:lane:right`.
However, `both` already covers both sides of a street, so the latter are redundant.'''))
        self.errors[31615] = self.def_class(item = 3161, level = 3, tags = ['highway', 'parking', 'fix:chair'],
            title = T_('Bad parking:lane:[side] value'),
            fix = T_('''Use any of the following values: `{0}`.''', "`, `".join(self.parkingLaneValues)),
            resource = "https://wiki.openstreetmap.org/wiki/Key:parking:lane")
        self.errors[31616] = self.def_class(item = 3161, level = 3, tags = ['highway', 'parking', 'fix:survey'],
            title = T_('parking:condition:[side] without parking:lane:[side] value'),
            detail = T_(
'''A parking condition is present but without parking kind.'''))
        self.errors[31617] = self.def_class(item = 3161, level = 3, tags = ['highway', 'parking', 'fix:survey'],
            title = T_('parking:condition:[side] not applicable'),
            detail = T_(
'''A parking condition is set for a parking:lane:[side] value that forbids parking.'''))
        self.errors[31618] = self.def_class(item = 3161, level = 3, tags = ['highway', 'parking', 'fix:survey'],
            title = T_('parking:condition:[side] should be mapped on separately mapped parking area'),
            detail = T_(
'''A parking condition is set for a parking:lane:[side] value that indicates
that the parking area is mapped separately. Any parking conditions should
be tagged on that object instead.'''))
        self.errors[31619] = self.def_class(item = 3161, level = 3, tags = ['highway', 'parking', 'fix:survey'],
            title = T_('Bad parking:condition:[side] value'),
            fix = T_('''Use any of the following values: `{0}`.''', ", ".join(self.parkingConditionValues)),
            resource = "https://wiki.openstreetmap.org/wiki/Key:parking:condition")

    def way(self, data, tags, nds):
        if not "highway" in tags:
            return

        err = []

        if (("parking:condition:right" in tags and not "parking:lane:right" in tags and not "parking:lane:both" in tags) or
            ("parking:condition:left" in tags and not "parking:lane:left" in tags and not "parking:lane:both" in tags) or
            ("parking:condition:both" in tags and not "parking:lane:both" in tags and not ("parking:lane:left" in tags and "parking:lane:right" in tags))):
            err.append({"class": 31616})

        sides = list(map(lambda tag: tag[len("parking:lane:"):].split(":")[0], filter(lambda tag: tag.startswith("parking:lane:"), tags)))
        if len(sides) == 0:
            return err
        sides = [i for i in sides if i not in ("left", "right", "both")]

        if len(sides) > 0:
            err.append({"class": 31611})

        if "parking:lane:both" in tags and (("parking:lane:right" in tags and tags["parking:lane:right"] == tags["parking:lane:both"]) or
                                            ("parking:lane:left" in tags and tags["parking:lane:left"] == tags["parking:lane:both"])):
            # Conflicting values are dealt with in Highway_Sides
            err.append({"class": 31614})

        for side in ("parking:lane:right", "parking:lane:left", "parking:lane:both"):
            if side in tags:
                if tags[side] not in self.parkingLaneValues:
                    # Unknown value of parking:lane:[side]
                    if tags[side] in self.parkingConditionValues:
                        err.append({"class": 31615, "subclass": stablehash64(side), "text": T_("`{0}` is a value for key `{1}`", tags[side], "parking:condition:[side]")})
                    elif tags[side] in self.parkingConditionReasonValues:
                        err.append({"class": 31615, "subclass": stablehash64(side), "text": T_("`{0}` is a value for key `{1}`", tags[side], "parking:condition:[side]:reason")})
                    else:
                        err.append({"class": 31615, "subclass": stablehash64(side)})
                condition = side.replace("lane", "condition")
                if not condition in tags:
                    condition = "parking:condition:both"
                if condition in tags:
                    if tags[side] == "no" and tags[condition][0:2] != "no":
                        # parking:lane:[side] = no together with parking:condition:[side]
                        err.append({"class": 31617, "subclass": stablehash64(side)})
                    elif tags[side] == "separate":
                        # parking:lane:[side] = separate together with parking:condition:[side]
                        err.append({"class": 31618, "subclass": stablehash64(side)})
                    elif tags[condition] in self.parkingLaneValues and tags[condition] not in self.parkingConditionValues:
                        # A value for parking:lane:[side] was used as condition
                        err.append({"class": 31619, "subclass": stablehash64(side), "text": T_("`{0}` is a value for key `{1}`", tags[condition], "parking:lane:[side]")})

        return err

###########################################################################
from plugins.Plugin import TestPluginCommon

class Test(TestPluginCommon):
    def test(self):
        a = Highway_Parking_Lane(None)
        a.init(None)

        for t in [{"highway": "r", "parking:lane:side": "t"},
                  {"highway": "r", "parking:lane:right": "parallel", "parking:lane:both": "parallel"},
                  {"highway": "r", "parking:lane:right": "p"},
                  {"highway": "r", "parking:lane:right": "free"},
                  {"highway": "r", "parking:lane:right": "bus_stop"},
                  {"highway": "r", "parking:condition:right": "parallel"},
                  {"highway": "r", "parking:lane:left": "no", "parking:condition:both": "no"},
                  {"highway": "r", "parking:lane:both": "no", "parking:condition:both": "free"},
                  {"highway": "r", "parking:lane:left": "no", "parking:lane:right": "parallel", "parking:condition:both": "free"},
                  {"highway": "r", "parking:lane:both": "separate", "parking:condition:both": "free"},
                  {"highway": "r", "parking:lane:both": "yes", "parking:condition:both": "parallel"},
                 ]:
            self.check_err(a.way(None, t, None), t)
            del t["highway"]
            assert not a.way(None, t, None), t

        for t in [{"highway": "r", "parking:lane:both:parallel": "t"},
                  {"highway": "r", "parking:condition:both": "private", "parking:lane:both": "perpendicular"},
                  {"highway": "r", "parking:lane:right": "parallel", "parking:lane:both": "no"}, # Checked by Highway_Sides plugin
                  {"highway": "r", "parking:condition:right": "private", "parking:condition:left": "private", "parking:lane:both": "perpendicular"},
                  {"highway": "r", "parking:lane:right": "perpendicular", "parking:condition:right": "customers", "parking:condition:right:capacity": "19"},
                  {"highway": "r", "parking:lane:left": "separate", "parking:lane:right": "parallel"},
                  {"highway": "r", "parking:lane:left": "parallel", "parking:lane:right": "separate"},
                  {"highway": "r", "parking:lane:both": "separate"},
                  {"highway": "r", "parking:lane:left": "parallel", "parking:condition:left": "free", "parking:lane:right": "separate"},
                  {"highway": "r", "parking:lane:both": "no", "parking:condition:both": "no_stopping"},
                  {"highway": "r", "parking:condition:both": "private", "parking:lane:left": "parallel", "parking:lane:right": "perpendicular"},
                 ]:
            assert not a.way(None, t, None), t


def get_int(haystack, needle, default=0, min_value=None, max_value=None):
    # Get integer
    try:
        value = int(haystack.get(needle, default))
    except ValueError:
        value = default

    # Check range
    if min_value is not None:
        value = max(min_value, value)

    if max_value is not None:
        value = min(max_value, value)

    # Done
    return value


import pytest
import rumps
from src.app_functions.update_menu import update_menu

@pytest.fixture(name="basic_app")
def create_app():
    """Creates a basic app object with some variables to pass to functions

    Returns:
        rumps.App: Basic app
    """
    app = rumps.App("TestApp")
    app.load_vocabulary_wrapper = "SetToVocabWrapper"
    app.settings = {
        "auto_login": True,
        "time_in_menu_bar": True,
        "strength_levels_to_practice": [1, 2, 3, 4],
    }

    def test_callback():
        return None

    app.test_callback = test_callback
    app.menu = [
        rumps.MenuItem("Login to Duolingo", callback=app.test_callback),
        rumps.MenuItem("Reload vocabulary", callback=app.test_callback),
        {
            "Settings": [
                rumps.MenuItem("Auto-login", callback=app.test_callback),
                rumps.MenuItem(
                    "Show countdown in status bar",
                    callback=app.test_callback,
                ),
                {
                    "Change strength levels to be included": [
                        rumps.MenuItem(
                            "Level 1",
                            callback=app.test_callback,
                        ),
                        rumps.MenuItem(
                            "Level 2",
                            callback=app.test_callback,
                        ),
                        rumps.MenuItem(
                            "Level 3",
                            callback=app.test_callback,
                        ),
                        rumps.MenuItem(
                            "Level 4",
                            callback=app.test_callback,
                        ),
                    ],
                },
            ],
        },
    ]
    return app

def test_if_logged_in(basic_app):
    """Check if menu is updated correctly if logged in"""
    basic_app.logged_in = True
    update_menu(basic_app)
    assert basic_app.menu["Reload vocabulary"].callback == "SetToVocabWrapper"
    assert basic_app.menu["Login to Duolingo"].state == 1
    assert basic_app.menu["Settings"]["Auto-login"].state == basic_app.settings["auto_login"]
    assert (
        basic_app.menu["Settings"]["Show countdown in status bar"].state
        == basic_app.settings["time_in_menu_bar"]
    )

def test_if_not_logged_in(basic_app):
    """Check if menu is updated correctly if not logged in"""
    basic_app.logged_in = False
    update_menu(basic_app)
    assert basic_app.menu["Reload vocabulary"].callback is None
    assert basic_app.menu["Login to Duolingo"].state == 0
    assert basic_app.menu["Settings"]["Auto-login"].state == basic_app.settings["auto_login"]
    assert (
        basic_app.menu["Settings"]["Show countdown in status bar"].state
        == basic_app.settings["time_in_menu_bar"]
    )


"""
COMP.CS.100 Ohjelmointi 1 / Programming 1
Fractions code template
"""

class Fraction:
    """
    This class represents one single fraction that consists of
    numerator (osoittaja) and denominator (nimittäjä).
    """

    def __init__(self, numerator, denominator):
        """
        Constructor. Checks that the numerator and denominator are of
        correct type and initializes them.

        :param numerator: int, fraction's numerator
        :param denominator: int, fraction's denominator
        """

        # isinstance is a standard function which can be used to check if
        # a value is an object of a certain class.  Remember, in Python
        # all the data types are implemented as classes.
        # ``isinstance(a, b´´) means more or less the same as ``type(a) is b´´
        # So, the following test checks that both parameters are ints as
        # they should be in a valid fraction.
        if not isinstance(numerator, int) or not isinstance(denominator, int):
            raise TypeError

        # Denominator can't be zero, not in mathematics, and not here either.
        elif denominator == 0:
            raise ValueError

        self.__numerator = numerator
        self.__denominator = denominator

    def return_string(self):
        """
        :returns: str, a string-presentation of the fraction in the format
                       numerator/denominator.
        """

        if self.__numerator * self.__denominator < 0:
            sign = "-"

        else:
            sign = ""

        return f"{sign}{abs(self.__numerator)}/{abs(self.__denominator)}"

    def simplify(self):
        greatest_common = greatest_common_divisor(self.__numerator,
                                                  self.__denominator)
        self.__numerator = self.__numerator // greatest_common
        self.__denominator = self.__denominator // greatest_common
        clause = self.return_string()
        return clause

    # FI: Käänteisluku
    def reciprocal(self):
        return Fraction(self.__denominator, self.__numerator)

    # FI: Vastaluku
    def complement(self):
        return Fraction(-self.__numerator, self.__denominator)

    def multiply(self, other):
        new_numerator = self.__numerator * other.__numerator
        new_denominator = self.__denominator * other.__denominator
        return Fraction(new_numerator, new_denominator)

    def divide(self, other):
        new_numerator = self.__numerator * other.__denominator
        new_denominator = other.__numerator * self.__denominator
        return Fraction(new_numerator, new_denominator)

    def add(self, other):
        self_expanded_denominator = self.__denominator * other.__denominator
        self_numerator_sum = self.__numerator * other.__denominator + \
                            other.__numerator * self.__denominator

        # other_expanded_denominator = other.__denominator * self.__denominator
        # other_expanded_numerator = other.__numerator * self.__denominator

        return Fraction(self_numerator_sum, self_expanded_denominator)

    def deduct(self, other):
        self_expanded_denominator = self.__denominator * other.__denominator
        self_numerator_deduction = (self.__numerator * other.__denominator) - \
                                   other.__numerator * self.__denominator
        return Fraction(self_numerator_deduction, self_expanded_denominator)

    def __str__(self):
        str_return_clause = self.return_string()
        str_return_clause_simplified = self.simplify()
        return f"{str_return_clause} = {str_return_clause_simplified}"

def greatest_common_divisor(a, b):
    """
    Euclidean algorithm. Returns the greatest common
    divisor (suurin yhteinen tekijä).  When both the numerator
    and the denominator are divided by their greatest common divisor,
    the result will be the most reduced version of the fraction in question.
    """

    while b != 0:
        a, b = b, a % b

    return a

def command_quit():
    """This command is run when the user inputs the word quit. It prints the
    decided message and returns to the main program.  """
    print("Bye bye!")
    return

def command_add(frac_dict):
    """
    The user inputs a fraction to be added to a dictionary. Then the user
    chooses a name for the fraction. The fraction gets added to a dictionary
    as a pair. The key will be the name and the payload will be the fraction.
    """

    # Integers
    numerator = 0
    denominator = 0

    # Lists
    my_stripped_input = []

    # Strings
    frac_name = ""
    frac_str = ""
    my_input = ""

    my_input = input("Enter a fraction in the form integer/integer: ")

    my_splitted_input = my_input.split("/")
    numerator = int(my_splitted_input[0])
    denominator = int(my_splitted_input[1])

    frac = Fraction(numerator, denominator)
    frac_str = frac.return_string()

    frac_name = input("Enter a name: ")

    frac_dict[frac_name] = frac_str

    # TODO: Toteuta lisättävän murtoluvun nimeäminen

def command_unknown_command():
    """This function prints an error message when the user inputs a command
    which doesn't exist. """
    print("Unknown command!")

def command_list(frac_dict):
    """This command acts essentially as a print command. It iterates over a
    dictionary and prints its contents in the desired format."""
    for key, payload in sorted(frac_dict.items()):
        print(f"{key} = {payload}")

def command_times(frac_dict):
    """This command multiplies two values by input. The program seeks for
    these values in the dictionary and does the calculation if found."""

    # Strings
    first_operand = ""
    first_fraction = ""
    second_fraction = ""
    second_operand = ""
    simplified_str = ""
    operand_product = ""
    multi_str = ""

    # Integers
    first_numerator = 0
    first_denominator = 0
    second_numerator = 0
    second_denominator = 0

    # Lists
    first_fraction_split = []

    first_operand = input("1st operand: ")
    if first_operand in frac_dict:
        for key, first_operand_payload in frac_dict.items():
            if key == first_operand:
                first_fraction = first_operand_payload
    else:
        print(f"Name {first_operand} was not found")
        return

    first_fraction_split = first_fraction.split("/")
    first_numerator = int(first_fraction_split[0])
    first_denominator = int(first_fraction_split[1])

    second_operand = input("2nd operand: ")
    if second_operand in frac_dict:
        for key, second_operand_payload in frac_dict.items():
            if key == second_operand:
                second_fraction = second_operand_payload

    else:
        print(f"Name {second_operand} was not found")
        return

    second_fraction_split = second_fraction.split("/")
    second_numerator = int(second_fraction_split[0])
    second_denominator = int(second_fraction_split[1])

    first_frac = Fraction(first_numerator, first_denominator)
    second_frac = Fraction(second_numerator, second_denominator)

    multiplied_fraction = first_frac.multiply(second_frac)
    multi_str = multiplied_fraction.return_string()

    print(f"{first_numerator}/{first_denominator} * {second_numerator}/"
          f"{second_denominator} ="
          f" {multi_str}")

    simplified_str = multiplied_fraction.simplify()

    print(f"simplified {simplified_str}")

def command_file(frac_dict):
    """TBA: This function reads a file and its contents and copies them over
    to a dictionary in the desired format."""

    fraction_name = ""
    filename = ""

    split_row = []
    split_fraction = []

    filename = input("Enter the name of the file: ")

    try:
        my_file = open(filename, "r")
    except FileNotFoundError:
        print("Error: the file cannot be read.")
        return

    for line in my_file:
        try:
            split_row = line.split("=")
            fraction_name = split_row[0]
            original_fraction = split_row[1]
        except IndexError:
            print("Error: the file cannot be read.")
            return

        try:
            split_fraction = original_fraction.split("/")
            numerator = int(split_fraction[0])
            denominator = int(split_fraction[1])
            frac_obj = Fraction(numerator, denominator)
            frac_clause = frac_obj.return_string()
            frac_dict[fraction_name] = frac_clause
        except IndexError:
            print("Error: the file cannot be read.")
            return

def command_print(frac_dict):
    """The function goes through a desired file and adds all rows as entries
    to the fraction dictionary."""
    frac_name = ""

    frac_name = input("Enter a name: ")

    if frac_name in frac_dict:
        for key, payload in sorted(frac_dict.items()):
            if key == frac_name:
                print(f"{key} = {payload}")
    else:
        print(f"Name {frac_name} was not found")

def main():

    # Booleans
    is_input_quit = False

    # Dictionaries
    frac_dict = {}

    # Strings
    my_input = ""

    while not is_input_quit:
        my_input = input("> ")

        # Stripataan välilyönnit, jotta komennot toimisivat oikein
        my_stripped_input = my_input.strip()

        if my_stripped_input.lower() == "quit":
            command_quit()
            is_input_quit = True

        elif my_stripped_input == "add":
            command_add(frac_dict)

        elif my_stripped_input == "list":
            command_list(frac_dict)

        elif my_stripped_input == "print":
            command_print(frac_dict)

        elif my_stripped_input == "*":
            command_times(frac_dict)

        elif my_stripped_input == "file":
            command_file(frac_dict)

        else:
            command_unknown_command()

if __name__ == "__main__":
    main()


# disclaimer: please note that the commented functions selectRegion() and dynamicCreateSlate()
#             have been commented out due to their dependency on the module pyautogui.
#             If you'd like to use them as well install pyautogui, its a fairly straightforward
#             process and pyautogui is a verrrry useful library.

# ===============================================================================================
'''
Instructions pour utiliser (thats french for "instructions to use") (I'm funny like that..)

1. create an object:
    One object per drawing slate. So if you want multiple drawing slates you can do that.
'''
    # eg> slate1 = slate('name of the slate')
'''
2. You have two options here:
    use static or dynamic create.

    a. If you decide to use staticCreateSlate(), you wont need the additional library 'pyautogui'
'''
      # eg> slate1.staticCreateSlate( (x,y), image )    x,y being the position of the slate.
'''
    b. If you wanna use dynamicCreateSlate(), you will need the additional library 'pyautogui'
'''
      # eg> slate1.dynamicCreateSlate()
'''
3. Simply Show it:
'''
   # eg> slate1.showSlate(value)          value --> when you press this key the slate closes
   #                                      value has to be an ascii value.
   #                                      tip : use ord() to find ascii values
# ===============================================================================================

import cv2
import numpy as np
# import pyautogui as pg

# def selectRegion():

#     input('move mouse to position of left upper corner and press enter ')
#     LUC =  pg.position()
#     input('move mouse to position of right lower corner and press enter ')
#     RLC = pg.position()
#     size = (RLC[0] - LUC[0], RLC[1] - LUC[1])
#     pos = tuple(LUC)
#     return pos,size

class slate:
    def __init__(self,name):
        self.touch = False
        self.name = name
        self.sheet = None
        self.thickness = 2
        self.colour = [0,0,0]

    def staticCreateSlate(self,position,image):  # hardcoded slate create

        self.sheet = image
        cv2.namedWindow(self.name,cv2.WINDOW_NORMAL)
        cv2.moveWindow(self.name,position[0],position[1])

    # def DynamicCreateSlate(self):

    #     pos,size = selectRegion()
    #     size = (size[1], size[0], 3)
    #     self.sheet = np.zeros(size, np.uint8)
    #     cv2.namedWindow(self.name,cv2.WINDOW_AUTOSIZE)
    #     cv2.moveWindow(self.name,pos[0],pos[1])

    def createAllTrackBars(self):

        cv2.createTrackbar('B',self.name,0,255,self.BtrackbarCall)
        cv2.createTrackbar('G',self.name,0,255,self.GtrackbarCall)
        cv2.createTrackbar('R',self.name,0,255,self.RtrackbarCall)
        cv2.createTrackbar('W',self.name,1,20,self.WtrackbarCall)

    def BtrackbarCall(self,value):
        self.colour[0] = value

    def GtrackbarCall(self,value):
        self.colour[1] = value

    def RtrackbarCall(self,value):
        self.colour[2] = value

    def WtrackbarCall(self,value):
        self.thickness = value

    def showSlate(self,key = 27):                # key parameter has to be int
        self.createAllTrackBars()
        cv2.setMouseCallback(self.name, self.chalk)
        while True:
            cv2.imshow(self.name,self.sheet)
            if cv2.waitKey(1) == key:
                break
        cv2.destroyWindow(self.name)

    def chalk(self,event,x,y,flags,param):
        global prevX,prevY

        if event == cv2.EVENT_LBUTTONDOWN:
            self.touch = True
            prevX,prevY = x,y

        elif event == cv2.EVENT_MOUSEMOVE:
            if self.touch == True:
                cv2.line(self.sheet, (prevX,prevY) , (x,y) , tuple(self.colour) , self.thickness )
                prevX,prevY = x,y

        elif event == cv2.EVENT_LBUTTONUP:
            self.touch = False
            cv2.line(self.sheet, (prevX,prevY) , (x,y) , tuple(self.colour) , self.thickness )
            prevX,prevY = x,y

        return x,y


import networkx as nx
from networkx.utils import not_implemented_for
__author__ = "Aric Hagberg <aric.hagberg@gmail.com>"
__all__ = ['stochastic_graph']

@not_implemented_for('multigraph')
@not_implemented_for('undirected')
def stochastic_graph(G, copy=True, weight='weight'):
    """Return a right-stochastic representation of G.

    A right-stochastic graph is a weighted digraph in which all of
    the node (out) neighbors edge weights sum to 1.

    Parameters
    -----------
    G : directed graph
      A NetworkX DiGraph

    copy : boolean, optional
      If True make a copy of the graph, otherwise modify the original graph

    weight : edge attribute key (optional, default='weight')
      Edge data key used for weight.  If no attribute is found for an edge
      the edge weight is set to 1.  Weights must be positive numbers.
    """
    import warnings
    if copy:
        W = nx.DiGraph(G)
    else:
        W = G # reference original graph, no copy
    degree = W.out_degree(weight=weight)
    for (u,v,d) in W.edges(data=True):
        if degree[u] == 0:
            warnings.warn('zero out-degree for node %s'%u)
            d[weight] = 0.0
        else:
            d[weight] = float(d.get(weight,1.0))/degree[u]
    return W


def setup():
    global bg
    size(400, 400)
    background(0)
    colorMode(HSB)
    bg = createGraphics(500, 500)
    bg.beginDraw()
    bg.textSize(140)
    bg.text("Hello", 25, 250)
    bg.endDraw()
    strokeWeight(3)
    step = 8
    i = 0
    for x in range(0, width, step):
        for y in range(0, width, step):
            c = bg.get(x, y)
            if c != 0:
                i = (i + 1) % 256
                stroke(i, 255, 255)
            else:
                stroke(32)
            point(x, y)


from repiet._backends.generic import backend
import subprocess

class cppbackend(backend):
    def define(self, name, ops, dest):
        if dest is None:
            return "{}: {}return 0;".format(name, ops)
        else:
            return "{}: {}goto {};".format(name, ops, dest)

    def pointer(self, options):
        p0, p1, p2, p3 = options
        return """if (pop(a)) {
    switch((a%%4+4)%%4) {case 1: goto %s; case 2: goto %s; case 3: goto %s;}
} goto %s;"""%(p1, p2, p3, p0)

    def switch(self, options):
        p0, p1 = options
        return "if (pop(a) && a&1) goto {}; goto {};".format(p1, p0);

    def push(self, x):
        return "psh(%d);"%x

    def execute(self, filename, capture_output=False):
        prog = subprocess.run("g++ -o {}.out {}".format(filename, filename), shell=True)
        args = dict(stdout=subprocess.PIPE, stderr=subprocess.PIPE) if capture_output else {}
        prog = subprocess.run("./{}.out".format(filename), *args)
        if capture_output:
            return prog.stdout, prog.stderr

    def instruction(self, i):
        return {
            "NOP" : "",
            "POP" : "pop(a);",
            "ADD" : "if (pop(a, b)) psh(b+a);",
            "SBT" : "if (pop(a, b)) psh(b-a);",
            "MLT" : "if (pop(a, b)) psh(b*a);",
            "DVD" : "if (pop(a, b) && a) psh(b/a);",
            "MOD" : "if (pop(a, b) && a) psh((a+b%a)%a);",
            "NOT" : "if (pop(a)) psh(!a);",
            "GRT" : "if (pop(a, b)) psh(b>a);",
            "DPL" : "if (pop(a)) { psh(a); psh(a); }",
            "RLL" : "if (pop(a, b)) rll(a, b);",
            "DIN" : "cin >> a; if(!cin.fail()) psh(cin.eof()?-1:a);",
            "CIN" : "cin.get(A); if(!cin.bad()) psh(cin.eof()?-1:static_cast<int>(A));",
            "DUT" : "if (pop(a)) cout << a;",
            "CUT" : "if (pop(A)) cout << A;",
         }[i]

    def render(self, defs, start):
        if start is None:
            defs = "end:return 0;"
            start = "end"

        return """#include <vector>
#include <iostream>
using namespace std;
vector<int> d;
void psh(int x) {d.push_back(x);}
template<typename t> int pop(t &x) {if (d.size()) {x = d.back();d.pop_back();return 1;}return 0;}
int pop(int &x, int &y) {if (d.size() > 1) {x = d.back();d.pop_back();y = d.back();d.pop_back();;return 1;}return 0;}
void rll(int x, int y) {
 if (y<=0 || y > d.size()) return;
 x = (y+x%y)%y;
 if (x == 0) return;
 int z = (x<0)?x+y:-x+y;
 vector<int> t(y);
 copy(d.end()-y, d.end()-z, t.end()-z);
 copy(d.end()-y+z, d.end(), t.begin());
 copy(t.begin(), t.end(), d.end()-y);
}
int main() {
int t=0,i=0,a,b;
char A;
""" + defs + """
goto """ + start + """;
}"""