import matplotlib.pyplot as plt
import math
import shapely.ops as ops
from shapely.geometry import LineString
from shapely.geometry import Point
import numpy as np
from shapely.geometry import Polygon
from shapely.geometry import box
import shapely.geometry as geometry
import copy as cp
import cv2

def get_insect(line: LineString, boundary: LineString):
    coord1 = line.coords[0]
    coord2 = line.coords[-1]
    if coord1[0] - coord2[0] == 0:
        k = 1000
    else:
        k = np.abs((coord1[1] - coord2[1]) / (coord1[0] - coord2[0]))
    coord1 = boundary.coords[0]
    for coord2 in boundary.coords[1:]:
        if coord2[0] - coord1[0] == 0:
            k1 = 1000
        else:
            k1 = np.abs((coord2[1] - coord1[1]) / (coord2[0] - coord1[0]))
        if np.abs(k1 - k) < 0.01:
            return LineString([coord1, coord2])
        coord1 = coord2

def unitity(agent, other):
    assert isinstance(agent, Polygon) and isinstance(other, Polygon)
    interset = agent.intersection(other)
    union = ops.unary_union([agent, other])
    interset_coords = union.boundary.intersection(interset.boundary)
    if isinstance(interset_coords, geometry.MultiLineString):
        coord1 = interset_coords[0].coords[0]
        coord2 = interset_coords[1].coords[0] if interset_coords[1].coords[0][0] != coord1[0] and \
                                                 interset_coords[1].coords[0][1] != coord1[1] else \
            interset_coords[1].coords[1]
        line = LineString([coord1, coord2])
    else:
        line = LineString(interset_coords)
    unitity = ops.split(union, line)
    index = 0
    for i in range(len(unitity)):
        if np.abs(agent.intersection(unitity[i]).area - unitity[i].area) < 1e-4:
            index = i
    return unitity[index], unitity[1 - index], line

def figure(points, color='y'):
    # for data in points:
    #     plt.scatter(data[0],data[1],marker='*',c='b')
    for i, data in enumerate(points):
        # plt.scatter(data[0],data[1],c=color)
        plt.plot([points[i][0], points[(i + 1) % len(points)][0]], [points[i][1], points[(i + 1) % len(points)][1]],
                 c=color)

def get_side(agent, other):
    pass

def get_circle(central_pos, radius, num=64):
    x, y = central_pos[0], central_pos[1]
    theta = np.arange(0, 2 * np.pi, 2 * np.pi / num)
    cycle_points = []
    for i in range(num):
        cycle_points.append([x + radius * np.cos(theta[i]), y + radius * np.sin(theta[i])])
    return Polygon(cycle_points)

def cos_multi(v1, v2):  # when the rotate is unclock the value > 0

    return v1[1] * v2[0] - v1[0] * v2[1]

def vector_norm(v):
    return np.sqrt(np.sum(np.square(v)))

def make_agent(central_pos, radius, num, world):
    return Agent(central_pos, radius, num, world)

def get_agent(agents, num):
    if isinstance(agents, Agent):
        return agents
    for i, agent in enumerate(agents):
        if agent.num == num:
            return i, agent
    return None

def offset_points(offset,points:np.ndarray):
    if points.ndim == 1:
        points = points + offset
        return np.array(points,dtype=np.int)
    else:
        for i in range(points.shape[0]):
            points[i] = np.array((points[i] + offset),dtype=np.int)
        return points

