""" Written by David Besson, 5 Oct 2018"""

import time
import krpc
from numpy import *
import pandas as pd

# Initiate krpc objects
conn = krpc.connect(name='Landing Site')
vessel = conn.space_center.active_vessel
body = vessel.orbit.body
ap = vessel.auto_pilot
create_relative = conn.space_center.ReferenceFrame.create_relative
canvas = conn.ui.stock_canvas

# Get the size of the game window in pixels
screen_size = canvas.rect_transform.size

# Add a panel to contain the UI elements
panel = canvas.add_panel()

# Position the panel on the left of the screen
rect = panel.rect_transform
rect.size = (400,200)
rect.position = (200.-(screen_size[0]/2.), 0)

# Add some text displaying the current and final errors
text = panel.add_text("Horizontal Error (m): ")
text.rect_transform.size = (325.,30.)
text.rect_transform.position = (-20, 50)
text.color = (1, 1, 1)
text.size = 18

text2 = panel.add_text("Predicted Final Error (m): ")
text2.rect_transform.size = (325.,30.)
text2.rect_transform.position = (-20, 20)
text2.color = (1, 1, 1)
text2.size = 18

# Add some text describing what the code is doing right now
text3 = panel.add_text("Launching to 18,000 m. Adjusting heading towards landing site. Pitch at 85 deg.")
text3.rect_transform.size = (325.,100.)
text3.rect_transform.position = (-20, -60)
text3.color = (1, 1, 1)
text3.size = 18

# Coordinates of landing site
landing_latitude = -(1.+(31./60)+(15./60/60))
landing_longitude = -(71.+(53./60)+(50./60/60))
landing_altitude = 20

# Determine landing site reference frame
# (orientation: x=zenith, y=north, z=east)
landing_position = body.surface_position(
    landing_latitude, landing_longitude, body.reference_frame)
q_long = (
    0,
    sin(-landing_longitude * 0.5 * pi / 180),
    0,
    cos(-landing_longitude * 0.5 * pi / 180)
)
q_lat = (
    0,
    0,
    sin(landing_latitude * 0.5 * pi / 180),
    cos(landing_latitude * 0.5 * pi / 180)
)

landing_reference_frame = \
    create_relative(
        create_relative(
            create_relative(
                body.reference_frame,
                landing_position,
                q_long),
            (0, 0, 0),
            q_lat),
        (landing_altitude, 0, 0))

# Create krpc data streams
altitude = conn.add_stream(getattr, vessel.flight(), 'surface_altitude')
ut = conn.add_stream(getattr, conn.space_center, 'ut')
velocity = conn.add_stream(vessel.velocity,landing_reference_frame)
v_speed = conn.add_stream(getattr,vessel.flight(landing_reference_frame), 'vertical_speed')
h_speed = conn.add_stream(getattr,vessel.flight(landing_reference_frame), 'horizontal_speed')
position = conn.add_stream(vessel.position,landing_reference_frame)
rotation = conn.add_stream(vessel.rotation,landing_reference_frame)
direction = conn.add_stream(vessel.direction,landing_reference_frame)
angular_velocity = conn.add_stream(vessel.angular_velocity,landing_reference_frame)
aero_force = conn.add_stream(getattr, vessel.flight(), 'aerodynamic_force')
Engine = vessel.parts.engines[0]
gimb_angle = conn.add_stream(vessel.parts.engines[0].thrusters[0].part.direction,vessel.reference_frame)
gimb_pos = conn.add_stream(vessel.parts.engines[0].thrusters[0].part.position,vessel.reference_frame)
mass = conn.add_stream(getattr, vessel, 'mass')
moment_of_inertia = conn.add_stream(getattr, vessel, 'moment_of_inertia')
inertia_tensor = conn.add_stream(getattr, vessel, 'inertia_tensor')
com = conn.add_stream(getattr, vessel.flight(), 'center_of_mass')
available_torque = conn.add_stream(getattr, vessel, 'available_torque')
g = conn.add_stream(getattr,body, 'surface_gravity')
latitude = conn.add_stream(getattr, vessel.flight(), 'latitude')
longitude = conn.add_stream(getattr, vessel.flight(), 'longitude')
atm_density = conn.add_stream(getattr, vessel.flight(), 'atmosphere_density')
dyn_pressure = conn.add_stream(getattr, vessel.flight(), 'dynamic_pressure')
stat_pressure = conn.add_stream(getattr, vessel.flight(), 'static_pressure')
lift = conn.add_stream(getattr, vessel.flight(), 'lift')
drag = conn.add_stream(getattr, vessel.flight(), 'drag')
pitch = conn.add_stream(getattr, vessel.flight(), 'pitch')
heading = conn.add_stream(getattr, vessel.flight(), 'heading')
roll = conn.add_stream(getattr, vessel.flight(), 'roll')
throttle = conn.add_stream(getattr, vessel.control, 'throttle')
right = conn.add_stream(getattr, vessel.control, 'right')
up = conn.add_stream(getattr, vessel.control, 'up')
pitch_control = conn.add_stream(getattr, vessel.control, 'pitch')
roll_control = conn.add_stream(getattr, vessel.control, 'roll')
yaw_control = conn.add_stream(getattr, vessel.control, 'yaw')
vessel.control.activate_next_stage()
available_thrust = conn.add_stream(getattr,vessel,'available_thrust')
roll_pid = conn.add_stream(getattr, ap,'roll_pid_gains')
yaw_pid = conn.add_stream(getattr, ap,'yaw_pid_gains')
pitch_pid = conn.add_stream(getattr, ap,'pitch_pid_gains')

# Draw landing reference frame
land_x = conn.drawing.add_line((0, 0, 0), (50000, 0, 0), landing_reference_frame)
land_y = conn.drawing.add_line((0, 0, 0), (0, 50000, 0), landing_reference_frame)
land_z = conn.drawing.add_line((0, 0, 0), (0, 0, 50000), landing_reference_frame)

land_x.color = (0,255,0)
land_y.color = (0,255,0)
land_z.color = (0,255,0)

land_x.thickness = 5.
land_y.thickness = 5.
land_z.thickness = 5.

# Draw drone ship
verts = [(1., 52. / 2., 91. / 2.),
             (1., -52. / 2., 91. / 2.),
             (1., -52. / 2., -91. / 2.),
             (1., 52. / 2., -91. / 2.)]

droneship = conn.drawing.add_polygon(verts, landing_reference_frame)
droneship.thickness = 5.

# Define autopilot reference frame
ap.reference_frame = vessel.surface_reference_frame
time.sleep(0.01)
ap.engage()
time.sleep(0.01)

# Create empty data logging arrays
alt = []
t = []
vel_0 = []
vel_1 = []
vel_2 = []
v_sp = []
h_sp = []
pos_0 = []
pos_1 = []
pos_2 = []
rot_0 = []
rot_1 = []
rot_2 = []
rot_3 = []
dir_0 = []
dir_1 = []
dir_2 = []
ang_vel_0 = []
ang_vel_1 = []
ang_vel_2 = []
m_kg = []
MOI_0 = []
MOI_1 = []
MOI_2 = []
i_tensor_0 = []
i_tensor_1 = []
i_tensor_2 = []
i_tensor_3 = []
i_tensor_4 = []
i_tensor_5 = []
i_tensor_6 = []
i_tensor_7 = []
i_tensor_8 = []
CM_0 = []
CM_1 = []
CM_2 = []
av_torq_0 = []
av_torq_1 = []
av_torq_2 = []
av_torq_3 = []
av_torq_4 = []
av_torq_5 = []
av_thrust = []
lat = []
long = []
throt = []
atm_den = []
dyn_pres = []
stat_pres = []
aero_force_0 = []
aero_force_1 = []
aero_force_2 = []
lift_force_0 = []
lift_force_1 = []
lift_force_2 = []
drag_force_0 = []
drag_force_1 = []
drag_force_2 = []
t_F = []
r_F = []
u_F = []
p_Nm = []
r_Nm = []
y_Nm = []
p_deg = []
head_deg = []
roll_deg = []
ut_0 = ut()
roll_gains_0 = []
roll_gains_1 = []
roll_gains_2 = []
pitch_gains_0 = []
pitch_gains_1 = []
pitch_gains_2 = []
yaw_gains_0 = []
yaw_gains_1 = []
yaw_gains_2 = []

def unit_vector(vector):
    """ Returns the unit vector of the vector.  """
    return vector / linalg.norm(vector)

def angle_between(v1, v2):
    """ Returns the angle in radians between vectors 'v1' and 'v2'::

            >>> angle_between((1, 0, 0), (0, 1, 0))
            1.5707963267948966
            >>> angle_between((1, 0, 0), (1, 0, 0))
            0.0
            >>> angle_between((1, 0, 0), (-1, 0, 0))
            3.141592653589793
    """
    v1_u = unit_vector(v1)
    v2_u = unit_vector(v2)
    return arccos(clip(dot(v1_u, v2_u), -1.0, 1.0))

def logdata():
    """Adds current data stream values to data logging arrays"""
    alt.append(altitude())
    t.append(ut() - ut_0)
    vel_0.append(velocity()[0])
    vel_1.append(velocity()[1])
    vel_2.append(velocity()[2])
    v_sp.append(v_speed())
    h_sp.append(h_speed())
    pos_0.append(position()[0])
    pos_1.append(position()[1])
    pos_2.append(position()[2])
    rot_0.append(rotation()[0])
    rot_1.append(rotation()[1])
    rot_2.append(rotation()[2])
    rot_3.append(rotation()[3])
    dir_0.append(direction()[0])
    dir_1.append(direction()[1])
    dir_2.append(direction()[2])
    ang_vel_0.append(angular_velocity()[0])
    ang_vel_1.append(angular_velocity()[1])
    ang_vel_2.append(angular_velocity()[2])
    m_kg.append(mass())
    MOI_0.append(moment_of_inertia()[0])
    MOI_1.append(moment_of_inertia()[0])
    MOI_2.append(moment_of_inertia()[0])
    i_tensor_0.append(inertia_tensor()[0])
    i_tensor_1.append(inertia_tensor()[1])
    i_tensor_2.append(inertia_tensor()[2])
    i_tensor_3.append(inertia_tensor()[3])
    i_tensor_4.append(inertia_tensor()[4])
    i_tensor_5.append(inertia_tensor()[5])
    i_tensor_6.append(inertia_tensor()[6])
    i_tensor_7.append(inertia_tensor()[7])
    i_tensor_8.append(inertia_tensor()[8])
    CM_0.append(com()[0])
    CM_1.append(com()[1])
    CM_2.append(com()[2])
    av_torq_0.append(available_torque()[0][0])
    av_torq_1.append(available_torque()[0][1])
    av_torq_2.append(available_torque()[0][2])
    av_torq_3.append(available_torque()[1][0])
    av_torq_4.append(available_torque()[1][1])
    av_torq_5.append(available_torque()[1][2])
    av_thrust.append(available_thrust())
    lat.append(latitude())
    long.append(longitude())
    throt.append(u)
    atm_den.append(atm_density())
    dyn_pres.append(dyn_pressure())
    stat_pres.append(stat_pressure())
    aero_force_0.append(aero_force()[0])
    aero_force_1.append(aero_force()[1])
    aero_force_2.append(aero_force()[2])
    lift_force_0.append(lift()[0])
    lift_force_1.append(lift()[1])
    lift_force_2.append(lift()[2])
    drag_force_0.append(drag()[0])
    drag_force_1.append(drag()[1])
    drag_force_2.append(drag()[2])
    t_F.append(throttle())
    r_F.append(right())
    u_F.append(up())
    p_Nm.append(pitch_control())
    r_Nm.append(roll_control())
    y_Nm.append(yaw_control())
    p_deg.append(pitch())
    head_deg.append(heading())
    roll_deg.append(roll())
    pitch_gains_0.append(pitch_pid()[0])
    pitch_gains_1.append(pitch_pid()[1])
    pitch_gains_2.append(pitch_pid()[2])
    roll_gains_0.append(roll_pid()[0])
    roll_gains_1.append(roll_pid()[1])
    roll_gains_2.append(roll_pid()[2])
    yaw_gains_0.append(yaw_pid()[0])
    yaw_gains_1.append(yaw_pid()[1])
    yaw_gains_2.append(yaw_pid()[2])

