#!/usr/bin/python
"""*****************************************************************************************************************
    DropPi by Kim Dalmeijer, 2021

    Relay board 0: valve relays [VALVE1, VALVE2, VALVE3, VALVE4]
    Relay board 1: flash and camera relays [CAM, FLASH1, FLASH2, FLASH3]
********************************************************************************************************************"""
from __future__ import print_function
import logging
import sys
import time
import ctypes
import threading
from DropPi_lib import *

# Load libc shared library:
libc = ctypes.CDLL('libc.so.6')

# General Definitions
DEF_FLASH_DELAY = 30  # (ms)
DEF_CAMERA_DELAY = 2500  # (ms)

MIRROR_LOCKUP = True

# Definitions of timings, these are defaults which will be set with the GUI before execution of the firing process
# Each timing consists of the starttime in ms, and the duration in ms. Valve timings have 4 slots (4 drops).
# Camera and flash timings have a single slot
# Timings for VALVE_1
TIMES_VALVE_1 = list()
TIMES_VALVE_2 = list()
TIMES_VALVE_3 = list()
TIMES_VALVE_4 = list()

TIME_CAMERA = 100
TIME_FLASH = ''

# placeholders for elapsed thread times
v1_elapsed_time = 0
v2_elapsed_time = 0
v3_elapsed_time = 0
v4_elapsed_time = 0
c_elapsed_time = 0
f_elapsed_time = 0

def delayus(us):
    """ Delay microseconds with libc usleep() using ctypes. """
    libc.usleep(int(us))
# ------------------------------------

def thread_valve_1_function():
    global v1_elapsed_time
    start_time = time.perf_counter()
    if MIRROR_LOCKUP:
        delayus(700 * 1000)
    for i in range(len(TIMES_VALVE_1)):
        delayus(float(TIMES_VALVE_1[i][0]) * 1000)
        relay_on(VALVE_1)
        delayus(float(TIMES_VALVE_1[i][1]) * 1000)
        relay_off(VALVE_1)
    v1_elapsed_time = time.perf_counter() - start_time

def thread_valve_2_function():
    global v2_elapsed_time
    start_time = time.perf_counter()
    if MIRROR_LOCKUP:
        delayus(700 * 1000)
    for i in range(len(TIMES_VALVE_2)):
        delayus(float(TIMES_VALVE_2[i][0]) * 1000)
        relay_on(VALVE_2)
        delayus(float(TIMES_VALVE_2[i][1]) * 1000)
        relay_off(VALVE_2)
    v2_elapsed_time = time.perf_counter() - start_time

def thread_valve_3_function():
    global v3_elapsed_time
    start_time = time.perf_counter()
    if MIRROR_LOCKUP:
        delayus(700 * 1000)
    for i in range(len(TIMES_VALVE_3)):
        delayus(float(TIMES_VALVE_3[i][0]) * 1000)
        relay_on(VALVE_3)
        delayus(float(TIMES_VALVE_3[i][1]) * 1000)
        relay_off(VALVE_3)
    v3_elapsed_time = time.perf_counter() - start_time

def thread_valve_4_function():
    global v4_elapsed_time
    start_time = time.perf_counter()
    if MIRROR_LOCKUP:
        delayus(700 * 1000)
    for i in range(len(TIMES_VALVE_4)):
        delayus(float(TIMES_VALVE_4[i][0]) * 1000)
        relay_on(VALVE_4)
        delayus(float(TIMES_VALVE_4[i][1]) * 1000)
        relay_off(VALVE_4)
    v4_elapsed_time = time.perf_counter() - start_time

def thread_camera_function():
    global c_elapsed_time
    start_time = time.perf_counter()
    if MIRROR_LOCKUP:
        relay_on(CAMERA)
        delayus(150 * 1000)
        relay_off(CAMERA)
        delayus(550 * 1000)
    delayus(TIME_CAMERA * 1000)
    relay_on(CAMERA)
    delayus(DEF_CAMERA_DELAY * 1000)
    relay_off(CAMERA)
    c_elapsed_time = time.perf_counter() - start_time

def thread_flash_function(flash1, flash2, flash3):
    global f_elapsed_time
    start_time = time.perf_counter()
    # WAIT FOR MIRROR LOCKUP IF NEEDED
    if MIRROR_LOCKUP:
        delayus(700 * 1000)
    # TURN ON
    delayus(float(TIME_FLASH) * 1000)
    if not flash1:
        TMPFLASH_1 = 0
    else:
        TMPFLASH_1 = FLASH_1
    if not flash2:
        TMPFLASH_2 = 0
    else:
        TMPFLASH_2 = FLASH_2
    if not flash3:
        TMPFLASH_3 = 0
    else:
        TMPFLASH_3 = FLASH_3
    relay_on(TMPFLASH_1, TMPFLASH_2, TMPFLASH_3)
    # TURN OFF
    delayus(DEF_FLASH_DELAY * 1000)
    relay_off(TMPFLASH_1, TMPFLASH_2, TMPFLASH_3)
    f_elapsed_time = time.perf_counter() - start_time

def main(**kwargs):
    # do whatever and return 0 for success and an
    # integer x, 1 <= x <= 256 for failure
    logformat = '%(asctime)s.%(msecs)03d %(message)s'
    logging.basicConfig(format=logformat, level=logging.INFO, datefmt='%H:%M:%S')

    # set variables for this run from what the main has passed
    global DEF_FLASH_DELAY
    global DEF_CAMERA_DELAY
    global TIME_CAMERA
    global TIME_FLASH
    global TIMES_VALVE_1
    global TIMES_VALVE_2
    global TIMES_VALVE_3
    global TIMES_VALVE_4
    global MIRROR_LOCKUP
    global v1_elapsed_time
    global v2_elapsed_time
    global v3_elapsed_time
    global v4_elapsed_time
    global c_elapsed_time
    global f_elapsed_time

    DEF_FLASH_DELAY = float(kwargs['flash_def'])
    logging.info("FLASH DELAY: %i", DEF_FLASH_DELAY)
    DEF_CAMERA_DELAY = float(kwargs['cam_def'])
    logging.info("CAMERA DELAY: %i", DEF_CAMERA_DELAY)
    TIME_CAMERA = float(kwargs['cam_on'])
    logging.info("CAMERA TIME: %i", TIME_CAMERA)
    TIME_FLASH = float(kwargs['flash_on'])
    logging.info("FLASH TIME: %i", TIME_FLASH)

    MIRROR_LOCKUP = kwargs['mirror']
    TIMES_VALVE_1 = kwargs['v1times']
    TIMES_VALVE_2 = kwargs['v2times']
    TIMES_VALVE_3 = kwargs['v3times']
    TIMES_VALVE_4 = kwargs['v4times']

    logging.info("DropPi    : before creating threads")
    thread_valve_1 = threading.Thread(target=thread_valve_1_function)
    thread_valve_2 = threading.Thread(target=thread_valve_2_function)
    thread_valve_3 = threading.Thread(target=thread_valve_3_function)
    thread_valve_4 = threading.Thread(target=thread_valve_4_function)
    thread_camera = threading.Thread(target=thread_camera_function)
    thread_flash = threading.Thread(target=thread_flash_function, args=(
        kwargs['flash1_on'], kwargs['flash2_on'], kwargs['flash3_on']))

    logging.info("DropPi    : before running threads")
    thread_camera.start()
    thread_valve_1.start()
    thread_valve_2.start()
    thread_valve_3.start()
    thread_valve_4.start()
    thread_flash.start()

    logging.info("DropPi    : waiting for all threads to finish")
    thread_camera.join()
    thread_valve_1.join()
    thread_valve_2.join()
    thread_valve_3.join()
    thread_valve_4.join()
    thread_flash.join()
    logging.info("DropPi    : all done")

    # calculate error from elapsed times and display results to indicate how trustworthy the app runs
    # if an elapsed time is zero, the valve of flash for that time was not used

    # V1 ERROR CALCULATION
    calculated_elapsed_time = 0
    if v1_elapsed_time != 0:
        if MIRROR_LOCKUP:
            calculated_elapsed_time += 700
        for i in range(len(TIMES_VALVE_1)):
            calculated_elapsed_time += float(TIMES_VALVE_1[i][0])
            calculated_elapsed_time += float(TIMES_VALVE_1[i][1])
        calculated_elapsed_time = calculated_elapsed_time / 1000
        try:
            calculated_error = ((calculated_elapsed_time - v1_elapsed_time) / calculated_elapsed_time) * 100
        except ZeroDivisionError:
            calculated_error = 0
        logging.info(
            f'Valve1 timings: real; {v1_elapsed_time:.4f},'
            f' calculated; {calculated_elapsed_time},'
            f' error; {abs(calculated_error):.1f}%')

    # V2 ERROR CALCULATION
    calculated_elapsed_time = 0
    if v2_elapsed_time != 0:
        if MIRROR_LOCKUP:
            calculated_elapsed_time += 700
        for i in range(len(TIMES_VALVE_2)):
            calculated_elapsed_time += float(TIMES_VALVE_2[i][0])
            calculated_elapsed_time += float(TIMES_VALVE_2[i][1])
        calculated_elapsed_time = calculated_elapsed_time / 1000
        try:
            calculated_error = ((calculated_elapsed_time - v2_elapsed_time) / calculated_elapsed_time) * 100
        except ZeroDivisionError:
            calculated_error = 0
        logging.info(
            f'Valve2 timings: real; {v2_elapsed_time:.4f},'
            f' calculated; {calculated_elapsed_time},'
            f' error; {abs(calculated_error):.1f}%')

    # V3 ERROR CALCULATION
    calculated_elapsed_time = 0
    if v3_elapsed_time != 0:
        if MIRROR_LOCKUP:
            calculated_elapsed_time += 700
        for i in range(len(TIMES_VALVE_3)):
            calculated_elapsed_time += float(TIMES_VALVE_3[i][0])
            calculated_elapsed_time += float(TIMES_VALVE_3[i][1])
        calculated_elapsed_time = calculated_elapsed_time / 1000
        try:
            calculated_error = ((calculated_elapsed_time - v3_elapsed_time) / calculated_elapsed_time) * 100
        except ZeroDivisionError:
            calculated_error = 0
        logging.info(
            f'Valve3 timings: real; {v3_elapsed_time:.4f},'
            f' calculated; {calculated_elapsed_time},'
            f' error; {abs(calculated_error):.1f}%')

    # V4 ERROR CALCULATION
    calculated_elapsed_time = 0
    if v4_elapsed_time != 0:
        if MIRROR_LOCKUP:
            calculated_elapsed_time += 700
        for i in range(len(TIMES_VALVE_4)):
            calculated_elapsed_time += float(TIMES_VALVE_4[i][0])
            calculated_elapsed_time += float(TIMES_VALVE_4[i][1])
        calculated_elapsed_time = calculated_elapsed_time / 1000
        try:
            calculated_error = ((calculated_elapsed_time - v4_elapsed_time) / calculated_elapsed_time) * 100
        except ZeroDivisionError:
            calculated_error = 0
        logging.info(
            f'Valve4 timings: real; {v4_elapsed_time:.4f},'
            f' calculated; {calculated_elapsed_time},'
            f' error; {abs(calculated_error):.1f}%')

    # CAMERA ERROR CALCULATION
    calculated_elapsed_time = 0
    if c_elapsed_time != 0:
        if MIRROR_LOCKUP:
            calculated_elapsed_time += 700
        calculated_elapsed_time += float(TIME_CAMERA)
        calculated_elapsed_time += float(DEF_CAMERA_DELAY)
        calculated_elapsed_time = calculated_elapsed_time / 1000
        try:
            calculated_error = ((calculated_elapsed_time - c_elapsed_time) / calculated_elapsed_time) * 100
        except ZeroDivisionError:
            calculated_error = 0
        logging.info(
            f'Camera timings: real; {c_elapsed_time:.4f},'
            f' calculated; {calculated_elapsed_time},'
            f' error; {abs(calculated_error):.1f}%')

    # FLASH ERROR CALCULATION
    calculated_elapsed_time = 0
    if f_elapsed_time != 0:
        if MIRROR_LOCKUP:
            calculated_elapsed_time += 700
        calculated_elapsed_time += float(TIME_FLASH)
        calculated_elapsed_time += float(DEF_FLASH_DELAY)
        calculated_elapsed_time = calculated_elapsed_time / 1000
        try:
            calculated_error = ((calculated_elapsed_time - f_elapsed_time) / calculated_elapsed_time) * 100
        except ZeroDivisionError:
            calculated_error = 0
        logging.info(
            f'Flash timings: real; {f_elapsed_time:.4f},'
            f' calculated; {calculated_elapsed_time},'
            f' error; {abs(calculated_error):.1f}%')

    return 0

