"""
USP  Computação Gráfica - SCC0250 2020/1
Prof. Ricardo Marcondes Marcacini

Richard Calderan - 3672382

Trabalho 2

obs:
Requisito 5- ao invés do terreno ter 2 texturas, eu optei por deixar os outros objetos com mais texturas
O "gollum", por exemplo tem 4

requisito 9: Eu gostaria de limitar o movimento da camera criando uma função que pegasse a sua posição e comparasse com um
o vertice mais proximo dela comparando suas coordenadas no eixo Y, mas infelizmente esta abordagem se demostrou ineficiente. Eu poderia
ter escolhido um plano ou uma caixa para o terreno externo, seria mais facil...

tecla O e L avança a câmera mais rápido.

"""

import glfw
from OpenGL.GL import *
import OpenGL.GL.shaders
import numpy as np
import glm
import math
from PIL import Image

glfw.init()
glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
altura = 1600
largura = 1200
window = glfw.create_window(largura, altura, "Malhas e Texturas", None, None)
glfw.make_context_current(window)

vertex_code = """
        attribute vec3 position;
        attribute vec2 texture_coord;
        varying vec2 out_texture;

        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;

        void main(){
            gl_Position = projection * view * model * vec4(position,1.0);
            out_texture = vec2(texture_coord);
        }
        """

fragment_code = """
        uniform vec4 color;
        varying vec2 out_texture;
        uniform sampler2D samplerTexture;

        void main(){
            vec4 texture = texture2D(samplerTexture, out_texture);
            gl_FragColor = texture;
        }
        """
# Request a program and shader slots from GPU
program  = glCreateProgram()
vertex   = glCreateShader(GL_VERTEX_SHADER)
fragment = glCreateShader(GL_FRAGMENT_SHADER)

# Set shaders source
glShaderSource(vertex, vertex_code)
glShaderSource(fragment, fragment_code)

# Compile shaders
glCompileShader(vertex)
if not glGetShaderiv(vertex, GL_COMPILE_STATUS):
    error = glGetShaderInfoLog(vertex).decode()
    print(error)
    raise RuntimeError("Erro de compilacao do Vertex Shader")

glCompileShader(fragment)
if not glGetShaderiv(fragment, GL_COMPILE_STATUS):
    error = glGetShaderInfoLog(fragment).decode()
    print(error)
    raise RuntimeError("Erro de compilacao do Fragment Shader")

# Attach shader objects to the program
glAttachShader(program, vertex)
glAttachShader(program, fragment)

# Build program
glLinkProgram(program)
if not glGetProgramiv(program, GL_LINK_STATUS):
    print(glGetProgramInfoLog(program))
    raise RuntimeError('Linking error')

# Make program the default program
glUseProgram(program)

def load_model_from_file(filename):
    """Loads a Wavefront OBJ file. """
    objects = {}
    vertices = []
    texture_coords = []
    faces = []

    material = None

    # abre o arquivo obj para leitura
    for line in open(filename, "r"): ## para cada linha do arquivo .obj
        if line.startswith('#'): continue ## ignora comentarios
        values = line.split() # quebra a linha por espaço
        if not values: continue

        ### recuperando vertices
        if values[0] == 'v':
            vertices.append(values[1:4])

        ### recuperando coordenadas de textura
        elif values[0] == 'vt':
            texture_coords.append(values[1:3])
        ### recuperando faces
        elif values[0] in ('usemtl', 'usemat'):
            material = values[1]
        elif values[0] == 'f':
            face = []
            face_texture = []
            for v in values[1:]:
                w = v.split('/')
                face.append(int(w[0]))
                if len(w) >= 2 and len(w[1]) > 0:
                    face_texture.append(int(w[1]))
                else:
                    face_texture.append(0)
            faces.append((face, face_texture, material))

    model = {}
    model['vertices'] = vertices
    model['texture'] = texture_coords
    model['faces'] = faces

    return model

glEnable(GL_TEXTURE_2D)
qtd_texturas = 20
textures = glGenTextures(qtd_texturas)

def load_texture_from_file(texture_id, img_textura):
    glBindTexture(GL_TEXTURE_2D, texture_id)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    img = Image.open(img_textura)
    img_width = img.size[0]
    img_height = img.size[1]
    image_data = img.tobytes("raw", "RGB", 0, -1)
    #image_data = np.array(list(img.getdata()), np.uint8)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img_width, img_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data)

vertices_list = []
textures_coord_list = []