def predict_landing(posx,posy,posz,velx,vely,velz):
    """Solves a basic quadratic equation to predict where the vehicle will land if engine is off"""
    zf = 20
    coeff = [-0.5*g(),velz,posz - zf]
    t = roots(coeff)
    t_num = [float(t[0]),float(t[1])]
    tf = max(t_num)
    xf = posx + 1.0*velx*tf
    yf = posy + 1.0*vely*tf
    return xf,yf,zf

def calculate_thrust():
    """Solves a basic sum of forces equation to determine direction and magnitude of force required to align
    velocity vector with position vector"""

    # Define all vectors in the vessel reference frame
    pos0 = (-position()[0], -position()[1], -position()[2])
    pos0_vessel = conn.space_center.transform_direction(pos0, landing_reference_frame, vessel.reference_frame)
    vel0 = (velocity()[0], velocity()[1], velocity()[2])
    vel0_vessel = conn.space_center.transform_direction(vel0, landing_reference_frame, vessel.reference_frame)
    phat = unit_vector(pos0_vessel)
    grav_force = (-mass()*g(), 0, 0)
    grav_force_vessel = conn.space_center.transform_direction(grav_force, landing_reference_frame,
                                                              vessel.reference_frame)
    aeroforces_vessel = conn.space_center.transform_direction(aero_force(),
                                                              vessel.surface_reference_frame,
                                                              vessel.reference_frame)

    # Desired final velocity vector
    vel0_final_vessel = 200 * phat

    # Difference between current and final velocity vectors
    delta_v_vessel = vel0_final_vessel - vel0_vessel

    # Verrry simple "integration" block.  Determines how hard the engine will burn.
    delta_t = 1

    # Solve for the thrust vector required to achieve the desired velocity vector change
    Fthrust = (
        (mass() / delta_t) * delta_v_vessel[0] - aeroforces_vessel[0] - grav_force_vessel[0],
        (mass() / delta_t) * delta_v_vessel[1] - aeroforces_vessel[1] - grav_force_vessel[1],
        (mass() / delta_t) * delta_v_vessel[2] - aeroforces_vessel[2] - grav_force_vessel[2])

    # Define the vector in the vessel surface reference frame (for the autopilot)
    Fthrust_surface = conn.space_center.transform_direction(Fthrust,
                                                              vessel.reference_frame,
                                                              vessel.surface_reference_frame)

    # Convert the thrust vector to a unit vector (improves autopilot performance)
    F_dir = unit_vector(Fthrust_surface)

    # Predict where the vessel is going to land
    (posx, posy, posz) = predict_landing(position()[2], position()[1], position()[0], velocity()[2], velocity()[1],
                                         velocity()[0])
    land_error = sqrt(posx**2. + posy**2.)

    # Determine the thrust required to cancel out gravity acceleration (assuming vessel is vertical)
    hover_throt = mass() * g() / available_thrust()

    # A heuristic to smooth out the burn so that the final error doesn't overshoot
    if land_error > 2000:
        des_throt = 2.0 * hover_throt
    elif land_error > 1000:
        des_throt = 1.25 * hover_throt
    elif land_error > 500:
        des_throt = 1.0 * hover_throt
    else:
        des_throt = 0.75 * hover_throt

    # Set the throttle and autopilot direction
    vessel.control.throttle = des_throt
    ap.target_direction = F_dir

def calculate_cruise():
    """Solves a basic sum of forces equation to determine direction and magnitude of force required to align
        horizontal components (in landing frame) of velocity and position vectors"""

    # Define all vectors in the vessel surface reference frame
    pos0 = (-position()[0], -position()[1], -position()[2])
    pos0_vessel = conn.space_center.transform_direction(pos0, landing_reference_frame, vessel.surface_reference_frame)
    vel0 = (velocity()[0], velocity()[1], velocity()[2])
    vel0_vessel = conn.space_center.transform_direction(vel0, landing_reference_frame, vessel.surface_reference_frame)
    phat = unit_vector((pos0_vessel[1],pos0_vessel[2]))
    grav_force = (-mass()*g(), 0, 0)
    grav_force_vessel = conn.space_center.transform_direction(grav_force, landing_reference_frame,
                                                              vessel.surface_reference_frame)
    aeroforces_vessel = aero_force()

    # Desired final velocity vector
    vel0_final_vessel = 400 * phat

    # Difference between current and final velocity vectors
    delta_v_vessel = vel0_final_vessel - (vel0_vessel[1],vel0_vessel[2])

    # Verrry simple "integration" block.  Determines how hard the engine will burn.
    delta_t = 30.

    # Solve for the thrust vector required to achieve the desired velocity vector change
    Fthrust = (0,
               (mass() / delta_t) * delta_v_vessel[0] - aeroforces_vessel[1] - grav_force_vessel[1],
               (mass() / delta_t) * delta_v_vessel[1] - aeroforces_vessel[2] - grav_force_vessel[2])

    # Calculate magnitude and direction of thrust vector
    F_des = linalg.norm(Fthrust)/available_thrust()
    F_dir = unit_vector(Fthrust)

    # Set the throttle and autopilot direction
    vessel.control.throttle = F_des
    ap.target_direction = F_dir

def draw_lines(ship_pos, ship_vel, landing_est, landing_est2, combined_line):
    """Draw visualization lines in the game
    - Green: landing reference frame
    - White: position
    - Red: Velocity
    - Blue: Acceleration
    - Red X: Predicted landing spot
    - White rectangle: dimensions of droneship"""

    # Position
    (posx, posy, posz) = position()
    pos0 = (-position()[0], -position()[1], -position()[2])
    pos0_vessel = conn.space_center.transform_direction(pos0, landing_reference_frame, vessel.reference_frame)

    # Velocity
    vel0 = (velocity()[0], velocity()[1], velocity()[2])
    vel0_vessel = conn.space_center.transform_direction(vel0, landing_reference_frame, vessel.reference_frame)

    # Acceleration due to gravity
    grav_force = (-g(),0,0)
    grav_force_vessel = conn.space_center.transform_direction(grav_force,landing_reference_frame,vessel.reference_frame)

    # Acceleration due to ngine thrust
    thrust = available_thrust() * throttle() / mass()

    # Acceleration due to aerodynamic forces
    aeroforces_vessel = conn.space_center.transform_direction((aero_force()[0] / mass(),
                                                               aero_force()[1] / mass(),
                                                               aero_force()[2] / mass()),
                                                              vessel.surface_reference_frame,
                                                              vessel.reference_frame)

    # Acceleration due to all forces
    combined_forces = (
                          (aeroforces_vessel[0] + gimb_angle()[0] * thrust + grav_force_vessel[0]),
                          (aeroforces_vessel[1] + gimb_angle()[1] * thrust + grav_force_vessel[1]),
                          (aeroforces_vessel[2] + gimb_angle()[2] * thrust + grav_force_vessel[2]))

    # Show the predicted landing spot if altitude over 500m
    if altitude() > 500:
        (posx, posy, posz) = predict_landing(position()[2], position()[1], position()[0], velocity()[2], velocity()[1],
                                             velocity()[0])
        text2.content = "Predicted Final Error (m): %.2f" % (linalg.norm((posx, posy)))
        landing_est.visible = True
        landing_est2.visible = True
    else:
        text2.content = "Predicted Final Error (m): " % (linalg.norm((posx, posy)))
        landing_est.visible = False
        landing_est2.visible = False

    # Update line visualization data
    combined_line.end = combined_forces
    ship_pos.end = pos0_vessel
    ship_vel.end = vel0_vessel
    landing_est.start = (posz + 100, posy - 30, posx - 30)
    landing_est.end = (posz + 100, posy + 30, posx + 30)
    landing_est2.start = (posz + 100, posy + 30, posx - 30)
    landing_est2.end = (posz + 100, posy - 30, posx + 30)

    text.content = "Horizontal Error (m): %.2f" % (linalg.norm((position()[1],position()[2])))

    return ship_pos, ship_vel, landing_est, landing_est2, combined_line

# Control vessel from middle docking port. Makes everything smoother.
part = vessel.parts.with_title('Clamp-O-Tron Docking Port')[0]
vessel.parts.controlling = part

# Create initial drawing objects
# Acceleration
combined_line = conn.drawing.add_line((0, 0, 0), (0,0,0), vessel.reference_frame)
combined_line.color = (0, 0, 255)
combined_line.thickness = 3.

# Position
pos0 = (-position()[0], -position()[1], -position()[2])
pos0_vessel = conn.space_center.transform_direction(pos0, landing_reference_frame, vessel.reference_frame)
ship_pos = conn.drawing.add_line((0, 0, 0), pos0_vessel, vessel.reference_frame)
ship_pos.thickness = 1.

# Velocity
vel0 = (velocity()[0], velocity()[1], velocity()[2])
vel0_vessel = conn.space_center.transform_direction(vel0, landing_reference_frame, vessel.reference_frame)
ship_vel = conn.drawing.add_line((0, 0, 0), vel0_vessel, vessel.reference_frame)
ship_vel.color = (255,0,0)
ship_vel.thickness = 2.

# Predicted landing spot
landing_est = conn.drawing.add_line((position()[0]+100, position()[1]-10, position()[2]-10), (position()[0]+100, position()[1]+10, position()[2]+10), landing_reference_frame)
landing_est.color = (255, 0, 0)
landing_est.thickness = 200.

landing_est2 = conn.drawing.add_line((position()[0]+100, position()[1]+10, position()[2]-10), (position()[0]+100, position()[1]-10, position()[2]+10), landing_reference_frame)
landing_est2.color = (255, 0, 0)
landing_est2.thickness = 200.

landing_est.visible = False
landing_est2.visible = False

while altitude() < 17500:
    """Initial ascent."""

    # set pitch angle to 85 degrees (engine gimbal only)
    ap.target_pitch = 85.

    # set heading towards landing site
    y = position()[1]
    x = position()[2]
    dy = velocity()[1]
    dx = velocity()[2]
    ap.target_heading = 90 + (180. / math.pi) * math.atan2(y, abs(x))

    # Altitude PID values
    p = 25000. - altitude()
    d = 100. - v_speed()
    T0 = available_thrust()
    m = mass()
    F0 = m * g()

    # set throttle
    u = (F0 + 300*p + 7000*d) / T0
    vessel.control.throttle = u

    ship_pos, ship_vel, landing_est, landing_est2, combined_line = draw_lines(ship_pos, ship_vel, landing_est, landing_est2, combined_line)

    try:
        logdata()
    except:
        pass

# Turn on rcs thrusters
vessel.control.rcs = True
time.sleep(0.01)

while (pitch() > 10.):
    """Set the pitch to 0 deg."""

    text3.content = "Adjusting pitch to 0 deg.  Heading towards landing site."

    vessel.control.throttle = 0.3

    # Keep heading pointing towards the landing site
    y = position()[1]
    x = position()[2]
    dy = velocity()[1]
    dx = velocity()[2]

    ap.target_heading = 90. + (180. / math.pi) * math.atan2(y, abs(x))  + 0.

    # Heuristic to smooth out pitch control.
    if pitch() > 80:
        ap.target_pitch = 75.
    elif pitch() > 65:
        ap.target_pitch = 60.
    elif pitch() > 50:
        ap.target_pitch = 45
    elif pitch() > 35:
        ap.target_pitch = 30
    elif pitch() > 20:
        ap.target_pitch = 15
    else:
        ap.target_pitch = 5.

    ship_pos, ship_vel, landing_est, landing_est2, combined_line = draw_lines(ship_pos, ship_vel,
                                                                                landing_est, landing_est2,
                                                                                combined_line)
    logdata()

land_error = sqrt(position()[2]**2. + position()[1]**2.)
vessel.control.throttle = 0.3