# Now see what we're supposed to do next
if __name__ == "__main__":
    sys.exit(main())


"""
Search (Chapters 3-4)
The way to use this code is to subclass Problem to create a class of problems,
then create problem instances and solve them with calls to the various search
functions.
"""

import sys
from collections import deque

from pac_man.utils import *
from pac_man.node import Node

# ______________________________________________________________________________
# Uninformed Search algorithms

def breadth_first_tree_search(problem):
    """
    [Figure 3.7]
    Search the shallowest nodes in the search tree first.
    Search through the successors of a problem to find a goal.
    The argument frontier should be an empty queue.
    Repeats infinitely in case of loops.
    """

    frontier = deque([Node(problem.initial)])  # FIFO queue

    while frontier:
        node = frontier.popleft()
        if problem.goal_test(node.state):
            return node
        frontier.extend(node.expand(problem))
    return None

def depth_first_tree_search(problem):
    """
    [Figure 3.7]
    Search the deepest nodes in the search tree first.
    Search through the successors of a problem to find a goal.
    The argument frontier should be an empty queue.
    Repeats infinitely in case of loops.
    """

    frontier = [Node(problem.initial)]  # Stack

    while frontier:
        node = frontier.pop()
        if problem.goal_test(node.state):
            return node
        frontier.extend(node.expand(problem))
    return None

def depth_first_graph_search(problem):
    """
    [Figure 3.7]
    Search the deepest nodes in the search tree first.
    Search through the successors of a problem to find a goal.
    The argument frontier should be an empty queue.
    Does not get trapped by loops.
    If two paths reach a state, only use the first one.
    """
    frontier = [(Node(problem.initial))]  # Stack

    explored = set()
    while frontier:
        node = frontier.pop()
        if problem.goal_test(node.state):
            return node
        explored.add(node.state)
        frontier.extend(
            child
            for child in node.expand(problem)
            if child.state not in explored and child not in frontier
        )
    return None

def breadth_first_graph_search(problem):
    """[Figure 3.11]
    Note that this function can be implemented in a
    single line as below:
    return graph_search(problem, FIFOQueue())
    """
    node = Node(problem.initial)
    if problem.goal_test(node.state):
        return node
    frontier = deque([node])
    explored = set()
    while frontier:
        node = frontier.popleft()
        explored.add(node.state)
        for child in node.expand(problem):
            if child.state not in explored and child not in frontier:
                if problem.goal_test(child.state):
                    return child
                frontier.append(child)
    return None

def best_first_graph_search(problem, f, display=False):
    """Search the nodes with the lowest f scores first.
    You specify the function f(node) that you want to minimize; for example,
    if f is a heuristic estimate to the goal, then we have greedy best
    first search; if f is node.depth then we have breadth-first search.
    There is a subtlety: the line "f = memoize(f, 'f')" means that the f
    values will be cached on the nodes as they are computed. So after doing
    a best first search you can examine the f values of the path returned."""
    f = memoize(f, "f")
    node = Node(problem.initial)
    frontier = PriorityQueue("min", f)
    frontier.append(node)
    explored = set()
    while frontier:
        node = frontier.pop()
        if problem.goal_test(node.state):
            if display:
                print(
                    len(explored),
                    "paths have been expanded and",
                    len(frontier),
                    "paths remain in the frontier",
                )
            return node
        explored.add(node.state)
        for child in node.expand(problem):
            if child.state not in explored and child not in frontier:
                frontier.append(child)
            elif child in frontier:
                if f(child) < frontier[child]:
                    del frontier[child]
                    frontier.append(child)
    return None

def uniform_cost_search(problem, display=False):
    """[Figure 3.14]"""
    return best_first_graph_search(problem, lambda node: node.path_cost, display)

def depth_limited_search(problem, limit=50):
    """[Figure 3.17]"""

    def recursive_dls(node, problem, limit):
        if problem.goal_test(node.state):
            return node
        elif limit == 0:
            return "cutoff"
        else:
            cutoff_occurred = False
            for child in node.expand(problem):
                result = recursive_dls(child, problem, limit - 1)
                if result == "cutoff":
                    cutoff_occurred = True
                elif result is not None:
                    return result
            return "cutoff" if cutoff_occurred else None

    # Body of depth_limited_search:
    return recursive_dls(Node(problem.initial), problem, limit)

def iterative_deepening_search(problem):
    """[Figure 3.18]"""
    for depth in range(sys.maxsize):
        result = depth_limited_search(problem, depth)
        if result != "cutoff":
            return result

# ______________________________________________________________________________
# Bidirectional Search
# Pseudocode from https://webdocs.cs.ualberta.ca/%7Eholte/Publications/MM-AAAI2016.pdf

def bidirectional_search(problem):
    e = 0
    if isinstance(problem, GraphProblem):
        e = problem.find_min_edge()
    gF, gB = {Node(problem.initial): 0}, {Node(problem.goal): 0}
    openF, openB = [Node(problem.initial)], [Node(problem.goal)]
    closedF, closedB = [], []
    U = np.inf

    def extend(U, open_dir, open_other, g_dir, g_other, closed_dir):
        """Extend search in given direction"""
        n = find_key(C, open_dir, g_dir)

        open_dir.remove(n)
        closed_dir.append(n)

        for c in n.expand(problem):
            if c in open_dir or c in closed_dir:
                if g_dir[c] <= problem.path_cost(g_dir[n], n.state, None, c.state):
                    continue

                open_dir.remove(c)

            g_dir[c] = problem.path_cost(g_dir[n], n.state, None, c.state)
            open_dir.append(c)

            if c in open_other:
                U = min(U, g_dir[c] + g_other[c])

        return U, open_dir, closed_dir, g_dir

    def find_min(open_dir, g):
        """Finds minimum priority, g and f values in open_dir"""
        # pr_min_f isn't forward pr_min instead it's the f-value
        # of node with priority pr_min.
        pr_min, pr_min_f = np.inf, np.inf
        for n in open_dir:
            f = g[n] + problem.h(n)
            pr = max(f, 2 * g[n])
            pr_min = min(pr_min, pr)
            pr_min_f = min(pr_min_f, f)

        return pr_min, pr_min_f, min(g.values())

    def find_key(pr_min, open_dir, g):
        """Finds key in open_dir with value equal to pr_min
        and minimum g value."""
        m = np.inf
        node = Node(-1)
        for n in open_dir:
            pr = max(g[n] + problem.h(n), 2 * g[n])
            if pr == pr_min:
                if g[n] < m:
                    m = g[n]
                    node = n

        return node

    while openF and openB:
        pr_min_f, f_min_f, g_min_f = find_min(openF, gF)
        pr_min_b, f_min_b, g_min_b = find_min(openB, gB)
        C = min(pr_min_f, pr_min_b)

        if U <= max(C, f_min_f, f_min_b, g_min_f + g_min_b + e):
            return U

        if C == pr_min_f:
            # Extend forward
            U, openF, closedF, gF = extend(U, openF, openB, gF, gB, closedF)
        else:
            # Extend backward
            U, openB, closedB, gB = extend(U, openB, openF, gB, gF, closedB)

    return np.inf

# ______________________________________________________________________________
# Informed (Heuristic) Search

greedy_best_first_graph_search = best_first_graph_search

# Greedy best-first search is accomplished by specifying f(n) = h(n).

def astar_search(problem, h=None, display=False):
    """A* search is best-first graph search with f(n) = g(n)+h(n).
    You need to specify the h function when you call astar_search, or
    else in your Problem subclass."""
    h = memoize(h or problem.h, "h")
    return best_first_graph_search(problem, lambda n: n.path_cost + h(n), display)

# ______________________________________________________________________________
# Other search algorithms

def recursive_best_first_search(problem, h=None):
    """[Figure 3.26]"""
    h = memoize(h or problem.h, "h")

    def RBFS(problem, node, flimit):
        if problem.goal_test(node.state):
            return node, 0  # (The second value is immaterial)
        successors = node.expand(problem)
        if len(successors) == 0:
            return None, np.inf
        for s in successors:
            s.f = max(s.path_cost + h(s), node.f)
        while True:
            # Order by lowest f value
            successors.sort(key=lambda x: x.f)
            best = successors[0]
            if best.f > flimit:
                return None, best.f
            if len(successors) > 1:
                alternative = successors[1].f
            else:
                alternative = np.inf
            result, best.f = RBFS(problem, best, min(flimit, alternative))
            if result is not None:
                return result, best.f

    node = Node(problem.initial)
    node.f = h(node)
    result, bestf = RBFS(problem, node, np.inf)
    return result