modelo = load_model_from_file('assets/casa/casa.obj')
### inserindo vertices do modelo no vetor de vertices
print('Processando modelo casa.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo casa.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(0,'assets/casa/casa.jpg')

modelo = load_model_from_file('assets/cama/cama.obj')
### inserindo vertices do modelo no vetor de vertices
print('Processando modelo cama.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo cama.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(1,'assets/cama/cama.png')

modelo = load_model_from_file('assets/sky/sky.obj')

#armazena os vertices do chao para vinculá-los a um sistema de colisão
maxVetexes=modelo['vertices']

### inserindo vertices do modelo no vetor de vertices
print('Processando modelo sky.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo sky.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(2,'assets/sky/sky.jpg')

faces_visitadas = []
modelo = load_model_from_file('assets/chao/chao.obj')
#armazena os vertices do chao para vinculá-los a um sistema de colisão
chaoVert=[]

chaoSize = 451
off_x=100.0
off_y=-15.0
off_z=45.0

### inserindo vertices do modelo no vetor de vertices
print('Processando modelo chao.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    if face[2] not in faces_visitadas:
        print(face[2], 'face vertice inicial: ',len(vertices_list))
        faces_visitadas.append(face[2])
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
        chaoVert.append(modelo['vertices'][vertice_id-1])
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo chao.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(3,'assets/chao/terra.jpg')
#load_texture_from_file(4,'assets/chao/field.jpg')

modelo = load_model_from_file('assets/Tree 02/Tree.obj')
### inserindo vertices do modelo no vetor de vertices
print('Processando modelo Tree.obj. Vertice inicial:',len(vertices_list))
faces_visitadas = []
for face in modelo['faces']:
    if face[2] not in faces_visitadas:
        print(face[2], 'face vertice inicial: ',len(vertices_list))
        faces_visitadas.append(face[2])
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo chao.Tree. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(5,'assets/Tree 02/bark_0004.jpg')
load_texture_from_file(6,'assets/Tree 02/DB2X2_L01.png')

modelo = load_model_from_file('assets/elsa/elsa.obj')
### inserindo vertices do modelo no vetor de vertices
print('Processando modelo elsa.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo elsa.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(7,'assets/elsa/elsa.png')

faces_visitadas = []
modelo = load_model_from_file('assets/dog/dog.obj')
### inserindo vertices do modelo no vetor de vertices
print('Processando modelo dog.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    if face[2] not in faces_visitadas:
        print(face[2], 'face vertice inicial: ',len(vertices_list))
        faces_visitadas.append(face[2])
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo dog.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
#load_texture_from_file(8,'assets/dog/Tex_0093_0.tga')
#load_texture_from_file(9,'assets/dog/Tex_0369_0.tga')
load_texture_from_file(8,'assets/dog/Tex_0552_7.tga')

faces_visitadas = []
modelo = load_model_from_file('assets/gollum/gollum.obj')
### inserindo vertices do modelo no vetor de vertices
print('Processando modelo gollum.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    if face[2] not in faces_visitadas:
        print(face[2], 'face vertice inicial: ',len(vertices_list))
        faces_visitadas.append(face[2])
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo gollum.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(9,'assets/gollum/4e4e0374.PNG')
load_texture_from_file(10,'assets/gollum/553e267b.PNG')
load_texture_from_file(11,'assets/gollum/2093f02c.PNG')
load_texture_from_file(12,'assets/gollum/c581eba0.PNG')

modelo = load_model_from_file('assets/ring/ring.obj')
### inserindo vertices do modelo no vetor de vertices
print('Processando modelo ring.obj. Vertice inicial:',len(vertices_list))
for face in modelo['faces']:
    for vertice_id in face[0]:
        vertices_list.append( modelo['vertices'][vertice_id-1] )
    for texture_id in face[1]:
        textures_coord_list.append( modelo['texture'][texture_id-1] )
print('Processando modelo ring.obj. Vertice final:',len(vertices_list))
### inserindo coordenadas de textura do modelo no vetor de texturas
### carregando textura equivalente e definindo um id (buffer): use um id por textura!
load_texture_from_file(13,'assets/ring/ring.png')

# Request a buffer slot from GPU
buffer = glGenBuffers(2)

vertices = np.zeros(len(vertices_list), [("position", np.float32, 3)])
vertices['position'] = vertices_list

# Upload data
glBindBuffer(GL_ARRAY_BUFFER, buffer[0])
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
stride = vertices.strides[0]
offset = ctypes.c_void_p(0)
loc_vertices = glGetAttribLocation(program, "position")
glEnableVertexAttribArray(loc_vertices)
glVertexAttribPointer(loc_vertices, 3, GL_FLOAT, False, stride, offset)

textures = np.zeros(len(textures_coord_list), [("position", np.float32, 2)]) # duas coordenadas
textures['position'] = textures_coord_list

# Upload data
glBindBuffer(GL_ARRAY_BUFFER, buffer[1])
glBufferData(GL_ARRAY_BUFFER, textures.nbytes, textures, GL_STATIC_DRAW)
stride = textures.strides[0]
offset = ctypes.c_void_p(0)
loc_texture_coord = glGetAttribLocation(program, "texture_coord")
glEnableVertexAttribArray(loc_texture_coord)
glVertexAttribPointer(loc_texture_coord, 2, GL_FLOAT, False, stride, offset)

def desenha_casa():
    # aplica a matriz model
    # rotacao
    angle = 90.0
    r_x = 0.0; r_y = 1.0; r_z = 0.0

    # translacao
    t_x = 25.0; t_y = -12.0; t_z = -150.0

    # escala
    s_x = 1.0; s_y = 1.0; s_z = 1.0

    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    glBindTexture(GL_TEXTURE_2D, 0)

    # desenha o modelo
    glDrawArrays(GL_TRIANGLES, 0, 1770) ## renderizando

def desenha_cama():
    # aplica a matriz model
    # rotacao
    angle = 180.0
    r_x = 0.0; r_y = 1.0; r_z = 0.0

    # translacao
    t_x = 140.0; t_y = -11.0; t_z = 3.5

    # escala
    s_x = 5.0; s_y = 5.0; s_z = 5.0

    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    glBindTexture(GL_TEXTURE_2D, 1)

    # desenha o modelo
    glDrawArrays(GL_TRIANGLES, 1770, 3156-1770) ## renderizando

def desenha_sky():
    # aplica a matriz model
    # rotacao
    angle = 0.0
    r_x = 0.0; r_y = 0.0; r_z = 1.0

    # translacao
    t_x = 0.0; t_y = -50.0; t_z = 0.0

    # escala
    s_x = 1500.0; s_y = 1500.0; s_z = 1500.0

    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    glBindTexture(GL_TEXTURE_2D, 2)

    # desenha o modelo
    glDrawArrays(GL_TRIANGLES, 3156, 4596-3156) ## renderizando

def desenha_chao():
    global chaoSize,off_x,off_y,off_z
    # aplica a matriz model
    # rotacao
    angle = 0.0
    r_x = off_x; r_y = 0.0; r_z = 1.0
    # translacao
    t_x = 100.0; t_y = off_y; t_z = off_z
    # escala
    s_x = chaoSize; s_y =chaoSize; s_z = chaoSize
    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    glBindTexture(GL_TEXTURE_2D, 3)
    # desenha o modelo
    glDrawArrays(GL_TRIANGLES, 4596, 102900-4596) ## renderizando

def desenha_Tree():
    # aplica a matriz model
    # rotacao
    global obj_x,obj_y,obj_z
    angle = 0.0
    r_x = 0.0; r_y = 0.0; r_z = 1.0

    # translacao
    t_x = -101.5; t_y = -12.50; t_z = 43.0

    # escala
    s_x = 15.0; s_y = 15.0; s_z = 15.0
    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo# desenha o modelo
    glBindTexture(GL_TEXTURE_2D, 5)
    glDrawArrays(GL_TRIANGLES, 102900, 139344-102900)

    glBindTexture(GL_TEXTURE_2D, 6)
    glDrawArrays(GL_TRIANGLES, 139344, 195714-139344)

def desenha_frozen():
    # aplica a matriz model
    # rotacao
    angle = -90.0
    r_x = 0.0; r_y = 1.0; r_z = 0.0

    # translacao
    t_x = -25.0; t_y = -12.0; t_z = 152.5

    # escala
    s_x = 8.0; s_y = 8.0; s_z = 8.0

    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    glBindTexture(GL_TEXTURE_2D, 7)

    # desenha o modelo
    glDrawArrays(GL_TRIANGLES, 195714, 207645-195714) ## renderizando

obj_x=-34
obj_y=-11.5
obj_z=132.5

def desenha_dog():
    # aplica a matriz model
    # rotacao
    angle = -90.0
    r_x = 0.0; r_y = 1.0; r_z = 0.0

    # translacao
    t_x = 15.0; t_y =-15.0; t_z = 194.0

    # escala
    s_x = .10; s_y = .10; s_z = .10

    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    # desenha o modelo
    glBindTexture(GL_TEXTURE_2D, 8)
    glDrawArrays(GL_TRIANGLES, 207645, 221943-207645)

#retorna a altura na posição x,z Tentar outra abordagem, esta está ruim
def getHei(x,z,vertList):
    global chaoSize, off_x,off_y,off_z
    tolerancia =0.001
    #checa qual é o vertice mais proximo, quando achar basta retornar
    for v in vertList:
        vx = float(v[0])*chaoSize + off_x
        vz = float(v[2])*chaoSize + off_z
        if math.isclose(x,vx,abs_tol=tolerancia):
            if math.isclose(z,vz,abs_tol=tolerancia):
                return float(v[1])*chaoSize+off_y
    print('não achou...')

jump = -21.50
def desenha_gollum():
    global jump
    # aplica a matriz model
    # rotacao
    angle=90
    r_x = 0.0; r_y = 1.0; r_z = 0.0

    # translacao
    t_x = 6.0; t_y = jump; t_z = -244.0

    # escala
    s_x = 15.0; s_y = 15.0; s_z = 15.0
    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    glBindTexture(GL_TEXTURE_2D, 9)
    glDrawArrays(GL_TRIANGLES, 221943, 226224-221943) ## renderizando
    glBindTexture(GL_TEXTURE_2D, 10)
    glDrawArrays(GL_TRIANGLES, 226224, 227010-226224) ## renderizando
    glBindTexture(GL_TEXTURE_2D, 11)
    glDrawArrays(GL_TRIANGLES, 227010, 227823-227010) ## renderizando
    glBindTexture(GL_TEXTURE_2D, 12)
    glDrawArrays(GL_TRIANGLES, 227823, 231060-227823) ## renderizando

def desenha_ring():
    # aplica a matriz model
    # rotacao
    angle=90
    r_x = 0.0; r_y = 0.0; r_z = 1.0

    # translacao
    t_x = -5.0; t_y = 110; t_z = -26.0

    # escala
    s_x = 1.0; s_y = 1.0; s_z = 1.0
    mat_model = model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z)
    loc_model = glGetUniformLocation(program, "model")
    glUniformMatrix4fv(loc_model, 1, GL_TRUE, mat_model)

    #define id da textura do modelo
    glBindTexture(GL_TEXTURE_2D, 13)

    # desenha o modelo
    glDrawArrays(GL_TRIANGLES, 231060, 233364-231060) ## renderizando

cameraPos   = glm.vec3(-50.0,  110.0,  200.0)
cameraFront = glm.vec3(-25.0,  -12.0, 152.0)
cameraUp    = glm.vec3(0.0,  1.0,  0.0)

polygonal_mode = False

def key_event(window,key,scancode,action,mods):
    global cameraPos, cameraFront, cameraUp,polygonal_mode,obj_x,obj_y,obj_z
    """para limitar a camera, a idea era criar uma função (getHei) que retorne a coordenada Y (altura) do chao e do céu
    e limitar a movimentação da câmera. Porém desta forma fica muito ineficiente e mesmo assim (até a data de entrega)
    não consegui retornar o valor desejado
    """
    #print('camera Y:',cameraPos.y, ' Terrain heigth: ',getHei(cameraPos.x,cameraPos.z,chaoVert))

    #controles de objeto (para descobrir os valores de translação de cada matriz model)
    if key == 266 and (action==1 or action==2): # tecla pageup
        obj_z+=.5
        print('Z: ',obj_z)
    if key == 267 and (action==1 or action==2): # tecla pagedown
        obj_z-=.5
        print('Z: ',obj_z)
    if key == 268 and (action==1 or action==2): # tecla home
        obj_y+=.5
        print('Y: ',obj_y)
    if key == 269 and (action==1 or action==2): # tecla end
        obj_y-=.5
        print('Y: ',obj_y)
    if key == 260 and (action==1 or action==2): # tecla insert
        obj_x+=.5
        print('X: ',obj_x)
    if key == 261 and (action==1 or action==2): # tecla delete
        obj_x-=.5
        print('X: ',obj_x)

    cameraSpeed = 3.2
    #movimentar a camera um pouco mais rapido
    if key == 79 and (action==1 or action==2): # tecla O sobe rapidao
        cameraPos += 30 * cameraFront
    if key == 76 and (action==1 or action==2): # tecla l desce rapidao
        cameraPos -= 30 * cameraFront

    if key == 87 and (action==1 or action==2): # tecla W
        cameraPos += cameraSpeed * cameraFront

    if key == 83 and (action==1 or action==2): # tecla S
        cameraPos -= cameraSpeed * cameraFront

    if key == 65 and (action==1 or action==2): # tecla A
        cameraPos -= glm.normalize(glm.cross(cameraFront, cameraUp)) * cameraSpeed

    if key == 68 and (action==1 or action==2): # tecla D
        cameraPos += glm.normalize(glm.cross(cameraFront, cameraUp)) * cameraSpeed

    if key == 80 and action==1 and polygonal_mode==True:
        polygonal_mode=False
    else:
        if key == 80 and action==1 and polygonal_mode==False:
            polygonal_mode=True

firstMouse = True
yaw = -90.0
pitch = 0.0
lastX =  largura/2
lastY =  altura/2

def mouse_event(window, xpos, ypos):
    global firstMouse, cameraFront, yaw, pitch, lastX, lastY
    if firstMouse:
        lastX = xpos
        lastY = ypos
        firstMouse = False

    xoffset = xpos - lastX
    yoffset = lastY - ypos
    lastX = xpos
    lastY = ypos

    sensitivity = 0.3
    xoffset *= sensitivity
    yoffset *= sensitivity

    yaw += xoffset
    pitch += yoffset

    if pitch >= 90.0: pitch = 90.0
    if pitch <= -90.0: pitch = -90.0

    front = glm.vec3()
    front.x = math.cos(glm.radians(yaw)) * math.cos(glm.radians(pitch))
    front.y = math.sin(glm.radians(pitch))
    front.z = math.sin(glm.radians(yaw)) * math.cos(glm.radians(pitch))
    cameraFront = glm.normalize(front)

#teste de scrool do mouse
def scroll_callback(window, xoffset, yoffset):
    global cameraPos
    cameraPos += yoffset

glfw.set_key_callback(window,key_event)
glfw.set_cursor_pos_callback(window, mouse_event)
glfw.set_scroll_callback(window,scroll_callback)

def model(angle, r_x, r_y, r_z, t_x, t_y, t_z, s_x, s_y, s_z):

    angle = math.radians(angle)

    matrix_transform = glm.mat4(1.0) # instanciando uma matriz identidade

    # aplicando rotacao
    matrix_transform = glm.rotate(matrix_transform, angle, glm.vec3(r_x, r_y, r_z))

    # aplicando translacao
    matrix_transform = glm.translate(matrix_transform, glm.vec3(t_x, t_y, t_z))

    # aplicando escala
    matrix_transform = glm.scale(matrix_transform, glm.vec3(s_x, s_y, s_z))

    matrix_transform = np.array(matrix_transform).T # pegando a transposta da matriz (glm trabalha com ela invertida)

    return matrix_transform

def view():
    global cameraPos, cameraFront, cameraUp
    mat_view = glm.lookAt(cameraPos, cameraPos + cameraFront, cameraUp)
    mat_view = np.array(mat_view)
    return mat_view

def projection():
    global altura, largura
    # perspective parameters: fovy, aspect, near, far
    mat_projection = glm.perspective(glm.radians(45.0), largura/altura, 0.1, 3000.0)
    mat_projection = np.array(mat_projection)
    return mat_projection

glfw.show_window(window)
glfw.set_cursor_pos(window, lastX, lastY)

glEnable(GL_DEPTH_TEST) ### importante para 3D

#fazer o gollum ficar pulando
jump_speed =0.35
while not glfw.window_should_close(window):

    glfw.poll_events()

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glClearColor(1.0, 1.0, 1.0, 1.0)

    if polygonal_mode==True:
        glPolygonMode(GL_FRONT_AND_BACK,GL_LINE)
    if polygonal_mode==False:
        glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)

    desenha_casa()
    desenha_cama()
    desenha_sky()
    desenha_chao()
    desenha_Tree()
    desenha_frozen()
    desenha_dog()
    desenha_gollum()
    desenha_ring()

    #gollum fica se mechendo...
    if jump>-14:
        jump_speed= -0.35
    if jump <-21.50:
        jump_speed = 0.35
    jump+=jump_speed

    mat_view = view()
    loc_view = glGetUniformLocation(program, "view")
    glUniformMatrix4fv(loc_view, 1, GL_FALSE, mat_view)

    mat_projection = projection()
    loc_projection = glGetUniformLocation(program, "projection")
    glUniformMatrix4fv(loc_projection, 1, GL_FALSE, mat_projection)

    glfw.swap_buffers(window)

glfw.terminate()


import logging
import os

import click

from packit.cli.types import LocalProjectParameter
from packit.cli.utils import cover_packit_exception, get_packit_api
from packit.config import pass_config, get_context_settings
from packit.constants import DEFAULT_BODHI_NOTE

logger = logging.getLogger(__file__)

@click.command("create-update", context_settings=get_context_settings())
@click.option("--dist-git-branch", help="Target branch in dist-git to release into.")
@click.option(
    "--koji-build",
    help="Koji build (NVR) to add to the bodhi update (can be specified multiple times)",
    required=False,
    multiple=True,
)
# It would make sense to open an editor here,
# just like `git commit` and get notes like that
@click.option(
    "--update-notes",
    help="Bodhi update notes",
    required=False,
    default=DEFAULT_BODHI_NOTE,
)
@click.option(
    "--update-type",
    type=click.types.Choice(("security", "bugfix", "enhancement", "newpackage")),
    help="Type of the bodhi update",
    required=False,
    default="enhancement",
)
@click.argument(
    "path_or_url", type=LocalProjectParameter(), default=os.path.abspath(os.path.curdir)
)
@pass_config
@cover_packit_exception
def create_update(
    config, dist_git_branch, koji_build, update_notes, update_type, path_or_url
):
    """
    Create a bodhi update for the selected upstream project

    PATH_OR_URL argument is a local path or a URL to the upstream git repository,
    it defaults to the current working directory
    """
    api = get_packit_api(config=config, local_project=path_or_url)
    api.create_update(
        koji_builds=koji_build,
        dist_git_branch=dist_git_branch,
        update_notes=update_notes,
        update_type=update_type,
    )


#!/usr/bin/python
# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

"""This module provides shared functionality for the system to generate
dart:html APIs from the IDL database."""

from generator import AnalyzeOperation, ConstantOutputOrder, \
    DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \
    IsPureInterface, TypeOrNothing

# Types that are accessible cross-frame in a limited fashion.
# In these cases, the base type (e.g., Window) provides restricted access
# while the subtype (e.g., LocalWindow) provides full access to the
# corresponding objects if there are from the same frame.
_secure_base_types = {
  'LocalWindow': 'Window',
  'LocalLocation': 'Location',
  'LocalHistory': 'History',
}

class HtmlDartGenerator(object):
  def __init__(self, interface, options):
    self._database = options.database
    self._interface = interface
    self._type_registry = options.type_registry
    self._interface_type_info = self._type_registry.TypeInfo(self._interface.id)
    self._renamer = options.renamer

  def EmitAttributeDocumentation(self, attribute):
    """ Emits the MDN dartdoc comment for an attribute.
    """
    dom_name = DartDomNameOfAttribute(attribute)
    self._members_emitter.Emit('\n  /// @domName $DOMINTERFACE.$DOMNAME;'
                               ' @docsEditable true',
        DOMINTERFACE=attribute.doc_js_interface_name,
        DOMNAME=dom_name)

  def EmitOperationDocumentation(self, operation):
    """ Emits the MDN dartdoc comment for an operation.
    """
    self._members_emitter.Emit('\n  /// @domName $DOMINTERFACE.$DOMNAME;'
                               ' @docsEditable true',
        DOMINTERFACE=operation.overloads[0].doc_js_interface_name,
        DOMNAME=operation.name)

  def EmitEventGetter(self, events_class_name):
    self._members_emitter.Emit(
        '\n  /// @domName EventTarget.addEventListener, '
        'EventTarget.removeEventListener, EventTarget.dispatchEvent;'
        ' @docsEditable true'
        '\n  $TYPE get on =>\n    new $TYPE(this);\n',
        TYPE=events_class_name)

  def AddMembers(self, interface, declare_only=False):
    for const in sorted(interface.constants, ConstantOutputOrder):
      self.AddConstant(const)

    for attr in sorted(interface.attributes, ConstantOutputOrder):
      if attr.type.id != 'EventListener':
        self.AddAttribute(attr, declare_only)

    # The implementation should define an indexer if the interface directly
    # extends List.
    element_type = None
    requires_indexer = False
    if self._interface_type_info.list_item_type():
      self.AddIndexer(self._interface_type_info.list_item_type())
    else:
      for parent in self._database.Hierarchy(self._interface):
        if parent == self._interface:
          continue
        parent_type_info = self._type_registry.TypeInfo(parent.id)
        if parent_type_info.list_item_type():
          self.AmendIndexer(parent_type_info.list_item_type())
          break

    # Group overloaded operations by id.
    operationsById = {}
    for operation in interface.operations:
      if operation.id not in operationsById:
        operationsById[operation.id] = []
      operationsById[operation.id].append(operation)

    # Generate operations.
    for id in sorted(operationsById.keys()):
      operations = operationsById[id]
      info = AnalyzeOperation(interface, operations)
      self.AddOperation(info, declare_only)

  def AddSecondaryMembers(self, interface):
    # With multiple inheritance, attributes and operations of non-first
    # interfaces need to be added.  Sometimes the attribute or operation is
    # defined in the current interface as well as a parent.  In that case we
    # avoid making a duplicate definition and pray that the signatures match.
    secondary_parents = self._TransitiveSecondaryParents(interface)
    for parent_interface in sorted(secondary_parents):
      if isinstance(parent_interface, str):
        continue
      for attr in sorted(parent_interface.attributes, ConstantOutputOrder):
        if not FindMatchingAttribute(interface, attr):
          self.SecondaryContext(parent_interface)
          self.AddAttribute(attr)

      # Group overloaded operations by id.
      operationsById = {}
      for operation in parent_interface.operations:
        if operation.id not in operationsById:
          operationsById[operation.id] = []
        operationsById[operation.id].append(operation)

      # Generate operations.
      for id in sorted(operationsById.keys()):
        if not any(op.id == id for op in interface.operations):
          operations = operationsById[id]
          info = AnalyzeOperation(interface, operations)
          self.SecondaryContext(parent_interface)
          self.AddOperation(info)

  def AddConstant(self, constant):
    const_name = self._renamer.RenameMember(
        self._interface.id, constant, constant.id, dartify_name=False)
    if not const_name:
      return
    type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id)
    self._members_emitter.Emit('\n  static const $TYPE$NAME = $VALUE;\n',
        NAME=const_name,
        TYPE=type,
        VALUE=constant.value)

  def AddAttribute(self, attribute, declare_only=False):
    """ Adds an attribute to the generated class.
    Arguments:
      attribute - The attribute which is to be added.
      declare_only- True if the attribute should be declared as an abstract
        member and not include invocation code.
    """
    dom_name = DartDomNameOfAttribute(attribute)
    attr_name = self._renamer.RenameMember(
      self._interface.id, attribute, dom_name, 'get:')
    if not attr_name or self._IsPrivate(attr_name):
      return

    html_setter_name = self._renamer.RenameMember(
        self._interface.id, attribute, dom_name, 'set:')
    read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs
                 or not html_setter_name)

    # We don't yet handle inconsistent renames of the getter and setter yet.
    assert(not html_setter_name or attr_name == html_setter_name)

    if declare_only:
      self.DeclareAttribute(attribute,
          self.SecureOutputType(attribute.type.id), attr_name, read_only)
    else:
      self.EmitAttribute(attribute, attr_name, read_only)

  def AddOperation(self, info, declare_only=False):
    """ Adds an operation to the generated class.
    Arguments:
      info - The operation info of the operation to be added.
      declare_only- True if the operation should be declared as an abstract
        member and not include invocation code.
    """
    # FIXME: When we pass in operations[0] below, we're assuming all
    # overloaded operations have the same security attributes.  This
    # is currently true, but we should consider filtering earlier or
    # merging the relevant data into info itself.
    method_name = self._renamer.RenameMember(self._interface.id,
                                             info.operations[0],
                                             info.name)
    if not method_name:
      if info.name == 'item':
        # FIXME: item should be renamed to operator[], not removed.
        self.EmitOperation(info, '_item')
      return

    if declare_only:
      self.DeclareOperation(info,
          self.SecureOutputType(info.type_name), method_name)
    else:
      self.EmitOperation(info, method_name)

  def AdditionalImplementedInterfaces(self):
    # TODO: Include all implemented interfaces, including other Lists.
    implements = []
    if self._interface_type_info.is_typed_array():
      element_type = self._interface_type_info.list_item_type()
      implements.append('List<%s>' % self._DartType(element_type))
    if self._interface_type_info.list_item_type():
      item_type_info = self._type_registry.TypeInfo(
          self._interface_type_info.list_item_type())
      implements.append('List<%s>' % item_type_info.dart_type())
    return implements

  def AddConstructors(self, constructors, factory_name, class_name,
      base_class, factory_constructor_name=None):
    """ Adds all of the constructors.
    Arguments:
      constructors - List of the constructors to be added.
      factory_name - Name of the factory for this class.
      class_name - The name of this class.
      base_class - The name of the base class which this extends.
      factory_constructor_name - The name of the constructor on the
          factory_name to call (calls an autogenerated FactoryProvider
          if unspecified)
    """
    for constructor_info in constructors:
      self._AddConstructor(constructor_info, factory_name,
          factory_constructor_name, constructor_info.factory_parameters)

    typed_array_type = None
    for interface in self._database.Hierarchy(self._interface):
      type_info = self._type_registry.TypeInfo(interface.id)
      if type_info.is_typed_array():
        typed_array_type = type_info.list_item_type()
        break
    if typed_array_type:
      self._members_emitter.Emit(
          '\n'
          '  factory $CTOR(int length) =>\n'
          '    $FACTORY.create$(CTOR)(length);\n'
          '\n'
          '  factory $CTOR.fromList(List<$TYPE> list) =>\n'
          '    $FACTORY.create$(CTOR)_fromList(list);\n'
          '\n'
          '  factory $CTOR.fromBuffer(ArrayBuffer buffer, '
              '[int byteOffset, int length]) => \n'
          '    $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n',
        CTOR=self._interface.id,
        TYPE=self._DartType(typed_array_type),
        FACTORY=factory_name)

  def _AddConstructor(self, constructor_info, factory_name,
      factory_constructor_name, factory_constructor_params):
    self._members_emitter.Emit('\n  ///@docsEditable true');
    constructor_info.GenerateFactoryInvocation(
        self._DartType, self._members_emitter, factory_name,
        factory_constructor_name=factory_constructor_name,
        factory_parameters=factory_constructor_params)

  def DeclareAttribute(self, attribute, type_name, attr_name, read_only):
    """ Declares an attribute but does not include the code to invoke it.
    """
    self.EmitAttributeDocumentation(attribute)
    if read_only:
      template = '\n  $TYPE get $NAME;\n'
    else:
      template = '\n  $TYPE $NAME;\n'

    self._members_emitter.Emit(template,
        NAME=attr_name,
        TYPE=type_name)

  def DeclareOperation(self, operation, return_type_name, method_name):
    """ Declares an operation but does not include the code to invoke it.
    Arguments:
      operation - The operation to be declared.
      return_type_name - The name of the return type.
      method_name - The name of the method.
    """
    self.EmitOperationDocumentation(operation)
    self._members_emitter.Emit(
             '\n'
             '  $TYPE $NAME($PARAMS);\n',
             TYPE=return_type_name,
             NAME=method_name,
             PARAMS=operation.ParametersDeclaration(self._DartType))

  def EmitListMixin(self, element_name):
    # TODO(sra): Use separate mixins for mutable implementations of List<T>.
    # TODO(sra): Use separate mixins for typed array implementations of List<T>.
    template_file = 'immutable_list_mixin.darttemplate'
    has_contains = any(op.id == 'contains' for op in self._interface.operations)
    has_clear = any(op.id == 'clear' for op in self._interface.operations)
    has_length = False
    has_length_setter = False
    for attr in self._interface.attributes:
      if attr.id == 'length':
        has_length = True
        has_length_setter = not attr.is_read_only

    has_num_items = any(attr.id == 'numberOfItems'
        for attr in self._interface.attributes)

    template = self._template_loader.Load(
        template_file,
        {
          'DEFINE_CONTAINS': not has_contains,
          'DEFINE_CLEAR': not has_clear,
          'DEFINE_LENGTH_AS_NUM_ITEMS': not has_length and has_num_items,
          'DEFINE_LENGTH_SETTER': not has_length_setter,
        })
    self._members_emitter.Emit(template, E=element_name)

  def SecureOutputType(self, type_name, is_dart_type=False):
    """ Converts the type name to the secure type name for return types.
    """
    if is_dart_type:
      dart_name = type_name
    else:
      dart_name = self._DartType(type_name)
    # We only need to secure Window.  Only local History and Location are
    # returned in generated code.
    assert(dart_name != 'History' and dart_name != 'Location')
    if dart_name == 'LocalWindow':
      return _secure_base_types[dart_name]
    return dart_name

  def SecureBaseName(self, type_name):
    if type_name in _secure_base_types:
      return _secure_base_types[type_name]

  def _TransitiveSecondaryParents(self, interface):
    """Returns a list of all non-primary parents.

    The list contains the interface objects for interfaces defined in the
    database, and the name for undefined interfaces.
    """
    def walk(parents):
      for parent in parents:
        parent_name = parent.type.id
        if parent_name == 'EventTarget':
          # Currently EventTarget is implemented as a mixin, not a proper
          # super interface---ignore its members.
          continue
        if IsDartCollectionType(parent_name):
          result.append(parent_name)
          continue
        if self._database.HasInterface(parent_name):
          parent_interface = self._database.GetInterface(parent_name)
          result.append(parent_interface)
          walk(parent_interface.parents)

    result = []
    if interface.parents:
      parent = interface.parents[0]
      if IsPureInterface(parent.type.id):
        walk(interface.parents)
      else:
        walk(interface.parents[1:])
    return result

  def _DartType(self, type_name):
    return self._type_registry.DartType(type_name)

  def _IsPrivate(self, name):
    return name.startswith('_')


import unittest
from collector.helpers import remove_characters

class RemoveCharactersTest(unittest.TestCase):
    def test_remove_character_from_start(self):
        # given
        source_str = "baobab"
        chars_str = 'b'
        expected_result = "aoa"

        # when
        result = remove_characters(source_str, chars_str)

        # then
        self.assertEqual(expected_result, result)

    def test_remove_character_from_end(self):
        # given
        source_str = "darkness"
        chars_str = 's'
        expected_result = "darkne"

        # when
        result = remove_characters(source_str, chars_str)

        # then
        self.assertEqual(expected_result, result)

    def test_remove_character_in_the_middle(self):
        # given
        source_str = "debris"
        chars_str = 'b'
        expected_result = "deris"

        # when
        result = remove_characters(source_str, chars_str)

        # then
        self.assertEqual(expected_result, result)

    def test_remove_character_from_begin_center_end(self):
        # given
        source_str = "amanda"
        chars_str = 'a'
        expected_result = "mnd"

        # when
        result = remove_characters(source_str, chars_str)

        # then
        self.assertEqual(expected_result, result)

    def test_remove_two_characters(self):
        # given
        source_str = "Duis at tellus at urna condimentum mattis pellentesque id."
        expected_result = "Duis t tllus t urn condimntum mttis pllntsqu id."

        # when
        result = remove_characters(source_str, 'a')
        result = remove_characters(result, 'e')

        # then
        self.assertEqual(expected_result, result)

if __name__ == '__main__':
    unittest.main()


import matplotlib.pyplot as plt
import numpy as np
from core.const import OUTPUT_PATH
from core.configIO import fetchConfigList
from core.classifier import Classifier
import sys
from json import dumps
import os
sys.path.append('.\\')
print(OUTPUT_PATH)

def fit(data: list):
    if len(data) == 0:
        return None
    tmpList = dict()
    for i in data:
        if i[3] in tmpList:
            tmpList[i[3]][i[4]] += 1
        else:
            tmpList[i[3]] = [0, 0]
            tmpList[i[3]][i[4]] += 1
    for i in tmpList:
        tmpList[i] = tmpList[i][1]/sum(tmpList[i])
    x, y = [x for x in tmpList], [tmpList[x] for x in tmpList]
    res = np.polyfit(x, y, 1)
    for i in range(len(res)):
        res[i] = round(res[i], 6)
    return {'poly': list(res), 'min': min([x[3] for x in data]), 'max': max([x[3] for x in data])}
    # return (res, min(data), max(data))

def draw(data: list):
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.title('poly fit for %d centers' % len(data))
    fig, axs = plt.subplots(len(data), 1, sharex=True)
    fig.subplots_adjust(hspace =0)
    for i in range(len(data)):
        if data[i] is None:
            continue
        min, max = data[i]['min'], data[i]['max']
        pol = data[i]['poly']
        x = np.arange(min, max, 0.1)
        y = pol[0]*x+pol[1]
        axs[i].plot(x, y)
    fileName = os.path.join(OUTPUT_PATH, 'P01line%d.jpg' % calc.typeCount)
    plt.savefig(fileName)

if __name__ == "__main__":
    configList = fetchConfigList()
    calc = Classifier()
    for conf in configList:
        calc.loadConfig(conf)
        calc.calc()
        resList = list()
        for group in calc.classList:
            resList.append(fit(group))
        fileName = os.path.join(OUTPUT_PATH, 'P01line%d.json' % calc.typeCount)
        with open(fileName, 'w') as w:
            w.write(dumps(resList))
        print(fileName)
        draw(resList)


import requests
from ubidots import ApiClient
from datetime import date, datetime

import time

api = ApiClient(token='Sm5ihUyNjAoPy7FZMsVhgLS07VzFxp')
my_variable = api.get_variable('5851fb1476254275dcc8b27e')

response=requests.get('http://earthquake.usgs.gov/fdsnws/event/1/query?format=text&starttime=2016-04-16&endtime=2016-04-26')
data=response.text

a=0
datosSeparados=data.split("\n")
listSinOrdenar=[]
for i in datosSeparados:
    lineaDatos=i.split("|")
    for x in lineaDatos:
        if (x.find("Ecuador") != -1):
            lista=[]
            timestamp=lineaDatos[1]

            #Aqui va el codigo para hacer lo del timestamp
            time_tuple = time.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f")
            print(time_tuple)
            dt=time.mktime(time_tuple)
            dt-=(5*60*60)
            print (dt)
            lat=lineaDatos[2]
            lon=lineaDatos[3]

            #|2016-04-25T23:54:22.710|

            a+=1
            dato=lineaDatos[10]
            magnitud=float(dato)
            lista.append(dt)
            lista.append(lat)
            lista.append(lon)
            lista.append(magnitud)
            #new_value=my_variable.save_value({'value':magnitud})
            #fecha del evento, llevar de string a Time o TimeStamp
            #Info geografica Lat, Long
            #Dashboard presentar la info geografica por medio de un mapa
            listSinOrdenar.append(lista.copy())
            print("Envio: ", a)

listSinOrdenar.reverse()
a=0
for x in listSinOrdenar:
    a+=1
    new_value=my_variable.save_value({'value':x[3], "context": {"lat": float(x[1]), "lng": float(x[2])}, "timestamp":int(x[0])*1000})
    print("Envio: ", a)


"""
Created on Tue Dec  4 14:20:33 2018

@author: YSu
"""

import os
from shutil import copy

for run in range(0,1200):

    path=os.getcwd()+'\\PNW' + str(run)
    os.makedirs(path,exist_ok=True)
    update='PNW_wrapper.py'
    update_2='CA_wrapper.py'
    path=os.getcwd()+'\\PNW' + str(run)+'\\'+'UCED'
    copy(update,path)
    copy(update_2,path)


def stats_analysis(file_path_list, summary_onoff):
    import matplotlib.pyplot as plt
    import os
    from datetime import datetime

    def filetolist(filename):
        with open(filename, 'r') as f:
            f_list = list(f)

        return f_list

    def datasettocsv(list, filename, separator=','):
        f = open(filename, 'w')

        for l in list:
            line = ''
            for x in l:
                line = line + str(x) + separator
            line = line + '\n'
            f.write(line)
        f.flush()
        f.close()

    first_file_path = file_path_list[0]
    first_file_name = (first_file_path.split('/'))[-1]
    first_file_dir = first_file_path.replace(first_file_name, "")

    now = datetime.now()
    nowDate = now.strftime('%Y%m%d_')

    save_path = first_file_dir + nowDate + first_file_name

    if os.path.isdir(save_path) == True:
        pass
    elif os.path.isdir(save_path) == False:
        os.mkdir(save_path)

    final_stats_all_list = []
    for u in file_path_list :
        file_path = u

        raw = filetolist(file_path)
        file_name = (file_path.split('/'))[-1]

        raw_split = []
        for ii in range(len(raw)):
            xx = raw[ii].split()
            if 'ITERATION' in xx:
                raw_split.append(xx)
            elif 'ORIENTATION' in xx and 'OVERLAP:' in xx:
                raw_split.append(xx)
            elif 'CORRELATION' in xx:
                raw_split.append(xx)
            elif 'SPECSCORE' in xx:
                raw_split.append(xx)
            else:
                pass

        raw_split2 = []
        for ii in range(len(raw_split)):
            yy = raw_split[ii]
            del yy[0]
            raw_split2.append(yy)

        if (len(raw_split2)) % 4 == 0:
            pass
        elif (len(raw_split2)) % 4 == 1:
            del raw_split2[len(raw_split2) - 1]
        elif (len(raw_split2)) % 4 == 2:
            del raw_split2[len(raw_split2) - 1]
            del raw_split2[len(raw_split2) - 1]
        elif (len(raw_split2)) % 4 == 3:
            del raw_split2[len(raw_split2) - 1]
            del raw_split2[len(raw_split2) - 1]
            del raw_split2[len(raw_split2) - 1]
        else:
            pass

        raw_split3 = []
        for ii in range(int(len(raw_split2) / 4)):
            raw_split3.append(raw_split2[4 * ii])
            zz = []
            zz.append(raw_split2[4 * ii + 1][0] + ' ' + raw_split2[4 * ii + 1][1])
            zz.append(raw_split2[4 * ii + 1][2])
            raw_split3.append(zz)

            zz2 = (raw_split2[4 * ii + 2][1]).split('/')
            zz_corr_AVG = [zz2[0], raw_split2[4 * ii + 2][2]]
            zz_corr_SDEV = [zz2[1], raw_split2[4 * ii + 2][3]]
            zz_corr_MIN = [zz2[2], raw_split2[4 * ii + 2][4]]
            zz_corr_MAX = [zz2[3], raw_split2[4 * ii + 2][5]]
            zz_corr = [raw_split2[4 * ii + 2][0], zz_corr_AVG, zz_corr_SDEV, zz_corr_MIN, zz_corr_MAX]
            raw_split3.append(zz_corr)

            zz3 = (raw_split2[4 * ii + 3][1]).split('/')
            zz_spec_AVG = [zz3[0], raw_split2[4 * ii + 3][2]]
            zz_spec_SDEV = [zz3[1], raw_split2[4 * ii + 3][3]]
            zz_spec_MIN = [zz3[2], raw_split2[4 * ii + 3][4]]
            zz_spec_MAX = [zz3[3], raw_split2[4 * ii + 3][5]]
            zz_spec = [raw_split2[4 * ii + 3][0], zz_spec_AVG, zz_spec_SDEV, zz_spec_MIN, zz_spec_MAX]
            raw_split3.append(zz_spec)

        gadget = []
        stats_list = []
        for ii in range(int(len(raw_split3) / 4)):
            gadget.append(raw_split3[4 * ii])
            gadget.append(raw_split3[4 * ii + 1])
            gadget.append(raw_split3[4 * ii + 2])
            gadget.append(raw_split3[4 * ii + 3])
            stats_list.append(gadget)
            gadget = []

        stats_iter = []
        stats_overlap = []
        stats_corr_AVG = []
        stats_corr_SDEV = []
        stats_corr_MIN = []
        stats_corr_MAX = []
        stats_spec_AVG = []
        stats_spec_SDEV = []
        stats_spec_MIN = []
        stats_spec_MAX = []
        for ii in range(len(stats_list)):
            stats_iter.append(float(stats_list[ii][0][1]))
            stats_overlap.append(float(stats_list[ii][1][1]))
            stats_corr_AVG.append(float(stats_list[ii][2][1][1]))
            stats_corr_SDEV.append(float(stats_list[ii][2][2][1]))
            stats_corr_MIN.append(float(stats_list[ii][2][3][1]))
            stats_corr_MAX.append(float(stats_list[ii][2][4][1]))
            stats_spec_AVG.append(float(stats_list[ii][3][1][1]))
            stats_spec_SDEV.append(float(stats_list[ii][3][2][1]))
            stats_spec_MIN.append(float(stats_list[ii][3][3][1]))
            stats_spec_MAX.append(float(stats_list[ii][3][4][1]))

        plt.figure(figsize=(15, 5))

        plt.subplot(131)
        plt.title('Orientation overlap')
        plt.xlabel('Iterations')
        plt.ylabel('Orientation overlap')
        plt.scatter(stats_iter, stats_overlap, s=3, color='red')
        plt.axhline(y=0.9, color='blue', linewidth=1, label='Overlap=0.9 line')
        plt.legend(loc='upper left', fontsize=7)
        plt.ylim((-0.05, 1.05))
        plt.xlim((-0.05, len(stats_list) + 0.05))

        plt.subplot(132)
        plt.title('Correlation')
        plt.xlabel('Iterations')
        plt.ylabel('Correlation')
        plt.scatter(stats_iter, stats_corr_AVG, s=3, color='red', label='AVG')
        plt.scatter(stats_iter, stats_corr_SDEV, s=3, color='blue', label='SDEV')
        plt.scatter(stats_iter, stats_corr_MIN, s=3, color='green', label='MIN')
        plt.scatter(stats_iter, stats_corr_MAX, s=3, color='grey', label='MAX')
        plt.legend(loc='upper left', fontsize=6)
        plt.ylim((-0.05, 1.05))
        plt.xlim((-0.05, len(stats_list) + 0.05))

        plt.subplot(133)
        plt.title('Specscore')
        plt.xlabel('Iterations')
        plt.ylabel('Specscore')
        plt.scatter(stats_iter, stats_spec_AVG, s=3, color='red', label='AVG')
        plt.scatter(stats_iter, stats_spec_SDEV, s=3, color='blue', label='SDEV')
        plt.scatter(stats_iter, stats_spec_MIN, s=3, color='green', label='MIN')
        plt.scatter(stats_iter, stats_spec_MAX, s=3, color='grey', label='MAX')
        plt.legend(loc='upper left', fontsize=6)
        plt.ylim((-0.05, 1.05))
        plt.xlim((-0.05, len(stats_list) + 0.05))

        plt.savefig(save_path + '/SIMPLE_stats_fig_' + file_name + '.png')

        stats_list_for_csv = []
        stats_list_for_csv.append(
            ['ITERATION', 'ORIENTATION OVERLAP', 'CORRELATION', '', '', '', 'SPECSCORE', '', '', ''])
        stats_list_for_csv.append(['', '', 'AVG', 'SDEV', 'MIN', 'MAX', 'AVG', 'SDEV', 'MIN', 'MAX'])
        for ii in range(len(stats_list)):
            aa = stats_list[ii]
            for_csv_element = [aa[0][1], aa[1][1], aa[2][1][1], aa[2][2][1], aa[2][3][1], aa[2][4][1], aa[3][1][1],
                               aa[3][2][1], aa[3][3][1], aa[3][4][1]]
            stats_list_for_csv.append(for_csv_element)

        datasettocsv(stats_list_for_csv, save_path + '/stats_info_' + file_name + '.csv')

        final_stats_list = stats_list[-1]
        final_stats_list.append(file_name)
        final_stats_all_list.append(final_stats_list)

    if summary_onoff == 'on':
        summary_stats_list = []
        summary_stats_list.append(['EXP NAME', 'ITERATION', 'OVERLAP', 'CORRELATION', '', 'SPECSCORE', ''])
        summary_stats_list.append(['', '', '', 'AVG', 'SDEV', 'AVG', 'SDEV'])
        # summary_stats_list.append(final_stats_all_list[0])
        for u in final_stats_all_list :
            summary_stats_list.append([u[-1], u[0][1], u[1][1], u[2][1][1], u[2][2][1], u[3][1][1], u[3][2][1]])

        datasettocsv(summary_stats_list, save_path + '/summary_stats_info.csv')

    elif summary_onoff == 'off':
        pass

    return save_path


# Licensed to the .NET Foundation under one or more agreements.
# The .NET Foundation licenses this file to you under the MIT license.
# See the LICENSE file in the project root for more information.

from dataclasses import dataclass
from os import getcwd
from pathlib import Path
from typing import Sequence, Callable, List, Optional

from .chart_utils import chart_lines_from_fields, Trace
from .types import ProcessedTrace, ProcessedGC

from .clr import get_clr, Clr
from .clr_types import (
    AbstractCallTreeNodeBase,
    AbstractTimeSpan,
    AbstractSymbolReader,
    AbstractTraceLog,
    AbstractStackSource,
)
from ..commonlib.type_utils import with_slots, doc_field

@doc_field(
    "trace_info", "ProcessedTrace object with all the trace's data. Definition is in types.py."
)
@doc_field(
    "trace_log",
    "TraceLog object associated with the trace. This is part of TraceEvent, and "
    "contains all the streams of events in the trace and is used by GCPerf.",
)
@doc_field(
    "symbol_reader",
    "SymbolReader object in charge of finding and applying the PDB's to resolve "
    "the trace's symbols. This is part of TraceEvent.",
)
@doc_field(
    "stack_source",
    "StackSource object that contains a list of all the samples captured in the "
    "trace. This is part of TraceEvent.",
)
@with_slots
@dataclass(frozen=False)
class TraceReadAndParseUtils:
    trace_info: ProcessedTrace
    trace_log: AbstractTraceLog
    symbol_reader: AbstractSymbolReader
    stack_source: AbstractStackSource

    def __init__(self, ptrace: ProcessedTrace, symbol_path: Path):
        clr = get_clr()
        workdir = Path(getcwd())

        # Make sure we have the process name, otherwise GCPerf won't be able to
        # filter the stacks.

        assert ptrace.process_name is not None, (
            "Unknown error occurred. Was not able to get the process name ",
            "from test status yaml file.",
        )
        process_to_analyze = ptrace.process_name

        # Create and fetch the TraceLog, SymbolReader, and StackSource objects
        # associated with this trace.

        self.trace_info = ptrace
        self.trace_log = clr.Analysis.GetOpenedTraceLog(str(ptrace.test_result.trace_path))
        self.symbol_reader = clr.Analysis.GetSymbolReader(
            str(workdir / "GCPerf-Symbols-Log.txt"), str(symbol_path)
        )
        self.stack_source = clr.Analysis.GetProcessFullStackSource(
            self.trace_log, self.symbol_reader, process_to_analyze
        )

    # Clean up resources and print the metrics data. Also free the usage on
    # the symbols log file, as future calls to CPU Samples Analysis functions
    # with different traces would fail otherwise, due to the resource being used.
    def __del__(self) -> None:
        self.symbol_reader.Dispose()
        self.symbol_reader.Log.Close()

    # Since the ProcessTrace object stores the test's duration in seconds,
    # multiply by 1000 to get the msec GCPerf requires.
    @property
    def trace_duration_msec(self) -> float:
        return float(self.trace_info.TotalSecondsTaken.value) * 1000.0

    # Property for easy access to the trace's processed GC's.
    @property
    def trace_processed_gcs(self) -> Sequence[ProcessedGC]:
        return self.trace_info.gcs

    # Property for easy access to the trace's test name.
    @property
    def trace_name(self) -> str:
        return self.trace_info.name

@doc_field("gc_index", "Index/Number/ID of the GC.")
@doc_field("function", "Function to analyze samples of.")
@doc_field("inclusive_count", "Number of CPU Samples of the analyzed function and its callees.")
@doc_field("exclusive_count", "Number of CPU Samples of the analyzed function only.")
@doc_field(
    "inclusive_metric_percent", "Percent of CPU Samples belonging to this function and its callees."
)
@doc_field("exclusive_metric_percent", "Percent of CPU Samples belonging to this function only.")
@doc_field("first_time_msec", "Timestamp in msec where this function's first sample was found.")
@doc_field("last_time_msec", "Timestamp in msec where this function's last sample was found.")
@with_slots
@dataclass(frozen=True)
class GCAndCPUSamples:
    gc_index: int
    function: str
    inclusive_count: float
    exclusive_count: float
    inclusive_metric_percent: float
    exclusive_metric_percent: float
    first_time_msec: float
    last_time_msec: float

def _print_node(node: AbstractCallTreeNodeBase) -> None:
    print(f"Name: {node.Name}")
    print(f"Inclusive Metric %: {node.InclusiveMetricPercent}")
    print(f"Exclusive Metric %: {node.ExclusiveMetricPercent}")
    print(f"Inclusive Count: {node.InclusiveCount}")
    print(f"Exclusive Count: {node.ExclusiveCount}")
    print(f"First Time Relative MSec: {node.FirstTimeRelativeMSec}")
    print(f"Last Time Relative MSec: {node.LastTimeRelativeMSec}")

# Summary: Generates a list of TimeSpan objects, which contain the start and end
# times of each individual GC from the list provided as parameter.
#
# The TimeSpan class is part of GCPerf and is defined in managed-lib/Analysis.cs.
#
# Parameters:
#   gcs: List of ProcessedGC objects, which contain all the information of
#        each individual GC.
#
# Returns:
#    List with the time ranges of each GC. This list is later used in
#    _get_cpu_samples_from_trace() to fetch each GC's sample metrics.

def _get_gcs_time_ranges(gcs: Sequence[ProcessedGC]) -> List[AbstractTimeSpan]:
    time_ranges = []
    clr = get_clr()
    for gc in gcs:
        start = gc.StartRelativeMSec
        end = gc.EndRelativeMSec
        time_ranges.append(clr.TimeSpanUtil.FromStartEndMSec(start, end))
    return time_ranges

# Summary: Filters the GC's (if a filter is specified) of the given trace,
#          and retrieves all the samples metrics of each one, for each of
#          the specified functions. The metrics of each GC in each function
#          create a set of "points", which is then appended to the 'all_data_to_chart'
#          list. Chart_cpu_samples_per_gcs() uses this list to draw the final chart.
#
# Parameters:
#   clr: Clr object which provides the capability to call GCPerf from here.
#   trace_utils: TraceReadAndParseUtils object with the trace's associated
#       ProcessedTrace, TraceLog, SymbolReader, and StackSource objects.
#   functions: List with the names of the runtime functions to analyze.
#   all_data_to_chart: List where Trace objects with the points to chart
#       are appended. This class is defined in chart_utils.py.
#   gc_filter: Function used to filter the trace's GC's. This parameter is
#       optional and can be omitted to chart all the GC's samples.
#
# Returns: Nothing

def _get_cpu_samples_from_trace(
    clr: Clr,
    ptrace_utils: TraceReadAndParseUtils,
    functions: Sequence[str],
    all_data_to_chart: List[Trace[GCAndCPUSamples]],
    gc_filter: Optional[Callable[[ProcessedGC], bool]] = None,
) -> None:

    # Filter the GC's we want and obtain their time lapses.

    gcs_to_analyze = list(filter(gc_filter, ptrace_utils.trace_processed_gcs))
    gcs_time_ranges = _get_gcs_time_ranges(gcs_to_analyze)

    # Read each GC's metrics for each of the given functions and create a new
    # GCAndCPUSamples object with this data and add it to a list of points.
    #
    # Finally, wrap this list in a Trace object and append it to the result list.
    # The reason it is done this way instead of returning the result, is because
    # when one wants to chart from more than one trace, chart_cpu_samples_per_gcs()
    # would end up with a list of lists, instead of a list of traces, which is
    # what the charting utilities require.

    for func in functions:
        sample_points = []

        for gc, trange in zip(gcs_to_analyze, gcs_time_ranges):
            node_metrics = clr.Analysis.GetFunctionMetricsWithinTimeRange(
                ptrace_utils.trace_log,
                ptrace_utils.symbol_reader,
                ptrace_utils.stack_source,
                trange,
                func,
            )
            sample_points.append(
                GCAndCPUSamples(
                    gc_index=gc.index,
                    function=func,
                    inclusive_count=node_metrics.InclusiveCount,
                    exclusive_count=node_metrics.ExclusiveCount,
                    inclusive_metric_percent=node_metrics.InclusiveMetricPercent,
                    exclusive_metric_percent=node_metrics.ExclusiveMetricPercent,
                    first_time_msec=node_metrics.FirstTimeRelativeMSec,
                    last_time_msec=node_metrics.LastTimeRelativeMSec,
                )
            )
        all_data_to_chart.append(
            Trace(name=f"{ptrace_utils.trace_name}---{func}", data=sample_points)
        )

# Summary: Reads all the given traces and calls _get_cpu_samples_from_trace()
#          accordingly to get all the samples data to chart. Then, calls
#          chart_lines_from_fields() to display the chart.
#
# Parameters:
#   ptraces_utils: List with the TraceReadAndParseUtils objects containing
#       all the information and helper objects for each trace to analyze.
#   functions_to_chart: List with the names of the runtime functions to analyze.
#   x_property_name: Metric to chart on the X-Axis.
#   y_property_name: Metric(s) to chart on the Y-Axis.
#   gc_filter: Function used to filter the trace's GC's. This parameter is
#       optional and can be omitted to chart all the GC's samples.
#
# Returns: Nothing

def chart_cpu_samples_per_gcs(
    ptraces_utils: Sequence[TraceReadAndParseUtils],
    functions_to_chart: Sequence[str],
    x_property_name: str,
    y_property_names: Sequence[str],
    gc_filter: Optional[Callable[[ProcessedGC], bool]] = None,
) -> None:
    clr = get_clr()
    all_data_to_chart: List[Trace[GCAndCPUSamples]] = []

    # Read each trace and get the samples data to chart.

    for ptrace in ptraces_utils:
        _get_cpu_samples_from_trace(
            clr=clr,
            ptrace_utils=ptrace,
            functions=functions_to_chart,
            all_data_to_chart=all_data_to_chart,
            gc_filter=gc_filter,
        )

    # Display the chart.

    chart_lines_from_fields(
        t=GCAndCPUSamples,
        traces=all_data_to_chart,
        x_property_name=x_property_name,
        y_property_names=y_property_names,
    )

# Summary: Displays the main CPU samples metrics of the given function, within
#          the specified time range.
#
# Parameters:
#   trace_utils: TraceReadAndParseUtils object with the trace's associated
#       ProcessedTrace, TraceLog, SymbolReader, and StackSource objects.
#   function: Runtime function to look at samples information.
#   start_time_msec: Timestamp in msec where we want to begin observations.
#       This parameter is optional and if omitted, analysis will start at
#       the beginning of the trace.
#   end_time_msec: Timestamp in msec where we want to end observations.
#       This parameter is optional and if omitted, analysis will finish at
#       the end of the trace.
#
# Returns: Nothing

def show_cpu_samples_metrics(
    ptrace_utils: TraceReadAndParseUtils,
    function: str,
    start_time_msec: float = 0.0,
    end_time_msec: float = 0.0,
) -> None:
    clr = get_clr()

    # If end time was not specified, search for the trace's length to set
    # this boundary.

    if end_time_msec == 0.0:
        end_time_msec = ptrace_utils.trace_duration_msec

    # Make sure we have a positive time range to look at.

    assert start_time_msec < end_time_msec, (
        f"Check the timestamp values. Start time is {start_time_msec}, ",
        f"which is later than End time {end_time_msec}.",
    )

    # Get the samples metrics data.

    node_metrics = clr.Analysis.GetFunctionMetricsWithinTimeRange(
        ptrace_utils.trace_log,
        ptrace_utils.symbol_reader,
        ptrace_utils.stack_source,
        clr.TimeSpanUtil.FromStartEndMSec(start_time_msec, end_time_msec),
        function,
    )
    _print_node(node_metrics)


import socket
import re
import multiprocessing

import os,sys
# base_dir=os.path.dirname(__file__)
# sys.path.append(base_dir)
# import mini_framework

class WebServer(object):
    def __init__(self, port, static_path, app):
        # 创建套接字
        self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    # 解决当服务器端关闭时需要等待2MSL的问题
        # 绑定端口
        self.tcp_socket.bind(("", int(port)))
        # 监听套接字
        self.tcp_socket.listen(128)
        self.static_path = static_path
        self.application = app

    def server_client(self, client_socket):
        # 1.接收浏览器发送的消息
        request_msg = client_socket.recv(1024).decode('utf-8')
        # request_msg = request_msg.splitlines()      # 将 request_msg 一行一行切割成列表
        print(request_msg)

        # 2.提取文件名
        file_name = ''
        # ret = re.match(r"[^/]+(/[^ ]*)", request_msg[0])   # 问题：若正则没匹配到内容，会重新执行一次代码，为什么没在accept阻塞？
        ret = re.match(r"[^/]+(/[^ ]*)", request_msg)
        if ret:
            file_name = ret.group(1)
            print(file_name)
            if file_name == "/":
                file_name = "/index.html"
        # 3.返回HTTP格式的数据给浏览器
        # 判断file_path是否py文件后缀，如果不是则请求静态资源，如果是则请求动态资源（html/css/js/png、jpg等）
        if not file_name.endswith(".py"):
            try:
                f = open(self.static_path + file_name, "rb")
                content = f.read()
                f.close()
            except Exception as e:
                response_headers = "HTTP/1.1 404 ok\r\n"
                response_headers += "\r\n"
                response_body = "------file not found------"
                response_msg = response_headers + response_body
                client_socket.send(response_msg.encode('utf-8'))
            else:   # else 子句将在 try 子句没有发生任何异常的时候执行。
                # 2.1 模拟header部分
                response_headers = "HTTP/1.1 200 ok\r\n"  # 浏览器会把 \r\n 识别为换行
                # 2.2 浏览器会把header空行后的内容当成响应体
                response_headers += "\r\n"
                # 2.3 返回数据给浏览器
                client_socket.send(response_headers.encode('utf-8'))  # send只能发送byte类型的内容，需要转换成utf-8
                client_socket.send(content)
        else:
            # 根据WSGI协议，框架端需要定义一个application方法，包含两个参数：env参数为字典，start_response参数为一个函数的引用
            """
            env参数默认定义参数为：
                PATH_INFO：路由信息；
                SERVER_PORT：端口；
                HTTP_HOST：ip；
                SERVER_PROTOCOL：服务器端通信协议
            """
            env = {"PATH_INFO": file_name}
            # content = mini_framework.application(env, self.start_response)
            content = self.application(env, self.start_response)
            response_headers = F"{self.status}\r\n"
            for key, value in self.headers:
                response_headers += F"{key}:{value}\r\n"
            response_headers += "\r\n"
            response_body = content
            response_msg = response_headers + response_body
            client_socket.send(response_msg.encode("utf-8"))
            print(response_msg)

        # 3.服务完成关闭接口
        client_socket.close()

    def start_response(self, status, headers):
        self.status = status
        self.headers = [("server", "nginx")]
        self.headers = headers

    def run(self):
        # 等待客户连接
        while True:
            client_socket, client_addr = self.tcp_socket.accept()
            # 多进程为客户服务。注：虽然使用了多进程，但是当两个客户端同时发送请求时，有个客户会请求不到数据
            p = multiprocessing.Process(target=self.server_client, args=(client_socket,))
            p.start()
            client_socket.close()   # 子进程会完全复制一份注进程信息，这里关闭主进程的接口不会影响到子进程，反而不关闭在linux中会导致接口无法释放

def main():
    # 从配置文件读取数据
    with open("./web_server.cnf", "r") as f:
        config = eval(f.read())  # eval()将字符串转换成字典
        static_path = config["static_path"]     # 获取静态文件配置路径
        port = config["port"]
        framework = config["framework"]
    base_dir = os.path.dirname(__file__)
    sys.path.append(base_dir)   # 将当前文件执行路径临时加入环境变量
    fw = __import__(framework)  # 返回值是个对象，标记着mini_framework模块
    app = getattr(fw, "application")    # 此时app指向的就是mini_framework模块中的application函数
    # sys.argv：获取当前执行的命令被空格分隔后的列表
    print(sys.argv)
    if len(sys.argv) == 2:
        # 从cmd命令界面传参
        # 使用命令  python web_server.py 7777 时，获取7777的输入值
        port = sys.argv[1]
    web_server = WebServer(port, static_path, app)
    web_server.run()

if __name__ == '__main__':
    main()


#!/usr/bin/env python2
from __future__ import division
import os.path
import re

def log_filename(role, node_id, exp_id):
    if role not in ['AUV', 'NODE']:
        raise ValueError('Unknown role')
    return 'Uwpolling_%(role)s_%(node_id)d_%(exp_id)d.out' % \
        {'role': role, 'node_id': node_id, 'exp_id': exp_id}

def clock_shift(exp_id, ref, node):
    if exp_id == 40:
        shifts_ref1 = {1: 0, 2: 2, 3: 5, 4: 8, 5: 11}
        return shifts_ref1[node] - shifts_ref1[ref]
    elif exp_id == 35:
        shifts_ref5 = {1: 3, 2: 3, 3: 3, 4: 3, 5: 0}
        return shifts_ref5[node] - shifts_ref5[ref]

def process_logfile(fname, function, counters):
    with open(fname, 'r') as f:
        for line in f:
            function(counters, line)

def process_auv_line(counters, line):
    # Keep the last time
    m = re.match('([\d\.]+)Uwpolling.*', line)
    if not m:
        raise RuntimeError('All lines should match')
    counters['last_auv_time'] = float(m.group(1))

    # Save the time of the recvd pkts
    m = re.match('(?P<time>[\d\.]+)Uwpolling_.*RX_DATA_ID_(?P<pkt_id>\d+)_FROM_NODE_(?P<node_id>\d+)', line)
    if m:
        n_id = int(m.group('node_id'))
        pkt_id = int(m.group('pkt_id'))
        t = float(m.group('time'))

        all_times = counters.setdefault('pkt_rx_times', dict())
        node = all_times.setdefault(n_id, dict())
        if pkt_id in node:
            raise RuntimeError('Duplicated pkt id')
        node[pkt_id] = t

    # Count the received packets
    m = re.match('.*RX_DATA_ID_\d+_FROM_NODE_(\d+)', line)
    if m:
        n_id = int(m.group(1))

        tot = counters.setdefault('pkt_rx_total', 0)
        pernode = counters.setdefault('pkt_rx_node', dict())
        node = pernode.setdefault(n_id, 0)

        counters['pkt_rx_total'] = tot + 1
        pernode[n_id] = node + 1
        return

    # Count the trigger pkts sent
    m = re.match('.*TX_TRIGGER', line)
    if m:
        cnt = counters.setdefault('trigger_tx', 0)
        counters['trigger_tx'] = cnt + 1
        return

    # Count the poll pkts sent
    m = re.match('.*TX_POLL_.*', line)
    if m:
        cnt = counters.setdefault('poll_tx', 0)
        counters['poll_tx'] = cnt + 1
        return

def process_node_line(counters, line):
    # Save the times of the pkts generated by the app
    m = re.match('(?P<time>[\d\.]+)Uwpolling_NODE\((?P<node_id>\d+)\)::RECV_FROM_U_LAYERS_ID_(?P<pkt_id>\d+)', line)
    if m:
        n_id = int(m.group('node_id'))
        pkt_id = int(m.group('pkt_id'))
        t = float(m.group('time'))

        all_times = counters.setdefault('pkt_tx_times', dict())
        node = all_times.setdefault(n_id, dict())
        if pkt_id in node:
            raise RuntimeError('Duplicated pkt id')
        node[pkt_id] = t

    # Count the pkts sent
    m = re.match('.*NODE\((\d+)\)::TX_DATA_.*', line)
    if m:
        n_id = int(m.group(1))

        tot = counters.setdefault('pkt_tx_total', 0)
        pernode = counters.setdefault('pkt_tx_node', dict())
        node = pernode.setdefault(n_id, 0)

        counters['pkt_tx_total'] = tot + 1
        pernode[n_id] = node + 1
        return

    # Count the pkts generated by the app layer
    m = re.match('.*NODE\((\d+)\)::RECV_FROM_U_LAYERS_.*', line)
    if m:
        n_id = int(m.group(1))

        tot = counters.setdefault('pkt_tx_app_total', 0)
        pernode = counters.setdefault('pkt_tx_app_node', dict())
        node = pernode.setdefault(n_id, 0)

        counters['pkt_tx_app_total'] = tot + 1
        pernode[n_id] = node + 1
        return

    # Count the probe pkts sent
    m = re.match('.*TX_PROBE_.*', line)
    if m:
        cnt = counters.setdefault('probe_tx', 0)
        counters['probe_tx'] = cnt + 1
        return

LOGDIR = './uwpolling_logs'
EXP_IDS = [35, 40]
NODE_IDS = range(1,5)
AUV_ID = 5

counters_all = dict()
for exp_id in EXP_IDS:
    dname = os.path.join(LOGDIR, str(exp_id))
    counters = counters_all.setdefault(exp_id, dict())

    fname_auv = os.path.join(dname, log_filename('AUV', AUV_ID, exp_id))
    process_logfile(fname_auv, process_auv_line, counters)

    for i in NODE_IDS:
        fname_node = os.path.join(dname, log_filename('NODE', i, exp_id))
        process_logfile(fname_node, process_node_line, counters)

for exp_id in EXP_IDS:
    print('Experiment %d' % exp_id)
    counters = counters_all[exp_id]

    # PDR at MAC layer
    pdr_mac_tot = counters['pkt_rx_total'] / counters['pkt_tx_total']
    print('Global PDR at MAC layer = %f' % pdr_mac_tot)
    for n_id in NODE_IDS:
        pdr_mac_node = (counters['pkt_rx_node'][n_id] /
                       counters['pkt_tx_node'][n_id])
        print('PDR at MAC layer for node %d = %f' % (n_id, pdr_mac_node))

    # PDR at app layer
    pdr_app_tot = counters['pkt_rx_total'] / counters['pkt_tx_app_total']
    print('Global PDR at app layer = %f' % pdr_app_tot)
    for n_id in NODE_IDS:
        pdr_app_node = (counters['pkt_rx_node'][n_id] /
                       counters['pkt_tx_app_node'][n_id])
        print('PDR at app layer for node %d = %f' % (n_id, pdr_app_node))

    # Throughput
    thr_tot = counters['pkt_rx_total'] / counters['last_auv_time']
    thr_tot *= 60
    print('Global throughput = %f pkts/min' % thr_tot)
    for n_id in NODE_IDS:
        thr_node = counters['pkt_rx_node'][n_id] / counters['last_auv_time']
        thr_node *= 60
        print('Throughput for node %d = %f pkts/min' % (n_id, thr_node))

    # Overhead
    txed_control_bits = (48 * counters['trigger_tx'] + 72 * counters['probe_tx'] +
                         24 * counters['poll_tx'] + 61 * counters['pkt_tx_total'])
    overhead = txed_control_bits / counters['pkt_rx_total']
    print('Overhead = %f bits/pkt' % overhead)

    #Delay
    all_delays = list()
    for n_id in NODE_IDS:
        delays = list()
        for pkt_id in counters['pkt_rx_times'][n_id]:
            sent_time = counters['pkt_tx_times'][n_id][pkt_id]
            recvd_time = counters['pkt_rx_times'][n_id][pkt_id]
            delays.append(recvd_time - sent_time - clock_shift(exp_id, AUV_ID, n_id))
        all_delays.extend(delays)
        mean_delay = sum(delays) / len(delays)
        print('Avg. pkt delay for node %d = %f s' % (n_id, mean_delay))
    global_mean = sum(all_delays) / len(all_delays)
    print('Avg. pkt delay = %f s' % global_mean)
    print('')


"""
Calculating a List of Cumulative Totals (Read the whole question before starting the work!)
Accountant Annie wants you to write a program to calculate the monthly cumulative totals for incomes.
The program should ask for the number of monthly incomes to enter,
then get and store them in a list.
When the incomes have been entered,
the program should display a list of the month’s income next to the
cumulative income at that point - for each month. Here’s some sample output:
"""

def main():
    """Display income report for incomes over a given number of TotalMonths."""
    incomes = []
    total_months = int(input("How many Months? "))

    for month in range(1, total_months + 1):
        income = float(input("Enter income for month {}: ".format(month)))
        incomes.append(income)

    income_report(incomes, total_months)

def income_report(incomes, total_months):
    print("\nIncome Report\n-------------")
    total = 0
    for month in range(1, total_months + 1):
        income = incomes[month - 1]
        total += income
        print("Month {:2} - Income: ${:7.2f} Total: ${:7.2f}".format(month, income, total))

main()

Calculating  a list of cumulative totals.py


import setuptools

with open("README.md") as f:
    long_description = f.read()

setuptools.setup(
    name="telemeter",
    version="3.0.9",
    author="Killian Meersman",
    author_email="hi@killianm.dev",
    description="Retrieves information about Telenet internet usage",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/KillianMeersman/telemeter",
    packages=setuptools.find_packages(),
    keywords="telenet telemeter",
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    install_requires=["requests"],
)


#! /usr/bin/env python3
# Simple gossip tests.

from lnprototest import Connect, Block, ExpectMsg, Msg, RawMsg, Funding, Side, MustNotMsg, Disconnect, Runner
from helpers import tx_spendable, utxo
import time

def test_gossip(runner: Runner) -> None:
    # Make up a channel between nodes 02 and 03, using bitcoin privkeys 10 and 20
    funding, funding_tx = Funding.from_utxo(*utxo(0),
                                            local_node_privkey='02',
                                            local_funding_privkey='10',
                                            remote_node_privkey='03',
                                            remote_funding_privkey='20')

    test = [Block(blockheight=102, txs=[tx_spendable]),
            Connect(connprivkey='03'),
            ExpectMsg('init'),
            Msg('init', globalfeatures='', features=''),

            Block(blockheight=103, number=6, txs=[funding_tx]),

            RawMsg(funding.channel_announcement('103x1x0', '')),

            # New peer connects, asking for initial_routing_sync.  We *won't* relay channel_announcement, as there is no channel_update.
            Connect(connprivkey='05'),
            ExpectMsg('init'),
            Msg('init', globalfeatures='', features='08'),
            MustNotMsg('channel_announcement'),
            Disconnect(),

            RawMsg(funding.channel_update('103x1x0',
                                          Side.local,
                                          disable=False,
                                          cltv_expiry_delta=144,
                                          htlc_minimum_msat=0,
                                          fee_base_msat=1000,
                                          fee_proportional_millionths=10,
                                          timestamp=int(time.time()),
                                          htlc_maximum_msat=None),
                   connprivkey='03'),

            # Now we'll relay to a new peer.
            Connect(connprivkey='05'),
            ExpectMsg('init'),
            Msg('init', globalfeatures='', features='08'),
            ExpectMsg('channel_announcement',
                      short_channel_id='103x1x0'),
            ExpectMsg('channel_update',
                      short_channel_id='103x1x0',
                      message_flags=0,
                      channel_flags=0),
            Disconnect(),

            # BOLT #7:
            # A node:
            #   - SHOULD monitor the funding transactions in the blockchain, to
            #   identify channels that are being closed.
            #  - if the funding output of a channel is being spent:
            #    - SHOULD be removed from the local network view AND be
            #      considered closed.
            Block(blockheight=109, txs=[funding.close_tx(200, '99')]),

            Connect(connprivkey='05'),
            ExpectMsg('init'),
            Msg('init', globalfeatures='', features='08'),
            MustNotMsg('channel_announcement'),
            MustNotMsg('channel_update')]

    runner.run(test)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Filename : experiment_bj_meden
# @Date     : 01/24/2019 16:56:00
# @Poject   : DGMP
# @Author   : FEI, hfut_jf@aliyun.com
# @Desc     :

from __future__ import print_function

import os
import sys

sys.path.append(os.path.abspath('/network/rit/lab/ceashpc/fjie/projects/DGMP'))

import logging

import pickle

from subprocess import Popen, PIPE
from multiprocessing import Pool

import numpy as np

from utility import evaluate_global

# fixme, logger must be in the last part, calls in other files will overlap current setting
logger = logging.getLogger('x')
formatter = logging.Formatter('')
consoled_handler = logging.StreamHandler()
consoled_handler.setFormatter(formatter)
logger.addHandler(consoled_handler)
logger.setLevel(logging.DEBUG)
logger.propagate = False

TOP_K = 30

def one_file_test():

    date = '20130912'
    hour = 10
    threshold = 5.0
    k = 10

    rfn = '/network/rit/lab/ceashpc/share_data/Beijing/run0/binarize/train/{}_hour_{:d}_{:.1f}.txt'.format(date, hour, threshold)
    action = '-runtopk'
    edge_type = 'w'
    num_windows = 6

    proc = Popen(['java', '-jar', 'meden.jar', action, '{:d}'.format(k), rfn, '0', '{:d}'.format(num_windows - 1), edge_type], stdout=PIPE)

    output = proc.stdout.read()

    # print(output)

def run_one_file(paras):

    rfn, wfn, action, num_windows, edge_type, k = paras

    if os.path.isfile(wfn):
        print('File {} already exists'.format(wfn))
        return

    proc = None
    if action == '-run':
        proc = Popen(['java', '-jar', 'meden.jar', action, rfn, '0', '{:d}'.format(num_windows-1), edge_type], stdout=PIPE)
    elif action == '-runtopk':
        proc = Popen(['java', '-jar', 'meden.jar', action, '{:d}'.format(k), rfn, '0', '{:d}'.format(num_windows-1), edge_type], stdout=PIPE)
    else:
        logger.debug('Wrong action command !')
        exit(0)

    output = proc.stdout.read()

    logger.debug('Run experiment on {}'.format(rfn))
    logger.debug('Write to {}'.format(wfn))

    with open(wfn, 'w') as wfile:
        wfile.write(output)

def run_multi_files():
    paras_comb = []
    num_cpus = 18

    action = '-runtopk'
    edge_type = 'w'
    num_windows = 6
    # k_list = [10, 20, 30, 40, 50]
    k_list = [100]

    # path = '/network/rit/lab/ceashpc/share_data/Beijing/run0/binarize/train'
    path = '/network/rit/lab/ceashpc/share_data/Beijing/run0/binarize/test'
    # output_path = '/network/rit/lab/ceashpc/share_data/Beijing/results/meden/run0/train'
    output_path = '/network/rit/lab/ceashpc/share_data/Beijing/results/meden/run0/test'

    # hour_list = range(5, 14)
    hour_list = range(14, 23)
    # hour_list = range(5, 6)
    # date = '20130912' # training
    date = '20130913' # testing
    # threshold_list = np.arange(5, 15.1, 2.5)
    threshold_list = [12.5]
    for threshold in threshold_list:
        for hour in hour_list:
            for k in k_list:
                fn = '{}_hour_{:d}_{:.1f}.txt'.format(date, hour, threshold)
                rfn = os.path.join(path, fn)
                fn_2 = '{}_hour_{:d}_{:.1f}_{:.1f}.txt'.format(date, hour, threshold, k)
                wfn = os.path.join(output_path, fn_2)

                paras = rfn, wfn, action, num_windows, edge_type, k
                paras_comb.append(paras)

    pool = Pool(processes=num_cpus)
    pool.map(run_one_file, paras_comb)
    pool.close()
    pool.join()

def evaluate_multi_files():

    num_windows = 6
    # k_list = [10, 20, 30, 40, 50]
    k_list = [100]
    # threshold_list = np.arange(5, 15.1, 2.5)
    threshold_list = [12.5]

    path = '/network/rit/lab/ceashpc/share_data/Beijing/run0/dgmp'
    # output_path = '/network/rit/lab/ceashpc/share_data/Beijing/results/meden/run0/train'
    output_path = '/network/rit/lab/ceashpc/share_data/Beijing/results/meden/run0/test'

    # date = '20130912'
    date = '20130913'
    hour_list = range(5, 23)
    all_results = {}
    for hour in hour_list:
        for k in k_list:
            for threshold in threshold_list:

                if (k, threshold) not in all_results.keys():
                    all_results[(k, threshold)] = []

                print('hour={:d}, k={:d}, threshold={:.1f}'.format(hour, k, threshold))
                fn = '{}_hour_{:d}.pkl'.format(date, hour)
                with open(os.path.join(path, fn), 'rb') as rfile:
                    dataset = pickle.load(rfile)

                top_k_true_subgraphs = dataset['top_k_true_subgraphs']
                true_subgraphs = []
                for t in range(num_windows):
                    true_nodes = []
                    # top k subgraphs combination at t
                    for i in range(TOP_K): # note: top k, 30 !!!
                        true_nodes += top_k_true_subgraphs[i][t]

                    true_subgraphs.append(true_nodes)

                # output_path = '/network/rit/lab/ceashpc/share_data/DC/results/meden/run2/train'

                dataset_results = []
                instance_results = []
                pred_fn = '{}_hour_{:d}_{:.1f}_{:.1f}.txt'.format(date, hour, threshold, k)
                pred_subgraphs = []
                nodes_dict = {}
                with open(os.path.join(output_path, pred_fn)) as rfile:
                    while True:
                        line = rfile.readline().strip()
                        if not line:
                            break

                        if line.startswith('TOP'):
                            line = rfile.readline()
                            terms = line[1:line.find(']')].split(',')
                            pred_start, pred_end = int(terms[0]), int(terms[1])
                            # print(pred_start, pred_end)

                            for t in range(pred_start, pred_end+1, 1):
                                nodes = set()
                                line = rfile.readline()
                                terms = line[line.find('{')+1:-1].strip().split(' ')
                                for term in terms:
                                    node_1 = int(term[:term.find('-')])
                                    node_2 = int(term[term.find('-')+1:term.find('(')])
                                    nodes.add(node_1)
                                    nodes.add(node_2)
                                if t in nodes_dict.keys():
                                    nodes_dict[t].append(np.sort(list(nodes))) # note: keep data type consistency
                                else:
                                    nodes_dict[t] = []
                                    nodes_dict[t].append(np.sort(list(nodes)))
                # print(nodes_dict)
                for t in range(num_windows):
                    if t not in nodes_dict.keys():
                        pred_subgraphs.append([])
                    else:
                        windows_nodes = set()
                        for x in nodes_dict[t]:
                            for node in x:
                                windows_nodes.add(node)
                        pred_subgraphs.append(np.sort(list(windows_nodes)))

                # calculate performacen of an instance
                original_performance = evaluate_global(all_true_subgraphs=true_subgraphs, all_pred_subgraphs=pred_subgraphs)

                # for true_subgraph in data['true_subgraphs']:
                #     print(np.sort(true_subgraph))

                # for pred_subgraph in pred_subgraphs:
                #     print(np.sort(pred_subgraph))

                print(np.array(original_performance).reshape((-1, 1)))

                all_results[(k, threshold)].append(original_performance)

                # dataset_results = np.array(dataset_results)
                # print(dataset_results.transpose())
                #
                # print(np.mean(dataset_results, axis=0).reshape((-1, 1)))
                #
                # results[:, i] = np.mean(dataset_results, axis=0)
        # print(num_files)

            # print(mu_1)
            # print(results)
            # np.savetxt(sys.stdout, np.array(threshold_list).reshape((1, -1)), fmt='%d', delimiter='\t')
            # np.savetxt(sys.stdout, results, fmt='%.5f', delimiter='\t')

    for k in k_list:
        for threshold in threshold_list:
            print('k={:d}, threshold={:1f}'.format(k, threshold))
            setting_result = np.array(all_results[(k, threshold)])
            print(setting_result.transpose())
            print(np.mean(setting_result, axis=0).reshape((-1, 1)))

if __name__ == '__main__':
    np.set_printoptions(linewidth=2000, threshold=np.nan)

    # one_file_test()

    # run_multi_files()

    evaluate_multi_files()