while land_error > 10000: #take another few hundred meters off
    """Burn towards landing site. Adjust horizontal components of velocity to be parallel with position."""

    text3.content = "Cruising until horizontal error is 10 km from landing site.  Adjusting (x,y) of velocity vector to align with (x,y) of position vector."

    (posx, posy, posz) = predict_landing(position()[2], position()[1], position()[0], velocity()[2], velocity()[1],
                                         velocity()[0])
    land_error = sqrt(position()[2] ** 2. + position()[1] ** 2.)

    calculate_cruise()

    ship_pos, ship_vel, landing_est, landing_est2, combined_line = draw_lines(ship_pos, ship_vel, landing_est,
                                                                                landing_est2, combined_line)
    logdata()

# Point vessel in retrograde direction.
ap.disengage()
time.sleep(0.01)
vessel.control.sas = True
time.sleep(0.01)
vessel.control.throttle = 0.
vessel.control.brakes = True
vessel.control.sas_mode = conn.space_center.SASMode.retrograde

while abs(ap.error) > 5:
    text3.content = "Pointing towards retrograde direction."
    ship_pos, ship_vel, landing_est, landing_est2, combined_line = draw_lines(ship_pos, ship_vel, landing_est,
                                                                                landing_est2, combined_line)
    logdata()
    pass

vessel.control.sas = False
time.sleep(0.01)
ap.engage()

# Create a list to keep track of predicted final error
(posx, posy, posz) = predict_landing(position()[2], position()[1], position()[0], velocity()[2], velocity()[1],
                                         velocity()[0])
land_error = sqrt(posx ** 2. + posy ** 2.)
error_list = []
error_list.append(land_error)
error_diff = 0

while land_error > 1000 or error_diff < 0:
    """Burn to align entire velocity vector with position vector.
     Stop burning when predicted final error begins to increase"""

    text3.content = "Align entire velocity vector in direction of position vector.  Burn until predicted final error reaches minimum."
    (posx, posy, posz) = predict_landing(position()[2], position()[1], position()[0], velocity()[2], velocity()[1],
                                         velocity()[0])

    land_error = sqrt(posx ** 2. + posy ** 2.)
    error_list.append(land_error)
    error_diff = error_list[-1] - error_list[-2]

    calculate_thrust()

    ship_pos, ship_vel, landing_est, landing_est2, combined_line = draw_lines(ship_pos, ship_vel, landing_est,
                                                                                landing_est2, combined_line)
    logdata()

ap.disengage()
time.sleep(0.01)

while altitude() > 15:
    """ Fall towards target.  Make final translation adjustments with RCS thrusters."""
    (posx, posy, posz) = predict_landing(position()[2], position()[1], position()[0], velocity()[2], velocity()[1],
                                         velocity()[0])

    if altitude() > 300:
        text3.content = "Fall towards landing site. Use RCS thrusters to push predicted final error towards 0."
        pos0 = (posz, posy, posx)
        pos0_vessel = conn.space_center.transform_direction(pos0, landing_reference_frame, vessel.reference_frame)
        vessel.control.up = pos0_vessel[2]
        vessel.control.right = -pos0_vessel[0]
    else:
        text3.content = "Use RCS thrusters to eliminate (x,y) velocity.  Use main engine to slow fall. "
        vessel.control.sas = True
        vessel.control.sas_mode = conn.space_center.SASMode.radial
        vel0 = (velocity()[0], velocity()[1], velocity()[2])
        vel0_vessel = conn.space_center.transform_direction(vel0, landing_reference_frame, vessel.reference_frame)
        vessel.control.up = vel0_vessel[2]
        vessel.control.right = -vel0_vessel[0]
        vessel.control.gear = True

    # PID values for main engine control over altitude
    p = 0. - altitude()
    d = 0. - v_speed()
    d_h = 0 - h_speed()
    T0 = available_thrust()
    m = mass()
    F0 = 0.93 * m * g()
    u = (F0 + 300*p + 7000*d) / T0
    vessel.control.throttle = u
    ship_pos, ship_vel, landing_est, landing_est2, combined_line = draw_lines(ship_pos, ship_vel, landing_est,
                                                                                landing_est2, combined_line)
    logdata()

text3.content = "Pretty prettyyyyy pretty good."

# Turn everything off except the droneship
vessel.control.throttle = 0.
vessel.control.sas = False
vessel.control.rcs = False

land_x.visible = False
land_y.visible = False
land_z.visible = False
combined_line.visible = False
ship_pos.visible = False
ship_vel.visible = False

# Create a dictionary to hold the final data set.
data_dict = {'time': t,
             'altitude': alt,
             'velocity0':vel_0,
             'velocity1':vel_1,
             'velocity2':vel_2,
             'vertical speed':v_sp,
             'horizontal speed': h_sp,
             'position0':pos_0,
             'position1':pos_1,
             'position2':pos_2,
             'rotation0':rot_0,
             'rotation1':rot_1,
             'rotation2':rot_2,
             'rotation3':rot_3,
             'direction0':dir_0,
             'direction1':dir_1,
             'direction2':dir_2,
             'angular velocity0': ang_vel_0,
             'angular velocity1': ang_vel_1,
             'angular velocity2': ang_vel_2,
             'mass':m_kg,
             'moment of inertia0': MOI_0,
             'moment of inertia1': MOI_1,
             'moment of inertia2': MOI_2,
             'inertia tensor0':i_tensor_0,
             'inertia tensor1':i_tensor_1,
             'inertia tensor2':i_tensor_2,
             'inertia tensor3':i_tensor_3,
             'inertia tensor4':i_tensor_4,
             'inertia tensor5':i_tensor_5,
             'inertia tensor6':i_tensor_6,
             'inertia tensor7':i_tensor_7,
             'inertia tensor8':i_tensor_8,
             'center of mass0':CM_0,
             'center of mass1':CM_1,
             'center of mass2':CM_2,
             'available torque0':av_torq_0,
             'available torque1':av_torq_1,
             'available torque2':av_torq_2,
             'available torque3':av_torq_3,
             'available torque4':av_torq_4,
             'available torque5':av_torq_5,
             'available thrust':av_thrust,
             'latitude': lat,
             'longitude':long,
             'throttle':throt,
             'atmosphere density': atm_den,
             'dynamic pressure': dyn_pres,
             'static pressure': stat_pres,
             'aero_force0': aero_force_0,
             'aero_force1': aero_force_1,
             'aero_force2': aero_force_2,
             'lift0': lift_force_0,
             'lift1': lift_force_1,
             'lift2': lift_force_2,
             'drag0': drag_force_0,
             'drag1': drag_force_1,
             'drag2': drag_force_2,
             'throttle_F':t_F,
             'right':r_F,
             'up':u_F,
             'pitch':p_deg,
             'roll':roll_deg,
             'heading':head_deg,
             'pitch control':p_Nm,
             'roll control':r_Nm,
             'yaw control':y_Nm,
             'pitch gain 0':pitch_gains_0,
             'pitch gain 1': pitch_gains_1,
             'pitch gain 2': pitch_gains_2,
             'roll gain 0': roll_gains_0,
             'roll gain 1': roll_gains_1,
             'roll gain 2': roll_gains_2,
             'yaw gain 0': yaw_gains_0,
             'yaw gain 1': yaw_gains_1,
             'yaw gain 2': yaw_gains_2}

# Put the dictionary into a pandas dataframe
df = pd.DataFrame(data=data_dict)
df.to_csv('test48.csv')

# Keep the fake droneship displayed
while True:
    pass


from typing import List
from course_manager.helpers import project_helper
from course_manager.models.schedule import Schedule

def get_schedule(course_codes: List[str]) -> Schedule:
    """Get a Schedule object containing projects of courses in <course_codes>.

    Precondition: all courses in <course_code> exists.
    """
    schedule = Schedule()

    # For each course, add all projects into schedule
    for course_code in course_codes:
        for project_id in project_helper.get_project_ids(course_code):
            settings = project_helper.read_project_settings(course_code, project_id)

            if settings is not None:
                schedule.add_project(course_code, settings)

    return schedule


"""usage_maya.py

    Example usage of the Resizable MessageBox widget.
"""

from Qt.QtWidgets import (
    QApplication
)

import dialogs

def getMayaWindow():
    top_level_widgets = QApplication.topLevelWidgets()
    return next(
        widget for widget in top_level_widgets
            if widget.objectName() == "MayaWindow"
    )

def run():

    long_text = (
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
        "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
        "enim ad minim veniam, quis nostrud exercitation ullamco laboris"
        " nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor"
        " in reprehenderit in voluptate velit esse cillum dolore eu "
        "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "
        "proident, sunt in culpa qui officia deserunt mollit anim id est"
        " laborum. Lorem ipsum dolor sit amet, consectetur adipiscing "
        "elit, sed do eiusmod tempor incididunt ut labore et dolore magna"
        " aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
        "ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis "
        "aute irure dolor in reprehenderit in voluptate velit esse cillum"
        " dolore eu fugiat nulla pariatur. Excepteur sint occaecat "
        "cupidatat non proident, sunt in culpa qui officia deserunt "
        "mollit anim id est laborum."
    )

    parent = getMayaWindow()

    dialogs.success(
        parent,
        "Success message",
        details=long_text
    )

    dialogs.warning(
        parent,
        "Warning message",
        details=long_text
    )

    dialogs.alert(
        parent,
        "Alert message",
        details=long_text
    )

    dialogs.question(
        parent,
        "Question?",
        details=long_text
    )

    dialogs.questionWarning(
        parent,
        "Question as warning?",
        details=long_text
    )

run()


def check_status(bmi):
    if bmi < 18.5:
        return "underweight"
    elif 18.5 <= bmi < 25:
        return "normal"
    elif 25 <= bmi < 30:
        return "overweight"
    elif bmi >= 30:
        return "obese"

num = int(input("What is your number: "))
print(f"You are {check_status(num)}")


import turtle

num_sides = int(input("How many sides would you like?:"))
side_length = int(input("How long would you like your sides to be?:"))

def draw_eq_shape(myturt, num_sides, side_length):

    internal_angle = 360/num_sides

    window = turtle.Screen()

    for i in range(num_sides):
        myturt.forward(side_length)
        myturt.left(internal_angle)

    window.exitonclick()

myturt = turtle.Turtle()
myturt.color("green")
myturt.shape("turtle")

draw_eq_shape(myturt, num_sides, side_length)


import discord
from discord.ext import commands
from discord import app_commands
from discord.utils import MISSING

import asyncio
from itertools import chain

from smart_bot import SmartBot
from utils.common import prevent_task_garbage_collection

class ExtensionDependencyNotLoaded(commands.errors.ExtensionError):
    """
    Thrown when attempting to load an extension that depends on another extension which has not yet been loaded.
    """
    def __init__(self, name: str, dependency: str) -> None:
        msg = f"Cannot load extension {name!r} - extension {dependency!r} is required to be loaded beforehand!"
        super().__init__(msg, name=name)

class CommandPropertiesMismatch(commands.errors.ExtensionError):
    """
    Thrown when attempting to load an extension that contains commands with mismatching properties.
    """
    def __init__(self, name: str, command: str) -> None:
        msg = f"Cannot load extension {name!r} - command {command!r} contains mismatching values! (Check your decorators.)"
        super().__init__(msg, name=name)