def hill_climbing(problem):
    """
    [Figure 4.2]
    From the initial node, keep choosing the neighbor with highest value,
    stopping when no neighbor is better.
    """
    states = []
    current = Node(problem.initial)
    dead_ends = set()

    while current.state != problem.goal:
        states.append(current.state)
        all_neighbors = current.expand(problem)
        neighbors = [n for n in all_neighbors if n.state not in dead_ends]

        # if the current node has only one neighbor and it is equal to the
        # last visited node, it is a dead end
        if len(neighbors) == 1 and len(states) > 1 and neighbors[0].state == states[-2]:
            dead_ends.add(current.state)

        if not neighbors:
            break

        neighbor = argmax_random_tie(
            neighbors, key=lambda node: problem.value(node.state)
        )

        #if problem.value(neighbor.state) < problem.value(current.state):
        #    break

        current = neighbor
        problem.record_choice(current)

    return current.state, states

def exp_schedule(k=20, lam=0.005, limit=100):
    """One possible schedule function for simulated annealing"""
    return lambda t: (k * np.exp(-lam * t) if t < limit else 0)

def simulated_annealing(problem, schedule=exp_schedule()):
    """[Figure 4.5] CAUTION: This differs from the pseudocode as it
    returns a state instead of a Node."""
    current = Node(problem.initial)
    for t in range(sys.maxsize):
        T = schedule(t)
        if T == 0:
            return current.state
        neighbors = current.expand(problem)
        if not neighbors:
            return current.state
        next_choice = random.choice(neighbors)
        delta_e = problem.value(next_choice.state) - problem.value(current.state)
        if delta_e > 0 or probability(np.exp(delta_e / T)):
            current = next_choice

def simulated_annealing_full(problem, schedule=exp_schedule()):
    """ This version returns all the states encountered in reaching
    the goal state."""
    states = []
    current = Node(problem.initial)
    for t in range(sys.maxsize):
        states.append(current.state)
        T = schedule(t)
        if T == 0:
            return states
        neighbors = current.expand(problem)
        if not neighbors:
            return current.state
        next_choice = random.choice(neighbors)
        delta_e = problem.value(next_choice.state) - problem.value(current.state)
        if delta_e > 0 or probability(np.exp(delta_e / T)):
            current = next_choice

def and_or_graph_search(problem):
    """[Figure 4.11]Used when the environment is nondeterministic and completely observable.
    Contains OR nodes where the agent is free to choose any action.
    After every action there is an AND node which contains all possible states
    the agent may reach due to stochastic nature of environment.
    The agent must be able to handle all possible states of the AND node (as it
    may end up in any of them).
    Returns a conditional plan to reach goal state,
    or failure if the former is not possible."""

    # functions used by and_or_search
    def or_search(state, problem, path):
        """returns a plan as a list of actions"""
        if problem.goal_test(state):
            return []
        if state in path:
            return None
        for action in problem.actions(state):
            plan = and_search(problem.result(state, action), problem, path + [state])
            if plan is not None:
                return [action, plan]

    def and_search(states, problem, path):
        """Returns plan in form of dictionary where we take action plan[s] if we reach state s."""
        plan = {}
        for s in states:
            plan[s] = or_search(s, problem, path)
            if plan[s] is None:
                return None
        return plan

    # body of and or search
    return or_search(problem.initial, problem, [])


#!/usr/bin/env python
# encoding: utf-8
"""
cheetah.py

Created by Graham Dennis on 2009-02-28.
"""

try:
    from Cheetah.Template import Template
except ImportError:
    Template = None

from waflib import Task, TaskGen

def configure(conf):
    conf.start_msg('Checking for the Cheetah python module')
    if Template:
        conf.end_msg('ok')
    else:
        conf.end_msg('Not found')

class cheetah(Task.Task):
    ext_in  = ['.tmpl']
    ext_out = ['.py']
    vars = ['CHEETAH_SETTINGS']

    def run(self):
        env = self.env
        bld = self.generator.bld

        input_node = self.inputs[0]
        output_node = self.outputs[0]

        compilerSettings = 'CHEETAH_SETTINGS' in env and env['CHEETAH_SETTINGS'] or {}

        basename = input_node.change_ext('').name

        pysrc = Template.compile(
            file = input_node.abspath(),
            compilerSettings = compilerSettings,
            moduleName = basename,
            className = basename,
            returnAClass = False,
        )

        output_node.write(pysrc)
        return 0

@TaskGen.extension('.tmpl')
def cheetah_callback(self, node):
    out = node.change_ext('.py').name
    self.create_task('cheetah', node, node.parent.find_or_declare(out))


import os
from flask import Flask, request, jsonify, abort
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from models import setup_db, Actor, Movie
from auth import AuthError, requires_auth

def create_app(test_config=None):
    app = Flask(__name__)
    setup_db(app)
    # CORS(app)
    CORS(app, resources={r"/api/*": {"origins": "*"}})

    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods', 'GET,PATCH,POST,DELETE,OPTIONS')
        return response

# -------------------------------------------------------------
# Endpoints
# -------------------------------------------------------------

    # @app.route('/')
    # def index():
    #     return "Welcome to the cast-it agency"

# -----------------------------------
# Movies Endpoints
# -----------------------------------

    # Retrieves list of all movies
    @app.route('/movies', methods=['GET'])
    @requires_auth('get:movies')
    def get_movies(payload):
        movies = Movie.query.all()
        formatted_movies = [movie.format() for movie in movies]
        return jsonify({
            'success': True,
            'movies': formatted_movies
        })

    #Adds a new movie to DB
    @app.route('/movies', methods=['POST'])
    @requires_auth('post:movies')
    def add_movie(payload):
        body = request.get_json()
        title = body.get('title', None)
        release_date = body.get('release_date', None)
        # try:
        entry = Movie(title=title, release_date=release_date)
        entry.insert()
        return jsonify({
            'success': True,
            'movies': entry.format()
        })
        # except:
        #     abort(422)

    @app.route('/movies/<int:movie_id>', methods=['PATCH'])
    @requires_auth('patch:movies')
    def update_movie(payload, movie_id):
        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()
        try:
            if movie is None:
                abort(404)
            else:
                body = request.get_json()
                movie.title = body.get('title', None)
                movie.release_date = body.get('release_date', None)
                movie.update()
                return jsonify({
                'success': True,
                'movieid': movie_id
                }),200
        except:
            abort(422)

    @app.route('/movies/<int:movie_id>', methods=['DELETE'])
    @requires_auth('delete:movies')
    def delete_movie(payload, movie_id):
        movie = Movie.query.filter(Movie.id == movie_id).one_or_none()
        try:
            if movie is None:
                abort(404)
            else:
                movie.delete()
                return jsonify({
                'success': True,
                'movieid': movie_id
                })
        except:
            abort(422)

# -----------------------------------
# Actors Endpoints
# -----------------------------------

    # Retrives list of all actors

    @app.route('/actors', methods=['GET'])
    @requires_auth('get:actors')
    def get_actors(payload):
        actors = Actor.query.all()
        formatted_actors = [actor.format() for actor in actors]
        return jsonify({
        'success': True,
        'actors': formatted_actors
        })

    @app.route('/actors', methods=['POST'])
    @requires_auth('post:actors')
    def add_actor(payload):
        body = request.get_json()
        name = body.get('name', None)
        age = body.get('age', None)
        gender = body.get('gender', None)

        try:
            entry = Actor(name=name, age=age, gender=gender)
            entry.insert()
            return jsonify({
                'success': True,
                'movies': entry.format()
            })
        except:
            abort(422)

    @app.route('/actors/<int:actor_id>', methods=['PATCH'])
    @requires_auth('patch:actors')
    def update_actor(payload, actor_id):
        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()
        try:
            if actor is None:
                abort(404)
            else:
                body = request.get_json()
                actor.name = body.get('name', None)
                actor.age = body.get('age', None)
                actor.gender = body.get('gender', None)
                actor.update()
                return jsonify({
                'success': True,
                'movieid': actor_id
                }),200
        except:
            abort(422)

    @app.route('/actors/<int:actor_id>', methods=['DELETE'])
    @requires_auth('delete:actors')
    def delete_actor(payload, actor_id):
        actor = Actor.query.filter(Actor.id == actor_id).one_or_none()
        try:
            if actor is None:
                abort(404)
            else:
                actor.delete()
                return jsonify({
                'success': True,
                'movieid': actor_id
                })
        except:
            abort(422)

# after_request decorator to set Access-Control-Allow
    @app.after_request
    def after_request(response):
        response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,true')
        response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
        return response

# Error Handling
    '''
    Example error handling for unprocessable entity
    '''
    @app.errorhandler(AuthError)
    def handle_auth_error(ex):
        response = jsonify(ex.error)
        response.status_code = ex.status_code
        return response

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(404)
    def resource_not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(500)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "Internal Server Error"
        }), 500

    @app.errorhandler(401)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "Authorization header is expected"
        }), 401

    @app.errorhandler(403)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 403,
            "message": "forbidden"
        }), 403

    @app.errorhandler(400)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "unprocessable"
        }), 400

    return app

app = create_app()
db = SQLAlchemy(app)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)


import torch
import os
from tqdm import tqdm
import torchvision

images = []
files = []
tx = torchvision.transforms.Resize((128, 128))
for f in tqdm(os.listdir("train")):
    img = torchvision.io.read_image("train/" + f)
    images.append(tx(img.float() / 255))
    files.append(f)

torch.save({
    'names': files,
    'images': torch.stack(images),
}, 'data/x_train_resized_normalized.pt')


import json
import time
from gsmmodem.exceptions import CommandError
from twisted.web.resource import Resource

__author__ = 'kbsoft'

from libs import modem_manager

class ModemService(Resource):
    def __init__(self, serviceType):
        Resource.__init__(self)
        self.serviceType = serviceType

    def getChild(self, path, request):
        if path == 'ping':
            return Ping()
        elif path == 'all':
            return ModemsInfo()
        elif path == 'dial':
            return Dial()
            # def render_GET(self, request):
            # pass

class Ping(Resource):
    isLeaf = True

    def render_GET(self, request):
        request.responseHeaders.addRawHeader(b"content-type", b"application/json")
        timestamp = int(time.time())
        live = []
        if len(request.args) != 0 and request.args['fd']:
            modem = modem_manager.modems.get(request.args['fd'][0])
            live = modem.port
        else:
            for modem in modem_manager.modems.itervalues():
                if modem.alive:
                    live.append(modem.port)
        return_value = {
            u'result': u'true',
            u'timestamp': timestamp,
            u'modems_count': modem_manager.modems.count,
            u'live': live,
            u'status': u'pong',
        }

        return json.dumps(return_value)