class World():
    def __init__(self, points, agents_pos=None, radius=None):
        self.agents = None if agents_pos is None and radius is None else [make_agent(agents_pos[i], radius, i, self) for
                                                                          i in range(agents_pos.shape[0])]
        self.k = 50
        self.edge = Polygon(points)
        _,_,maxx,maxy = self.edge.bounds
        self.W = int(max(maxy, maxx) * self.k * 2)
    def render(self,iteration):
        points = np.array(self.edge.exterior.coords[:]) * self.k
        offset = np.array([self.W /4,self.W/4])
        points = offset_points(offset,points)
        img = np.zeros((self.W, self.W, 3), np.uint8)
        img[:] = (200, 200, 200)

        for i,point in enumerate(points):
            j = (i+1) %(len(points))
            cv2.line(img, (int(points[i][0]),int(points[i][1])), (int(points[j][0]),int(points[j][1])), (200, 0, 0), 3,lineType=cv2.LINE_AA)
        for agent in self.agents:
            central_pos = agent.central_pos * self.k
            central = offset_points(offset,central_pos)
            radius = agent.radius * self.k
            cv2.circle(img, (central[0], central[1]), int(radius), (0, 0, 200), -1, lineType=cv2.LINE_AA)
            cv2.circle(img, (central[0], central[1]), int(radius/self.k * 5), (40, 40, 40), -1, lineType=cv2.LINE_AA)

        cv2.putText(img, "Iteration: " +str(iteration), (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (40, 40, 40),
                    lineType=cv2.LINE_AA)
        cv2.namedWindow("Environment")
        cv2.imshow("Environment", img)
        cv2.waitKey(1)

class base_agent():
    def __init__(self, central_pos, radius, num):
        self.central_pos = np.array(central_pos)
        self.radius = radius
        self.sense_area = get_circle(self.central_pos, self.radius)
        self.num = num
        self.unitity_area = None

    def reset_central(self, central_pos):
        self.central_pos = np.array(central_pos)
        self.sense_area = get_circle(self.central_pos, self.radius)
        self.unitity_area = None

class q_fun():
    def __init__(self, q_ij: dict) -> 'Any':
        self.q_ij = q_ij

    def computer_g(self, agent: base_agent, world: World):
        assert isinstance(agent, base_agent)
        gradient = np.zeros(2)
        for message in self.q_ij:
            message['value'].reset_u(agent)
            message['value'].computer_edge(world)
            gradient += message['value'].computer_g(agent)
        return gradient

class Agent(base_agent):
    def __init__(self, central_pos, radius, num, world):  # note all the coords are operared based np.array
        super(Agent, self).__init__(central_pos, radius, num)
        self.receive_Q = None
        self.receive_R = None
        self.send_R = None
        self.send_Q = None
        self.neighbors = None
        self.U = []
        self.world = world

    def message_change(self):
        self.send_Q = cp.deepcopy(self.receive_R)

    @property
    def Agent_copy(self):
        return base_agent(self.central_pos, self.radius, self.num)

    def receive_message(self, agents):
        self.receive_R = []
        self.receive_Q = []
        for agent in agents:
            if agent.send_Q is None:
                self.receive_Q is None
            else:
                q_ij = []
                for message in agent.send_Q:  # send_Q is the copy of receive_R
                    if message['num'] == self.num: continue
                    q_ij.append(dict(num=message['num'], value=message['value']))
                q_ij = q_fun(q_ij)
                self.receive_Q.append(dict(num=agent.num, value=q_ij))
            for message in agent.send_R:
                if message['num'] == self.num:
                    self.receive_R.append(dict(num=agent.num, value=message['value']))

    def send_r(self):
        self.send_R = []
        self.get_neighbors(self.world)
        agents = [self] + self.neighbors
        r_g = self.message_initialize(agents)
        x_star = [agents[i].central_pos + 0.1 * r_g[i]/(1e-4+vector_norm(r_g[i])) for i in range(len(r_g))]
        agents_cp = [agents[i].Agent_copy for i in range(len(agents))]
        for i,agent in enumerate(agents_cp): agent.reset_central(x_star[i])
        for agent in agents:
            self.send_R.append(dict(num=agent.num, value=U_fun(agents_cp[0], agents_cp[1:])))

    def message_initialize(self, agents):  # the agents is the form of list [self, self.neighbors]
        agents_cp = [agent.Agent_copy for agent in agents]
        U_self = U_fun(agents_cp[0], agents_cp[1:])
        U_self.computer_edge(self.world)

        u_g = [U_self.computer_g(agent) for agent in agents_cp]

        if self.receive_Q is None:
            return u_g
        for message in self.receive_Q:
            p = get_agent(agents, message['num'])
            if p is None:
                continue
            i, agent = p[0], p[1].Agent_copy
            u_g[i] += message['value'].computer_g(agent, self.world)
        return u_g

    def show_sense_area(self):
        figure(self.sense_area.exterior.coords[:], color='r')

    def update_state(self):
        g = np.zeros(2)
        for message in self.receive_R:
            u = message['value']
            u.reset_u(self.Agent_copy)
            u.computer_edge(self.world)
            g += u.computer_g(self.Agent_copy)
        step = 0.1 * g/vector_norm(g)
        central_points = self.central_pos + step
        self.reset_central(central_points)

    def get_neighbors(self, world):
        self.neighbors = []
        for agent in world.agents:
            if self is agent:  continue
            if self.sense_area.intersects(agent.sense_area):
                self.neighbors.append(agent)

class U_fun():
    def __init__(self, central_agent=None, other_agents=None):
        self.a = central_agent
        self.b = other_agents

        self.agent = central_agent.sense_area
        self.central_pos = np.array(self.agent.centroid.coords[0])
        self.others = [other.sense_area for other in other_agents]

        self.num = [agent.num for agent in [self.a] + self.b]
        self.g = None
        self.u = None
        self.A = []
        self.B = []

    def reset_u(self, agent):
        assert isinstance(agent, Agent) or isinstance(agent, base_agent)
        if agent.num == self.a.num:
            self.a = agent
            self.agent = self.a.sense_area
            self.central_pos = np.array(self.agent.centroid.coords[0])
        else:
            for i, ag in enumerate(self.b):
                if ag.num == agent.num:
                    self.b[i] = agent
            self.others = [other.sense_area for other in self.b]
        self.num = [agent.num for agent in [self.a] + self.b]
        self.g = None
        self.u = None
        self.A = []
        self.B = []

    def computer_edge(self, world: World):
        lines = []
        intersect_pos = []
        u = self.agent
        for other in self.others:
            if not self.agent.intersects(other):
                lines.append(None)
                intersect_pos.append(None)
                continue
            U, _, line = unitity(self.agent, other)
            u = u.intersection(U)
            lines.append(line)
            intersect_pos.append(0.5 * self.central_pos + 0.5 * np.array(other.centroid.coords[0]))
        self.u = u.intersection(world.edge)
        lines_A = self.agent.boundary.intersection(self.u)
        if not lines_A.is_empty and not isinstance(lines_A, Point):
            if isinstance(lines_A, LineString):
                lines_A = [lines_A]
            for line in lines_A:
                if isinstance(line, Point): continue
                coord0 = np.array(line.coords[0])
                coord1 = np.array(line.coords[1])
                coord = 0.5 * coord0 + 0.5 * coord1
                n = coord - self.central_pos
                n = n / vector_norm(n)
                length = line.length
                self.A.append(dict(v_n=n, length=length))
        lines_B = []

        for i, line in enumerate(lines):
            if line is None or self.u.distance(line) > 1e-5:
                lines_B.append(None)
                self.B.append(None)
                continue
            if not self.u.boundary.is_ring:
                print('not closed')
                self.u = self.u.convex_hull
            l = get_insect(line, self.u.boundary)
            lines_B.append(l)
            coord0 = np.array(l.coords[0])
            coord1 = np.array(l.coords[1])
            v0 = coord0 - intersect_pos[i]
            v1 = coord1 - intersect_pos[i]
            v = intersect_pos[i] - self.central_pos
            index = 0 if cos_multi(v0, v) >= cos_multi(v1, v) else 1
            edge_upper = np.sign(cos_multi(v0, v)) * vector_norm(v0) if index == 0 else np.sign(
                cos_multi(v1, v)) * vector_norm(v1)
            edge_low = np.sign(cos_multi(v1, v)) * vector_norm(v1) if index == 0 else np.sign(
                cos_multi(v0, v)) * vector_norm(v0)
            self.B.append((edge_low, edge_upper))

        g_self = np.zeros(2)
        g_other = []
        for line in self.A:
            g_self += line['v_n'] * line['length']

        for i, line in enumerate(self.B):
            if line is None:
                g_other.append(np.zeros(2))
                continue
            v_n = np.array(self.others[i].centroid.coords[0]) - self.central_pos
            v_n = v_n / vector_norm(v_n)

            integral_low, integral_upper = line[0], line[1]
            c1, c2, c2_other = self.integral_c(self.others[i])
            c1 = c1 * (integral_upper - integral_low)
            c2 = c2 * (integral_upper ** 2 - integral_low * 2)
            c2_other = c2_other * (integral_upper ** 2 - integral_low * 2)
            g_other.append(v_n @ (c1 + c2_other))
            g_self += v_n @ (c1 + c2)
        self.g = [g_self] + g_other

    def computer_g(self, agent):
        for i, num in enumerate(self.num):
            if agent.num == num:
                return self.g[i]  # return the gradient of the given agent
        return np.zeros(2)

    def integral_c(self, other: Polygon):
        p = np.zeros(2)
        c1 = np.zeros((2, 2))
        c2 = np.zeros((2, 2))
        x_i, x_j = self.central_pos, other.centroid.coords[0]
        p[0], p[1] = 0.5 * (x_i[1] - x_j[1]), 0.5 * (x_j[0] - x_i[0])
        p = vector_norm(p)
        c1[0][0] = 0.5
        c1[1][1] = 0.5
        c2[0][0] = -1 / 16 * p ** -3 * (x_i[1] - x_j[1]) * (x_i[0] - x_j[0])
        c2[0][1] = 1 / 4 * p ** -3 * (p ** 2 - 0.25 * (x_i[1] - x_j[1]) ** 2)
        c2[1][0] = -1 / 4 * p ** -3 * (p ** 2 - 0.25 * (x_i[0] - x_j[0]) ** 2)
        c2[1][1] = 1 / 16 * p ** -3 * (x_j[0] - x_i[0]) * (x_j[1] - x_i[1])
        return c1, c2, -c2

if __name__ == '__main__':
    pos = np.array([[2, 2], [3.5, 2], [3, 3],[4,4],[10,10],[0,10]])
    #world = World([[0, 0], [8, 0], [8, 8],[0,8]], agents_pos=pos, radius=2)
    world = World([[0,0],[10,0],[10,10],[0,10]],agents_pos=pos, radius=2)
    agents = world.agents
    for i in range(200):
        for agent in agents:
            agent.send_r()
        for agent in agents:
            agent.receive_message([agent]+agent.neighbors)
        for agent in agents:
            agent.message_change()
            agent.update_state()
        area =ops.unary_union([agent.sense_area for agent in agents])
        print('the coverage area is :{}'.format(area.intersection(world.edge).area))
        world.render(i)
    plt.figure()
    figure(world.edge.exterior.coords[:])
    for agent in agents:
        figure(agent.sense_area.exterior.coords[:],color='r')
    plt.show()
#     figure(world.edge.exterior.coords[:])
#     for agent in world.agents:
#         agent.show_sense_area()
# if __name__ == '__main__':
#     pos = np.array([[2, 2], [5, 2], [4, 4], [3, 3]])
#     world = World([[0, 0], [10, 0], [5, 10]], agents_pos=pos, radius=2)
#     agents = world.agents
#     plt.figure()
#     figure(world.edge.exterior.coords[:])
#     for agent in world.agents:
#         agent.show_sense_area()
#     for t in range(400):
#         for agent in agents:
#             agent.update_state(world)
#         if t % 10 == 0:
#             cover_area = ops.unary_union([agent.u for agent in agents])
#             print('in {} the full coverage area is :{}'.format(t, cover_area.area))
#     plt.figure()
#     figure(world.edge.exterior.coords[:])
#     for agent in world.agents:
#         agent.show_sense_area()
#     plt.show()

# class Agent():
#     def __init__(self, central_pos,radius):  # note all the coords are operared based np.array
#         self.central_pos = np.array(central_pos)
#         self.radius = radius
#         self.sense_area = get_circle(self.central_pos,self.radius)
#         self.unitity_area = None
#         self.Q = []
#         self.R = []
#         self.neighbors = None
#         self.calculate_A = []
#         self.calculate_B = []
#         self.p_v = []
#
#     def reset_central(self,central_pos):
#         self.central_pos = np.array(central_pos)
#         self.sense_area = get_circle(self.central_pos, self.radius)
#         self.unitity_area = None
#     def show_sense_area(self):
#         figure(self.sense_area.exterior.coords[:])
#
#     def get_neighbors(self, world):
#         self.neighbors = []
#         for agent in world.agents:
#             if self is agent:continue
#             if self.sense_area.intersects(agent.sense_area):
#                 self.neighbors.append(agent)
#
#     def reset_calculate(self):
#         self.p_v = []
#         self.calculate_A = []
#         self.calculate_B = []
#
#     def compute_edge(self, world):
#         assert isinstance(world, World)
#         lines = []
#         intersect_pos = []
#         vs_area = self.sense_area
#         for other in self.neighbors:
#             intersect_pos.append(0.5 * self.central_pos + 0.5 * other.central_pos)
#             u, _, line = unitity(self.sense_area,
#                                  other.sense_area)  # the line is the intersection between the agent and other agent
#             vs_area = vs_area.intersection(u)
#             self.p_v.append(vector_norm(np.array(line.coords[0]) - np.array(line.coords[1])))
#             lines.append(line)
#         u = vs_area.intersection(world.edge)
#
#         boundary = u.boundary
#         lines_A = self.sense_area.boundary.intersection(u.boundary)
#         if not lines_A.is_empty and not isinstance(lines_A,Point):
#             if isinstance(lines_A,LineString):
#                 print(lines_A)
#                 lines_A = [lines_A]
#             for line in lines_A:
#                 if isinstance(line,Point): continue
#                 coord0 = np.array(line.coords[0])
#                 coord1 = np.array(line.coords[1])
#                 coord = 0.5 *coord0 + 0.5 *coord1
#                 n = coord - self.central_pos
#                 n = n / vector_norm(n)
#                 length = line.length
#                 self.calculate_A.append(dict(v_n = n,length = length))
#             # if coord[0] == 0:
#             #     if coord[1] >= 0:
#             #         self.calculate_A['up'].append(vector_norm(coord))
#             #     else:
#             #         self.calculate_A['down'].append(vector_norm(coord))
#             # else:
#             #     if coord[0] >= 0:
#             #         self.calculate_A['right'].append(vector_norm(coord))
#             #     else:
#             #         self.calculate_A['left'].append(vector_norm(coord))
#         # plt.figure()
#         # figure(u.exterior.coords[:],color = 'y')
#
#
#         for i in range(len(lines)):
#             l = lines[i].intersection(boundary)
#
#             if not isinstance(l, LineString):
#                 if isinstance(l,geometry.MultiPoint):
#                     #print('warning this is a Multipoint')
#                     l = LineString(l)
#                     # plt.figure()
#                     # figure(u.boundary.coords[:])
#                     # figure(l.coords[:],color='r')
#                     # plt.show()
#                 elif isinstance(l,Point):
#                     #print('warning this is a point:{}'.format(l))
#                     l = ops.snap(lines[i], boundary,tolerance=0.1)
#                     l = l.intersection(boundary)
#                     if isinstance(l,geometry.MultiLineString):
#                         max_line = l[0]
#                         for line in l:
#                            if line.length > max_line.length:
#                                max_line  = line
#                         l = max_line
#                     # plt.figure()
#                     # figure(u.boundary.coords[:])
#                     # figure(l.coords[:], color='r')
#                     # plt.show()
#
#                 elif isinstance(l,geometry.MultiLineString):
#                     points =[]
#                     points.append(l[0].coords[0])
#                     points.append(l[-1].coords[1])
#                     l = LineString(points)
#                     # print('MultilineString')
#                     # plt.figure()
#                     # figure(u.boundary.coords[:])
#                     # figure(l.coords[:], color='r')
#                     # plt.show()
#                 else:
#                     print(l)
#                     plt.figure()
#                     figure(u.boundary.coords[:])
#                     for line in l:
#                         figure(line.coords[:],color='b')
#                     plt.show()
#                     raise ValueError
#             #figure(l.coords[:],color='r')
#             if l.is_empty:
#                 self.calculate_B.append(None)
#                 continue
#             else:
#                 coord0 = np.array(l.coords[0])
#                 coord1 = np.array(l.coords[1])
#                 v0 = coord0 - intersect_pos[i]
#                 v1 = coord1 - intersect_pos[i]
#                 v = intersect_pos[i] - self.central_pos
#                 index = 0 if cos_multi(v0, v) >= cos_multi(v1, v) else 1
#                 edge_upper = np.sign(cos_multi(v0, v)) * vector_norm(v0) if index == 0 else np.sign(cos_multi(v1, v)) * vector_norm(v1)
#                 edge_low = np.sign(cos_multi(v1, v)) * vector_norm(v1) if index ==0 else  np.sign(cos_multi(v0, v)) * vector_norm(v0)
#                 self.calculate_B.append((edge_low, edge_upper))
#         #plt.show()
#
#         self.unitity_area = u
#         return u
#
#     def integral_c(self,other:'Agent'):
#         p = np.zeros(2)
#         c1 = np.zeros((2,2))
#         c2 = np.zeros((2,2))
#         x_i,x_j = self.central_pos,other.central_pos
#         p[0], p[1]  = 0.5 * (x_i[1] - x_j[1]),0.5 * (x_j[0] - x_i[0])
#         p = vector_norm(p)
#         c1[0][0] = 0.5
#         c1[1][1] = 0.5
#         c2[0][0] = -1/16 * p**-3 * (x_i[1] - x_j[1]) * (x_i[0] - x_j[0])
#         c2[0][1] = 1/4 * p**-3 * (p**2 - 0.25 * (x_i[1] - x_j[1])**2)
#         c2[1][0] = -1/4 * p**-3 * (p**2 - 0.25 * (x_i[0] -x_j[0])**2)
#         c2[1][1] = 1/16 * p**-3 * (x_j[0] - x_i[0]) * (x_j[1] - x_i[1])
#         return c1 ,c2,-c2
#     def computer_graindient_U(self,world = None):
#         graindient1 = np.zeros(2)
#         others_graindient = []
#         for line in self.calculate_A:
#             graindient1 += line['v_n'] * line['length']
#         graindient2 = np.zeros(2)
#         other_graidient = []
#         for i,line in enumerate(self.calculate_B):
#             if line is None:
#                 other_graidient.append(None)
#                 continue
#             v_n = self.neighbors[i].central_pos - self.central_pos
#             v_n = v_n / vector_norm(v_n)
#             integral_low,integral_upper = line[0],line[1]
#             c1,c2,c2_other = self.integral_c(self.neighbors[i])
#             c1 = c1 * (integral_upper - integral_low)
#             c2 = c2 * (integral_upper**2 - integral_low*2)
#             c2_other * (integral_upper**2 - integral_low*2)
#             other_graidient.append(c1+c2_other)
#             graindient2 += v_n @ (c1 + c2)
#         return graindient1, graindient2,other_graidient

# #if __name__ == '__main__':
#     frame = Polygon([[0, 0], [10, 0], [5, 10]])
#
#     points = frame.boundary.coords[:]
#     pos = np.array([[2,2],[5,2],[4,4],[3,3]])
#
#     world = World(points=points, agents_pos=pos,radius=2)
#     # figure(world.edge.exterior.coords[:],color='b')
#
#     for iter_count in range(200):
#         u, r_central = [], []
#         for agent in world.agents:
#             agent.get_neighbors(world)
#             agent.reset_calculate()
#             u.append(agent.compute_edge(world))
#             g1,g2 = agent.computer_graindient_U()
#             g = g1 + g2
#             g = g/ (vector_norm(g) + 1e-6)
#             r_central .append(agent.central_pos + 0.02*g)
#         s = [agent.sense_area for agent in world.agents]
#         if iter_count % 30 ==0:
#             print('the full coverage area:{} and :{}'.format(ops.unary_union(u).area, ops.unary_union(s).intersection(world.edge).area))
#         i = 0
#         for agent in world.agents:
#             agent.reset_central(r_central[i])
#             i +=1
#     plt.figure()
#     figure(world.edge.exterior.coords[:],color='b')
#     for agent in world.agents:
#         figure(agent.sense_area.exterior.coords[:],color='r')
#
#
#
#
#
#
#
#
#
#     # for agent in world.agents:
#     #     print(agent.calculate_B)
#     # for agent in world.agents:
#     #     print(agent.calculate_A)
#
#     plt.show()

# plt.figure()
# figure(frame.exterior.coords[:])
# figure(square1.exterior.coords[:])
# figure(square2.exterior.coords[:])
# figure(square3.exterior.coords[:])
# plt.show()

# plt.figure()
# figure(square1.exterior.coords[:])
# figure(square2.exterior.coords[:])
# figure(square3.exterior.coords[:])
#
# u = [None] * 3
# lines = [[],[],[]]
# plt.figure()
# for i, bx in enumerate(boxs):
#     u[i] = bx
#     for j in range(len(boxs)):
#         if j == i: continue
#         intersect, _ , line = unitity(bx, boxs[j])
#         u[i] = intersect.intersection(u[i])
#         lines[i].append(line)
#     # plt.figure()
#     figure(u[i].exterior.coords[:])
# for U in u:
#     print(U.exterior.coords[:][::-1])
#
# centrals = []
# for b in boxs:
#     centrals.append(np.array(b.centroid.coords[:][0]))
# coord1 = np.array(lines[2][1].coords[0])
# coord2 = np.array(lines[2][1].coords[1])
# print(coord1, coord2)
# coord3 = 0.5 *centrals[0] + 0.5 *centrals[2]
# print(coord3)
#
# v1 = coord3 - centrals[0]
# v2 = coord1 - coord3
# v3 = coord2 - coord3
# print('v1:{} v2:{}'.format(v1,v2))
# print('v1_:{},v2_:{}


from Pipe import Pipe
from Packet import ClientReqPacket, Packet, ClientRespPacket, TrackerRespPacket
from TitForTat import TitForTat
from FileStorage import FileStorage
import threading
import time
from multiprocessing import Process

'''
职能：client对特定文件的维护类
'''

class DownloadTask(Process):
    def __init__(self, fileStorage: FileStorage, rec_queue, send_queue, file_queue, selfPort=None, tit_tat=False):
        Process.__init__(self)

        self.fid = fileStorage.fid
        self.peers = set()
        self.closed = False
        self.downloadingPeers = set()
        self.pipe = Pipe(rec_queue, send_queue, file_queue)
        self.fileStorage = fileStorage
        self.selfPort = selfPort
        self.tit_tat = tit_tat

    def run(self):
        if self.tit_tat:
            self.titfortat = TitForTat(self.selfPort)
            # print("Outer" + str(self.selfPort) + str(self.titfortat))

        threading.Thread(target=self.run_sub).start()
        threading.Thread(target=self._autoAsk).start()
        threading.Thread(target=self.getFile).start()

    def run_sub(self):
        """
        实现recv的核心线程
        :return:
        """
        while not self.closed:
            packet = self.pipe.recv()
            self.opPacket(packet)

    def opPacket(self, packet):
        all = time.time()
        if self.tit_tat:
            self.titfortat.monitoring(packet)
        data, cid = packet
        type = Packet.getType(data)
        # tracker
        print(f'{self.selfPort}\t{self.fileStorage}\n', end='')
        if type == 2:
            p = TrackerRespPacket.fromBytes(data)
            for c in self.peers - p.info:
                self.fileStorage.cancel(c)
            # print(f'{cid[1]} > {self.selfPort} | {p}\n', end='')
            self.peers = p.info
            # self.downloadingPeers = self.downloadingPeers & self.peers
        elif type == 3:
            start = time.time()
            p = ClientReqPacket.fromBytes(data)
            # print(f'{cid[1]} > {self.selfPort} | {p}\n', end='')
            if p.index == -1:
                self.pipe.send(ClientRespPacket(self.fid, self.fileStorage.haveFilePieces, -1, b'').toBytes(), cid)
            else:
                if self.tit_tat:
                    self.titfortat.tryRegister(cid)
                    able = self.fileStorage.haveFilePieces[p.index] and not self.titfortat.isChoking(cid)
                    if self.titfortat.isChoking(cid):
                        # print(f"{self.selfPort} receiving speed: {self.titfortat.speed}\n")
                        print(self.titfortat.get_speed_of_top4() +
                              f"{self.selfPort} is choking {cid[1]}: {round(self.titfortat.speed[cid], 3)}\n",
                              end="")
                else:
                    able = self.fileStorage.haveFilePieces[p.index]
                if able:
                    # print(f'{self.selfPort} send {cid[1]} {p.index}')
                    self.pipe.send(ClientRespPacket(self.fid, self.fileStorage.haveFilePieces, p.index,
                                                    self.fileStorage.filePieces[p.index]).toBytes(), cid)
                else:
                    self.pipe.send(ClientRespPacket(self.fid, self.fileStorage.haveFilePieces, -2, b'').toBytes(), cid)

        # get response
        elif type == 4:
            start = time.time()
            p = ClientRespPacket.fromBytes(data)
            # print(f'{cid[1]} > {self.selfPort} | {p}\n', end='')
            if p.index == -2:
                self.fileStorage.cancel(cid)
                # self.downloadingPeers.remove(cid)
            else:
                if p.index == -1:
                    if not self.fileStorage.isInteresting(p.haveFilePieces) and \
                            cid in self.fileStorage.promisesMap.keys() and \
                            len(self.fileStorage.promisesMap[cid]) > 0:
                        self.fileStorage.cancel(cid)
                if p.index != -1:
                    if self.fileStorage.haveFilePieces[p.index]: return
                    self.fileStorage.add(p.index, p.data)
                if cid in self.fileStorage.promisesMap.keys() and len(self.fileStorage.promisesMap[cid]) > 2:
                    return
                if self.fileStorage.isInteresting(p.haveFilePieces):
                    chosenIndex = self.fileStorage.generateRequest(p.haveFilePieces, cid)
                    assert chosenIndex != -1
                    # print(f'{cid[1]} promise {self.selfPort} {chosenIndex}\n', end='')
                    self.fileStorage.promise(chosenIndex, cid)
                    self.pipe.send(ClientReqPacket(self.fileStorage.fid, chosenIndex).toBytes(), cid)
                else:
                    if cid in self.downloadingPeers: self.downloadingPeers.remove(cid)

            # print(f"??4-{time.time() - start}")
        # print(f'??A{time.time() - all}')

        # if self.pipe.recv_queue.qsize() > 0: continue
        # if len(self.fileStorage.promisesMap[cid]) < 999999:
        #     chosenIndex = self.fileStorage.generateRequest(p.haveFilePieces)
        #     if chosenIndex == -1: continue
        #     self.fileStorage.promise(chosenIndex, cid)
        #     self.pipe.send(ClientReqPacket(self.fileStorage.fid, chosenIndex).toBytes(), cid)

    def _autoAsk(self):
        while not self.closed:
            num = sum(self.fileStorage.promises)
            have_temp = [self.fileStorage.haveFilePieces[i] or self.fileStorage.promises[i] > 0 for i in
                         range(len(self.fileStorage.haveFilePieces))]
            percent = sum(have_temp) / len(self.fileStorage.haveFilePieces)
            rest = len(have_temp) - sum(have_temp)
            # print(f"{self.selfPort} autoAsk {self.fileStorage.isComplete()}")
            if self.fileStorage.isComplete():
                return
            possiblePeers = list(self.peers - {('127.0.0.1', self.selfPort)})
            for peer in possiblePeers:
                self.pipe.send(ClientReqPacket(self.fileStorage.fid, -1).toBytes(), peer)

                if num < 2 and rest > 10 and percent < 0.5:

                    time.sleep(0.1)
                else:
                    time.sleep(1)
            time.sleep(0.1)

            # if possiblePeers:
            #     randomPeerCid = random.choice(possiblePeers)
            #     self.pipe.send(ClientReqPacket(self.fileStorage.fid, -1).toBytes(), randomPeerCid)
            #     self.pipe.send(ClientReqPacket(self.fileStorage.fid, -1).toBytes(), randomPeerCid)
            #     self.downloadingPeers.add(randomPeerCid)
            #     time.sleep(5)
            # time.sleep(1)

    def getFile(self):
        """
        获取文件
        :return:
        """
        while not self.closed:
            time.sleep(2)
            if self.fileStorage.isComplete():
                self.pipe.send_file(self.fileStorage.getFile(), ('OUT_FILE', self.fid))
                break


import random

name = input('Please enter your name: ')
range = input(f'Hello {name.capitalize()}, please type a number: ')

def isdigit(d):
    if d.isdigit():
        d = int(d)
        return d
    else:
        print('Please enter a number next time')
        quit()

def guesses(score):
    score = 0
    while True:
        guess = input(f'Enter a number between 0 and {str(range)}: ')
        guess = isdigit(guess)
        score += 1
        if guess == r:
            print(f'Congratulations {name.capitalize()}, you got it right!')
            return score
        elif guess > r:
            print('Too high')
            continue
        else:
            print('Too low')
            continue

range = isdigit(range)
r = random.randint(0, range)
score = guesses(r)
print('It took you', score, 'guesses')


from django.test import TestCase
from wellspring.services import device_service, value_service, vest_service
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from wellspring.exceptions import DeviceNotRegistered

sarah_uuid = "Android@SarahHTCXXX464"
john_uuid = "IOS@JohnIPhoneXXX221"
wrong_uuid = "Windows8@WrongWindowsPhoneXXX090"

class DeviceServiceTest(TestCase):
    def setUp(self):
        sarah = device_service.add_device(sarah_uuid)
        john = device_service.add_device(john_uuid)

        lifestyle = vest_service.add_section("LIFESTYLE")
        equilibrium = vest_service.add_section("EQUILIBRIUM")
        support = vest_service.add_section("SUPPORT")

        diet = vest_service.add_subsection(lifestyle.section_name, "DIET")
        exercise = vest_service.add_subsection(lifestyle.section_name, "EXERCISE")
        school = vest_service.add_subsection(equilibrium.section_name, "SCHOOL")
        vest_self = vest_service.add_subsection(equilibrium.section_name, "SELF")
        family = vest_service.add_subsection(support.section_name, "FAMILY")
        friends = vest_service.add_subsection(support.section_name, "FRIENDS")

        self.sarah_value_1 = value_service.add_value_by_string_params("Math", "I really like math", sarah_uuid, "SCHOOL")
        self.sarah_value_2 = value_service.add_value_by_string_params("Money", "Money is very valuable", sarah_uuid, "EXERCISE")
        self.sarah_value_3 = value_service.add_value_by_string_params("Running", "I value running long distances", sarah_uuid, "EXERCISE")

        self.john_value_1 = value_service.add_value_by_domain_objects("Reading", "I read every day", john, school)
        self.john_value_2 = value_service.add_value_by_domain_objects("Thinking", "Thinking is very valuable", john, vest_self)
        self.john_value_3 = value_service.add_value_by_domain_objects("Discipline", "It is important to me to be disciplined", john, vest_self)

        self.wrong_id = [i for i in range(1, 20) if i not in [value.id for value in [self.sarah_value_1,
                                                                                self.sarah_value_2,
                                                                                self.sarah_value_3,
                                                                                self.john_value_1,
                                                                                self.john_value_2,
                                                                                self.john_value_3]]][0]

    def test_get_all_values_for_device(self):
        john_values = value_service.get_all_values_for_device(john_uuid)
        sarah_values = value_service.get_all_values_for_device(sarah_uuid)
        self.assertRaises(DeviceNotRegistered, value_service.get_all_values_for_device, device_uuid = wrong_uuid)

        sarah_value_names = [value.value_name for value in sarah_values]
        john_value_names = [value.value_name for value in john_values]

        sarah_value_descriptions = [value.value_description for value in sarah_values]
        john_value_descriptions = [value.value_description for value in john_values]

        sarah_value_vest_subsections = [value.vest_subsection.subsection_name for value in sarah_values]
        john_value_vest_subsections = [value.vest_subsection.subsection_name for value in john_values]

        sarah_value_vest_sections = [value.vest_subsection.vest_section.section_name for value in sarah_values]
        john_value_vest_sections = [value.vest_subsection.vest_section.section_name for value in john_values]

        self.assertTrue("Math" in sarah_value_names)
        self.assertTrue("Money" in sarah_value_names)
        self.assertFalse("Wrong" in sarah_value_names)

        self.assertTrue("Reading" in john_value_names)
        self.assertTrue("Thinking" in john_value_names)
        self.assertFalse("Math" in john_value_names)

        self.assertTrue("I really like math" in sarah_value_descriptions)
        self.assertFalse("I don't like math" in sarah_value_descriptions)

        self.assertTrue("Thinking is very valuable" in john_value_descriptions)
        self.assertFalse("Thinking is for brainy-types" in john_value_descriptions)

        self.assertTrue("SCHOOL" in sarah_value_vest_subsections)
        self.assertFalse("FAMILY" in sarah_value_vest_subsections)

        self.assertTrue("SELF" in john_value_vest_subsections)
        self.assertFalse("FAMILY" in john_value_vest_subsections)

        self.assertTrue("LIFESTYLE" in sarah_value_vest_sections)
        self.assertFalse("SUPPORT" in sarah_value_vest_sections)

        self.assertTrue("EQUILIBRIUM" in john_value_vest_sections)
        self.assertFalse("LIFESTYLE" in john_value_vest_sections)

    def test_get_value_by_id(self):
        sarah_value_1 = value_service.get_value_by_id(sarah_uuid, self.sarah_value_1.id)
        sarah_value_3 = value_service.get_value_by_id(sarah_uuid, self.sarah_value_3.id)
        john_value_2 = value_service.get_value_by_id(john_uuid, self.john_value_2.id)

        self.assertRaises(PermissionDenied, value_service.get_value_by_id, device_uuid = john_uuid, value_id = self.sarah_value_2.id)
        self.assertRaises(PermissionDenied, value_service.get_value_by_id, device_uuid = wrong_uuid, value_id = self.john_value_1.id)
        self.assertRaises(ObjectDoesNotExist, value_service.get_value_by_id, device_uuid = sarah_uuid, value_id = self.wrong_id)

        self.assertEqual(sarah_value_1, self.sarah_value_1) ## This one compares IDs
        self.assertEqual(sarah_value_3.value_name, self.sarah_value_3.value_name)
        self.assertEqual(john_value_2.device.device_uuid, john_uuid)
        self.assertEqual(john_value_2.vest_subsection.subsection_name, self.john_value_2.vest_subsection.subsection_name)

    def test_delete_value_by_id(self):
        sarah_value_1_id = self.sarah_value_1.id
        self.assertEqual(value_service.get_value_by_id(sarah_uuid, sarah_value_1_id), self.sarah_value_1)

        value_service.delete_value(sarah_uuid, self.sarah_value_1.id)

        ## Assert that the object was deleted
        self.assertRaises(ObjectDoesNotExist, value_service.get_value_by_id, device_uuid = sarah_uuid, value_id = sarah_value_1_id)

        ## Assert that security check is being made before deletion
        self.assertRaises(PermissionDenied, value_service.delete_value, device_uuid = john_uuid, value_id = self.sarah_value_2.id)

        ## Assert that you can't delete something that doesn't exist
        self.assertRaises(ObjectDoesNotExist, value_service.delete_value, device_uuid = john_uuid, value_id = self.wrong_id)

    def test_update_value(self):
        sarah_value_1_id = self.sarah_value_1.id
        original_name = self.sarah_value_1.value_name
        original_description = self.sarah_value_2.value_description
        original_vest_subsection = self.sarah_value_2.vest_subsection.subsection_name

        new_value_returned = value_service.update_value(sarah_value_1_id, sarah_uuid, "Latin", "I don't like math any more. I like Latin!", "FRIENDS")
        new_value = value_service.get_value_by_id(sarah_uuid, sarah_value_1_id)

        self.assertEqual(new_value, new_value_returned)
        self.assertEqual(new_value.value_name, new_value_returned.value_name)
        self.assertEqual(new_value.value_description, new_value_returned.value_description)
        self.assertEqual(new_value.vest_subsection.subsection_name, new_value_returned.vest_subsection.subsection_name)

        self.assertNotEqual(original_name, new_value.value_name)
        self.assertNotEqual(original_description, new_value.value_description)
        self.assertNotEqual(original_vest_subsection, new_value.vest_subsection)

        self.assertRaises(PermissionDenied, value_service.update_value, value_id = self.sarah_value_2.id,
                          device_uuid = john_uuid, name = "Treachery", description = "I like updating other people's data",
                          vest_subsection_name = "SELF")

        self.assertRaises(ObjectDoesNotExist, value_service.update_value, value_id = self.wrong_id,
                          device_uuid = john_uuid, name = "Stupidity", description = "I like retrieving data that doesn't exist",
                          vest_subsection_name = "SELF")

    def test_get_value_for_subsection(self):
        self.assertEquals(value_service.get_value_for_subsection("SCHOOL", sarah_uuid).value_name, "Math")

        for i in range(10):
            self.assertTrue(value_service.get_value_for_subsection("SELF", john_uuid).value_name in ["Thinking", "Discipline"])


from typing import List, Dict

import nltk

from fertility.eval.lev import MyMetric
from fertility.tree_utils.read_funql import reconstruct_tree_with_partial_brackets, sort_tree_by_hash

@MyMetric.register("funql_acc")
class FunqlAcc(MyMetric):
    def __init__(self,  arities: Dict[str, int], sortable_nodes = ("intersection", "or")):
        self.sortable_nodes = set(sortable_nodes)
        self.reset()
        self.arities = arities

    def reset(self):
        self.correct = 0
        self.total = 0

    def get_metric(self, reset: bool) -> Dict[str, float]:
        if self.total == 0:
            return {"tree_acc": 0}
        a = self.correct / self.total
        if reset:
            self.reset()

        return {"tree_acc": a}

    def add_instances(self, predictions: List[List[str]], gold: List[List[str]]) -> None:
        assert len(predictions) == len(gold)

        self.total += len(gold)

        for p, g in zip(predictions, gold):
            # For BART, which outputs strings instead of lists of tokens:
            if isinstance(p, str):
                p = p.split(" ")
                if p[0] == "": # if we start with a space (due to bart tokenization), remove it here
                    p = p[1:]
            if isinstance(g, str):
                g = g.split(" ")
                if g[0] == "": # if we start with a space (due to bart tokenization), remove it here
                    g = g[1:]

            try:
                g_t = reconstruct_tree_with_partial_brackets(g, self.arities)
            except Exception as ex:
                print("Warning, could not convert gold sequence into tree", g)
                continue
            try:
                p_t = reconstruct_tree_with_partial_brackets(p, self.arities)
            except Exception:
                continue

            self.correct += sort_tree_by_hash(nltk.ImmutableTree.convert(g_t), self.sortable_nodes) == \
                            sort_tree_by_hash(nltk.ImmutableTree.convert(p_t), self.sortable_nodes)


from collections import defaultdict
import queue

import math
import itertools

class Machine(object):
    def __init__(self, mem):
        self.memory = defaultdict(lambda: 0, enumerate(mem))
        self.mem_len = len(mem)
        self.pointer = 0
        self.len = len(mem)
        self.out = 0
        self.relative_location = 0
        self.__output_queue = queue.Queue(maxsize=1)
        self.__output_list = []
        self.__halt = False
        self.__initialized = False
        self.__needs_input = False
        self.__error = False

    def input(self, v):
        self.run(v)

    def output(self):
        return self.out

    def output_queue(self):
        return self.__output_queue

    def needs_input(self):
        return self.__needs_input

    def output_list(self):
        return self.__output_list

    def halted(self):
        return self.__halt

    def initialized(self):
        return self.__initialized

    def errored(self):
        return self.__error

    def run(self, input=None):
        if input != None:
            self.__initialized = True
        while self.pointer < self.len:
            op_code = self.memory[self.pointer]
            operation = op_code % 100
            m1 = op_code // 100 % 10
            m2 = op_code // 1000 % 10
            m3 = op_code // 10000 % 10
            o1 = self.relative_location if m1 == 2 else 0
            o2 = self.relative_location if m2 == 2 else 0
            o3 = self.relative_location if m3 == 2 else 0
            p1, p2, p3 = self.memory[self.pointer + 1], self.memory[self.pointer + 2], self.memory[self.pointer + 3]
            v1 = p1 if m1 == 1 else self.memory[o1+p1]
            v2 = p2 if m2 == 1 else self.memory[o2+p2]
            if operation == 99:
                self.__halt = True
                print('Halting')
                break
            elif operation == 1:
                self.memory[o3+p3] = v1 + v2
                self.pointer += 4
            elif operation == 2:
                self.memory[o3+p3] = v1 * v2
                self.pointer += 4
            elif operation == 3:
                if input == None:
                    self.__needs_input = True
                    break
                self.memory[o1+p1] = input
                input = None
                self.__needs_input = False
                self.pointer += 2
            elif operation == 4:
                self.pointer += 2
                self.__output_queue.put(v1)
                self.out = v1
                return v1
            elif operation == 5:
                self.pointer = v2 if v1 != 0 else self.pointer + 3
            elif operation == 6:
                self.pointer = v2 if v1 == 0 else self.pointer + 3
            elif operation == 7:
                self.memory[o3+p3] = 1 if v1 < v2 else 0
                self.pointer += 4
            elif operation == 8:
                self.memory[o3+p3] = 1 if v1 == v2 else 0
                self.pointer += 4
            elif operation == 9:
                self.relative_location += v1
                self.pointer += 2
            else:
                print("ERROR", self.pointer, operation, [op_code, p1, p2, p3])
                self.__error = True
                break

def find_pad_and_ball(board):
    for y in range(21):
        for x in range(44):
            item = board.get((x,y),0)
            if item == 4:
                ball=x
            if item == 3:
                return x, ball

def show_board(board):
    for y in range(21):
        print(''.join([' #*=o'[board.get((x, y), 0)] for x in range(44)]))

mreset = []
for l in open('input.txt', 'r'):
    mreset = [int(x) for x in l.strip().split(',')]
mreset[0] = 2
m = Machine(mreset)
board = {}
score = 0
previous_score = 0
while not m.halted():
    if m.needs_input():
        if score-previous_score > 100:
            show_board(board)
            print(score)
            previous_score = score
        pad, ball = find_pad_and_ball(board)
        m.input(1 if pad < ball else (-1 if pad > ball else 0))
    elif m.output_queue().full():
        x = m.output_queue().get()
        m.run()
        y = m.output_queue().get()
        m.run()
        if x == -1 and y == 0:
            score = m.output_queue().get()
        else:
            board[(x,y)] = m.output_queue().get()
    elif m.halted():
        print('exiting')
        break
    else:
        m.run()
show_board(board)
print(score)


# Custom Imports
import iumsutils           # library of functions specific to my "-IUMS" class of MS Neural Network applications
import TimTkLib as ttl     # library of custom tkinter widgets I've written to make GUI assembly more straightforward
from PLATINUMS_Trainer import TrainingWindow # the trainer component of the app

# Built-in Imports
import json
from pathlib import Path

# Built-in GUI Imports
import tkinter as tk
from tkinter import messagebox
from tkinter import simpledialog
from tkinter import filedialog

class PLATINUMS_App:
    '''PLATINUMS : Prediction, Training, And Labelling INterface for Unlabelled Mobility Spectra'''
    default_paths = {'data_path'    : Path('TDMS Datasets'),  # configure names of default file locations here
                     'preset_path'  : Path('Training Presets'),
                     'save_path'    : Path('Saved Training Results'),
                     'weights_path' : Path('Saved Models')}

    def __init__(self, main):
    #Main Window
        self.main = main
        self.main.title('PLATINUMS v-7.0.5a') # set name with version here
        self.parameters = {}

        for path_type, path in self.default_paths.items(): # on creation, reference class-wide default paths to set up appropriate folders
            path.mkdir(exist_ok=True) # create the path
            setattr(self, path_type, path) # map said path to an internal object attribute

        self.tpmode = tk.BooleanVar() # option to switch from training to prediction mode, WIP and disabled for now

        self.quit_button   = tk.Button(self.main, text='Quit', underline=0, padx=22, pady=11, bg='red', command=self.quit)
        self.tpmode_button = tk.Checkbutton(self.main, text='Predict', var=self.tpmode, underline=2, command=self.switch_tpmode, state='disabled')
        self.reset_button  = tk.Button(self.main, text='Reset', underline=0, padx=20, bg='orange', command=self.reset)

        self.quit_button.grid(  row=0, column=4, sticky='s')
        self.tpmode_button.grid(row=2, column=4)
        self.reset_button.grid( row=6, column=4, padx=2)

        # Primary menu method - universally keybound, irrespective of which cell is enabled
        self.main.bind('q', lambda event : self.quit())
        self.main.bind('e', lambda event : self.tpmode_button.invoke()) # doesn't work while button is disabled, due to invoke (not by accident)
        self.main.bind('r', lambda event : self.reset())

    # Frame 0
        self.spectrum_size  = 0  # initialize empty variables for various data attributes
        self.species        = []
        self.families       = []
        self.evaluands      = []
        self.family_mapping = {}

        self.input_frame = ttl.ToggleFrame(self.main, text='Select Parameter Input Method: ', padx=4)
        self.input_mode  = tk.StringVar()
        for i, mode in enumerate(('Manual Input', 'Preset from File')):  # build selection type buttons sequentially w/o class references (not needed)
            tk.Radiobutton(self.input_frame, text=mode, value=mode, underline=0, padx=9, var=self.input_mode, command=self.initial_input).grid(row=0, column=i)

        self.input_button = tk.Button(self.input_frame, text='Confirm Selection', command=self.confirm_input_mode, bg='deepskyblue2', underline=0, padx=4)
        self.input_button.grid(row=0, column=2)

    #Frame 1
        self.selection_frame = ttl.ToggleFrame(self.main, text='Select Instances to Evaluate: ', padx=5, row=2)
        self.read_mode       = tk.StringVar()

        for i, (mode, underline) in enumerate( (('Select All', 7), ('By Family', 3), ('By Species', 3)) ): # build selection type buttons sequentially w/o class references
            tk.Radiobutton(self.selection_frame, text=mode, value=mode, var=self.read_mode, underline=underline, command=self.evaluand_selection).grid(row=0, column=i)

        self.confirm_sels = tk.Button(self.selection_frame, text='Confirm Selection', command=self.confirm_evaluand_selection, bg='deepskyblue2', underline=0, padx=4)
        self.confirm_sels.grid(row=0, column=3)

    #Frame 2
        self.hyperparam_frame    = ttl.ToggleFrame(self.main, text='Set Hyperparameters: ', padx=8, row=3)

        self.epoch_entry         = ttl.LabelledEntry(self.hyperparam_frame, text='Epochs:',    var=tk.IntVar(),    default=2048, width=16, row=0, col=0)
        self.batchsize_entry     = ttl.LabelledEntry(self.hyperparam_frame, text='Batchsize:', var=tk.IntVar(),    default=32,   width=16, row=1, col=0)
        self.learnrate_entry     = ttl.LabelledEntry(self.hyperparam_frame, text='Learnrate:', var=tk.DoubleVar(), default=2e-5, width=18, row=0, col=2, spacing=(10,0))

        self.confirm_hyperparams = tk.Button(self.hyperparam_frame, text='Confirm Selection', command=self.confirm_hp, padx=5, bg='deepskyblue2', underline=0)
        self.confirm_hyperparams.grid(row=1, column=3, columnspan=2, sticky='e')

    #Frame 3
        self.slicing_frame       = ttl.ToggleFrame(self.main, text='Set Slicing Parameters: ', padx=7, row=4)

        self.n_slice_entry       = ttl.LabelledEntry(self.slicing_frame, text='Slices:',    var=tk.IntVar(), default=0,  width=18, row=0, col=0)
        self.lower_bound_entry   = ttl.LabelledEntry(self.slicing_frame, text='Bottom:',    var=tk.IntVar(), default=0,  width=18, row=1, col=0)
        self.slice_dec_entry     = ttl.LabelledEntry(self.slicing_frame, text='Decrement:', var=tk.IntVar(), default=10, width=18, row=0, col=2, spacing=(0, 0))

        self.confirm_sliceparams = tk.Button(self.slicing_frame, text='Confirm Selection', command=self.confirm_sparams, padx=5, bg='deepskyblue2', underline=0)
        self.confirm_sliceparams.grid(row=1, column=3, columnspan=2, sticky='e')

    #Frame 4
        self.param_frame  = ttl.ToggleFrame(self.main, text='Set Training Parameters:', padx=6, row=5)

        self.tolerance_entry = ttl.LabelledEntry(self.param_frame, text='Tolerance:', var=tk.DoubleVar(), default=0.01, width=16, row=2, col=2, spacing=(6, 0))
        self.fam_switch   = ttl.Switch(self.param_frame, text='Familiar Training:',  underline=0, row=0, col=0)
        self.cycle_switch = ttl.Switch(self.param_frame, text='Cycle Familiars: ',   underline=1, row=1, col=0)
        self.convergence_switch  = ttl.Switch(self.param_frame, text='Convergence:', underline=3, row=2, col=0, dependents=(self.tolerance_entry,),
                                             toggle_action=lambda state : self.epoch_entry.set_value(state and 10**6 or self.parameters['num_epochs'])) # toggle epochs based on convergence
        self.save_switch  = ttl.Switch(self.param_frame, text='Save Weights:',       underline=5, row=3, col=0)

        self.blank_var   = tk.BooleanVar()
        self.save_preset = tk.BooleanVar()

        self.blank_option_button = tk.Checkbutton(self.param_frame, text=' '*21, var=self.blank_var, padx=5) # leaving room for future expnadability
        self.save_preset_button   = tk.Checkbutton(self.param_frame, text='Save Preset?', var=self.save_preset, underline=0, padx=5)

        self.blank_option_button.grid(row=0, column=2, columnspan=2, sticky='e')
        self.save_preset_button.grid( row=1, column=2, columnspan=2, sticky='e')

        self.confirm_train_params = tk.Button(self.param_frame, text='Confirm Selection', command=self.confirm_tparams, bg='deepskyblue2', underline=0, padx=6)
        self.confirm_train_params.grid(row=3, column=2, columnspan=2, sticky='e')

    # Frame 5 - contains only the button used to trigger a main action
        self.activation_frame = ttl.ToggleFrame(self.main, text='', padx=0, pady=0, row=6)

        self.train_button = tk.Button(self.activation_frame, text='TRAIN', padx=22, width=44, bg='deepskyblue2', underline=0, command=self.training)
        self.pred_button = tk.Button(self.activation_frame, text='PREDICT', padx=22, width=44, bg='mediumorchid2', state='disabled', command=lambda:None)

        self.train_button.grid(row=0, column=0) # overlap buttons, so they can displace one another
        self.pred_button.grid( row=0, column=0)

        self.switch_tpmode()

    # Packaging together some widgets and attributes, for ease of reference (also useful for self.reset() and self.isolate() methods)
        self.arrays      = (self.parameters, self.species, self.families, self.evaluands, self.family_mapping)
        self.switch_vars = (self.read_mode, self.input_mode, self.blank_var, self.save_preset)
        self.frames      = (self.input_frame, self.selection_frame, self.hyperparam_frame, self.slicing_frame, self.param_frame, self.activation_frame)

        self.tparam_mapping = {self.convergence_switch : 'convergence',
                               self.tolerance_entry : 'tolerance', # strictly an entry, not a switch, but makes code cleaner of placed here
                               self.fam_switch : 'fam_training',
                               self.cycle_switch : 'cycle_fams',
                               self.save_switch : 'save_weights'}
        self.hp_entry_mapping = {self.epoch_entry : 'num_epochs',
                                 self.batchsize_entry : 'batchsize',
                                 self.learnrate_entry : 'learnrate'}
        self.slice_entry_mapping = {self.lower_bound_entry : 'trimming_min',
                                    self.slice_dec_entry : 'slice_decrement',
                                    self.n_slice_entry : 'num_slices'}
        self.field_mapping = {**self.tparam_mapping, **self.hp_entry_mapping, **self.slice_entry_mapping} # merged internal dict of all field which can be filled out within the app

        self.main.bind('<Key>', self.key_in_input) # activate internal conditional hotkey binding
        self.reset() # set menu to default configuration

    #General Methods
    def lift(self):
        '''Bring GUI window to front of tabs'''
        self.main.attributes('-topmost', True)
        self.main.attributes('-topmost', False)

    def isolate(self, on_frame):
        '''Enable just one frame.'''
        for frame in self.frames:
            if frame == on_frame:
                frame.enable()
            else:
                frame.disable()

    def quit(self):
        '''Close the application, with confirm prompt'''
        if messagebox.askokcancel('Quit PLATINUMS?', 'Are you sure you want to close?'):
            self.main.destroy()

    def switch_tpmode(self):
        '''Used to switch the mode of the training button; planned future feature, WIP at the moment'''
        target_button = self.tpmode.get() and self.pred_button or self.train_button
        target_button.tkraise()

    def key_in_input(self, event):
        '''Hotkey binding wrapper for all frames - ensures actions are only available when the parent frame is enabled'''
        if self.input_frame.state == 'normal': # do not allow hotkeys to work if frame is disabled
            if event.char in ('m', 'p'): # bindings for input modes
                self.input_mode.set((event.char == 'm' and 'Manual Input' or 'Preset from File'))
                self.initial_input()
            elif event.char == 'c': # binding for confirmation
                self.confirm_input_mode()
        elif self.selection_frame.state == 'normal':
            opt_mapping = {'a' : 'Select All',
                           'f' : 'By Family',
                           's' : 'By Species'}
            if event.char in opt_mapping:
                self.read_mode.set(opt_mapping[event.char]) # choose one of the read modes if the proper hotkey is selected
                self.evaluand_selection() # open further selection menu if not just selecting all
            elif event.char == 'c':
                self.confirm_evaluand_selection()
        elif self.hyperparam_frame.state == 'normal' and event.char == 'c':
            self.confirm_hp()
        elif self.slicing_frame.state == 'normal' and event.char == 'c':
            self.confirm_sparams()
        elif self.param_frame.state == 'normal':
            switch_mapping = {'f' : self.fam_switch,
                              'w' : self.save_switch,
                              'v' : self.convergence_switch,
                              'y' : self.cycle_switch}
            if event.char in switch_mapping:
                switch_mapping[event.char].toggle() # make parameter switches toggleable with keyboard
            elif event.char == 's': # add hotkey to save preset and proceed...
                self.save_preset.set(not self.save_preset.get()) # invert cycling status
            #elif event.char == 'n': # add hotkey to save preset and proceed...
            #    self.blank_var2.set(not self.blank_var2.get()) # invert status
            elif event.char == 'c': # or just to proceed
                self.confirm_tparams()
        elif self.activation_frame.state == 'normal' and event.char == 't': # do not allow hotkeys to work if frame is disabled
            self.training()

    def reset(self):
        '''reset the GUI to the opening state, along with all variables'''
        for widget in self.main.winfo_children(): # close any TopLevel windows that may happen to be open when reset is hit (be it for selection or training)
            if isinstance(widget, tk.Toplevel):
                widget.destroy()

        for tk_switch_var in self.switch_vars:
            tk_switch_var.set(0)

        self.spectrum_size = 0
        for array in self.arrays:
            array.clear()

        for field in self.field_mapping.keys():
            field.reset_default() # reset defaults for all switches and entries

        self.lift() # bring main window to forefront
        self.isolate(self.input_frame)

    # Frame 0 (Parameter Input) Methods
    def initial_input(self):
        '''Method called for initiating input (be it manual or from preset)'''
        if self.input_mode.get() == 'Manual Input':
            self.parameters['data_files'] = [] # ensure a list exists AND is empty when selecting files
            ttl.SelectionWindow(self.main, self.input_frame, sorted(iumsutils.get_by_filetype('.json', self.data_path)),
                                self.parameters['data_files'], window_title='Select data file(s) to train over', ncols=4)

        elif self.input_mode.get() == 'Preset from File':
            preset_path = Path(filedialog.askopenfilename(title='Choose Training Preset', initialdir='./Training Presets', filetypes=(('JSONs', '*.json'),) ))
            try:
                with preset_path.open() as preset_file: # load in the parameter preset (ALL settings)
                    self.parameters = json.load(preset_file)
            except json.decoder.JSONDecodeError:
                messagebox.showerror('Preset Format Error', 'Incorrect formatting in preset file;\n Please check preset for errors and try again')
            except PermissionError: # do nothing if user cancels selection
                self.input_mode.set(0)

    def check_input_files(self):
        '''Performs check to determine whether the files chosen for training have compatible data'''
        try:
            if not self.parameters['data_files']:
                messagebox.showerror('File Error', 'No data file(s) selected')
                self.reset()
            else:
                for file in self.parameters['data_files']:
                    json_data = iumsutils.load_chem_json(self.data_path/f'{file}.json')
                    for data_property in ('spectrum_size', 'species', 'families', 'family_mapping'):
                        self.main.update() # update main wndow every cycle to ensure window/cursor doesn't freeze during checking
                        if not getattr(self, data_property): # check if the fields are empty, relies on attribute names being same as json keys - note lack of default attr
                            setattr(self, data_property, json_data[data_property])
                        else:
                            if data_property == 'spectrum_size':
                                self.spectrum_size = min(self.spectrum_size, json_data['spectrum_size']) # ensures min_spectrum size is indeed the minimum across all files
                            elif json_data[data_property] != getattr(self, data_property):
                                messagebox.showerror('Property Mismatch', f'Attribute "{data_property}" in {file} does not match that of the other files chosen')
                                return # break out of loops
        except KeyError: # catch when the 'data_files' entry does not exist
            messagebox.showerror('Files Undefined', 'Property "data_files" missing from parameters, please check preset')
            self.reset()

    def confirm_input_mode(self):
        '''Performs final check over input and determines how to proceed appropriately'''
        if self.input_mode.get() not in ('Manual Input', 'Preset from File'):
            messagebox.showerror('No input mode selected!', 'Please choose either "Manual" or "Preset" input mode')
            self.reset()
        else:
            self.main.config(cursor='wait') # this make take a moment for large sets of files, indicate to user (via cursor) to be patient
            self.check_input_files()

            if self.input_mode.get() == 'Manual Input':
                self.isolate(self.selection_frame)
            elif self.input_mode.get() == 'Preset from File': # could simply leave as "else", but is more explicit as is

                for field, param in self.field_mapping.items():
                    try:
                        field.set_value(self.parameters[param]) # configure all the switch values in the GUI
                    except KeyError as error:
                        messagebox.showerror('Preset Error', f'The parameter "{error}" is either missing or misnamed;\n Please check preset file for errors')
                        break

                self.read_mode.set(self.parameters['read_mode'])
                self.confirm_evaluand_selection() # assigns evaluands based on the given read mode and selections buffer

                self.check_trimming_bounds() # ensure that bounds actually make sense
                self.isolate(self.activation_frame)
            self.main.config(cursor='') # return cursor to normal

    # Frame 1 (Evaluand Selection) Methods
    def evaluand_selection(self):
        '''logic for selection of evaluands to include in training, based on the chosen selection mode'''
        self.parameters['selections'] = [] # empties internal evaluand buffer when selection menu is re-clicked (ensures no overwriting or mixing, also serves as first-time list init)
        self.parameters['read_mode']  = self.read_mode.get() # record the read mode to parameters with each selection

        if self.read_mode.get() == 'By Species':
            ttl.SelectionWindow(self.main, self.selection_frame, self.species, self.parameters['selections'], window_title='Select Species to evaluate', ncols=8)
        elif self.read_mode.get() == 'By Family':
            ttl.SelectionWindow(self.main, self.selection_frame, self.families, self.parameters['selections'], window_title='Select Families to evaluate over', ncols=3)
        elif self.read_mode.get() == 'Select All':
            self.parameters['selections'].append('All Species') # add a flag to make clear that all species are being selected

    def confirm_evaluand_selection(self):
        '''Parsing and processing of the selections before proceeding'''
        if self.read_mode.get() == 'By Species':
            self.evaluands = self.parameters['selections']
        elif self.read_mode.get() == 'By Family':  # pick out species by family if selection by family is made
            self.evaluands = [species for species in self.species if iumsutils.get_family(species) in self.parameters['selections']]
        elif self.read_mode.get() == 'Select All':
            self.evaluands = self.species

        if not self.evaluands: # if the evaluands is still empty (or doesn't exist), instruct the user to make a choice
            messagebox.showerror('No evaluands selected', 'Please ensure one or more species have been selected for evaluation')
        else:
            self.isolate(self.hyperparam_frame)
            self.tolerance_entry.configure(state='disabled') # ensure tolerance dependent remains disabled

    # Frame 2 (hyperparameter) Methods
    def confirm_hp(self):
        '''Confirm the selected hyperparameters and proceed'''
        for hp_entry, param in self.hp_entry_mapping.items():
            self.parameters[param] = hp_entry.get_value()
        self.isolate(self.slicing_frame)

    # Frame 3 (slicing parameter) Methods
    def confirm_sparams(self):
        '''Confirm the selected slicing and proceed'''
        for slice_entry, param in self.slice_entry_mapping.items():
            self.parameters[param] = slice_entry.get_value()
        self.check_trimming_bounds() # ensure bounds make sense, notify the user if they don't
        self.isolate(self.param_frame)
        self.convergence_switch.disable() # ensure convergence is disabled by default

    # Frame 4 (training parameter) Methods
    def check_trimming_bounds(self):
        '''Performs error check over the trimming bounds held internally to ensure that sensible bounds are chosen to ensure that training will not fail'''
        trimming_min    = self.parameters['trimming_min'] # have pulled these out here solely for readability
        num_slices      = self.parameters['num_slices']
        slice_decrement = self.parameters['slice_decrement']

        if trimming_min < 0 or type(trimming_min) != int:
            messagebox.showerror('Boundary Value Error', 'Trimming Min must be a positive integer or zero')
        elif self.spectrum_size - num_slices*slice_decrement <= trimming_min: # note that spectrum size here is the minimum size; this guarantees all datasets will pass
            messagebox.showerror('Boundary Mismatch', 'Upper limit will not always exceed lower;\nDecrease either slice decrement or lower bound')

    def confirm_tparams(self):
        '''Confirm training parameter selections, perform pre-training error checks if necessary'''
        for field, param in self.tparam_mapping.items():
            self.parameters[param] = field.get_value() # configure parameters based on the switch values

        if self.convergence_switch.get_value(): # update the number of epochs in the parameters dict (to reflect the visual change in the GUI) if convergence is enabled
            self.parameters['num_epochs'] = self.epoch_entry.get_value()

        if self.save_preset.get(): # if the user has elected to save the current preset
            preset_path = Path( filedialog.asksaveasfilename(title='Save Preset to file', initialdir='./Training Presets', defaultextension='.json', filetypes=[('JSONs', '*.json')]) )
            try:
                with open(preset_path, 'w') as preset_file:
                    json.dump(self.parameters, preset_file)
            except PermissionError: # catch the case in which the user cancels the preset saving
                return

        self.isolate(self.activation_frame) # make the training button clickable if all goes well

    # Frame 5: the training routine itself, this is where the magic happens
    def training(self):
        '''Initialize a PLATINUMS_Trainer using the inputted parameters'''
        if self.parameters['convergence']:
            stop_str = f'{self.parameters["tolerance"]} Error'
        else:
            stop_str = f'{self.parameters["num_epochs"]} Epoch'

        if self.parameters["cycle_fams"]:
            training_type_str = 'cycled'
        else:
            training_type_str = (self.parameters["fam_training"] and 'familiar' or 'unfamiliar')

        parent_name = simpledialog.askstring(title='Set Result Folder Name', prompt='Please enter a name to save training results under:', initialvalue=f'{stop_str}, {training_type_str}')
        if not parent_name: # if file determination returns empty due to user cancellation/omission, exit training routine
            return
        else:
            self.activation_frame.disable()
            train_window = TrainingWindow(self, parent_name, nw_compat=False) # pass the GUI app to the training window object to allow for menu manipulation
            train_window.training(keras_verbosity=0)

if __name__ == '__main__':
    main_window = tk.Tk()
    app = PLATINUMS_App(main_window)
    main_window.mainloop()


""" Plays video """

import sys

import cv2 as cv
import imutils

from .reader import VideoStream

class VideoPlayer:
    """
    Plays videos, optionally calling `frame_callback` with every frame as
    parameter
    """

    def __init__(
        self,
        stream: VideoStream = None,
        scale=1,
        window_name="Rakali Video",
        frame_callback=None,
    ):
        """Video player"""

        self.stream = stream
        self.scale = scale
        self.window_name = window_name
        self.callback = frame_callback

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        cv.destroyAllWindows()

    def rescale(self, img):
        """Scale the resulting video display to better fit"""

        if self.scale != 1:
            return imutils.resize(img, width=int(img.shape[1] * self.scale))
        else:
            return img

    def autoplay(self):
        """
        read the stream and display each frame, applying the callback to each
        frame
        """
        with self.stream as st:
            while cv.waitKey(1) & 0xFF != ord("q"):
                ok, frame = st.read()
                if ok:
                    img = self.rescale(frame)
                    if self.callback:
                        img = self.callback(img)
                    cv.imshow(self.window_name, img)
                else:
                    print("No more frames")
                    sys.exit()

        cv.destroyAllWindows()
        sys.exit()

    def show(self, frame):
        """Show the frame"""

        img = self.rescale(frame)
        if self.callback:
            img = self.callback(img)
        cv.imshow(self.window_name, img)


from jinja2 import Template, exceptions
from glob import glob
from hcl import load
import re
import sys
import os
import logging
import argparse

logging.basicConfig()
logger = logging.getLogger('resolver')
log_lvl = 'ERROR'

class ResolverError(Exception):
  pass

def get_j2_files(directory):
  """
  Return all .tf.j2 files in a directory
  """
  if not directory.endswith("/"):
    directory = directory + '/'
    return get_j2_files(directory)
  else:
    j2_files = glob(directory + "*.tf.j2")
    logger.info
    if len(j2_files) > 0:
      logger.info('Listing .tf.j2 files.')
      return j2_files
    else:
      raise ResolverError("There are no .tf.j2 files, or the directory doesn't exist.")

def tfvars_to_dictionnary(tfvars_file):
  """
  Load a tfvars file and return a python dictionnary
  """
  try:
    with open(tfvars_file, 'r') as tfvars:
      return load(tfvars)
  except FileNotFoundError as error:
    raise ResolverError(error)
  except ValueError as error:
    raise ResolverError("Loading tfvars file : {}".format(error))

def render_j2(jinja2_file, values):
  """
  From the j2 template and the terraform values, render the j2 template with the Terraform variables
  """
  with open(jinja2_file) as jinja2:
    logger.info('Rendering {} template with the tfvars.'.format(jinja2_file))
    jinja_template = Template(jinja2.read())
    return jinja_template.render(values)

def generate_render_files(j2_files, tfvars):
  """
  From j2_files and tfvars dictionnary, generate .tf files and delete .tf.j2 files, and return the list of resolved Terraform code.
  """
  rendering_list = []
  for file in j2_files:
    file_tf = re.sub(".j2", "", file)
    logger.info('Creating {} file.'.format(file_tf))
    with open(file_tf, "w+") as render_file:
      logger.info('{} file created.'.format(file_tf))
      try:
        rendering = render_j2(file, tfvars)
        logger.debug('Rendering {0} :\n{1}'.format(file, rendering))
        logger.info('Write render result in {}'.format(file_tf))
        rendering_list.append(rendering)
        render_file.write(rendering)
      except exceptions.UndefinedError as error:
        raise ResolverError(error)
  return(rendering_list)

def resolve(directory, tfvars_files):
  """
  From the directory and a list of tfvars files, generate .tf files and delete .tf.j2 files, and return the list of resolved Terraform code.
  """
  logger.info('Starting the resolve on \'{0}\' directory with tfvars files {1}.'.format(directory, tfvars_files))
  j2_files = get_j2_files(directory)
  tfvars = {}
  for file in tfvars_files:
    logger.info('Aggregating {} to a central tfvars dictionnary.'.format(file))
    tfvars.update(tfvars_to_dictionnary(file))
  logger.debug('Aggregated tfvars : {}'.format(tfvars))
  rendering = generate_render_files(j2_files, tfvars)
  logger.info('Resolve completed.')
  return(rendering)

def get_args():
  """
  Get the command line parameters
  """
  parser = argparse.ArgumentParser('Generate Terraform files from Jinja2 templates.')
  parser.add_argument('--templates-dir', default='.', help='Location of the jinja2 template files. Default is current directory.')
  parser.add_argument('--tfvars', default=None, nargs='+', help='tfvars file to use with the templates.')
  parser.add_argument('--debug', action='store_const', const='DEBUG', help='DEBUG Level of verbosity.')

  args = parser.parse_args()
  return args

def main():
  """
  Entrypoint
  """
  args = get_args()

  if args.debug:
    log_level = args.debug
  else:
    log_level = 'ERROR'
  logger.setLevel(getattr(logging, log_level))

  try:
    resolve(args.templates_dir, args.tfvars)
  except ResolverError as error:
      if os.getenv('DEBUG', None):
          import traceback
          traceback.print_exc()
      else:
          logger.error(error)
      sys.exit(1)

if __name__ == "__main__":
    main()


# We need these imports to import every race.
from humans import human
from demons import demon
from elfs import elf
from goblins import goblin
from orks import ork

no = "no"
yes = "yes"
yes_no = ("yes" or "no")
available_classes = "Available classes: rogue, wizard, knight."

races = \
    (
        human, demon, elf, goblin, ork
    )
races_names = \
    (
            "human" or "demon" or "elf" or "goblin" or "ork"
    )

def main():
    pass

if __name__ == '__main__':
    main()


# Bootcamp "Geração Tech Unimed-BH - Ciência de Dados"
# Digital Innovation One
# Desafio de Código: As Duas Torres

# Dados de entrada na ordem N, X e Y, separados por espaços
entrada = input("Digite os valores de entrada, separados por espaços: ").split()

# a distância entre os Palantír - N(0 < N < 10000)
N = int(entrada[0])

# o diâmetro do Palantír de Sauron - X > 0
X = int(entrada[1])

#  o diâmetro do Palantír de Saruman - Y < 100
Y = int(entrada[2])

# Cálculo do ICM
ICM = N / (X + Y)

print("%.2f" %ICM)


# Crie um programa onde 4 jogadores joguem um dado e tenham resultados aleatórios.
# Guarde esses resultados em um dicionário.
# No final, coloque esse dicionário em ordem, sabendo que o vencedor tirou o maior numero no dado

import random
import time
import operator

ranking = []
bib = {'Jogador 1': random.randint(1, 6),
       'Jogador 2': random.randint(1, 6),
       'Jogador 3': random.randint(1, 6),
       'Jogador 4': random.randint(1, 6)}
for c, v in bib.items():
    print(f'O {c} tirou {v} no dado')
    time.sleep(1)
ranking = sorted(bib.items(), key=operator.itemgetter(1), reverse=True)
print('-=-' * 15)
for p, j in enumerate(ranking):
    print(f'{p + 1}o Lugar Ficou {j[0]} que tirou {j[1]} no dado')
    time.sleep(1)


import json
import os
import re
from os.path import join
import numpy as np
import matplotlib.pyplot as plt
#plt.interactive(False)

results_path = "./models/Round One"
integer_regex = "^[-+]?[0-9]+$"
pattern = re.compile(integer_regex)

filesDirectory = os.listdir(results_path)

accuracies = np.zeros(len(filesDirectory), dtype=list)
losses = np.zeros(len(filesDirectory), dtype=list)
lres = np.zeros(len(filesDirectory), dtype=list)
fnames = np.zeros(len(filesDirectory), dtype=str)

for idx, filename in enumerate(sorted(filesDirectory)):
    if(filename.endswith('.json')) and pattern.match(filename.replace('.json','')):
        with open(join(results_path, filename), 'r') as reader:
            json_data = json.load(reader)
            # if json_data['test_accuracy'] >= 0.12987012987012986:
            #     print('#########################################')
            #     print('Test acurracy: ', json_data['test_accuracy'])
            #     for key, param in json_data['params'].items():
            #         print(key, '                ', param)
            accuracies[idx] = json_data['history']['acc']
            losses[idx] = json_data['history']['loss']
            lres[idx] = json_data['history']['lr']
            fnames[idx] = filename

# print(len(accuracies))
# for idx, acc in enumerate(accuracies):
#     plt.plot(acc, label=idx)
#     if idx == 23:
#         print(acc)
#         print(fnames[idx])

print(len(lres))
for idx, acc in enumerate(lres):
    plt.plot(acc, label=idx)

plt.title('lr')
plt.ylabel('ylabel')
plt.xlabel('xlabel')
plt.legend(prop={'size': 6})
# for loss in losses:
#     plt.plot(loss)

plt.show()


import pytest

from .deps import *

class TestCompiler(Test):
    def test_unexpected_toplevel(self, internals):
        src = """
quasi "test"
"""
        with pytest.raises(CompilerError):
            program = internals.compiler.compile(src)

    def test_double_main(self, internals):
        src = """
und zwar main2 action please
    quasi "test"

und zwar main1 action please
    quasi "test"
"""
        with pytest.raises(CompilerError):
            program = internals.compiler.compile(src)

    def test_auto_main(self, internals):
        src = """
quasi "toplevel"
"""
        program = internals.compiler.compile(src, auto_main=True)
        self.assertTrue(pylovm2.ENTRY_POINT in program)

        import io
        stdout = io.StringIO()
        internals.interpreter._ctx.set_stdout(stdout)

        internals.interpreter.load(program)
        internals.interpreter.run()

        self.assertEqual('toplevel\n', stdout.getvalue())

    def test_misinterpreted_return(self, internals):
        src = '''
und zwar main action please
    4 im quadrat und fertig
        '''

        program = internals.compiler.compile(src)
        internals.interpreter.load(program)
        self.assertEqual(16, int(internals.interpreter.call('main')))


import  json
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin # new

from django.views.generic import (
    TemplateView,
    ListView,
    DeleteView,
)
from django.views import View
from django.views.generic.edit import CreateView
from .models import (
    Food,
    Order,
    Recreation,
    TableReservation,
    Reservation,
    Recreation,
    Activity,
)
from .forms import (
    RecreationForm,
    TableReservationForm,
)

# Create your views here.

class IndexPageView(ListView):
    template_name = 'restaurant/index.html'
    context_object_name = 'activities'
    model = Activity

class FoodListView(LoginRequiredMixin, ListView):
    template_name = 'food_list.html'
    context_object_name = 'foods'
    model = Food

class FoodOrderView(LoginRequiredMixin, View):
    template_name = 'restaurant/food_order.html'

    def get(self, request, pk, *args, **kwargs):
        my_food = Food.objects.get(pk=pk)
        print(my_food)
        context = {
            'my_food': my_food,
        }

        return render(request, self.template_name, context)

    def post(self, request, pk, *args, **kwargs):
        my_food = Food.objects.get(id=pk)
        quantity = int(request.POST.get('quantity'))
        email = request.POST.get('email')
        street = request.POST.get('street')
        city = request.POST.get('city')
        state = request.POST.get('state')
        zip_code = request.POST.get('zip')

        # calculate the purchase total
        price = quantity * my_food.price

        order = Order.objects.create(
            customer = request.user,
            food = my_food,
            quantity = quantity,
            price = price,
            email = email,
            street = street,
            city = city,
            state = state,
            zip_code = zip_code,
        )

        context = {
            'order': order,
        }

        return redirect('order-confirmation', pk=order.pk)

class OrderConfirmation(LoginRequiredMixin, View):
    def get(self, request, pk, *args, **kwargs):
        order = Order.objects.get(pk=pk)
        context = {
            'pk': order.pk,
            'price': order.price,
            'quantity': order.quantity,
            'food': order.food,
        }

        return render(request, 'restaurant/order_confirmation.html', context)

    def post(self, request, pk, *args, **kwargs):
        data = json.loads(request.body)
        if data['isPaid']:
            order = Order.objects.get(pk=pk)
            order.is_paid = True
            order.save()

        return redirect('payment-confirmation')

class OrderPayConfirmation(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        return render(request, 'restaurant/order_pay_confirmation.html')

class TableReservationView(LoginRequiredMixin, CreateView):
    model = TableReservation
    form_class = TableReservationForm
    template_name = 'restaurant/table_reservation.html'

class ReservationConfirmationView(LoginRequiredMixin, View):
    def get(self, request, pk, *args, **kwargs):
        table_reservation = TableReservation.objects.get(id = pk)
        print(table_reservation.type.price)

        context = {
            'id': table_reservation.id,
            'type': table_reservation.type,
            'no_people': table_reservation.no_people,
            'phone': table_reservation.phone,
            'price': table_reservation.type.price,
            'customer': request.user,
        }

        return render(request, 'restaurant/reservation_confirmation.html', context)

    def post(self, request, pk, *args, **kwargs):
        data = json.loads(request.body)
        if data['isPaid']:
            reservation = TableReservation.objects.get(id=pk)
            reservation.customer = request.user
            reservation.email = request.user.email
            reservation.price = float(data['price'])
            reservation.is_paid = True
            reservation.save()

        return redirect('payment-confirmation')

class RecreationalActivityView(LoginRequiredMixin, CreateView):
    model = Recreation
    form_class = RecreationForm
    template_name = 'restaurant/recreation.html'

class RecreationConfirmationView(LoginRequiredMixin, View):
    def get(self, request, pk, *args, **kwargs):
        recreation = Recreation.objects.get(id = pk)
        total_price = recreation.activity.price * recreation.no_days
        context = {
            'id': recreation.id,
            'activity': recreation.activity,
            'no_people': recreation.no_days,
            'phone': recreation.phone,
            'price': recreation.activity.price,
            'total_price': total_price,
        }

        return render(request, 'restaurant/recreation_confirmation.html', context)

    def post(self, request, pk, *args, **kwargs):
        data = json.loads(request.body)
        if data['isPaid']:
            recreation = Recreation.objects.get(id=pk)
            recreation.customer = request.user
            recreation.email = request.user.email
            recreation.price = float(data['price'])
            recreation.is_paid = True
            recreation.save()

        return redirect('payment-confirmation')

class DashboardView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        orders = Order.objects.filter(email=request.user.email)
        reservations = TableReservation.objects.filter(email= request.user.email)
        recreations = Recreation.objects.filter(email=request.user.email)

        print(orders)
        for order in orders:
            print(order.food)

        context = {
            'orders': orders,
            'reservations': reservations,
            'recreations': recreations,
        }

        return render(request, 'restaurant/dashboard.html', context)


from optparse import OptionParser
import os.path
import urllib.parse

VERSION = '1.0'

def get_strings(src_file):
    """getting strings from file"""
    res = []
    try:
        res = open(src_file,'r').readlines()
        res = [x.strip() for x in res]
    except:
        res = []
    return res

def append_sitename(strs,site):
    """adding site name to strings"""
    strs = [x+' site:'+site for x in strs]
    return strs

def save_output(strs,out_f):
    """saving/printing results"""
    res = "\n".join(strs)

    if out_f:
        try:
            open(out_f,'w').write(res)
        except:
            print ("Error! Couldn't save output file!")
            exit()
    else:
        print (res)

def main():
    """Parsing options and starting engine"""
    parser = OptionParser(usage="%prog <sourcefile> [-s site] [-q] [-t] [-f outfile]",
              version="SecPoint.com %prog "+VERSION,
              epilog="SecPoint.com Google Penetration Testing Hack Database v. "+VERSION)
    parser.add_option("-o", "--output", dest="filename",
                      help="save output to file", metavar="FILE")
    parser.add_option("-s", "--site", dest="sitename",
                      help="generate queries for the SITE", metavar="SITE")
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.print_help()
        exit()
        #parser.error("please set source file (could be found in 'db' dir)")
    #all options
    site_name = options.sitename
    out_file = options.filename
    db_dir = os.path.join(os.path.dirname(__file__),'db')
    source_file = os.path.join(db_dir,args[0])
    if not os.path.isfile(source_file):
        parser.error("could not find source file! Please check if it exists in 'db' dir")

    #starting!
    strs = get_strings(source_file)
    if not strs:
        print ("Can't get data from your source file!")
        exit()
    queries = []
    if site_name:
        strs = append_sitename(strs,site_name)

    save_output(strs,out_file)

if __name__ == "__main__":
    main()


#69. Sqrt(x)
class Solution:
    def mySqrt(self, x: int) -> int:
        start,end=0,x
        while start+1<end:
            mid=start+(end-start)//2
            if mid**2>x:
                end=mid
            else:
                start=mid
        if end**2<=x:
            return end
        else:
            return start

# 852. Peak Index in a Mountain Array
class Solution:
    def peakIndexInMountainArray(self, A: List[int]) -> int:
        if A is None or len(A)<3:
            return -1
        target=A[-1]
        start,end=0,len(A)-1
        while start+1<end:
            mid=start+(end-start)//2
            if A[mid-1]<A[mid]<A[mid+1]:
                start=mid
            elif A[mid-1]>A[mid]>A[mid+1]:
                end=mid
            else:
                return mid
#74. Search a 2D Matrix
class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        if matrix is None or len(matrix)==0:
            return False
        n, m = len(matrix), len(matrix[0])
        if m==0:
            return False
        start, end = 0, n * m - 1
        while start + 1 < end:
            mid = (start + end) // 2
            x, y = mid // m, mid % m
            if matrix[x][y] < target:
                start = mid
            else:
                end = mid
        x, y = start // m, start % m
        if matrix[x][y] == target:
            return True

        x, y = end // m, end % m
        if matrix[x][y] == target:
            return True

        return False

# 34. Find First and Last Position of Element in Sorted Array
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        left=self.left_index(nums, target, True)
        right=self.left_index(nums, target, False)-1
        if left==len(nums) or nums[left]!=target:
            return [-1,-1]
        return[left,right]

    def left_index(self,nums: List[int], target: int, left_or_right:bool):
        start,end=0,len(nums)
        while start<end:
            mid=(start+end)//2
            if nums[mid]>target or (nums[mid]==target and left_or_right):
                end=mid
            else:
                start=mid+1
        return start


from ojoqt.utils import point_math
from ojoqt.widget.graphics import Circle, Mouse
from ojoqt.widget.graphics import Line

class MouseIndicator:
    def __init__(self, event, color_origin, color_mouse, radius, press_time, swipe_distance):
        self._event = event
        self._radius = radius
        self._press_time = press_time
        self._swipe_distance = swipe_distance

        self._circle_origin = Circle(event)
        self._circle_origin.set_color(color_origin)
        self._circle_origin.pen.setWidth(2)

        self._circle_mouse = Circle(event)
        self._circle_mouse.set_color(color_mouse)
        self._circle_mouse.pen.setWidth(2)

        self._line_mouse = Line(event)

    @property
    def mouse(self) -> Mouse:
        return self._event['mouse']()

    def update(self):
        mouse = self.mouse
        mouse_l = mouse.button(mouse.BUTTON_LEFT)

        if mouse_l.press:
            p = min(mouse_l.press_time, self._press_time) / self._press_time

            rn = p * self._radius
            self._circle_mouse.set_radius(rn)
            self._circle_origin.set_radius(rn / 2)

            self._circle_mouse.set_position(*mouse.position)
            self._circle_origin.set_position(*mouse_l.down_position)

            ps, pe = self._circle_origin.position, self._circle_mouse.position
            ps = point_math.move(*ps, self._circle_origin.radius, point_math.angle(*ps, *pe))
            pe = point_math.move(*pe, self._circle_mouse.radius, point_math.angle(*pe, *ps))
            self._line_mouse.set_position(*ps)
            self._line_mouse.set_position_end(*pe)

    def draw(self):
        mouse = self.mouse
        mouse_l = mouse.button(mouse.BUTTON_LEFT)
        if mouse_l.press:
            if mouse_l.press_distance > self._swipe_distance:
                self._line_mouse.draw()
            self._circle_origin.draw()
            self._circle_mouse.draw()


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

# In[4]:

list1=[(1,2,3),[1,2],["a","hit","less"]]
list2=list1[1]+list1[2]
list1=list(list1[0])
list1.append(list2)
print(list1)

# In[ ]:


def select_sort(data):
    """选择排序
    :param data: list
    :return: list
    """
    length = len(data)
    for i in range(length - 1):
        min_index = i
        for j in range(i+1, length, 1):
            if data[j] < data[min_index]:
                min_index = j
        data[i], data[min_index] = data[min_index], data[i]
    return data

if __name__ == '__main__':
    # 将list分为两个部分，第一部分为已排好的数据，第二部分为未排序的数据，将第二部分最小的元素放到第一部分的最后
    # 但遇到相同元素时该排序算法不稳定
    data = [100, 1, 2, 3, 4, 50, 5, 6, 7, 8, 9]
    sorted_data = select_sort(data)
    print(sorted_data)
    # 时间复杂度为O(n*n)