class SmartCog(commands.Cog):
    """
    Special custom class attributes:
    .dependencies - list of extension import path strings required for this extension to run

    Special custom instance attributes:
    .bot - holds the bot instance
    .ready - boolean indicating whether the cog is fully loaded and the bot is ready
    .config - getter acting like a shortcut to the config specific to this extension saved in the bot

    Custom functions:
    .get_all_commands() -> list
    .get_hybrid_commands() -> list
    .get_app_commands_including_hybrid() -> list
    .get_app_commands_including_from_hybrid() -> list
    .get_only_classic_commands() -> list

    Hidden attributes/functions:
    ._loaded_on_startup
    ._ready_init
    """

    DEPENDENCIES = [] #all extensions (cogs) needed for this cog to function, written as strings in import path notation

    def __init__(self, bot: SmartBot):
        super().__init__()

        #check dependencies
        for req_path in self.DEPENDENCIES:
            if req_path not in bot.extensions:
                raise ExtensionDependencyNotLoaded(self.__module__, req_path)

        self.bot = bot
        self.ready = False #if the bot is ready and the _ready_init function ran
        self._loaded_on_startup = not self.bot.is_loaded

        #apply custom decorator effects to app/hybrid/classic commands
        for cmd in self.get_all_commands():
            #apply decorators even if it's not a pure app command
            if cmd.extras.get("__smartcog_command_for_all_guilds__", False):
                app_commands.guilds(*self.bot.guilds)(cmd)
            elif cmd.extras.get("__smartcog_command_for_main_guild__", False):
                app_commands.guilds(self.bot.main_server_id)(cmd)
            if cmd.extras.get("__smartcog_command_guild_only__", False):
                app_commands.guild_only(cmd)

            #decorate app commands inside hybrid commands
            if getattr(cmd, "__commands_is_hybrid__", False):
                appcmd = getattr(cmd, "app_command", None)
                if appcmd:
                    guild_ids = getattr(cmd, "__discord_app_commands_default_guilds__", None)
                    guild_ids_appcmd = getattr(appcmd, "_guild_ids", None)
                    if guild_ids is not None and guild_ids_appcmd is not None:
                        raise CommandPropertiesMismatch(self.__module__, cmd.name)
                    guild_ids = guild_ids or guild_ids_appcmd
                    if guild_ids:
                        #synchronize guild ids across both command types
                        cmd.__discord_app_commands_default_guilds__ = guild_ids
                        app_commands.guilds(*guild_ids)(appcmd)

                    guild_only = getattr(cmd, "__discord_app_commands_guild_only__", None)
                    if guild_only is None:
                        guild_only = getattr(appcmd, "guild_only", False)
                    if guild_only:
                        cmd.__discord_app_commands_guild_only__ = guild_only
                        app_commands.guild_only(appcmd)

        #apply efects of previous decorators to classical/hybrid commands
        for cmd in self.get_commands():
            guild_ids = getattr(cmd, "__discord_app_commands_default_guilds__", None)
            guild_only = getattr(cmd, "__discord_app_commands_guild_only__", False)
            if guild_ids or guild_only:
                for walkedcmd in chain([cmd], cmd.walk_commands() if getattr(cmd, "walk_commands", None) else []):
                    allowed_contexts(guild_ids, guild_only)(walkedcmd)

        #for attribute in self.__class__.__dict__.values():

    @property
    def config(self):
        """Getter acting like a shortcut for the config specific to this extension saved in the bot."""
        return self.bot.extconfig[self.__module__]

    #automatically called on initialization. if overridden, must call `await super().cog_load()` at the end
    async def cog_load(self):
        #if the bot is already loaded, _ready_init needs to be called manually
        if self.bot.is_loaded:
            prevent_task_garbage_collection(asyncio.create_task(self._ready_init()))
        await super().cog_load()

    @commands.Cog.listener("on_full_ready")
    async def _ready_init(self):
        """Triggered either automatically by the event itself, or, if the bot is already loaded,
        triggered manually by cog_load.
        Syncs app commands and runs all functions decorated to run on ready in this cog."""
        #sync guilds with appcommands from this cog
        #cannot be done on cog_load because the commands aren't registered yet
        if not self._loaded_on_startup and self.bot.autosync_appcommands:
            await self.bot.tree.sync_given(
                *self.get_app_commands_including_from_hybrid(),
                avoid_deletions=self.bot.avoid_appcommand_deletions,
                ignore_errors=True
            )

        #run @run_when_ready decorated functions
        for method in self.__class__.__dict__.values():
            if getattr(method, "__smartcog_func_run_when_ready__", False):
                await method(self)

        self.ready = True
        self.bot.dispatch("smart_cog_ready", self)

    #automatically called when unloading. if overridden, must call `await super().cog_unload()` at the end
    async def cog_unload(self):
        if self.bot.is_loaded and not self.bot.is_quitting and self.bot.remove_appcommands_on_unload and not self.bot.avoid_appcommand_deletions:
            await self.bot.tree.unsync_given(*self.get_app_commands_including_from_hybrid(), ignore_errors=True)
        await super().cog_unload()

    def get_all_commands(self) -> list:
        """Returns all classic, hybrid and app commands in a single list."""
        return self.get_commands() + self.get_app_commands()

    def get_hybrid_commands(self) -> list:
        """Returns a list of all hybrid commands defined in this cog."""
        return [cmd for cmd in self.get_commands() if getattr(cmd, "__commands_is_hybrid__", False)]

    def get_app_commands_including_hybrid(self) -> list:
        """Returns a list of all app commands and hybrid commands defined in this cog. Hybrid commands are kept as they are."""
        return self.get_hybrid_commands() + self.get_app_commands()

    def get_app_commands_including_from_hybrid(self) -> list:
        """Returns a list of app commands defined in this cog. From hybrid commands, the inner app command is returned."""
        return [cmd.app_command for cmd in self.get_hybrid_commands() if cmd.app_command] + self.get_app_commands()

    def get_only_classic_commands(self) -> list:
        """Returns a list of all classic commands defined in this cog. Hybrid commands are ignored."""
        return [cmd for cmd in self.get_commands() if not getattr(cmd, "__commands_is_hybrid__", False)]

##################################################

#DECORATOR for classic/hybrid commands (better to use the other ones below though)
def allowed_contexts(allowed_guilds: list, guild_only: bool = False):
    """This creates a command check for classic/hybrid commands that only lets
    the command run if it has been executed in an allowed guild/DM.
    This mimics the behavior of app_commands.guilds() decorator.
    This MUST be used ABOVE the command/group decorator!
    allowed_guilds: empty = allowed in every guild (global command)
    """
    guild_ids = [] if not allowed_guilds else [g if isinstance(g, int) else g.id for g in allowed_guilds]

    def allowed_guilds_check(ctx: commands.Context) -> bool:
        if not ctx.guild:
            return not guild_ids and not guild_only
        return not guild_ids or ctx.guild.id in guild_ids

    def decorator(cmd):
        cmd.add_check(allowed_guilds_check)
        return cmd

    return decorator

#DECORATOR for any function
def app_commands_Group(
    *,
    name: str = MISSING,
    description: str = MISSING,
    nsfw: bool = False,
    extras: dict = MISSING,
):
    """This is missing from the library even though it's very useful.
    Creates an application command group from any function.
    Behaves the same way as the @app_commands.command() decorator, just for groups.
    The function decorated by this will never be run, however!
    """
    def decorator(func) -> app_commands.Group:
        if description is MISSING:
            if func.__doc__ is None:
                desc = '…'
            else:
                desc = app_commands.commands._shorten(func.__doc__)
        else:
            desc = description

        return app_commands.Group(
            name=name if name is not MISSING else func.__name__,
            description=desc,
            parent=None,
            nsfw=nsfw,
            extras=extras,
        )

    return decorator

#DECORATOR for any command
def for_main_guild(cmd):
    """Decorator for marking any type of command to be assigned to the bot's main guild (instead of being global).
    This MUST be used ABOVE the command/group decorator!
    Only usable for top-level commands/groups!"""
    cmd.extras["__smartcog_command_for_main_guild__"] = True
    return cmd

#DECORATOR for any command
def for_all_guilds(cmd):
    """Decorator for marking an app command (or hybrid command) to be assigned to all guilds the bot is in (instead of being global).
    This MUST be used ABOVE the command/group decorator!
    Only usable for top-level commands/groups!"""
    cmd.extras["__smartcog_command_for_all_guilds__"] = True
    return cmd

#DECORATOR for any command
def guilds_only(cmd):
    cmd.extras["__smartcog_command_guild_only__"] = True
    return cmd

#DECORATOR for any command
def run_when_ready(func):
    """Decorator for marking a cog coroutine to be executed when the cog is fully ready."""
    func.__smartcog_func_run_when_ready__ = True
    return func

#DECORATOR for any function
def only_if_ready(func):
    """Decorator for making sure a coroutine only runs while the cog is already ready."""
    async def decorated(_self, *args, **kwargs):
        if _self.ready:
            return await func(_self, *args, **kwargs)
    return decorated

#DECORATOR for any function
def requires_extension(ext_import_path):
    """Decorator for letting a coroutine run only if a specified extension is currently loaded."""
    def decorator(func):
        async def decorated(_self, *args, **kwargs):
            if ext_import_path in _self.bot.extensions:
                return await func(_self, *args, **kwargs)
        return decorated
    return decorator


from proforma.Inputs import ProceedsHelper

class myProceeds:
    '''
    A generic proceeds class that can be used for any type of use:
    Residential, Commercial, Manufacturing
    '''

    # NYCHA Vacancy
    vacancy_rate = 0.05 #0.012
    income_escalation = 0.02 # 0.01

    #NYCHA Operation Costs
    operation_expense_persqft = 7 #USD
    realestate_taxes_persqft = 3 #0 #USD
    replacement_reserve_persqft = 1 #USD
    depreciation_yrs = 27.5   # in years

    income = 0
    vacancy = 0
    units = 0
    net_area = 0

    def __init__(self,
                 proceeds_type: str,
                 gross_floor_area: int,
                 avg_unit_size: float,
                 development_cost: int,
                 rent: int,
                 net_loss_factor: float,
                 ):

        self.development_cost = development_cost
        self.gross_floor_area = gross_floor_area
        self.avg_unit_size = avg_unit_size
        self.proceeds_type = proceeds_type
        self.rent = rent
        self.net_loss_factor = net_loss_factor

        #Proceeds
        common_circulation = ProceedsHelper.common_area_and_circulation(total_floor_area= gross_floor_area,
                                                                        net_loss_factor= self.net_loss_factor)

        self.net_area = ProceedsHelper.net_area(total_floor_area= gross_floor_area,
                                               common_area_and_circulation= gross_floor_area * self.net_loss_factor)

        self.units = ProceedsHelper.approximate_units(net_area= self.net_area,
                                                      avg_market_rate_unit_size= avg_unit_size)

        self.income = ProceedsHelper.total_income(approx_units= self.units,
                                                  rent_per_unit= self.rent)

        self.vacancy = ProceedsHelper.total_vacancy(vacancy_rate= self.vacancy_rate,
                                                    total_income= self.income)

        #Expenses
        self.operation_expense = ProceedsHelper.operational_expenses(net_area= self.net_area,
                                                                     operational_expenses= self.operation_expense_persqft)

        self.realestate_taxes = ProceedsHelper.real_estate_taxes(real_estate_taxes= self.realestate_taxes_persqft,
                                                                 net_area= self.net_area)

        self.replacement_reserve = ProceedsHelper.replacement_reserve(total_floor_area= gross_floor_area,
                                                                      replacement_reserve= self.replacement_reserve_persqft)

        #Depreciation

        self.depreciation = ProceedsHelper.depreciation(depreciation= self.depreciation_yrs,
                                                        use_sqft_total_cost= self.net_area * self.development_cost)

        print("\n")
        print("{} Proceeds".format(proceeds_type))
        print("Common Area and Circulation: {:,}".format(common_circulation))
        print("Net {} Area: {:,}".format(proceeds_type, self.net_area))
        print("Units: {}".format(self.units))
        print("{} Vacancy Rate: {:,}".format(proceeds_type, self.vacancy_rate))
        print("{} Market Rate Rent: ${:,}".format(proceeds_type, self.rent))
        print("{} Total Income: ${:,}".format(proceeds_type,self.income))
        print("{} Total Vacancy Cost: ${:,}".format(proceeds_type,self.vacancy))

        print("\n")
        print("{} Expenses".format(proceeds_type))
        print("{} Operational Expense per SqFt: ${:,}".format(proceeds_type, self.operation_expense_persqft))
        print("{} Real Estate Taxes per SqFt: ${:,}".format(proceeds_type, self.realestate_taxes_persqft))
        print("{} Replacement Reserve per SqFt: ${:,}".format(proceeds_type, self.replacement_reserve_persqft))
        print("{} Operational Expense Total: ${:,}".format(proceeds_type, self.operation_expense))
        print("{} Real Estate Taxes Total: ${:,}".format(proceeds_type, self.realestate_taxes))
        print("{} Replacement Reserve Total: ${:,}".format(proceeds_type, self.replacement_reserve))

        print("\n")
        print("{} Depreciation".format(proceeds_type))
        print("{} Depreciation in Yrs: {}".format(proceeds_type, self.depreciation_yrs))
        print("Total Depreciation: ${:,}".format(self.depreciation))