class ModemsInfo(Resource):
    isLeaf = True

    def render_GET(self, request):
        request.responseHeaders.addRawHeader(b"content-type", b"application/json")
        timestamp = int(time.time())
        modems = []
        failures = 0
        if len(request.args) != 0 and request.args['fd']:
            modem = modem_manager.modems.get(request.args['fd'][0])
            modems = self._modem_to_dict(modem)
            if not modems['alive']:
                failures += 1

        else:
            for modem in modem_manager.modems.itervalues():
                modem_dic = self._modem_to_dict(modem)
                if not modem_dic['alive']:
                    failures += 1
                modems.append(modem_dic)
        return_value = {
            u'result': u'true',
            u'timestamp': timestamp,
            u'modems': modems,
            u'status': u'pong',
            u'failures': failures
        }

        return json.dumps(return_value)

    def _modem_to_dict(self, modem):
        if modem.alive:
            return_value = {
                u'port': modem.port,
                u'baudrate': modem.baudrate,
                u'alive': modem.alive,
                u'imei': modem.imei,
                u'imsi': modem.imsi,
                u'manufacturer': modem.manufacturer,
                u'model': modem.model,
                u'networkName': modem.networkName,
                u'revision': modem.revision,
                u'signalStrength': modem.signalStrength,
                u'smsc': modem.smsc
            }
        else:
            return_value = {
                u'port': modem.port,
                u'baudrate': modem.baudrate,
                u'alive': modem.alive
            }
        return return_value

class Dial(Resource):
    isLeaf = True

    def render_POST(self, request):
        request.responseHeaders.addRawHeader(b"content-type", b"application/json")
        timestamp = int(time.time())
        number = request.args['number'].pop()
        modem = modem_manager.modems.get_random_modem()
        if 'fd' in request.args:
            fd = request.args['fd'].pop()
            modem = modem_manager.modems.get(fd)
        try:
            modem.dial(number)
            return_value = {
                u'result': u'true',
                u'timestamp': timestamp,
                u'status': u'dialed',
                u'fd': modem.port
            }
        except CommandError as error:
            # TODO: Send error exception string
            return_value = {
                u'result': u'false',
                u'timestamp': timestamp,
                u'status': u'fail',
                u'fd': modem.port,
                u'reason': error.message
            }

        return json.dumps(return_value)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from codecs import open

from setuptools import find_packages, setup

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

def read(*paths):
    """Build a file path from *paths and return the contents."""
    with open(os.path.join(*paths), 'r', 'utf-8') as f:
        return f.read()

extras_require = {
    'mailgun': [
        'django-mailgun==0.8.0',
    ],
    'raven': [
        'raven==5.8.1',
    ],
}

requires = [
    'Django==1.8.7',
    'dj-database-url==0.3.0',
    'django-braces==1.8.1',
    # django-configurations 0.8 does not work with Django 1.8. A fork has been
    # added to requirements/forks.pip that supports Django 1.8.
    # 'django-configurations==0.8',
    'django-crispy-forms==1.5.2',
    'django-grappelli==2.7.2',
    'django-model-utils==2.4',
    'envdir==0.7',
    'psycopg2==2.6.1',
    'pytz==2015.7',
]

setup(
    name='fog',
    version='0.1.0',
    description='a foreigners online guide',
    long_description=read(BASE_DIR, 'README.md'),
    author='Max Brauer <max@max-brauer.de>',
    author_email='noreply@example.com',
    packages=find_packages(),
    include_package_data=True,
    scripts=['manage.py'],
    install_requires=requires,
    license='BSD',
    zip_safe=False,
    classifiers=[
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Natural Language :: English',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: Implementation :: CPython',
    ],
)


from http.server import BaseHTTPRequestHandler, HTTPServer
from operator import attrgetter
from threading import Thread
import json
import time

import logger
import gamestate
import payloadparser

class GSIServer(HTTPServer):
    def __init__(self, server_address, auth_token):
        super(GSIServer, self).__init__(server_address, RequestHandler)

        self.auth_token = auth_token
        self.gamestate = gamestate.GameState()
        self.parser = payloadparser.PayloadParser()
        # self.setup_log_file()

        self.running = False

    # def setup_log_file(self):
    #     self.log_file = logger.LogFile(time.asctime())

    def start_server(self):
        try:
            thread = Thread(target=self.serve_forever)
            thread.start()
            first_time = True
            while self.running == False:
                if first_time == True:
                    print("CS:GO GSI Server starting..")
                first_time = False
        except:
            print("Could not start server.")

    def get_info(self, target, *argv):
        try:
            #print(target)
            if len(argv) == 0:
                state = attrgetter(f"{target}")(self.gamestate)
            elif len(argv) == 1:
                state = attrgetter(f"{target}.{argv[0]}")(self.gamestate)
            elif len(argv) == 2:
                state = attrgetter(f"{target}.{argv[0]}")(self.gamestate)[f"{argv[1]}"]
            else:
                print("Too many arguments.")
                return False
            if "object" in str(state):
                return vars(state)
            else:
                return state
        except Exception as E:
            #print(E)
            return False

    def stop_server(self):
        self.running = False
        print("sad")

class RequestHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers["Content-Length"])
        body = self.rfile.read(length).decode("utf-8")

        payload = json.loads(body)

        #self.server.log_file.log_event(time.asctime(), payload)

        if not self.authenticate_payload(payload):
            print("auth_token does not match.")
            return False
        else:
            self.server.running = True

        self.server.parser.parse_payload(payload, self.server.gamestate)

    def authenticate_payload(self, payload):
        if "auth" in payload and "token" in payload["auth"]:
            return payload["auth"]["token"] == self.server.auth_token
        else:
            return False

def scan_for_win(server, max_team_wins): #outputs
    while True:
        t_wins = server.get_info("map","team_t","score")
        ct_wins = server.get_info("map","team_ct","score")
        if t_wins == max_team_wins:
            return True , False
        elif ct_wins == max_team_wins:
            return False , True
        elif ct_wins == max_team_wins-1 and t_wins == max_team_wins-1:
            return None , None
        else:
            return False , False

def output(server): #outputs the match stats as dictionary and in console
    output = {}
    for i in range(12):
            if getattr(getattr(server.gamestate.allplayers, "p" + str(i) ) , "name") != None:

                name = getattr(getattr(server.gamestate.allplayers, "p" + str(i) ) , "name")
                stats = getattr(getattr(server.gamestate.allplayers, "p" + str(i) ) , "match_stats")
                stats.pop("score")
                stats.pop("mvps")
                stats["team"] = getattr(getattr(server.gamestate.allplayers, "p" + str(i) ) , "team")
                stats["steamid"] = getattr(getattr(server.gamestate.allplayers, "p" + str(i) ) , "steamid")
                output[name] = stats

                print("---------------------------------------------------------------")
                print(name, end=": ")
                print(stats)
            else:
                pass
    return output


from flask import Flask, request, jsonify
import chatbot

app = Flask(__name__)
bot = chatbot.chatbot()

@app.route("/chatbot/question", methods = ['GET', 'POST'])
def hello():
    if request.method == 'GET':
        entrada = request.args.get('input')
        print(entrada)
        resposta = bot.get_response(chatbot.pre_process_spacy(entrada)).text
        print(resposta)
        return jsonify(isError=False,
                       message="Success",
                       statusCode=200,
                       output=resposta,
                       input=entrada
                       ), 200

if __name__ == '__main__':
    app.run(debug=True)


import pandas as pd
import numpy as np
import os
from roller import Roller
from argparse import ArgumentParser

def main():
    # ------- Parse commandline arguements and Set all necessary variables ---------------- #
    # Working from within the directory where Roller.py is located
    parser = ArgumentParser()

    parser.add_argument("-i","--infile", help="Input excel or pickle file name", type=str)
    parser.add_argument("-o","--outfile", help="Output excel file name", type=str, default="new.xlsx")
    parser.add_argument("-c","--colnames", help="Comma separated list of column names in the input File", type=str)
    parser.add_argument("-a","--column2aggregate", help="Column names in the input Excel File", type=str)
    parser.add_argument("-f","--aggregate_functions", help="Comma delimited list of 2 functions to apply",
                        default="mean,std", type=str)
    parser.add_argument("-r","--rolling_interval", help="Rolling interval to use for aggregation", default=5, type=int)
    parser.add_argument("-s","--insheet", help="Rolling interval to use for aggregation", type=str)

    args = parser.parse_args()

    col_list = [col for col in args.colnames.split(",")]
    aggregate_functions = [function for function in args.aggregate_functions.split(",")]
    outsheeet =  f"edited-{args.insheet}"

    # Check to see if the input file is a pickle or excel file
    ispickle=False if args.infile.endswith("xlsx") else True
    # --- Create a Roller object#
    df = Roller(aggregate_functions, args.column2aggregate, args.rolling_interval,
              args.insheet, outsheeet, args.infile, args.outfile,
              ispickle, header=1, usecols=col_list)

    # Let roll baby
    df.run(True)

if __name__ == "__main__":
    main()


import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import random
import datetime
from tensorflow import keras
from tensorflow.keras import layers
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import make_column_transformer, make_column_selector
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GroupShuffleSplit
from tensorflow.keras import callbacks
from tensorflow.keras.callbacks import EarlyStopping
import logging

# Set up logging
logging.basicConfig(level=logging.INFO)

# Carga de datos
logging.info('Loading data...')
visits = pd.read_csv('/content/drive/MyDrive/deep_learning/data/visits/entrenamiento1.csv')
visits_features = visits.copy()

# Conversión de fechas a formato numérico
logging.info('Converting dates to numerical format...')
visits_features['FECHA_ENTRADA_REV'] = pd.to_datetime(visits_features['FECHA_ENTRADA_REV']).astype(int) / 10**9
visits_features['FECHA_SALIDA_REV'] = pd.to_datetime(visits_features['FECHA_SALIDA_REV']).astype(int) / 10**9

# Separación de características y objetivo
logging.info('Separating features and target...')
visits_objective = visits_features.pop('FECHA_SALIDA_REV')

# Codificación de características categóricas
logging.info('Encoding categorical features...')
visits_features_transf = pd.get_dummies(visits_features, columns=['ID_ACCION'])

# Normalización de características numéricas
logging.info('Normalizing numerical features...')
scaler = StandardScaler()
visits_features_transf_fit = scaler.fit_transform(visits_features_transf)

# Definición del modelo
logging.info('Defining model...')
input_shape = [170]
model = tf.keras.Sequential([
    layers.Dense(512, input_shape = input_shape),
    layers.Dense(512, activation='relu'),
    layers.Dense(512, activation='relu'),
    layers.Dense(512, activation='relu'),
    layers.Dense(1)
])

# Compilación del modelo
logging.info('Compiling model...')
model.compile(optimizer='adam', loss='mae')

# Entrenamiento del modelo
logging.info('Training model...')
out = model.fit(visits_features_transf_fit, visits_objective, batch_size=256, epochs=100)

# Análisis del SGD: Gráfica de pérdidas
logging.info('Plotting loss graph...')
history_df = pd.DataFrame(out.history)
history_df.loc[5:, ['loss']].plot();