import os
import json
import shutil
import tempfile
import argparse
import itertools
import urllib.parse
import urllib.request
import concurrent.futures

base = 'https://web.archive.org'

def archive_urls(domain, start, end):
    """
    Return a list of archive urls for a given domain.
    """

    params = {
        'url': domain,
        'matchType': 'domain',
        'filter': 'statuscode:200',
        'from': start,
        'to': end,
        'output': 'json'
    }
    url = base + '/cdx/search/cdx?' + urllib.parse.urlencode(params)
    req = urllib.request.urlopen(url)
    res = req.read()
    return json.loads(res.decode("utf-8"))[1:]

def group_archive_urls(urls):
    """
    Group urls by the url key and keep latest entry.
    """

    sorted(urls, key=lambda x: x[0])
    urls = [
        list(group) for _, group in itertools.groupby(urls, lambda x: x[0])
        ]
    return [max(i, key=lambda x:int(x[1])) for i in urls]

def download_ressource(url):
    """
    Download resource from wayback machine server.
    """

    f = open(os.path.join(os.getcwd(), "data", "metadata.csv"), "a")
    with urllib.request.urlopen(url) as response:
        content_type = response.info().get_content_subtype()
        final_dir = os.path.join(os.getcwd(), 'data', content_type)
        os.makedirs(final_dir, exist_ok=True)
        with tempfile.NamedTemporaryFile(
                suffix=f'.{content_type}',
                delete=False,
                dir=final_dir) as tmp_file:
            shutil.copyfileobj(response, tmp_file)
            f.write(f"'{tmp_file.name}','{url}'\n")
    f.close()

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--domain', required=True)
    parser.add_argument('--start', required=True)
    parser.add_argument('--end', required=True)
    args = parser.parse_args()

    urls = archive_urls(args.domain, args.start, args.end)
    grouped_urls = group_archive_urls(urls)
    uris = map(lambda x: base + f'/web/{x[1]}if_/{x[2]}', grouped_urls)
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        executor.map(download_ressource, uris)

if __name__ == "__main__":
    main()


from autobahn.asyncio.websocket import WebSocketServerProtocol, \
    WebSocketServerFactory

from MonPaquet import json_parser
#from MonPaquet import gpio_controler

class MyServerProtocol(WebSocketServerProtocol):

    def setGPIOList(self, GPIOList):
        self.myGPIOs = GPIOList
        #plus utilisé

    def onConnect(self, request):
        print("Client connecting: {0}".format(request.peer))
        self.myGPIOs = dict()
        json_parser.readconfig(self.myGPIOs, "gpio_def.xml")
        # gpio_controler.setupOutput(self.myGPIOs)

    def onOpen(self):
        print("WebSocket connection open.")

    def onMessage(self, payload, isBinary):
        if isBinary:
            print("Binary message received: {0} bytes".format(len(payload)))
        else:
            print("Text message received: {0}".format(payload.decode('utf8')))

        # echo back message verbatim
        # self.sendMessage(payload, isBinary)
        #jsonStr = json.loads(payload.decode('utf8'))

        jsonStr2 = payload.decode('utf8')

        json_parser.read_json(jsonStr2, self.myGPIOs)

        for keys in self.myGPIOs.keys():
            print(keys + " vaut : " + self.myGPIOs[keys].value)

        # gpio_controler.apply(self.myGPIOs)

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))
        # gpio_controler.close()

if __name__ == '__main__':
    import asyncio

    factory = WebSocketServerFactory(u"ws://127.0.0.1:9000")
    factory.protocol = MyServerProtocol

    loop = asyncio.get_event_loop()
    coro = loop.create_server(factory, '0.0.0.0', 9000)
    server = loop.run_until_complete(coro)

    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.close()
        loop.close()


import os
import shutil
import re
from glob import glob
import argparse
import cv2

# mode 1: copy all file in folder + delete select file extension
#python ./scripts/copyImage.py --input_dir data/SRRAW_text --output_dir data/SRRAW_textEdit --mode 1 --image_file_extension '*jpg' --delete_specific_file_extension TRUE --delete_file_extension '*ARW'
# mode 2: copy by quantity
#python ./scripts/copyImage.py --input_dir data/mini-imagenet-20220523T033428Z-001/mini-imagenet --output_dir data/mini-imagenet-20220523T033428Z-001/mini-imagenetEdit --image_file_extension '*jpg' --mode 2 --quantity 35

image_size = 96

def main(args) -> None:
    if args.mode == '1':
        mode1(args)
    elif args.mode == '2':
        mode2(args)
    else:
        print("Invalid Mode")

def mode1(args) -> None:
    delete_specific_file_extension = args.delete_specific_file_extension
    delete_file_extension = args.delete_file_extension
    input_dir = args.input_dir
    image_file_extension = args.image_file_extension
    output_dir = args.output_dir

    list_folder_input = [x[0] for x in os.walk(input_dir)]
    list_folder_input.sort(key=natural_keys)
    # print(list_folder_input)
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
        start = 1
        print('Start: ', start)
    else:
        list_output = os.listdir(output_dir)
        print('Length Output: ', len(list_output))
        if len(list_output) > 0:
            list_output.sort(key=natural_keys)
            end_output = list_output[-1]
            end_output = end_output.split('.')[0]
            start = int(end_output) + 1
            print('Start: ', start)
        else:
            start = 1
            print('Start: ', start)

    index = start
    for folder_input in list_folder_input:
        # print('Folder: ', folder_input)
        # Delete Specific file extention
        if delete_specific_file_extension:
            delete_file_names = glob(os.path.join(folder_input, delete_file_extension))
            for a in delete_file_names:
                os.remove(a)
        # Get all image paths
        image_file_names = glob(os.path.join(folder_input, image_file_extension))
        # print('List: ', image_file_names)
        # print('Length Input {dir}: '.format(dir=folder_input), len(image_file_names))
        for image in image_file_names:
            img = cv2.imread(image)
            [h, w, _] = img.shape
            if h >= image_size and w >= image_size:
                worker(folder_input, image, output_dir, index)
                index += 1

def mode2(args) -> None:
    quantity = args.quantity
    input_dir = args.input_dir
    image_file_extension = args.image_file_extension
    output_dir = args.output_dir

    list_folder_input = [x[0] for x in os.walk(input_dir)]
    list_folder_input.sort(key=natural_keys)
    # print(list_folder_input)
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
        start = 1
        print('Start: ', start)
    else:
        list_output = os.listdir(output_dir)
        print('Length Output: ', len(list_output))
        if len(list_output) > 0:
            list_output.sort(key=natural_keys)
            end_output = list_output[-1]
            end_output = end_output.split('.')[0]
            start = int(end_output) + 1
            print('Start: ', start)
        else:
            start = 1
            print('Start: ', start)

    index = start
    for folder_input in list_folder_input:
        # print('Folder: ', folder_input)
        # Get all image paths
        image_file_names = glob(os.path.join(folder_input, image_file_extension))
        # print('List: ', image_file_names)
        # print('Length Input {dir}: '.format(dir=folder_input), len(image_file_names))
        for image in image_file_names[0:quantity-1]:
            img = cv2.imread(image)
            [h, w, _] = img.shape
            print(h,w)
            if h >= image_size and w >= image_size:
                worker(folder_input, image, output_dir, index)
                index += 1

def worker(images_dir, image_file_name, output_dir, index) -> None:
    new_image_name = f"{index}.{image_file_name.split('.')[-1]}"
    shutil.copyfile(f"{image_file_name}", f"{output_dir}/{new_image_name}")

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    '''
    return [atoi(c) for c in re.split(r'(\d+)', text)]

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Prepare database scripts.")
    parser.add_argument("--input_dir", type=str, help="Path to input image directory.")
    parser.add_argument("--output_dir", type=str, help="Path to generator image directory.")
    parser.add_argument("--mode", type=str, help="1 or 2.")
    parser.add_argument("--quantity", type=int, help="Quantity need to copy", default=0)
    parser.add_argument("--image_file_extension", type=str, help="File extension of input image.")
    parser.add_argument("--delete_specific_file_extension", type=bool, default=False,
                        help="If True, all file with folow file extension will be delete.")
    parser.add_argument("--delete_file_extension", type=str, default=None, help="File extension need to delete.")
    args = parser.parse_args()

    main(args)


#! /usr/bin/python
# bulletPointAdder.py - Adds Wikipedia bullet points to the start of each line

print("Enter the lines you want to add bullet points on, end your input with line '!'")

lines = []
for line in iter(input, '!'):  # Read multiple lines from user input
    line = '* ' + line  # Add bullet points
    lines.append(line)
text = '\n'.join(lines)
print(text)


#source : https://github.com/georgestanley/CMC/blob/master/NCE/NCEAverage.py

import torch
from torch import nn
from utils.alias_multinomial import AliasMethod
import math

class ContLoss(nn.Module):

    def __init__(self, tau=0.07):
        super(ContLoss, self).__init__()
        self.tau = tau

    def forward(self,a,b):
        a_norm = torch.norm(a, dim=1).reshape(-1, 1)
        a_cap = torch.div(a, a_norm)
        b_norm = torch.norm(b, dim=1).reshape(-1, 1)
        b_cap = torch.div(b, b_norm)
        a_cap_b_cap = torch.cat([a_cap, b_cap], dim=0)
        a_cap_b_cap_transpose = torch.t(a_cap_b_cap)
        b_cap_a_cap = torch.cat([b_cap, a_cap], dim=0)
        sim = torch.mm(a_cap_b_cap, a_cap_b_cap_transpose)
        sim_by_tau = torch.div(sim, self.tau)
        exp_sim_by_tau = torch.exp(sim_by_tau)
        sum_of_rows = torch.sum(exp_sim_by_tau, dim=1)
        exp_sim_by_tau_diag = torch.diag(exp_sim_by_tau)
        numerators = torch.exp(torch.div(torch.nn.CosineSimilarity()(a_cap_b_cap, b_cap_a_cap), self.tau))
        denominators = sum_of_rows - exp_sim_by_tau_diag
        num_by_den = torch.div(numerators, denominators)
        neglog_num_by_den = -torch.log(num_by_den)
        return torch.mean(neglog_num_by_den)

'''
class NCEAverage(nn.Module):

    def __init__(self, inputSize, outputSize, K, T=0.07, momentum=0.5, use_softmax=False):
        super(NCEAverage, self).__init__()
        self.nLem = outputSize
        self.unigrams = torch.ones(self.nLem)
        self.multinomial = AliasMethod(self.unigrams)
        self.multinomial.cuda()
        self.K = K
        self.use_softmax = use_softmax

        self.register_buffer('params', torch.tensor([K, T, -1, -1, momentum]))
        stdv = 1. / math.sqrt(inputSize / 3)
        self.register_buffer('memory_l', torch.rand(outputSize, inputSize).mul_(2 * stdv).add_(-stdv))
        self.register_buffer('memory_ab', torch.rand(outputSize, inputSize).mul_(2 * stdv).add_(-stdv))

    def forward(self, l, ab, y, idx=None):
        K = int(self.params[0].item())
        T = self.params[1].item()
        Z_l = self.params[2].item()
        Z_ab = self.params[3].item()

        momentum = self.params[4].item()
        batchSize = l.size(0)
        outputSize = self.memory_l.size(0)
        inputSize = self.memory_l.size(1)

        # score computation
        if idx is None:
            idx = self.multinomial.draw(batchSize * (self.K + 1)).view(batchSize, -1)
            idx.select(1, 0).copy_(y.data)
        # sample
        weight_l = torch.index_select(self.memory_l, 0, idx.view(-1)).detach()
        weight_l = weight_l.view(batchSize, K + 1, inputSize)
        out_ab = torch.bmm(weight_l, ab.view(batchSize, inputSize, 1))
        # sample
        weight_ab = torch.index_select(self.memory_ab, 0, idx.view(-1)).detach()
        weight_ab = weight_ab.view(batchSize, K + 1, inputSize)
        out_l = torch.bmm(weight_ab, l.view(batchSize, inputSize, 1))

        if self.use_softmax:
            out_ab = torch.div(out_ab, T)
            out_l = torch.div(out_l, T)
            out_l = out_l.contiguous()
            out_ab = out_ab.contiguous()
        else:
            out_ab = torch.exp(torch.div(out_ab, T))
            out_l = torch.exp(torch.div(out_l, T))
            # set Z_0 if haven't been set yet,
            # Z_0 is used as a constant approximation of Z, to scale the probs
            if Z_l < 0:
                self.params[2] = out_l.mean() * outputSize
                Z_l = self.params[2].clone().detach().item()
                print("normalization constant Z_l is set to {:.1f}".format(Z_l))
            if Z_ab < 0:
                self.params[3] = out_ab.mean() * outputSize
                Z_ab = self.params[3].clone().detach().item()
                print("normalization constant Z_ab is set to {:.1f}".format(Z_ab))
            # compute out_l, out_ab
            out_l = torch.div(out_l, Z_l).contiguous()
            out_ab = torch.div(out_ab, Z_ab).contiguous()

        # # update memory
        with torch.no_grad():
            l_pos = torch.index_select(self.memory_l, 0, y.view(-1))
            l_pos.mul_(momentum)
            l_pos.add_(torch.mul(l, 1 - momentum))
            l_norm = l_pos.pow(2).sum(1, keepdim=True).pow(0.5)
            updated_l = l_pos.div(l_norm)
            self.memory_l.index_copy_(0, y, updated_l)

            ab_pos = torch.index_select(self.memory_ab, 0, y.view(-1))
            ab_pos.mul_(momentum)
            ab_pos.add_(torch.mul(ab, 1 - momentum))
            ab_norm = ab_pos.pow(2).sum(1, keepdim=True).pow(0.5)
            updated_ab = ab_pos.div(ab_norm)
            self.memory_ab.index_copy_(0, y, updated_ab)

        return out_l, out_ab
'''

'''
class NCESoftmaxLoss(nn.Module):
    """Softmax cross-entropy loss (a.k.a., info-NCE loss in CPC paper)"""
    def __init__(self):
        super(NCESoftmaxLoss, self).__init__()
        self.criterion = nn.CrossEntropyLoss()

    def forward(self, x):
        bsz = x.shape[0]
        x = x.squeeze()
        label = torch.zeros([bsz]).cuda().long()
        loss = self.criterion(x, label)
        return loss
'''


from django.conf.urls.defaults import *

from haystack.forms import FacetedSearchForm
from haystack.query import SearchQuerySet
from haystack.views import FacetedSearchView

sqs =SearchQuerySet().facet(
                      'funder_name'
                    ).facet(
                      'funder_party'
                    ).facet(
                      'funder_committee_type'
                    ).order_by(
                      '-pub_date'
                    )

urlpatterns = patterns('haystack.views',
        url(r'^$', FacetedSearchView(form_class=FacetedSearchForm,
                                        template='search/search.html',
                                        searchqueryset=sqs,
                                        results_per_page=15),
                                        name='haystack_search'),
        )


# Produces CSV file with the stats taken from all the SAM files in the
# directory given as a second argument. The first argument is the number of jobs
# in multiprocessing pool (optional). If the second argument is not present
# then the list of files is read from stdin.

import sys
import sam_utils
import os

from multiprocessing import Pool

def get_read_stats(file_path):
    alignment = sam_utils.get_best_alignment(file_path)
    if alignment is None:
        return None

    read_name = file_path[:-len(".sam")]

    fasta_file = open(read_name + ".fasta")
    fasta_header = fasta_file.readline().strip()
    whole_read = fasta_file.readline().strip()

    cigar_counts = sam_utils.get_cigar_counts(alignment)
    edit_distance = sam_utils.get_edit_distance_from(alignment)

    return (read_name, edit_distance,
            cigar_counts["INS"], cigar_counts["DEL"],
            cigar_counts["MATCH"], cigar_counts["SOFT_CLIP"],
            cigar_counts["HARD_CLIP"], cigar_counts["SKIP"],
            cigar_counts["PAD"], alignment.query_alignment_start,
            alignment.query_alignment_end, alignment.query_length,
            len(whole_read), alignment.reference_start,
            alignment.reference_end, alignment.reference_length)

jobs = 1
if len(sys.argv) == 2:
    jobs = int(sys.argv[1])

file_paths = []
if len(sys.argv) == 3:
    path_to_dir = sys.argv[2]
    file_paths = [path_to_dir + "/" +
                  file for file in os.listdir(path_to_dir) if file.endswith(".sam")]
else:
    file_paths = [path.strip() for path in sys.stdin]

pool = Pool(jobs)
chunk = len(file_paths) // jobs
stats = pool.map(get_read_stats, file_paths, chunk)
pool.close()

csv_header = str("path, edit_dist, I, D, M, S_CLIP, H_CLIP, SKIP, PAD, "
                 "query_start, query_end, query_length, read_len, ref_start, ref_end,"
                 " ref_length")
print(csv_header)
for row in stats:
    if row is None:
        cols = len(csv_header.split(','))
        print(",".join(["NA"] * cols))
        continue

    print(",".join(map(str, list(row))))


from django.conf.urls import patterns, url

from .views import *

urlpatterns = patterns(
    '',
    url('^$', generator_view, name='generator'),
    url('^domains$', domain_list_view, name='domain_list'),
    url('^domain/(?P<domain>.*)$', domain_view, name='domain'),
)


from ConfigParser import RawConfigParser, NoSectionError, NoOptionError
from argparse import ArgumentParser, RawDescriptionHelpFormatter
import os
from pushover import Pushover

def read_config(config_path):
    config_path = os.path.expanduser(config_path)
    config = RawConfigParser()
    params = {"users": {}}
    files = config.read(config_path)
    if not files:
        return params
    params["token"] = config.get("main", "token")
    for name in config.sections():
        if name != "main":
            user = {}
            user["user_key"] = config.get(name, "user_key")
            try:
                user["device"] = config.get(name, "device")
            except NoOptionError:
                user["device"] = None
            params["users"][name] = user
    return params

def main():
    parser = ArgumentParser(
        description="Send a message to pushover.",
        formatter_class=RawDescriptionHelpFormatter,
        epilog="""
For more details and bug reports, see: https://github.com/Thibauth/python-pushover""",
    )
    parser.add_argument("--token", help="API token")
    parser.add_argument(
        "--user",
        "-u",
        help="User key or section name in the configuration",
        required=True,
    )
    parser.add_argument(
        "-c",
        "--config",
        help="configuration file\
                        (default: ~/.pushoverrc)",
        default="~/.pushoverrc",
    )
    parser.add_argument("message", help="message to send")
    parser.add_argument("--url", help="additional url")
    parser.add_argument("--url-title", help="url title")
    parser.add_argument("--title", "-t", help="message title")
    parser.add_argument(
        "--priority", "-p", help="notification priority (-1, 0, 1 or 2)", type=int
    )
    parser.add_argument(
        "--retry",
        "-r",
        help="resend interval in seconds (required for priority 2)",
        type=int,
    )
    parser.add_argument(
        "--expire",
        "-e",
        help="expiration time in seconds (required for priority 2)",
        type=int,
    )
    parser.add_argument(
        "--version",
        "-v",
        action="version",
        help="output version information and exit",
        version="""
%(prog)s 1.0
Copyright (C) 2013-2018 Thibaut Horel <thibaut.horel@gmail.com>
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.""",
    )

    args = parser.parse_args()
    params = read_config(args.config)
    if args.priority == 2 and (args.retry is None or args.expire is None):
        parser.error("priority of 2 requires expire and retry")
    if args.user in params["users"]:
        user_key = params["users"][args.user]["user_key"]
        device = params["users"][args.user]["device"]
    else:
        user_key = args.user
        device = None
    token = args.token or params["token"]

    Pushover(token).message(
        user_key,
        args.message,
        device=device,
        title=args.title,
        priority=args.priority,
        url=args.url,
        url_title=args.url_title,
        timestamp=True,
        retry=args.retry,
        expire=args.expire,
    )

if __name__ == "__main__":
    main()


# import sys
# sys.path.append("NumPy_path")
# import NumPy
import numpy

print("............1.............")
def numAvg(num1, num2):
    return (num1+num2)/2
print(numAvg(3, 6))
print(numAvg(10, 26))

print("............2.............")
def numAvg2(num1, num2):
    print((num1+num2)/2)

numAvg2(3, 6)
numAvg2(10, 26)

print("............3.............")
def power(num1):
    return pow(num1, 3)
print(power(3))
print(power(10))

print("............4.............")
def minNum(num1, num2):
    print(min(num1, num2))

minNum(3, 6)
minNum(10, 26)

print("............5.............")
def oddEven(num1):
    if(num1%2==0):
        return False
    else:
        return True
print(oddEven(3))
print(oddEven(10))

print("............6.............")
def fact(num):
    if(num<=0):
        print("Factorial can not be calculated for ", num)
    else:
        fact = 1
        for i in range(1,num+1):
            fact = fact * i

        print ("The factorial of {} is : {}".format(num, fact))

fact(1)

print("............7.............")
def factorial(num):
    if num == 1:
        return 1
    else:
        return (num * factorial(num-1))

num = 5
print("The factorial of", num, "is", factorial(num))

print("............8.............")
numbs = [1, 2, 3, 4, 5]
print(sum(numbs))
print(min(numbs))
print(max(numbs))
print(sum(numbs)/len(numbs))
numbs.append(102)
numbs[2]=205
numbs.pop(3)
numbs.sort()
print(numbs)

print("............9.............")
def comparison(a, b):
    for i in a:
        for k in b:
            if i == k:
                return True
    return False

a = [1, 2, 3, 4, 5]
b = [7, 4, 8, 9, 0]
print(comparison(a, b))

print("............10.............")
arr1 = numpy.array([1, 5, 8, 4, 5])
arr2 = numpy.array([6, 7, 5, 3, 9])
print(arr1+arr2)

print("............1.1.............")
numbs = []
for i in range(20, 126):
    if(i%5==0):
        numbs.append(i)
print(numbs)

print("............1.2.............")
numbs = []
for i in range(20, 126):
    if(i%8==0):
        numbs.append(i)
numbs.sort(reverse=True)
print(numbs)

print("............1.3.............")
def numConf(num1, num2):
    if(num1>num2):
        sameDivider(num2, num1)
    elif(num1<num2):
        sameDivider(num1, num2)
    else:
        sameDivider(num1, num1)

def sameDivider(x, y):
    dividers= []
    for i in range(1, y+1):
        if(x % i == 0 and y % i == 0):
            dividers.append(i)
    print(dividers)

numConf(15,10)
numConf(50,50)

print("............1.4.............")
nums=[]
for i in range(1, 11):
    nums.append(int(input("Type Number {}: ".format(i))))
print(sum(nums)/len(nums))

print("............1.5.............")
sum=0
for i in range(1, 101):
    if (i%2==0):
        sum+=i
print(sum)

print("............1.6.............")
nums=[]
for i in range(1500, 2101):
    if (i%5==0 and i%7==0):
        nums.append(i)
print(nums)


from collections import defaultdict

import sys

from hmm.hw2_hmm import HMM

class Eval:
    """
    A class for evaluating POS-tagged data
    """

    def __init__(self, goldFile, testFile):
        """
        Reads the labeled corpus at goldFile and the unlabeled corpus at testFile
        :param goldFile: file with the labeled test corpus
        :param testFile: file with the unlabeled test corpus
        """
        # Read the labeled evaluation corpora
        self.pred_corpus = HMM.read_labeled_data(testFile)
        self.gold_corpus = HMM.read_labeled_data(goldFile)

    def getTokenAccuracy(self):
        """
        Compares the labels of the computed corpus against the gold corpus
        :return: float: token accuracy over all observations
        """
        correct = 0
        total = 0
        assert (len(self.pred_corpus) == len(self.gold_corpus))
        for i in range(len(self.pred_corpus)):
            predicted = self.pred_corpus[i]
            actual = self.gold_corpus[i]
            assert (len(predicted) == len(actual))
            for j in range(len(predicted)):
                ptw = predicted[j]
                atw = actual[j]
                assert (ptw.word == atw.word)
                total += 1
                if ptw.tag == atw.tag:
                    correct += 1
        return correct / total

    def getSentenceAccuracy(self):
        """
        Calculates the percentage of sentences that are tagged completely correctly (all words)
        :return: accuracy of predicting entire sentence correctly
        """
        correct = 0
        total = 0
        assert (len(self.pred_corpus) == len(self.gold_corpus))
        for i in range(len(self.pred_corpus)):
            predicted = self.pred_corpus[i]
            actual = self.gold_corpus[i]
            assert (len(predicted) == len(actual))
            sentence_correct = True
            total += 1
            for j in range(len(predicted)):
                ptw = predicted[j]
                atw = actual[j]
                assert (ptw.word == atw.word)
                if ptw.tag != atw.tag:
                    sentence_correct = False
            if sentence_correct:
                correct += 1
        return correct / total

    def writeConfusionMatrix(self, outFile):
        """
        Creates a confusion matrix for the tags then pretty prints it to a file
        :param outFile: location to write confusion matrix
        """
        # Count all of the ways a tag has been tagged
        confusion_dict = defaultdict(lambda: defaultdict(int))
        tags = set()
        assert (len(self.pred_corpus) == len(self.gold_corpus))
        for i in range(len(self.pred_corpus)):
            predicted = self.pred_corpus[i]
            actual = self.gold_corpus[i]
            assert (len(predicted) == len(actual))
            for j in range(len(predicted)):
                ptw = predicted[j]
                atw = actual[j]
                assert (ptw.word == atw.word)
                tags.add(ptw.tag)
                tags.add(atw.tag)
                confusion_dict[atw.tag][ptw.tag] += 1

        # Assign each tag an arbitrary unique id
        ti = {}
        for i, t0 in enumerate(tags):
            ti[i] = t0
        n = len(ti)

        # Print each tag in ordered by its id
        out = "{0:6}".format("")
        for i in range(n):
            out += "{0:>6}".format(ti[i])
        out += "\t\n"

        # Print each row by the tag
        for i in range(n):
            out += "{0:6}".format(ti[i])
            for j in range(n):
                out += "{0:6}".format(confusion_dict[ti[i]][ti[j]])
            out += "\t\n"

        # Write to file
        f = open(outFile, "w+")
        f.write(out)
        f.close()

    def getPrecision(self, tagTi):
        """
        Computes the precision of the HMM model for tagTi
        Precision is true positive divided by all positive predictions
        :param tagTi: tag to check for precision
        :return: precision
        """
        tp = 0
        fp = 0
        assert (len(self.pred_corpus) == len(self.gold_corpus))
        for i in range(len(self.pred_corpus)):
            predicted = self.pred_corpus[i]
            actual = self.gold_corpus[i]
            assert (len(predicted) == len(actual))
            for j in range(len(predicted)):
                ptw = predicted[j]
                atw = actual[j]
                assert (ptw.word == atw.word)
                if ptw.tag == tagTi:
                    if atw.tag == tagTi:
                        tp += 1
                    else:
                        fp += 1

        return tp / (tp + fp)

    def getRecall(self, tagTj):
        """
        Computes the recall of the HMM model for the tagTj
        Recall is the true positive divided by the number of actual positive
        :param tagTj: tag to check for recall
        :return: recall
        """
        tp = 0
        ap = 0
        assert (len(self.pred_corpus) == len(self.gold_corpus))
        for i in range(len(self.pred_corpus)):
            predicted = self.pred_corpus[i]
            actual = self.gold_corpus[i]
            assert (len(predicted) == len(actual))
            for j in range(len(predicted)):
                ptw = predicted[j]
                atw = actual[j]
                assert (ptw.word == atw.word)
                if ptw.tag == tagTj and atw.tag == tagTj:
                    tp += 1
                elif atw.tag == tagTj:
                    ap += 1
        return tp / (tp + ap)

if __name__ == "__main__":
    if len(sys.argv) <= 2:
        gold = "../data/gold.txt"
        test = "../data/out.txt"
    else:
        # Pass in the gold and test POS-tagged data as arguments
        gold = sys.argv[1]
        test = sys.argv[2]

    # You need to implement the evaluation class
    eval = Eval(gold, test)
    # Calculate accuracy (sentence and token level)
    print("Token accuracy: ", eval.getTokenAccuracy())
    print("Sentence accuracy: ", eval.getSentenceAccuracy())
    # Calculate recall and precision
    print("Recall on tag NNP: ", eval.getPrecision('NNP'))
    print("Precision for tag NNP: ", eval.getRecall('NNP'))
    # Write a confusion matrix
    eval.writeConfusionMatrix("conf_matrix.txt")


from __future__ import division
import json
import matplotlib.pyplot as plt

# global
global_10 = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/global_10.json').read())
global_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/global_dv.json').read())
global_walk = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/global_walk.json').read())
global_walk_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/global_walk_dv.json').read())
global_10_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/global_10_dv.json').read())
global_10_walk = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/global_10_walk.json').read())
global_10_walk_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/global_10_walk_dv.json').read())

# [thres, preci, recal, fone]
# plt.plot(global_walk[0][2], global_walk[0][1], linewidth=2, linestyle="-", label="graph2vec")
# plt.plot(global_walk_dv[0][2], global_walk_dv[0][1], linewidth=2, linestyle="-", label="graph2vec + doc2vec-SUP")
# plt.plot(global_10_walk[0][2], global_10_walk[0][1], linewidth=2, linestyle="-", label="10-FEAT + graph2vec")
# plt.plot(global_10_walk_dv[0][2], global_10_walk_dv[0][1], linewidth=2, linestyle="-", label="10-FEAT + graph2vec + doc2vec-SUP")

plt.plot(global_10[0][2], global_10[0][1], linewidth=2, linestyle="-", label="10-FEAT")
plt.plot(global_dv[0][2], global_dv[0][1], linewidth=2, linestyle="-", label="doc2vec-SUP")
plt.plot(global_10_dv[0][2], global_10_dv[0][1], linewidth=2, linestyle="-", label="10-FEAT + doc2vec-SUP")

plt.legend(loc='upper right')
plt.xlabel('recall', fontsize=20)
plt.ylabel('precision', fontsize=20)
plt.title('Recall-Precision Curve', fontsize=20)

# partition
# part1_10_walk_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/part1_10_walk_dv.json').read())
# part2_10_walk_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/part2_10_walk_dv.json').read())
# part3_10_walk_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/part3_10_walk_dv.json').read())
# part4_10_walk_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/part4_10_walk_dv.json').read())
# part5_10_walk_dv = json.loads(open(r'/Users/ZhangHaotian/desktop/LO/part5_10_walk_dv.json').read())

# create x axis to be 0.1:0.01:0.99
# x_axis = []
# initial = 0.1
# while initial <= 0.99:
#     x_axis.append(initial)
#     initial += 0.01
#     initial = round(initial, 2)


from frozendict import frozendict
from typing import Any, List, Set
from constants import COORDINATES

def table_coordinate_to_int(table_coordinate: str) -> int:
    if len(table_coordinate) != 1 or table_coordinate not in COORDINATES:
        return -1

    return COORDINATES.index(table_coordinate) + 1

def int_to_table_coordinate(int: int) -> str:
    return COORDINATES[(int - 1) % len(COORDINATES)]

def replace_substring_in_string_from_index(str: str, start_index: int, substr: str) -> str:
    return str[:start_index] + substr + str[start_index + len(substr):]

def check_if_string_is_number_in_range(str: str, low: int, high: int) -> int | None:
    if str.strip().isdigit():
        str = int(str)
        if str >= low and str <= high:
            return str
    return None

def update_tuple(tuple_to_update: tuple, index_to_update: int, new_value) -> tuple:
    tuple_list = list(tuple_to_update)
    tuple_list[index_to_update] = new_value
    return tuple(tuple_list)

def update_tuple_many(tuple_to_update: tuple, new_values: dict[int, Any]) -> tuple:
    tuple_list = list(tuple_to_update)
    for key, value in new_values.items():
        tuple_list[key] = value
    a = tuple(tuple_list)
    return a

def update_pawn_positions(
    old_positions: tuple[tuple[tuple[int, int], tuple[int, int]], tuple[tuple[int, int], tuple[int, int]]],
    selected_player_index: int,
    selected_pawn_index: int,
    new_pawn_position: tuple[int, int],
) -> tuple[tuple[tuple[int, int], tuple[int, int]], tuple[tuple[int, int], tuple[int, int]]]:
    tuple_list = list(old_positions[selected_player_index])
    tuple_list[selected_pawn_index] = new_pawn_position
    return (old_positions[0], tuple(tuple_list)) if selected_player_index else (tuple(tuple_list), old_positions[1])

def add_wall_in_tuple(
    walls: tuple[tuple[tuple[int, int], ...], tuple[tuple[int, int], ...]],
    new_wall: tuple[int, int],
    is_wall_horizontal: bool,
) -> tuple[tuple[tuple[int, int], ...], tuple[tuple[int, int], ...]]:
    updated_walls = add_to_tuple(walls[is_wall_horizontal], new_wall)
    return (walls[0], updated_walls) if is_wall_horizontal else (updated_walls, walls[1])

def remove_wall_from_tuple(
    walls: tuple[tuple[tuple[int, int], ...], tuple[tuple[int, int], ...]],
    to_remove_wall: tuple[int, int],
    is_wall_horizontal: bool,
    ):
    updated_walls = list(walls[is_wall_horizontal])
    updated_walls.remove(to_remove_wall)
    return (walls[0], updated_walls) if is_wall_horizontal else (updated_walls, walls[1])

def decrement_number_of_walls(
    number_of_walls: tuple[tuple[int, int], tuple[int, int]],
    selected_player_index: int,
    is_wall_horizontal: bool
) -> tuple[tuple[int, int], tuple[int, int]]:
    veritcal, horizontal = number_of_walls[selected_player_index]
    if is_wall_horizontal:
        horizontal -= 1
    else:
        veritcal -= 1
    return (number_of_walls[0], (veritcal, horizontal)) if selected_player_index else ((veritcal, horizontal), number_of_walls[1])

def add_to_tuple(tuple_to_update: tuple, new_value) -> tuple:
    tuple_list = list(tuple_to_update)
    tuple_list.append(new_value)
    return tuple(tuple_list)

def remove_from_tuple(tuple_to_update: tuple, value_to_delete) -> tuple:
    tuple_list = list(tuple_to_update)
    if value_to_delete in tuple_list:
        tuple_list.remove(value_to_delete)
    return tuple(tuple_list)

def tuple_4_positions(
    first1row: int, first1column, first2row: int, first2column: int,
    second1row: int, second1column: int, second2row: int, second2column: int
) -> tuple[tuple[tuple[int, int], tuple[int, int]], tuple[tuple[int, int], tuple[int, int]]]:
    return (((first1row, first1column), (first2row, first2column)), ((second1row, second1column), (second2row, second2column)))

def update_coordinate_tuple_dict_neighbors_or_insert_new_node(dict: dict[tuple[int, int], tuple[tuple[int, int], ...]], node: tuple[int, int], neighbor: tuple[int, int]) -> None:
    if node in dict.keys():
        if neighbor not in dict[node]:
            dict[node] = add_to_tuple(dict[node], neighbor)
        return
    dict[node] = ((neighbor),)

def remove_neighbor_coordinate_tuple_from_dict(connection_points: frozendict[tuple[int, int], tuple[tuple[int, int], ...]], node: tuple[int, int], neighbor: tuple[int, int]) -> dict[tuple[int, int], tuple[tuple[int, int], ...]]:
    connection_points_dict = dict(connection_points)
    if node in connection_points_dict.keys():
        if neighbor in connection_points_dict[node]:
            connection_points_dict[node] = remove_from_tuple(connection_points_dict[node], neighbor)
    return connection_points_dict


with open("day8.in", "r") as o:
    f = o.readlines()

registers = {}

operators = {">": lambda a, b: a > b,
             "<": lambda a, b: a < b,
             "==": lambda a, b: a == b,
             ">=": lambda a, b: a >= b,
             "<=": lambda a, b: a <= b,
             "!=": lambda a, b: a != b}

for line in f:
    l = line.replace("\n", "").split(" ")

    cond_l = l[4]
    cond_o = l[5]
    cond_r = int(l[6])

    if cond_l not in registers:
        registers[cond_l] = 0

    l_value = registers[cond_l]

    cond_result = operators[cond_o](l_value, cond_r)

    if l[0] not in registers:
        registers[l[0]] = 0

    if cond_result:
        if l[1] == "inc":
            registers[l[0]] += int(l[2])
        else:
            registers[l[0]] -= int(l[2])

print(registers)

max_value = None
for r in registers:
    if not max_value:
        max_value = registers[r]
    else:
        max_value = max(max_value, registers[r])

print(max_value)


#!/usr/bin/python3
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

import unittest
# add the root directory to sys.path
from pathlib import Path
import sys
sys.path.append(str(Path(__file__).absolute().parent.parent))

from GroupTools import *
import itertools
import re

class TestStrs(unittest.TestCase):

    def setUp(self):
        self.dt1 = DataTable(["AA","BBB"])
        self.dt2 = DataTable(["AA", "BBAA", "CCAC", "CCB"])
        self.m1 = Mappings(['A', 'B'])
        self.m1.createDefinition()
        self.m1.createDefinition()

    def test_strDataTable(self):
        self.assertEqual(str(self.dt1), ' A A | B B B\n1   1 1     1 ')
        self.assertEqual(str(self.dt2), ' A A | B B A A | C C A C | C C B\n'
                            + '1   1 1       1 1       1 1     1 ')

    def test_strMappings(self):
        self.assertEqual(str(self.m1), ' I A B\n 1 2 3\n 2    \n 3    ')

class Test_Mappings(unittest.TestCase):

    def setUp(self):
        self.m1 = Mappings(['A'])
        self.m2 = Mappings(['A', 'B'])
        self.m3 = Mappings('ABCD')

    def test_define(self):
        self.m1.define(1, 'A', 2)
        self.m1.define(2, 'A', 3)
        self.assertEqual(str(self.m1), ' I A\n 1 2\n 2 3\n 3  ')
        self.m2.define(1, 'A', 3)
        self.m2.define(1, 'B', 2)
        self.assertEqual(str(self.m2), ' I A B\n 1 3 2\n 2    \n 3    ')
        with self.assertRaises(RuntimeError):
            self.m2.define(1, 'A', 2)

    def test_createDefinition(self):
        for _ in range(3):
            self.m1.createDefinition()
        self.assertEqual(str(self.m1), ' I A\n 1 2\n 2 3\n 3 4\n 4  ')
        self.m2.define(1, 'B', 2)
        self.m2.createDefinition()
        self.assertEqual(str(self.m2), ' I A B\n 1 3 2\n 2    \n 3    ')
        self.m2.createDefinition()
        self.m2.createDefinition()
        self.assertEqual(str(self.m2),
            ' I A B\n 1 3 2\n 2 4 5\n 3    \n 4    \n 5    ')
        self.m3.define(2, 'B', 1)
        self.assertEqual(str(self.m3),
            ' I A B C D\n 1        \n 2   1    ')
        for _ in range(6):
            self.m3.createDefinition()
        self.assertEqual(str(self.m3),
            ' I A B C D\n 1 3 4 5 6\n 2 7 1 8  \n 3        \n'
            # empty lines
            + '\n'.join([' {}        '.format(i) for i in range(4, 9)]))

    def setUpLookups(self):
        for _ in range(4):
            self.m1.createDefinition()
            self.m2.createDefinition()
            self.m3.createDefinition()
        self.m2.define(5, 'B', 2)
        self.m3.define(5, 'D', 3)
        # m1:  m2:     m3:
        # I A  I A B   I A B C D
        # 1 2  1 2 3   1 2 3 4 5
        # 2 3  2 4 5   2
        # 3 4  3       3
        # 4 5  4       4
        # 5    5   2   5       3

    def test_fLookup(self):
        self.setUpLookups()
        for i in range(1, 5):
            self.assertEqual(self.m1.fLookup(i, 'A'), i+1)
        self.assertEqual(self.m2.fLookup(1, 'A'), 2)
        self.assertEqual(self.m2.fLookup(1, 'B'), 3)
        self.assertEqual(self.m2.fLookup(2, 'A'), 4)
        self.assertEqual(self.m2.fLookup(2, 'B'), 5)
        self.assertEqual(self.m2.fLookup(5, 'B'), 2)

        self.assertEqual(self.m3.fLookup(1, 'A'), 2)
        self.assertEqual(self.m3.fLookup(1, 'B'), 3)
        self.assertEqual(self.m3.fLookup(1, 'C'), 4)
        self.assertEqual(self.m3.fLookup(1, 'D'), 5)
        self.assertEqual(self.m3.fLookup(5, 'D'), 3)
        with self.assertRaises(KeyError):
            self.m1.fLookup(5, 'A')
        for n, c in [(3, 'A'), (3, 'B'), (4, 'A'), (4, 'B'), (5, 'A')]:
            with self.assertRaises(KeyError):
                self.m2.fLookup(n, c)
        for c in 'ABCD':
            for n in range(2, 6):
                if c != 'D' and n != 5:
                    with self.assertRaises(KeyError):
                        print('{}{}={}, when it should be undefined'.format(
                            n, c, self.m3.fLookup(n, c)))

    def test_bLookup(self):
        self.setUpLookups()
        for i in range(2, 6):
            self.assertEqual(self.m1.bLookup('A', i), i-1)
        self.assertEqual(self.m2.bLookup('A', 2), 1)
        self.assertEqual(self.m2.bLookup('B', 3), 1)
        self.assertEqual(self.m2.bLookup('A', 4), 2)
        self.assertEqual(self.m2.bLookup('B', 5), 2)

        self.assertEqual(self.m3.bLookup('A', 2), 1)
        self.assertEqual(self.m3.bLookup('B', 3), 1)
        self.assertEqual(self.m3.bLookup('C', 4), 1)
        self.assertEqual(self.m3.bLookup('D', 5), 1)

        with self.assertRaises(KeyError):
            self.m1.bLookup('A', 1)
        defined = {'A':[2, 4], 'B':[3, 5, 2]}
        for c in 'AB':
            for n in range(1, 6):
                if not n in defined[c]:
                    with self.assertRaises(KeyError):
                        print('{}{}={}, when it should be undefined'.format(
                            c, n, self.m2.bLookup(c, n)))
        defined = {'A':[2], 'B':[3], 'C':[4], 'D':[5, 3]}
        for c in 'ABCD':
            for n in range(1, 6):
                if not n in defined[c]:
                    with self.assertRaises(KeyError):
                        print('{}{}={}, when it should be undefined'.format(
                            c, n, self.m3.bLookup(c, n)))

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


#	This will eventually perform a few calculations and hold the bulk of the recipe data
#
#	-Settings should be imported from a CONFIG type of module
#		-in addition to settings things like recipe name and author should probably
#			be pulled
#	-The class should then import GRAIN and HOP and create a new instance of the objects
#		at the user's command
#	-It should use these to calculate overall recipe OG, SRM, and IBUs
#	-Data should be stored somehow (dic?)
#
#
#	Other thoughts:
#	-this might be a good place to compare to style guidelines
#	-as an "other" group is developed, it should probably also be included to keep
#		data in the same place(it probably makes sense for the yeast strain to be
#		in here even though it's pretty much superficial
#

import grains
import hops
import water

class Recipe(object):
#The umbrella class that will contain all of the recipe components

	count = 0
		#A count might come in handy for save logs or having a recipe book
	ogDict = {}

	statisticalDic = {'OG':0, 'IBUs':0, 'SRM':0, 'ABV':0}

	#grainList=[]		This will be the real one-- using multiple list items to test calculations
	grainList=[grains.Grain(),grains.Grain(ppg=20)]
		#This will hold all of the grain objects that are created

	def __init__(self):
		Recipe.count += 1

	def addGrain(self, type= 'generic', lb = 1, oz = 0, ppg = 25, degreesL = 1, sugarType="grain", use="mashed"):
		#Add a grain object to the grainList--this might make more sense outside of the class
		Recipe.grainList.append(grains.Grain(type, lb, oz, ppg, degreesL, sugarType))
		return Recipe.grainList

	def calculateTotalPoints(self, volume, efficiency):
		#This will calculate the points of the entire recipe
		#-this should eventually take no inputs, but rather pull directly
		#	from a CONFIG module

		totalPoints = 0
		pointList = []

		for grain in range(len(Recipe.grainList)):
			pointList.append(Recipe.grainList[grain].calculatePoints(volume, efficiency))
			totalPoints += pointList[grain]

		Recipe.ogDict.update({'pointList':pointList,'totalPoints':totalPoints})
			#It might be useful to store it in a dictionary in case
			#	we ever need to access the grain list (which may be
			#	unlikely)
		return Recipe.ogDict

	def returnTotalOG(self, volume, efficiency):
		#Calculates the OG of the recipe
		#-this should eventually take no inputs, but rather pull directly
		#	from a CONFIG module

		OG = Recipe.ogDict['totalPoints']
		OG = 1 + (OG / 1000)

		Recipe.ogDict.update({'OG': OG})
		return Recipe.ogDict

	def returnTotalColor(self, volume):
		#Estimates the recipe's SRM
		#-this should eventually take no inputs, but rather pull directly
		#	from a CONFIG module

		totalColor = 0
		colorList = []

		for grain in range(len(Recipe.grainList)):
			colorList.append(Recipe.grainList[grain].calculateColor())
			totalColor += colorList[grain]
		totalMCUs = totalColor / volume
		moreyColor = 1.4922 * totalMCUs**0.6859
		return moreyColor

#test main

print('pringing grains.Grain.count:',grains.Grain.count)

recipe = Recipe()

print('printing recipe.grainList:',recipe.grainList)
added=Recipe().addGrain(ppg=35)
print('printing added:',added)

print('printing added[0].ppg:',added[0].ppg)
print('testing calculateTotalPoints:',recipe.calculateTotalPoints(2,.75)['totalPoints'])
print('testing returnTotalOG:',recipe.returnTotalOG(2,.75)['OG'])

print('testing returnTotalColor:', recipe.returnTotalColor(2))

input('/nExit')


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

# packet header format
DIM_SIP, DIM_DIP, DIM_SPORT, DIM_DPORT, DIM_PROTO, DIM_MAX = range(6)
UINT32_MAX, UINT16_MAX, UINT8_MAX = ((1 << i) - 1 for i in [32, 16, 8])
DIM_POINT_MAX = [UINT32_MAX, UINT32_MAX, UINT16_MAX, UINT16_MAX, UINT8_MAX]
BIT_RANGE = [(0,31),(32,63),(64,79),(80,95),(96,103)]
FIELD_LENTH = [32, 32, 16, 16, 8]
BIT_LENGTH = 104

# memory size
NON_LEAF_BUCKET_STRUCTURE_SIZE = 13 + 4 + 4
LEAF_BUCKET_STRUCTURE_SIZE = 4
LINEAR_BUCKET_SIZE = 4

# BitCuts parameters
BINTH = 8
SPFAC = 4

# EffiCuts grouping parameters
IP_BIN_RATIO = 0.05
PORT_BIN_RATIO = 0.5
PROTO_BIN_RATIO = 1

# BitGrouping parameters
OPTIMIZE_RATIO = 0.8
MAX_REMAINED_RULES = 100
MAX_GROUP_NUM = 10