# Predicciones
logging.info('Making predictions...')
predictions = model.predict(visits_features_transf)
for i in range(len(predictions)):
        a = predictions[i][0]
        b = visits_features_transf.iloc[i]

        difference = a - b
        difference_in_minutes = difference.total_seconds() / 60
        logging.info(f"Prediction: {a}, Actual: {b}, Difference: {difference_in_minutes} minutos")


#!/usr/bin/env python

# wymagana funkcjonalnosc:
#
# listowanie wszystkich opchains wybranego modelu
# listowanie wszystkich sukcesji wybranego modelu
# wypisanie drzewa generalizacji opchains w wybranym modelu
#

from lxml import etree, objectify

class Model(object):
    def __init__(self, path):
        self.path = path
        try:
            f = open(self.path, 'r')
            self.content = f.read()
            self.model = objectify.fromstring(self.content)
            f.close()
        except Exception:
            print('Error while reading model')

    def get_successions(self):
        try:
            for Succession in self.model.Model.SuccessionList.Succession:
                yield Succession
        except AttributeError:
            print('There are no Successions in the model')

    def print_successions(self):
        try:
            for Succession in self.model.Model.SuccessionList.Succession:
                print('{} -> {}'.format(Succession.Predecessor, Succession.Successor))
        except AttributeError:
            print('There are no Successions in the model')

    def get_opchains(self):
        try:
            for OPCHAIN in self.model.Model.OpchainList.OPCHAIN:
                yield OPCHAIN
        except AttributeError:
            print('There are no OPCHAINs in the model')

    def print_opchain_short(self, OPCHAIN, prefix=''):
        print('{}{}: {}'.format(prefix, OPCHAIN.Id, OPCHAIN.Name))

    def print_tree_0(self):
        try:
            for OPCHAIN in self.model.Model.OpchainList.OPCHAIN:
                if(OPCHAIN.GeneralizationId == 0):
                    self.print_tree(OPCHAIN, '')
        except AttributeError:
            print('There are no OPCHAINs in the model')

    def print_opchain(self, id_):
        try:
            OPCHAIN = self.model.xpath('//OPCHAIN[Id={}]'.format(id_))[0]
            print('''
OPCHAIN-{}: {}:
Id: \t{}
GenId: \t{}
Name: \t{}
URL: \t{}

Description:
{}
--
'''.format(OPCHAIN.Id, OPCHAIN.Name, OPCHAIN.Id, OPCHAIN.GeneralizationId, OPCHAIN.Name, OPCHAIN.URL, OPCHAIN.Description))
        except IndexError:
            print('Not found')
            raise IndexError

    def print_tree(self, parent, prefix):
        self.print_opchain_short(parent, prefix)
        for OPCHAIN in self.model.Model.OpchainList.OPCHAIN:
            if(OPCHAIN.GeneralizationId == parent.Id):
                self.print_tree(OPCHAIN, prefix+' ')

    def get_last(self):
        try:
            s = sorted(self.model.Model.OpchainList.OPCHAIN, key=lambda x: x.Id, reverse=True)
            return s[0]
        except AttributeError:
            print('Model is empty')
            return None

    def print_last(self):
        try:
            s = sorted(self.model.Model.OpchainList.OPCHAIN, key=lambda x: x.Id, reverse=True)
            print(s[0].Id)
        except AttributeError:
            print('Model is empty')
            return None

    def append_opchain(self, OPCHAIN):
        self.model.Model.OpchainList.append(OPCHAIN)

    def append_succession(self, Succession):
        try:
            for s in self.model.Model.SuccessionList.Succession:
                if((s.Successor == Succession.Successor) and (s.Predecessor == Successor.Predecessor)):
                    print('Already there')
                    raise AttributeError
        except Exception:
            pass

        self.model.Model.SuccessionList.append(Succession)

    def remove_opchain(self, id_):
        #print('//OPCHAIN[Id={}]'.format(id_))
        try:
            bad = self.model.xpath('//OPCHAIN[Id={}]'.format(id_))[0]
            bad.getparent().remove(bad)
        except IndexError:
            print('Not found')
            raise IndexError

    def remove_succession(self, pid, sid):
        try:
            bad = self.model.xpath('//Succession[Predecessor={} and Successor={}]'.format(pid, sid))[0]
            bad.getparent().remove(bad)
            print('Removed')
        except AttributeError:
            print('There are no Successions in the model')

    def commit(self):
        f = open(self.path, 'wb')
        f.write(etree.tostring(self.model, pretty_print = True))
        f.close()


import numpy as np
from functools import partial
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_array, check_is_fitted
from sklearn.preprocessing import OneHotEncoder

class GELMClassifier(BaseEstimator, ClassifierMixin):
    '''
    Discriminative graph regularized Extreme Learning Machine (GELM) classifier.
    Implemented based on Yong Peng et al.'s proposed model [1].

    [1] Y. Peng, S. Wang, X. Long, and B. L. Lu, “Discriminative graph regularized
    extreme learning machine and its application to face recognition,” Neurocomputing,
    vol. 149, no. Part A, pp. 340-353, Feb. 2015, doi: 10.1016/J.NEUCOM.2013.12.065.

    Parameters
    ----------
    n_hidden: int or 'auto', default='auto'
        If int, the number of hidden nodes. If 'auto', set number of hidden nodes
        as ten times the size of numbe of features. Any value other than integers
        will be treated as 'auto'.

    activation: str, default='leakyrelu'
        Options are 'sigmoid', 'tanh', 'relu' and 'leakyReLU', case-insensitive.
        When using leakyReLU, "magnitude" parameter must be defined.

    magnitude: float, default=0.1
        The slope magnitude for leakyReLU activation function.
    '''

    def sigmoid(self, x):
        return 1/(1+np.exp(-x))

    def tanh(self, x):
        return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))

    def relu(self, x):
        return np.maximum(0.0, x)

    def leakyReLU(self, x, magnitude=0.1):
        return np.maximum(magnitude*x, x)

    def __init__(self, n_hidden='auto', l1=2**10, l2=2**-5, activation='leakyrelu',
                 magnitude=0.1, random_state=None):
        self.n_hidden = n_hidden
        self.l1 = l1
        self.l2 = l2
        self.activation = activation
        self.magnitude = magnitude
        self.random_state = random_state

        self._activation_funcs = {
            'sigmoid': self.sigmoid,
            'tanh': self.tanh,
            'relu': self.relu,
            'leakyrelu': partial(self.leakyReLU, magnitude=self.magnitude)
        }
        self.activation_func_ = self._activation_funcs[activation.lower()]

    def hidden_nodes(self, X):
        '''
        One forward pass to obtain hidden nodes outputs.

        Parameters
        ----------
        X : ndarray of shape (N, d)
            The input array. Here, N is the number of instances, and d is the number
            of features.

        Returns
        -------
        H : ndarray of shape (K, N)
            The hidden nodes output, where K is the number of hidden nodes.
        '''
        G = np.dot(self.w_, np.transpose(X))
        G = G + self.b_[:,np.newaxis]
        H = self.activation_func_(G)
        return H

    def laplacian(self, y):
        '''
        Compute graph laplacian from labels y.

        Parameters
        ----------
        y : ndarray of shape (N,)
            The labels for X, where N is the number of instances.

        Returns
        -------
        L : ndarray of shape (N, N)
            The graph laplacian, where N is the number of instances.
        '''
        y_ = y[np.newaxis]
        W = np.zeros([len(y), len(y)])
        for c in np.unique(y):
            y_c = y_ == c
            W += np.dot(np.transpose(y_c), y_c)/np.sum(y_c)
        D = np.diag(np.sum(W, axis=1))
        return D-W

    def fit(self, X, y):
        '''
        Fit the GELM given the training data.

        Parameters
        ----------
        X : ndarray of shape (N, d)
            The input array. Here, N is the number of instances, and d is the number
            of features.
        y : ndarray of shape (N,)
            The labels for X, where N is the number of instances.

        Returns
        -------
        self
            Fitted estimator.
        '''
        # Check that X and y have correct shape
        X, y = check_X_y(X, y)
        self.onehotenc_ = OneHotEncoder()
        self.n_features_in_ = X.shape[1]
        self.n_classes_ = np.unique(y).shape[0]

        self.k_ = self.n_hidden if type(self.n_hidden) == int else 10*self.n_features_in_
        self.w_ = np.random.default_rng(seed=self.random_state)\
                    .normal(size=[self.k_, self.n_features_in_])
        self.b_ = np.random.default_rng(seed=self.random_state).normal(size=[self.k_])
        H = self.hidden_nodes(X)

        # compute graph Laplacian
        L = self.laplacian(y)

        # compute beta using GEML's regularization term (equation 14 in [1])
        T = self.onehotenc_.fit_transform(y.reshape(-1, 1)).toarray().transpose()
        HHT = np.dot(H, H.transpose())
        HLHT = np.linalg.multi_dot([H, L, H.transpose()])
        I = np.diag([1]*H.shape[0])
        self.beta_ = np.linalg.multi_dot([np.linalg.inv(HHT + self.l1*HLHT + self.l2*I),
                                          H, T.transpose()])

        return self

    def predict(self, X):
        '''
        Predict class labels for samples in X.

        Parameters
        ----------
        X : ndarray of shape (N, d)
            The input array. Here, N is the number of instances, and d is the number
            of features.

        Returns
        -------
        y_pred : ndarray of shape (N,)
            Vector containing the class labels for each sample.
        '''
        # Check if fit has been called
        check_is_fitted(self)

        # Input validation
        X = check_array(X)

        TT = np.dot(self.beta_.transpose(), self.hidden_nodes(X)).transpose()
        return np.squeeze(self.onehotenc_.inverse_transform(TT))


#!/usr/bin/env python

# Verbose, notice, and spam log levels for Python's logging module.
#
# Author: Peter Odding <peter@peterodding.com>
# Last Change: March 7, 2017
# URL: https://verboselogs.readthedocs.io

"""Setup script for the `verboselogs` package."""

# Standard library modules.
import codecs
import os
import re

# De-facto standard solution for Python packaging.
from setuptools import find_packages, setup

def get_contents(*args):
    """Get the contents of a file relative to the source distribution directory."""
    with codecs.open(get_absolute_path(*args), 'r', 'UTF-8') as handle:
        return handle.read()

def get_version(*args):
    """Extract the version number from a Python module."""
    contents = get_contents(*args)
    metadata = dict(re.findall('__([a-z]+)__ = [\'"]([^\'"]+)', contents))
    return metadata['version']

def get_absolute_path(*args):
    """Transform relative pathnames into absolute pathnames."""
    return os.path.join(os.path.dirname(os.path.abspath(__file__)), *args)

setup(
    name='verboselogs',
    version=get_version('verboselogs', '__init__.py'),
    description="Verbose logging level for Python's logging module",
    long_description=get_contents('README.rst'),
    url='https://verboselogs.readthedocs.io',
    author='Peter Odding',
    author_email='peter@peterodding.com',
    packages=find_packages(),
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Intended Audience :: Information Technology',
        'Intended Audience :: System Administrators',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: Implementation :: CPython',
        'Programming Language :: Python :: Implementation :: PyPy',
        'Topic :: Software Development',
        'Topic :: Software Development :: Libraries',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'Topic :: System',
        'Topic :: System :: Logging',
        'Topic :: System :: Systems Administration',
        'Topic :: Terminals',
    ])


import os

import requests
from django.contrib import messages
from django.shortcuts import render, redirect

from order.models import Indent, IndentInventory
from user.models import Address
from .forms import storeForm, dishForm
from .models import Canteen, Store, Dish
from user.models import Manager

# Create your views here.

# 新增商铺
# def is_add_store(request):
#     if request.POST.get('add_store') is not None:
#         print('add_store')
#         return True
#     return False
# 整理菜品列表并输出
def get_order_dish_list(order_id):
    dish_list_ = None
    # 获取订单明细
    if order_id is not None:
        order = Indent.objects.get(indent_id=order_id)
        dish_list_ = IndentInventory.objects.filter(indent=order.indent_id)
        # 整理数据，方便输出
        dish_list = []
        for i in dish_list_:
            dish = {}
            dish['dish_price'] = i.dish.dish_price
            dish['dish_name'] = i.dish.dish_name
            dish['dish_num'] = i.dish_num
            dish_list.append(dish)
        return dish_list
    return None

# 整理菜品列表并输出
def get_dish_list(order_id):
    dish_list_ =None
    # 获取订单明细
    if order_id is not None:
        order = Indent.objects.get(indent_id=order_id)
        dish_list_ = IndentInventory.objects.filter(indent=order.indent_id)
    # 整理数据，方便输出
    dish_list = []
    for i in Dish.objects.all():
        dish = {}
        dish['dish_price'] = i.dish_price
        dish['dish_describe'] = i.dish_describe
        dish['dish_id'] = i.dish_id
        dish['store_id'] = i.store_id.store_id
        dish['dish_name'] = i.dish_name
        dish['dish_image'] = i.dish_image
        dish['get_order_url_add'] = i.get_order_url_add()
        dish['get_order_url_sub'] = i.get_order_url_sub()
        dish['dish_num'] = 0
        if dish_list_ is not None:
            try:
                cur_dish = dish_list_.get(dish_id=i.dish_id)
                dish['dish_num'] = cur_dish.dish_num
            except:
                dish['dish_num'] = 0
        dish_list.append(dish)
    return dish_list

def show_canteen(request):
    # 是否更改状态（只有食堂管理员能更改）
    canteen_id = request.POST.get('canteen_id')     # 选中的食堂
    # 是否更改状态
    if canteen_id is not None:
        user = Manager.objects.get(manager_label=1, manager_id=request.session.get('user_id'))
        # 用户管理的食堂
        canteen = user.manager_canteen
        # 用户只能修改自己管理的食堂
        if int(canteen_id) == canteen.canteen_id:
            pre_state = canteen.canteen_state   # 之前状态
            canteen.canteen_state = '营业中' if pre_state == '休息中' else '休息中'
            canteen.save()
        else:
            messages.warning(request,'管理员只能修改自己管理的食堂！')

    context = {
            'canteen_list': Canteen.objects.all(),
    }
    return render(request, 'canteen/canteen_list.html', context)

def show_store(request):
    # same_name_store = Store.objects.filter(store_name='猪肚鸡')
    # if len(same_name_store)==0:
    #     store = Store(canteen_id=Canteen.objects.get(canteen_id=9), store_name='猪肚鸡',
    #                   store_describe='猪肚包鸡，是一道广东省传统的地方名菜，属于客家菜系，又名猪肚煲鸡、凤凰投胎，流行于广东的深圳、惠州、河源、梅州等粤东一带，是广东客家地区酒席必备的餐前用汤，汤里浓中带清，有浓郁的药材味和胡椒香气。最早是客家女人坐月子时吃的一道菜肴。',
    #                   store_image='D:\hgs-3-1\DB\lab\DB4\img\猪肚鸡店铺.webp', store_state=1)
    #     store.save()
    #     dish = Dish(dish_name='柠檬猪肚鸡', dish_price=16, dish_image='../../../img/柠檬猪肚鸡_malpson.webp', dish_describe='经济实惠',
    #          dish_state=1)
    #     dish.save()
    #     store.dishes.add(dish)
    #     store.save()
    order_show, order = show_cur_order(request)
    # if is_add_store(request):
    #     print('is add')
    #     return redirect('/add_store/')
    context = {
        'canteen_list': Canteen.objects.all(),
        'store_list': Store.objects.all(),
        'order_show':order_show,
        'order':order,
        'order_state':['未下单','已下单','已发货','已送达','已评价'],
        'dish_list_':get_order_dish_list(request.session.get('order_id'))
    }
    # print(Canteen.objects.all()[0].canteen_id)
    # print(Store.objects.all()[0].canteen_id)
    # print(type(Canteen.objects.all()[0].canteen_id))
    # print(type(Store.objects.all()[0].canteen_id.canteen_id))
    # print(Canteen.objects.all()[0].canteen_id==Store.objects.all()[0].canteen_id)
    # print(Store.objects.all()[0].store_image)
    return render(request, 'canteen/store_list.html', context)

def show_dish(request):
    # dish_list = Dish.objects.all()
    # dishes = []
    # for item in dish_list:
    #     dishes.append()
    order_show, order = show_cur_order(request)
    context = {
        'canteen_list':Canteen.objects.all(),
        'store_list': Store.objects.all(),
        'dish_list': get_dish_list(request.session.get('order_id')),
        'order_show':order_show,
        'order':order,
        'order_state':['未下单','已下单','已发货','已送达','已评价'],
        'dish_list_':get_order_dish_list(request.session.get('order_id')),
    }
    if request.method == 'POST':
        dish_name = request.POST.get('dish_name')
        if dish_name is not None:
            try:
                dish = Dish.objects.get(dish_name=dish_name)
                return redirect('/dish/#{}'.format(dish.dish_id))
            except:
                # context['messages']=["该菜品不存在",]
                # return redirect('/dish/#{}'.format(context['dish_list'][0]['dish_id']))
                return redirect('/dish/')
    # print(Dish.objects.all()[0].dish_id)
    print(Store.objects.all())
    # print(dish_list_[0]['dish_id'])
    return render(request,'canteen/dish_list.html', context)

def show_cur_order(request):
    order_show = False
    order = None
    order_id = request.session.get('order_id')
    # dish_list = None
    # 每个菜品数量
    # if order_id is not None:
    #     order = Indent.objects.get(indent_id=order_id)
    #     dish_list = IndentInventory.objects.filter(indent=order.indent_id)

    # 能否获取到地址，能获取到则为下单
    order_address = request.POST.get('select_address')
    if order_address is not None:
        print('selected order_address:', order_address)
        order = Indent.objects.get(indent_id=order_id)
        order.indent_address = Address.objects.get(address_id=int(order_address))
        order.save()
        # 每道菜的数量设未0
        # for i in order.dishes.all():
        #     i.dish_order_num = 0
        #     i.save()
        # for i in dish_list:
        #     i.dish_num = 0
        #     i.save()
        order.indent_state='已下单'
        order.save()
        del request.session['order_id']
        messages.success(request,'下单成功！')
        return False, None

    show = request.POST.get('show')
    # 是否展示订单
    if show is not None:
        order_show = True
    else:
        if request.POST.get('close'):
            order_show = False
    if order_show:
        if not request.session.get('is_login', None) or request.session.get('label') != 0:
            messages.warning(request, "请先登录顾客账户~")
            return False, None
        if not request.session.get('order_id', None):
            messages.warning(request, "暂无订单~")
            return False, None
        order_id = request.session['order_id']
        order = Indent.objects.get(indent_id=order_id)
    return order_show, order

def del_store(request, store_id):
    print('del store:store_id:',store_id)
    Store.objects.get(store_id=store_id).delete()
    return redirect('/store/')

def update_store(request, store_id):
    print('update store:store_id:', store_id)
    print('user_id:',(request.session['user_id']))
    # 如果是商家，则只能修改自己的
    if request.session['label'] == 1:
        try:
            user = Manager.objects.get(manager_label=0,manager_id=request.session['user_id'])
            # print(type(user.manager_store.store_id))
            if user.manager_store.store_id != int(store_id):
                messages.warning(request, '商铺只允许被所属商家或食堂管理员修改！')
                return redirect('/store/')
        except:
            messages.warning(request, '商铺只允许被所属商家或食堂管理员修改！')
            return redirect('/store/')
    request.session['update_store_id'] = store_id
    return redirect('/add_store/')

def add_store(request):
    print('add_store')
    print(request.method)
    update_store_id = request.session.get('update_store_id')

    print('update_store_id:',update_store_id)
    # 判断是更新还是新增
    if update_store_id is not None:
        store = Store.objects.get(store_id=update_store_id)
        store_form = storeForm({
            'store_name':store.store_name,
            'store_des' :store.store_describe,
            'store_state' :store.store_state,
            'store_image' : store.store_image,
            # 'manager_name' = None,
        })
    else:
        store_form = storeForm()
    if request.method == "POST":
        store_form = storeForm(request.POST, request.FILES)    # 将表单用一个类封装起来 # request.POST返回一个字典，get是字典的内置方法
        message = '请检查填写内容！'
        print('store_form valid',store_form.is_valid())
        if store_form.is_valid():
            try:
                # 设置管理商铺的商家

                business = Manager.objects.get(manager_label=0,manager_name=store_form.cleaned_data.get('manager_name'))

            except:
                messages.warning(request,"商家不存在！")
                return render(request, 'canteen/add_store.html', locals())
            # 商铺属性
            name = store_form.cleaned_data.get('store_name')
            des = store_form.cleaned_data.get('store_des')
            image = store_form.cleaned_data.get('store_image')
            state = store_form.cleaned_data.get('store_state')
            # 创建商铺
            print(request.session['user_id'])
            # 是否为新建商铺
            if update_store_id is None:
                store = Store(canteen_id=Manager.objects.get(manager_label=1, manager_id=request.session['user_id']).manager_canteen,)

            store.store_name=name
            store.store_image=image
            store.store_state=state
            store.store_describe=des
            store.save()
            # 商铺与商家绑定
            if update_store_id is None:
                business.manager_store = store
                business.save()
            else:
                del request.session['update_store_id']

            return redirect('/store/')
    return render(request,'canteen/add_store.html',locals())

# 添加或修改菜品，store为要菜品对应的商铺
def add_dish(request, store_id):
    print('add_dish')
    print(request.method)
    update_dish_id = request.session.get('update_dish_id')

    print('update_dish_id:',update_dish_id)
    # 判断是更新还是新增
    if update_dish_id is not None:
        dish = Dish.objects.get(dish_id=update_dish_id)
        dish_form = dishForm({
            'dish_name':dish.dish_name,
            'dish_des' :dish.dish_describe,
            'dish_state' :dish.dish_state,
            'dish_image' : dish.dish_image,
            'dish_price' : dish.dish_price,
        })
    else:
        dish_form = dishForm()
    if request.method == "POST":
        dish_form = dishForm(request.POST, request.FILES)    # 将表单用一个类封装起来 # request.POST返回一个字典，get是字典的内置方法
        message = '请检查填写内容！'
        print('dish_form valid',dish_form.is_valid())
        if dish_form.is_valid():
            # 对应商铺
            print('store_id:',store_id)
            store = Store.objects.get(store_id=store_id)

            # 菜品属性
            name = dish_form.cleaned_data.get('dish_name')
            des = dish_form.cleaned_data.get('dish_des')
            image = dish_form.cleaned_data.get('dish_image')
            state = dish_form.cleaned_data.get('dish_state')
            price = dish_form.cleaned_data.get('dish_price')
            # 创建商铺
            print(request.session['user_id'])
            print('update_dish_id:',update_dish_id)
            # 是否为新建商铺
            if update_dish_id is None:
                dish = Dish(store_id=Store.objects.get(store_id=store_id))

            dish.dish_name=name
            dish.dish_image=image
            dish.dish_state=state
            dish.dish_describe=des
            dish.dish_price = price
            dish.save()
            if update_dish_id is not None:
                del request.session['update_dish_id']

            return redirect('/dish/')

    return render(request,'canteen/add_dish.html',locals())

def del_dish(request, dish_id):
    print('del dish:dish_id:',dish_id)
    dish = Dish.objects.get(dish_id=dish_id)
    # 如果是商家，则只能删除自己的
    if request.session['label'] == 1:
        try:
            user = Manager.objects.get(manager_label=0, manager_id=request.session['user_id'])
            if user.manager_store.store_id != dish.store_id.store_id:
                messages.warning(request, '菜品只允许被所属商家或食堂管理员删除！')
                return redirect('/dish/')
        except:
            messages.warning(request, '商铺只允许被所属商家或食堂管理员删除！')
            return redirect('/dish/')
    dish.delete()
    return redirect('/dish/')

def update_dish(request, dish_id):
    print('update dish:dish_id:', dish_id)
    print('user_id:',(request.session['user_id']))
    dish = Dish.objects.get(dish_id=dish_id)
    # 如果是商家，则只能修改自己的
    if request.session['label'] == 1:
        try:
            user = Manager.objects.get(manager_label=0,manager_id=request.session['user_id'])
            if user.manager_store.store_id != dish.store_id.store_id:
                messages.warning(request, '菜品只允许被所属商家或食堂管理员修改！')
                return redirect('/dish/')
        except:
            messages.warning(request, '菜品只允许被所属商家或食堂管理员修改！')
            return redirect('/dish/')
    request.session['update_dish_id'] = dish_id
    return redirect('/add_dish/{}'.format(dish.store_id.store_id))


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

import requests
from bs4 import BeautifulSoup
import re,json
import geopy
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter

locator = Nominatim(user_agent="myGeocoder")

def getAddress(lat,lng):
	coordinates = lat+","+lng
	location = locator.reverse(coordinates)
	return location

def extractPrice(text):
	textlst = re.findall(r'\d+', text)
	if len(textlst)==3:
		return textlst[0]+textlst[1]
	elif len(textlst)==2:
		return textlst[0]
	elif len(textlst)==1:
		raise Exception("Anomile Price Value Please Check")
	else:
		return text

def scrapDetail(soup):
	title = soup.find("div",class_="property__header-block").find("h1").text.strip()

	address = "NA"
	bedCount = "NA"
	latitude = "NA"
	longitude = "NA"
	city="NA"
	zipcode = "NA"
	rent = "NA"
	imgLst = []

	furnished,parking,balcony, = False,False,False

	add = soup.find("div",class_="property__header-block__adress__street")
	if add:
		address = add.text.strip()
	#==================================================================================================

	img_urls = soup.find("div",class_="prop-pictures").findAll("a")
	for img in img_urls:
		imgLst.append("https://www.rtvastgoed.be"+img["href"])

	#==================================================================================================
	description = soup.find("div",class_="property__details__block__description").text.strip()
	#==================================================================================================

	financial_table = soup.find("table",class_="financial detail-fields property__details__block__table")
	if financial_table:
		if "prijs" in financial_table.find("tr",class_="even").text.strip().lower():
			rent = extractPrice(financial_table.find("tr",class_="even").find("td",class_="value").text)
	#==================================================================================================

	building_det=soup.find("table",class_="construction property__details__block__table")
	if building_det:
		if "aantal slaapkamers" in building_det.text:
			bedCount = building_det.find("tr",class_="odd").find("td",class_="value").text.strip()
	#==================================================================================================

	if "ingericht" in soup.text.lower():
		furnished = True
	if "garage" in soup.text.lower() or "parking" in soup.text.lower():
		parking = True
	#==================================================================================================

	if soup.find("div",class_="gmap",id="pand-map"):
		latitude = soup.find("div",class_="gmap",id="pand-map")["data-geolat"]
		longitude = soup.find("div",class_="gmap",id="pand-map")["data-geolong"]

		location = getAddress(latitude,longitude)
		if address == "NA":
			address = location.address
		if zipcode == "NA":
			zipcode = location.raw["address"]["postcode"]
		if city == "NA":
			city=location.raw["address"]["city_district"]

	#==================================================================================================
	if address != "NA" and latitude == "NA":
		raise Exception("Latitude and longitude Missing")

	dic = {
		"title":title,
		"description":description,
		"address":address,
		"rent":rent,
		"room_count":bedCount,
		"images":imgLst,
		"city":city,
		"furnished":furnished,
		"balcony":balcony,
		"latitude":latitude,
		"longitude":longitude,
		"zipcode":zipcode,
		"parking":parking,
		"position":"NA",
		"external_images_count":len(imgLst),
		"landlord_name":"RT VERHUUR",
		"landlord_phone":"+32 11 69 76 40",
		"landlord_email":"verhuur@rtvastgoed.be"
	}

	return dic

def getPropertyDetails(url):

	count = 0
	while  count < 5:
		try:
			response = requests.get(url,timeout=30)
			count = 5
		except Exception as e:
			print (e)
		count +=1

	soup = BeautifulSoup(response.content,"html.parser")

	listProperty = []
	for section in soup.findAll("section"):
		proptyList = section.find("div",class_="row").findAll("div",class_="row")

		for index,propty in enumerate(proptyList):
			print (index)
			extrnlurl="https://www.rtvastgoed.be"+propty.find("a",class_="spotlight__content__moreinfo link")["href"]

			count = 0
			while  count < 5:
				try:
					response = requests.get(extrnlurl,timeout=30)
					count = 5
				except Exception as e:
					print (e)
				count +=1

			soup = BeautifulSoup(response.content,"html.parser")

			details_dic = scrapDetail(soup)

			details_dic.update({"property_type":section.find("h2").text.strip(),
				"external_link":extrnlurl,
				"external_source":"rtvastgoed.be"})

			listProperty.append(details_dic)

	return listProperty

url = "https://www.rtvastgoed.be/nl/te-huur/"
data = json.dumps(getPropertyDetails(url))

with open('rtvastgoed.json','w') as f:
    f.write(data)


from django.shortcuts import render,redirect
from django.http import HttpResponse
from datetime import datetime
from django.template import Template, Context, loader
from inicio.models import Perro
from inicio.form import CrearPerroFormulario, BuscarPerroFormulario, ModificarPerroFormulario
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView

def prueba(request):
    segundos = datetime.now().second
    diccionario = {
    "mensaje": "alilililili",
    "segundos": segundos,
    "segundo_par" : segundos%2 == 0,
    "segundo_redondo": segundos%10 == 0,
    "listado_de_numeros" : list(range(25))
    }
    return render(request,"inicio/prueba.html",diccionario)

def segunda_vista(request):
    return HttpResponse("
soy la segunda vista
")

def inicio(request):
    return render(request,"inicio/inicio.html")

def fecha_actual(request):
    fecha = datetime.now()
    return HttpResponse(f"la fecha es: {fecha}")

def saludo(request):
    return HttpResponse("hola")

def bienvenida(request, nombre, apellido):
    return HttpResponse(f"bienvenido {nombre} {apellido}!!!")
"""v1 crear perro
def crear_perro(request, nombre, edad):
    perro = Perro(nombre=nombre,edad=edad)
    perro.save()
    diccionario = {
        "perro":perro,
    }
    return render(request,"inicio/crear_perro.html",diccionario)
"""
"""
#v2 crear perro
def crear_perro(request):

    if request.method == "POST":
        formulario = CrearPerroFormulario(request.POST)
        if formulario.is_valid():
            info = formulario.cleaned_data
            perro = Perro(nombre=info["nombre"],edad=info["edad"])
            perro.save()
            return redirect("inicio:listar_perro")
        else:
            return render(request,"inicio/crear_perro.html",{"formulario": formulario})

    formulario = CrearPerroFormulario()
    return render(request,"inicio/crear_perro.html",{"formulario": formulario})

def listar_perro(request):
    request.GET
    formulario = BuscarPerroFormulario(request.GET)
    if formulario.is_valid():
        nombre_a_buscar = formulario.cleaned_data["nombre"]
        listado_de_perro  = Perro.objects.filter(nombre__icontains = nombre_a_buscar)

    formulario = BuscarPerroFormulario()
    return render(request,"inicio/listar_perro.html",{"formulario": formulario, "perros" : listado_de_perro})

def eliminar_perro(request, perro_id):
    perro = Perro.objects.get(id=perro_id)
    perro.delete()
    return redirect("inicio:listar_perro")

def modificar_perro(request, perro_id):
    perro_a_modificar = Perro.objects.get(id=perro_id)

    if request.method == "POST":
        formulario = ModificarPerroFormulario(request.POST)
        if formulario.is_valid():
            info = formulario.cleaned_data
            perro_a_modificar.nombre = info["nombre"]
            perro_a_modificar.edad = info["edad"]
            perro_a_modificar.save()
            return redirect("inicio:listar_perro")
        else:
            return render(request,"inicio/modificar_perro.html",{"formulario":formulario})

    formulario = ModificarPerroFormulario(initial={"nombre":perro_a_modificar.nombre, "edad":perro_a_modificar.edad})
    return render(request,"inicio/modificar_perro.html",{"formulario":formulario})

"""
class CrearPerro(CreateView):
    model = Perro
    template_name = "inicio/CBV/crear_perro_CBV.html"
    fields =["nombre","edad","descripcion"]
    success_url = reverse_lazy("inicio:listar_perros")

class ListarPerros(ListView):
    model = Perro
    template_name = "inicio/CBV/listar_perros_CBV.html"
    context_object_name = "perros"

class  ModificarPerro(UpdateView):
    model =  Perro
    template_name = "inicio/CBV/modificar_perro_CBV.html"
    fields =["nombre","edad","descripcion"]
    success_url = reverse_lazy("inicio:listar_perros")

class EliminarPerro(DeleteView):
    model = Perro
    template_name = "inicio/CBV/eliminar_perro_CBV.html"
    success_url = reverse_lazy("inicio:listar_perros")

class MostrarPerro(DetailView):
    model = Perro
    template_name ="inicio/CBV/mostrar_perro_CBV.html"


from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def get_browser(browser_name="Chrome"):

    # if browser_name == "Chrome":
    chrome_options = Options()
    chrome_options.add_argument('--disable-extensions --disable-extensions-file-access-check --disable-extensions-http-throttling')

    return webdriver.Chrome(
        executable_path='C:\\pyprojects\gordonso_test\gordonso\\resources\\drivers\\chromedriver.exe',
        chrome_options=chrome_options
    )


#coding=utf-8
import unittest

from appium import webdriver

class Login( unittest.TestCase ):

    def test_login(self):
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = '4.4.4'
        desired_caps['deviceName'] = '79KR8PU8SOLV79B6'
        desired_caps['appPackage'] = 'cn.zhimawu'
        desired_caps['appActivity'] = 'cn.zhimawu.SplashActivity'
        self.driver = webdriver.Remote( 'http://localhost:4723/wd/hub', desired_caps )

        self.driver.implicitly_wait( 10000 )

        self.driver.find_element_by_id("cn.zhimawu:id/login").click()
        self.driver.find_element_by_id("cn.zhimawu:id/editPhone").send_keys("18600105776")
        self.driver.find_element_by_id("cn.zhimawu:id/edit_pwd").send_keys("111111qq")
        self.driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.Button").click()

        self.driver.implicitly_wait( 10000 )

if __name__ == '__main__':
    login=Login()
    login.test_login()


from flask import Flask
from flask_mysqldb import MySQL, MySQLdb

app = Flask(__name__)

app.secret_key = 'rbvgjkihhofesdeplvzrqrtlefnlquze'
# database connection details
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'admin'
app.config['MYSQL_DB'] = 'ECOLION'
# Intialize MySQL
mysql = MySQL(app)

# Executes input function on a cursor called on the query input, and returns the result of the function
def execute(query, args=(), cursor_access=lambda cursor: None):
    cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)  # type:ignore
    if type(args) is not tuple:
        args = (args,)
    cursor.execute(query, args)
    return_value = cursor_access(cursor)
    cursor.close()
    return return_value

def dbfetch(query, args=(), one=False):
    def fetch_data(cursor):
        if one:
            return cursor.fetchone()
        return cursor.fetchall()

    return execute(query, args, cursor_access=fetch_data)

def dbcommit(query, args=()):
    result = execute(query, args)
    try:
        mysql.connection.commit()  # type:ignore
    except Exception as e:
        print("MySQL Error", e)
    return result


import matplotlib
matplotlib.use('Agg')
import numpy as np
import pandas as pd
from pylab import *
from scipy.stats import norm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

# read data from a text file. One number per line

def bii_hist(code,hdat,hstr):

    if hstr=="Innovation Index Score":
        file_name = "hist_score"
        col = 'green'
    else:
        file_name = "hist_cz"
        col = 'yellow'

    if len(code) == 2 and not isinstance(code, basestring):
        code = code[0] + " " + code[1]

    datos=hdat
    plt.figure()

    # best fit of data
    (mu, sigma) = norm.fit(datos)
    no_bins = 10
    if len(set(hdat)) < 20:
        no_bins = len(set(hdat))

    # the histogram of the data
    n, bins, patches = plt.hist(datos.values, no_bins, facecolor=col, alpha=0.75,label='Counts')

    height = n.max()

        # add a 'best fit' line
    y = mlab.normpdf( bins, mu, sigma)
    l = plt.plot(bins, y*height, 'r--', linewidth=1,label='Distribution')

    #plot

    plt.title(r'$\mathrm{Workgroup \ Result \ Statistics \ :}\ \mu=%.3f,\ \sigma=%.3f$' %(mu, sigma),fontsize=18,y=-0.29)
    plt.ylabel('Counts',fontsize=12)
    plt.xlabel(hstr)
    tit = plt.suptitle('Histogram of ' + hstr + ' ' + code, fontsize=14, fontweight='bold', y=1.05)
    plt.grid(True)
    plt.plot((mu, mu), (0, height), 'b',linewidth=2,label='Average')
    lgd = plt.legend(loc='upper center', shadow=True, fontsize='x-large',bbox_to_anchor=(1.2, 1),borderaxespad=0.)

    path_name = "static/%s" %file_name
    plt.tight_layout()
    plt.savefig(path_name, bbox_extra_artists=(lgd,tit,), bbox_inches='tight')


import modules.algact

def creDict():
    dictFile=modules.algact.adFile()
    dictFile=dictFile+'.txt'
    return dictFile

def wrFil(a,b):
    wr=a
    ndic=b
    fw=open(f'{ndic}', 'a+')#Añade al final de la línea
    fw.write(f'{wr}\n')
    fw.close


import json
from itertools import groupby
from operator import itemgetter
from pathlib import Path
from typing import List

from colorama import Fore

from model import FavorSchedule, MomotalkOutput, MomotalkContent
from utils import Localizer

def process_momotalk(resource_path: str | Path) -> List[MomotalkOutput]:
    raw_resource_path = Path(resource_path) if isinstance(resource_path, str) else resource_path
    raw_excel_path = raw_resource_path / "Excel"

    raw_academy_message_data = []
    localizer = Localizer(resource_path)

    academy_message_files = raw_excel_path.glob("AcademyMessanger[0-9]*ExcelTable.json")
    for file in academy_message_files:
        with open(file, encoding="utf8") as fd:
            raw_academy_message_data += json.load(fd)["DataList"]
    raw_academy_message_data = filter(itemgetter("CharacterId"), raw_academy_message_data)

    #  get_favor_schedule_titles
    with open(raw_excel_path / "AcademyFavorScheduleExcelTable.json", encoding="utf8") as fd:
        academy_favor_schedule_data = json.load(fd)["DataList"]
    academy_favor_schedule_data = filter(itemgetter("CharacterId"), academy_favor_schedule_data)

    chained = []
    momotalk_outputs = []
    character_ids = set()

    # 需要先排序，然后才能 groupby
    sorted_academy_message_data = sorted(raw_academy_message_data, key=itemgetter("CharacterId"))
    grouped_academy_message_data = groupby(sorted_academy_message_data, itemgetter("CharacterId"))
    for k, g in grouped_academy_message_data:
        character_ids.add(k)
        chained.append((k, list(g)))

    sorted_academy_favor_schedule_data = sorted(academy_favor_schedule_data, key=itemgetter("CharacterId"))
    grouped_academy_favor_schedule_data = groupby(sorted_academy_favor_schedule_data, itemgetter("CharacterId"))
    for k, g in grouped_academy_favor_schedule_data:
        if k in character_ids:
            chained.append((k, list(g)))
        else:
            print(f"{Fore.BLUE}Unmatched academy_favor_schedule_data: [character_id: {k}]{Fore.RESET}")

    sorted_chained = sorted(chained, key=lambda x: x[0])
    grouped_chained = groupby(sorted_chained, lambda x: x[0])
    for character_id, ((_, academy_messages), (_, favor_schedules)) in grouped_chained:
        print(f"processing momotalk: [character_id: {Fore.GREEN}{character_id}{Fore.RESET}]")
        momotalk_output = MomotalkOutput(CharacterId=character_id, translator='')
        for academy_message in academy_messages:
            momotalk_content = MomotalkContent(**academy_message)
            momotalk_output.content.append(momotalk_content)
        for favor_schedule in favor_schedules:
            favor_scenario = FavorSchedule(
                GroupId=favor_schedule["ScenarioSriptGroupId"],  # 棒子程序员拼错了，不需要把 Sript 改成 Script
                FavorScheduleId=favor_schedule["Id"],
                CharacterId=favor_schedule["CharacterId"],
                TextJp=localizer.localize(favor_schedule["LocalizeScenarioId"], "Jp"),
                TextCn=localizer.localize(favor_schedule["LocalizeScenarioId"], "Cn"),
                TextKr=localizer.localize(favor_schedule["LocalizeScenarioId"], "Kr"),
                TextEn=localizer.localize(favor_schedule["LocalizeScenarioId"], "En"),
                TextTh=localizer.localize(favor_schedule["LocalizeScenarioId"], "Th"),
                TextTw=localizer.localize(favor_schedule["LocalizeScenarioId"], "Tw"),
            )
            momotalk_output.title.append(favor_scenario)
        momotalk_outputs.append(momotalk_output)
    return momotalk_outputs


#!/usr/bin/env python
#  test3_kinesis_data_get.py

# https://aws.amazon.com/blogs/big-data/snakes-in-the-stream-feeding-and-eating-amazon-kinesis-streams-with-python/
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kinesis.html

import boto3
import pprint

kinesis = boto3.client('kinesis')

pp = pprint.PrettyPrinter(indent=4)

shard_list = kinesis.list_shards(StreamName="ExampleInputStream", MaxResults=4)
print("shards")
pp.pprint(shard_list)

if len(shard_list['Shards']) == 1:
    shard_id = shard_list['Shards'][0]['ShardId']
    shard_it = kinesis.get_shard_iterator(StreamName="ExampleInputStream",
                                          ShardId= shard_id, #'shardId-000000000000',
                                          #ShardId='shardId-000000000000',
                                          ShardIteratorType='TRIM_HORIZON')["ShardIterator"]
    loopcnt = 0
    last_ago = 0.0
    max_dif = 0.0
    while loopcnt < 4000:
        out = kinesis.get_records(ShardIterator=shard_it, Limit=2)
        shard_it = out["NextShardIterator"]
        retv_ago = out['MillisBehindLatest']
        retv_ago_sec, retv_ago_ms = int(retv_ago/1000), int(retv_ago % 1000)
        dif_ago = last_ago - retv_ago
        if dif_ago > max_dif: max_dif = dif_ago
        print("\n%s%s%s" % ( "Out for %d.%03d ago" % (retv_ago_sec, retv_ago_ms),
                             " %.2f hours diff %.2f sec max %.2f" % (
                                 retv_ago_sec / 3600.0, dif_ago, max_dif ),
                             " loopcnt %d" % loopcnt ))
        last_ago = retv_ago
        #pp.pprint(out)
        if len(out['Records']) < 1 and retv_ago_sec == 0 and retv_ago_ms == 0:
            break
        for x in out['Records']:
            pp.pprint(x)
        loopcnt += 1