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

from flask import (Blueprint,
                   g,
                   render_template,
                   flash,
                   redirect,
                   url_for,
                   abort)
from flask.ext.login import current_user
from ..services import projects, users, issues
from ..forms import NewIssueForm
from . import route

bp = Blueprint('issue', __name__, url_prefix='/<u_name>/<p_name>/issues')

@bp.url_value_preprocessor
def pull_project_code(endpoint, values):
    u_name = values.pop('u_name')
    p_name = values.pop('p_name')
    user = users.first(name=u_name)
    if not user:
        abort(404)
    project = projects.first(name=p_name, owner_id=user.id)
    if not project:
        abort(404)
    g.u_name = u_name
    g.p_name = p_name
    g.project = project

@route(bp, '/')
def index():
    context = {}
    context['u_name'] = g.u_name
    context['p_name'] = g.p_name
    context['project'] = g.project
    context['project_menu'] = 'Issues'
    project = g.project
    context['issues'] = issues.find(project_id=project.id)
    return render_template('issues/index.html', **context)

@route(bp, '/new')
def new():
    context = {}
    context['form'] = NewIssueForm()
    context['project'] = g.project
    context['project_menu'] = 'Issues'
    return render_template('issues/new.html', **context)

@route(bp, '/create', methods=['post'])
def create():
    context = {}
    context['u_name'] = g.u_name
    context['p_name'] = g.p_name
    context['project_menu'] = 'Issues'
    project = g.project
    form = NewIssueForm()
    if form.validate_on_submit():
        i = project.create_issue(creator_id=current_user.id,
                                 **form.data)
        flash('New issue was successfully created!', 'info')
        return redirect(url_for('.index', **context))
    context['form'] = form
    context['project'] = project
    return render_template('issues/new.html', **context)

@route(bp, '/<id>')
def issue_index(id):
    context = {}
    context['u_name'] = g.u_name
    context['p_name'] = g.p_name
    context['project'] = g.project
    context['project_menu'] = 'Issues'
    context['issue'] = issues.first(project_id=g.project.id,
                                    number=id)
    return render_template('issues/issue.html', **context)


#! /usr/bin/env python

## Trying something new:
"""
This script contains all the code for plotting figure 1 of Ammon's BayesBattleBots paper
For questions, contact Ammon Perkes (perkes.ammon@gmail.com)
"""

import numpy as np
from matplotlib import pyplot as plt
import copy
from tqdm import tqdm

from fish import Fish
from fight import Fight
from tank import Tank
from simulation import Simulation,SimParams
from matplotlib import cm
from params import Params
from simulation import Simulation

## Define some global variables to determine if you will plot and save figures.
PLOT = True
SAVE = False

sim = Simulation()
params = Params()
params.outcome_params = [0.5,-0.5,-0.8]
#params.set_L()
params.awareness = 0.5
params.acuity = 0.1

params.set_params()
#params.size=50
#params.prior = True

#params.effort_method = [None,'!']
#params.effort_method = 'ExplorePoly'
params.effort_method = 'SmoothPoly'
params.poly_param_c = 0

params.post_acuity = True
params.f_method = 'shuffled'

params.n_fish = 5
params.n_rounds = 30
params.iterations = 500
#params.n_rounds = params.n_fights * (params.n_fish-1)

## Set up a tank
cost_array = np.empty([params.iterations,params.n_fish,params.n_rounds * (params.n_fish-1)])
error_array = np.empty([params.iterations,params.n_fish,params.n_rounds * (params.n_fish - 1) + 1])

for i in tqdm(range(params.iterations)):
    fishes = [Fish(f,params) for f in range(5)]

    tank = Tank(fishes,params)
    tank.run_all(progress=False)

    error_array[i] = sim._calc_error(tank)
    for f in range(len(fishes)):
        cost_array[i,f] = np.array(tank.fishes[f].win_record)[:,3]

fig,(ax,ax1) = plt.subplots(1,2)

mean_int = np.nanmean(cost_array,axis=(0,1))
sem_int = np.nanstd(cost_array,axis=(0,1)) / np.sqrt(params.iterations)
ax.plot(mean_int,color='black')
ax.fill_between(range(len(mean_int)),mean_int-sem_int,mean_int+sem_int,color='gray',alpha=0.5)
ax.set_xlabel('Contest number')
ax.set_ylabel('Mean fight Intensity\n(+/- SEM of iterations')
ax.set_title('Fight intensity decreases over repeated contests')

## Plot error
mean_err = np.mean(error_array,axis=(0,1))
sem_err = np.std(error_array,axis=(0,1)) / np.sqrt(params.iterations)
ax1.plot(mean_err,color='black')
ax1.fill_between(range(len(mean_err)),mean_err-sem_err,mean_err+sem_err,color='gray',alpha=0.5)
ax1.set_xlabel('Contest number')
ax1.set_ylabel('Mean error \n(+/- SEM of iterations')
ax1.set_title('Estimate error decreases over repeated contests')

#fig.savefig('./figures/figure2c_intensity.png',dpi=300)

if PLOT:
    plt.show()


"""Web controller for motorized screen"""
import asyncio
import logging

import redis
from quart import Quart, request, jsonify, render_template
from quart_minify.minify import Minify

from screen import MotorizedScreen

app = Quart(__name__)
Minify(app=app)
logging.basicConfig(format="[%(asctime)s] %(message)s", level=logging.INFO)

SCREEN = MotorizedScreen()

@app.route("/")
async def _landing():  # pylint: disable=unused-variable
    """Landing Page"""
    moving = SCREEN.running_task is not None
    if moving:
        status = "moving"
    else:
        remote_state = redis.Redis(host='localhost', port=6379,
                                   db=0).get("state")
        status = remote_state.decode("utf-8")
    template = await render_template("index.html", status=status)
    return template

@app.route("/control", methods=["POST"])
async def _control():  # pylint: disable=unused-variable
    """Control API endpoint"""
    request_json = await request.get_json()
    action = request_json["action"]
    if not action or action not in ["extend", "retract", "stop"]:
        return jsonify(success=False)
    # Screen in motion, and a new request is made, return an error
    if SCREEN.running_task and action in ["extend", "retract"]:
        error_message = "Screen in motion. Must stop or complete"
        logging.error(error_message)
        return jsonify(error=error_message, success=False)
    if action == "stop" and SCREEN.running_task is not None:
        logging.debug("Stop running action")
        SCREEN.running_task.cancel()
    actions = {
        "extend": SCREEN.extend,
        "retract": SCREEN.retract,
        "stop": SCREEN.stop
    }
    action_task = actions.get(action)
    task = asyncio.ensure_future(action_task())
    redis.Redis(host='localhost', port=6379, db=0).set("state", f"{action}ed")
    SCREEN.running_task = task
    return jsonify(success=True)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80)


from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import Aer, execute
from qiskit.extensions.quantum_initializer.initializer import Initialize
import matplotlib.pyplot as plt
import random
import math

'''Calculate QC'''
def w(x):
    count=0
    while x:
        count+=1
        x&=(x-1)
    return count
def QC(x):
    QC=12*x-6*w(int(x/2))-6*math.floor(math.log2(x/2))-8-2
    print("QC=", QC)
    return QC

'''Important settings'''
add_bit=3   # Users can customize add_bit.
s_number=add_bit+1
total_qubit_number=QC(add_bit)

'''random addition'''
rand_int_a = random.randint(0, 2**add_bit-1)
rand_addend_a = bin(rand_int_a)[2:].zfill(add_bit)
rand_int_b = random.randint(0, 2**add_bit-1)
rand_addend_b = bin(rand_int_b)[2:].zfill(add_bit)
print("a =",rand_addend_a ,"b =",rand_addend_b)
rand_int_sum=rand_int_a+rand_int_b
rand_sum = bin(rand_int_sum)[2:].zfill(add_bit+1)
print("real sum =",rand_sum )
circuit = QuantumCircuit(total_qubit_number,s_number)
print(add_bit, "bits quantum Ling adder")

'''initialize'''

strr=''
for i in range(add_bit):
    strr=strr+'00'+rand_addend_b[i]+rand_addend_a[i]
print(strr)
Initial_state='0'*(total_qubit_number-4*add_bit)+strr
print("Initial_state",Initial_state)
circuit.append(Initialize(Initial_state), range(total_qubit_number))

'''customize OR gate'''
qc = QuantumCircuit(3, name='OR')
qc.x(0)
qc.x(1)
qc.ccx(0,1,2)
qc.x(0)
qc.x(1)
qc.x(2)
OR_gate = qc.to_instruction()
'''Different Steps'''
def step1(circuit,a0,b0,acilla0,acilla1):
    circuit.ccx(a0,b0,acilla0)
    circuit.cx(a0, acilla1)
    circuit.cx(b0, acilla1)
    circuit.cx(acilla0, acilla1)
    circuit.cx(a0, b0)
def step1_uncomputation(circuit,a0,b0,acilla0,acilla1):
    circuit.cx(acilla0, acilla1)
    circuit.cx(a0, acilla1)
    circuit.ccx(a0,acilla1,acilla0)
def step2(circuit,p_i,g_i,p_ii,g_ii,acilla0,acilla1):
    circuit.ccx(p_i, p_ii, acilla0)
    circuit.append(OR_gate, [g_i, g_ii, acilla1])
def step2_last(circuit,g_i,g_ii,acilla1):
    circuit.append(OR_gate, [g_i, g_ii, acilla1])
def step2_uncomputation(circuit,p_i,g_i,p_ii,g_ii,acilla0,acilla1):
    circuit.append(OR_gate, [g_i, g_ii, acilla1])
    circuit.ccx(p_i, p_ii, acilla0)
def step2_last_uncomputation(circuit,g_i,g_ii,acilla1):
    circuit.append(OR_gate, [g_i, g_ii, acilla1])
###################################################################
def step3_G(circuit,gx,px,gy,py,acilla0, acilla1): #p0=0,p1=0; g0=gl0
    circuit.ccx(gy,px, acilla0)
    circuit.append(OR_gate, [gx,acilla0, acilla1])
def step3_P(circuit,px,py,acilla2): #p0=0,p1=0; g0=gl0
    circuit.ccx(py,px, acilla2)
#(gx, px) ◦ (gy, py) = (gx + px · gy, px · py) (10)
#Hi = Gi + Pi−1 · Gi−2, Hi=final G?
def propagation(circuit,gx,px,gy,py,ancilla_base): #gp
    ancilla1=ancilla_base+1
    ancilla2=ancilla_base+2
    p_next=px
    #g_next=gx|p_special&gy #00 0
    print("G")
    step3_G(circuit, gx, px, gy, py,ancilla_base, ancilla1)
    g_next=ancilla1
    ancilla_base=ancilla1+1
    #g_next = gx | gy & px  # 00 0
    if (py!=3) and (px!=3):
        print("P")
        step3_P(circuit,px,py,ancilla2)
        p_next=ancilla2
        ancilla_base=ancilla2+1
    return g_next,p_next,ancilla_base#p_next

""" Utility functions"""
pow2 = lambda x: (2 ** x)
log2 = lambda x: x.bit_length()

'''Brent Kung Tree'''
def BKTree(bitwidth):
    log2_bitwidth = log2(bitwidth - 1)  # Upsweep length for BK
    """ Creates the prefix tree.
    """
    bitwidth_i = bitwidth - 1  # Counting from 0
    matrix = [[None for i in range(bitwidth_i)] for i in range(bitwidth_i)]
    for idx_row in range(log2_bitwidth):
        shift_length = pow2(idx_row + 1)  # Shift lenght; Sequence in the loop 2, 4, 8, 16..
        starting_index = shift_length - 2  # Starting indexes in the matrix; Sequence in the loop 0 2 6 14 ...
        starting_value = pow2(
            idx_row) - 1  # Starting values in the matrix; Sequence in the loop 0 1 3 7 15(shift_length/2 - 1)
        # Mades the row values and indexes sequences
        values_seq = list(range(starting_value, bitwidth_i, shift_length))
        indexes_seq = list(range(starting_index, bitwidth_i, shift_length))
        if not indexes_seq:  # There is no other index
            continue
            # If the root of prefixtree wasnt saved yet. The index (bitwidth) is not power of two.
            # indexes_seq = [bitwidth_i - 1] # Save the right-most index {The index of index -> (-1 -1)}
        # Fill the row
        for index, val in zip(indexes_seq, values_seq):
            matrix[idx_row][index] = val
    """ Creates the inverse tree.
    """
    for idx_row in range(1, log2_bitwidth + 1):
        shift = 2 ** idx_row  # Sequence  2 4 8 16 32
        values_start = shift - 1  # Sequence 1 3 7 15
        indexes_start = (-4 + 3 * (2 ** idx_row)) // 2  # Sequence 1 4 10 22 46 etc.
        values = range(values_start, bitwidth_i, shift)
        indexes = range(indexes_start, bitwidth_i, shift)
        # Fill the row
        for index, val in zip(indexes, values):
            matrix[-idx_row][
                index] = val  # Do not manipulate with idx_row, else it will not be usable for Lander Sklansky and Han Carlson adders
    return matrix

def Brent_Kung(circuit,g_location, p_location,ancilla_base):
    print("BK_Begin")
    print("length", len(g_location))
    bit_num = len(g_location)
    # establish bit_num BK tree, do propagation and generation
    BK_Matrix = BKTree(bit_num)
    size = bit_num - 1
    print("BKtest","g_location", g_location, "p_location", p_location)
    for i in range(size):
        for j in range(size):
            if BK_Matrix[i][j] != None:  # j小了一个1
                index_now = j + 1
                if BK_Matrix[i][j]==0:
                    p_location_x=0
                else:
                    p_location_x = p_location[BK_Matrix[i][j]-1]
                #列表p左移，G3,P2
                print("g_"+str(index_now),g_location[index_now],
                      "p_"+str(index_now),p_location[index_now],
                      "g_"+str(BK_Matrix[i][j]),g_location[BK_Matrix[i][j]],
                      "p_"+str(BK_Matrix[i][j]),p_location_x)
                g_location[index_now], p_location[index_now],ancilla_base= propagation(circuit,g_location[index_now],
                                                                       p_location[index_now],g_location[BK_Matrix[i][j]],
                                                                       p_location[BK_Matrix[i][j]],ancilla_base)
    print(BK_Matrix)
    print("BK_End")
    return ancilla_base

def step3(circuit, p_location, g_location,H_location,ancilla_base):
    print("Ling_Begin")
    print("length", len(g_location))
    bit_num=len(g_location)
    #establish Ling-based Brent Kung Propagation Tree to get H
    G_number = [0 for i in range(add_bit)]
    P_number = [0 for i in range(add_bit)]
    index_BK_1=[i for i in range(0,bit_num,2)]
    index_BK_2 = [i for i in range(1, bit_num, 2)]
    g_BK_1=[g_location[i] for i in index_BK_1]
    p_BK_1 = [p_location[i] for i in index_BK_1]
    g_BK_2=[g_location[i] for i in index_BK_2]
    p_BK_2 = [p_location[i] for i in index_BK_2]
    print("g_location=",g_location,"p_location=",p_location)
    print("g_BK_1",g_BK_1,"p_BK_1",p_BK_1)
    print("g_BK_2",g_BK_2,"p_BK_2",p_BK_2)
    print("index_BK_1",index_BK_1,"index_BK_2",index_BK_2)
    #BK trees=>H
    ancilla_base=Brent_Kung(circuit,g_BK_1, p_BK_1,ancilla_base)
    Brent_Kung(circuit,g_BK_2, p_BK_2,ancilla_base)
    print("After BK")
    print("g_BK_1",g_BK_1,"p_BK_1",p_BK_1)
    print("g_BK_2",g_BK_2,"p_BK_2",p_BK_2)
    for i in range(len(index_BK_1)):
        G_number[index_BK_1[i]]=g_BK_1[i]
        #print("G_"+str(index_BK_1[i]),g_BK_1[i])
        P_number[index_BK_1[i]]=p_BK_1[i]
        #print("P_"+str(index_BK_1[i]),p_BK_1[i])
    for i in range(len(index_BK_2)):
        G_number[index_BK_2[i]]=g_BK_2[i]
        #print("G_"+str(index_BK_2[i]),g_BK_2[i])
        P_number[index_BK_2[i]]=p_BK_2[i]
        #print("P_"+str(index_BK_2[i]),p_BK_2[i])
    print(G_number,P_number)
    # H_BK_1=Brent_Kung(g_BK_1,p_BK_1)
    # H_BK_2=Brent_Kung(g_BK_2, p_BK_2)
    for i in range(bit_num):
        H_location[i] = G_number[i]
        #H_number[i] = G_number[i]|(P_number[i-1]&G_number[i-2])
    print("G0", G_number[0],"g0",g_location[0])
    H_location[0] = g_location[0]  # H0 = g0
    print("Ling_End")
    print("H",H_location)
    return H_location,G_number,P_number
###################################################################
def step4(H_i, d_ii, p_i):
    # circuit.cx(d_ii, p_i)
    # circuit.cswap(H_i, d_ii, p_i)
    circuit.ccx(H_i, p_i, d_ii)
def step4_last(H_i,p_i,acilla0):
    circuit.ccx(H_i,p_i, acilla0)
'''Establish the proposed adder'''
#Step 1
for index in range(add_bit):
    step1(circuit, 4*index, 4*index+1, 4*index+2, 4*index+3) #d=4*index+1,g=4*index+2,p=4*index+3
    print("Step 1",4*index, 4*index+1, 4*index+2, 4*index+3)
circuit.barrier()

#Step 2
p_location=[0 for i in range(add_bit)]
g_location=[0 for i in range(add_bit)]
p_location[0]=3
p_location[1]=3
g_location[0]=2

Step2_ancilla_base=4*add_bit
ancilla_base=Step2_ancilla_base
odd_count=add_bit-1
even_count=add_bit-1
if (add_bit-1)%2==0:
    odd_count=odd_count-1
else:
    even_count=even_count-1
for index in range(0, even_count, 2):
    print("Step2_even", index)
    step2(circuit, 4 * index + 3, 4 * index + 2, 4 * (index + 1) + 3, 4 * (index + 1) + 2, ancilla_base,ancilla_base + 1)
    p_location[index+2]=ancilla_base
    g_location[index+1] = ancilla_base+1
    if index==0:
        H2=ancilla_base + 1
    ancilla_base=ancilla_base+2
if even_count!=add_bit-1:
    print("Step2_last", even_count)
    index=even_count
    step2_last(circuit, 4 * index + 2, 4 * (index + 1) + 2, ancilla_base)
    g_location[index+1] = ancilla_base
    ancilla_base = ancilla_base + 1
#circuit.barrier()
for index in range(1, odd_count , 2):
    print("Step2_odd", index)
    step2(circuit, 4 * index + 3, 4 * index + 2, 4 * (index + 1) + 3, 4 * (index + 1) + 2, ancilla_base,ancilla_base + 1)
    p_location[index+2]=ancilla_base
    g_location[index+1] = ancilla_base+1
    ancilla_base=ancilla_base+2
if odd_count != add_bit-1:
    print("Step2_last", odd_count)
    index = odd_count
    step2_last(circuit, 4 * index + 2, 4 * (index + 1) + 2, ancilla_base)
    g_location[index+1] = ancilla_base
    ancilla_base = ancilla_base + 1
print("ancilla_base",ancilla_base)
print("p",p_location)
print("g",g_location)
circuit.barrier()
# GL0=g0
# PL1=8
# GL1=9
# step2_last(circuit,g2,g3,20)
# GL3=20

#Step 3
#G0=g0
#P0=0,P1=0,前两个操作不做
#输入所有p，g的位置
H_location=[0 for i in range(add_bit)]
step3(circuit, p_location, g_location,H_location,ancilla_base)
#H_location=step3(circuit, p_location, g_location,H_location)
#[2,17,22,24]
circuit.barrier()
#Step 4
# step4(H0,d1,p0), step4(H1,d2,p1)
H1=2
index=1
#S0
step4(H1,4*index+1,4*(index-1)+3) #Hi-1,di,pi-1
index=2
step4(H2,4*index+1,4*(index-1)+3)
'''Hi位置怎么定'''
for index in range(3,add_bit):
    step4(H_location[index-1],4*index+1,4*(index-1)+3) #d=4*index+1,g=4*index+2,p=4*index+3
    print("H_location",H_location[index])
    print("Step 4",4*index+1,4*(index-1)+3)
index=add_bit-1
#最后两位，Hn,Sn+1 16,12,
step4_last(H_location[add_bit-1],4*index+3,total_qubit_number-1)#last qubit
circuit.barrier()

print("Uncomputation")
#Step 2-Uncomputation
if odd_count != add_bit-1:
    ancilla_base = ancilla_base - 1
    print("Step2_last", odd_count)
    index = odd_count
    step2_last_uncomputation(circuit, 4 * index + 2, 4 * (index + 1) + 2, ancilla_base)

for index in range(odd_count-2,-1 , -2):
    print("Step2_odd", index)
    ancilla_base = ancilla_base - 2
    step2_uncomputation(circuit, 4 * index + 3, 4 * index + 2, 4 * (index + 1) + 3, 4 * (index + 1) + 2, ancilla_base,ancilla_base + 1)
if even_count!=add_bit-1:
    print("Step2_last", even_count)
    ancilla_base = ancilla_base - 1
    index=even_count
    step2_last_uncomputation(circuit, 4 * index + 2, 4 * (index + 1) + 2, ancilla_base)
for index in range(even_count-2, -2, -2):
    print("Step2_even", index)
    ancilla_base=ancilla_base-2
    step2_uncomputation(circuit, 4 * index + 3, 4 * index + 2, 4 * (index + 1) + 3, 4 * (index + 1) + 2, ancilla_base,ancilla_base + 1)
circuit.barrier()
#################################################################
#Step 1-Uncomputation
for index in range(add_bit-1,-1,-1):
    step1_uncomputation(circuit, 4*index, 4*index+1, 4*index+2, 4*index+3) #d=4*index+1,g=4*index+2,p=4*index+3
    print("Step 1",4*index, 4*index+1, 4*index+2, 4*index+3)
circuit.barrier()

'''Simulation'''
print("Simulation")
# measure_list=[1,5,11,17,25] #S0,1,2,3,4
measure_list=[1+i*4 for i in range(add_bit)]
measure_list.append(total_qubit_number-1)
circuit.measure(measure_list, range(add_bit+1))
print("Finish setting")
# Select the QasmSimulator from the Aer provider
simulator = Aer.get_backend('qasm_simulator')
# Execute
print("Execute")
result = execute(circuit, simulator, shots=3, memory=True).result()
print("memory")
memory = result.get_memory(circuit)
print(memory)
print("real sum =",rand_sum )
flag=0
S_number=memory[0]
for i in range(add_bit+1):
    if S_number[i]!=str(rand_sum[i]):
        flag=flag+1
        print("i",i,S_number[i],int(rand_sum[i]))
        # Si = Hi−1 · di + Hi−1 · (di ⊕ pi−1) , if 0 < i < n
        # Si = (Hi−1 * pi−1) ⊕ di
if flag==0:
    print("Corret!")
else:
    print("Wrong!",flag)

'''Draw Diagram'''
#print(circuit.draw(output='latex_source'))
# circuit.draw(output='mpl')
# plt.show()


#!/usr/bin/env python

# Returns array of 26 morse code letters from the file
def smorse_ray(fileName):
    with open(fileName) as f:
        data = f.readline().split()
    return data

# Returns the string passed converted into morse code with no spaces
def smorse(strToMorse):
    data = smorse_ray('morse.txt')
    morsed = ""
    for letter in strToMorse:
        morsed += data[ord(letter) - 97]
    return morsed

# Returns a list of each line in the file smorsed
def file_smorse(fileName):
    with open(fileName) as f:
        data = f.read().splitlines()
        morsed = []
        for line in data:
            morsed.append(smorse(line))
    return morsed

# Returns a dictionary with each unique sequence as a key and the value being number of occurrences
def number_of_occurrences(dataList):
    morseDict = {}
    for item in dataList:
        if item not in morseDict:
            morseDict[item] = 1
        else:
            morseDict[item] += 1
    return morseDict

# Returns the word which translates to have fifteen sequential dashes
def sequential_dashes(dataList):
    lineCount = -1
    lineNumber = 0
    fifteenDashes = "---------------"
    for item in dataList:
        lineCount += 1
        if item.count(fifteenDashes) == 1:
            lineNumber = lineCount
    with open('enable1.txt') as f:
        data = f.read().splitlines()
    return data[lineNumber]

# Returns the words in a file of a specified length that have the same number of . and - when translated
def find_balanced(fileName, length):
    blackjack = []
    balanced = []
    with open(fileName) as f:
        data = f.read().splitlines()
        for line in data:
            if len(line) == length:
                blackjack.append(line)
    for word in blackjack:
        smorsed = smorse(word)
        if smorsed.count(".") == smorsed.count("-"):
            balanced.append(word)
    return balanced

'''
# Bonus 1: finding the only sequence that is the code for 13 different words
enableDict = number_of_occurrences(file_smorse('enable1.txt'))

for strMorse, occ in enableDict.items():
    if occ == 13:
        print(strMorse)
'''

'''
# Bonus 2: finding the only word that contains 15 sequential dashes when translated
print(sequential_dashes(file_smorse('enable1.txt')))
'''

# Bonus 3: finding the two words that are 21 characters long and contain the same number of . and - when translated
print(find_balanced('enable1.txt', 21))


import numpy as np

def sigmoid(z):
    return 1/(1+np.exp(z))

def feature_scaling(x):
    maxs = np.zeros((x.shape[1]))
    for i in range(x.shape[0]):
        for j in range(x.shape[1]):
            if x[i, j] > maxs[j]:
                maxs[j] = x[i, j]
    for i in range(x.shape[1]):
        x[:, i] = x[:, i]/maxs[i]
    return x

def probability(x, theta):
    return sigmoid(np.einsum('j,jk', x, theta))

def cost1(z):
    sol = np.zeros(z.shape)
    for i in range(sol.shape[0]):
        for j in range(sol.shape[1]):
            if z[i, j] >= 1:
                sol[i, j] = 0
            else:
                sol[i, j] = -1*np.log(1/(1+np.exp(-1*z[i, j])))
    return sol

def cost0(z):
    sol = np.zeros(z.shape)
    for i in range(sol.shape[0]):
        for j in range(sol.shape[1]):
            if z[i, j] <= -1:
                sol[i, j] = 0
            else:
                sol[i, j] = -1*np.log(1-(1/(1+np.exp(-1*z[i, j]))))
    return sol

def similarity(x1, x2):
    f = np.exp(-1*(np.linalg.norm(x1-x2)**2)/2*1**2)
    return f

def svm(self):
    x=feature_scaling(self.x)
    f = np.ones((self.x.shape[0],self.x.shape[0]+1), 'double')
    theta = np.ones((self.x.shape[0],self.x.shape[0]+1), 'double')
    y = self.y
    c = 1
    cont=0
    for i in range(f.shape[0]):
        for j in range(f.shape[1]-1):
            f[i, j+1] = similarity(x[i, :], x[j, :])

    j = c*np.sum((np.einsum('ji,jk', y, cost1(np.einsum('ij,kj', f, theta))) + np.einsum('ji,jk', (1-y), cost0(np.einsum('ij,kj',f,theta))))) + (1/2)*np.sum(np.einsum('ji,jk', theta, theta)) - np.sum(np.einsum('j,j', np.transpose(theta[:, 0]), theta[:, 0]))
    return theta


'''
[문제]
세 정수 A, B, C가 주어진다. 이때, 두 번째로 큰 정수를 출력하는 프로그램을 작성하시오.

[입력]
첫째 줄에 세 정수 A, B, C가 공백으로 구분되어 주어진다. (1 ≤ A, B, C ≤ 100)

[출력]
두 번째로 큰 정수를 출력한다.
'''

# 데이터 입력
three_num = input('세 수를 입력하세요 :')
three_num = three_num.split(' ')
x = float(three_num[0])
y = float(three_num[1])
z = float(three_num[2])

# 조건문 & 출력
if (x >= y) and (x >= z):
    if (y >= z):
        print(y)
    else:
        print(z)

elif (y >= x) and (y >= z):
    if (x >= z):
        print(x)
    else:
        print(z)

else:
    if (x >= y):
        print(x)
    if (y >= x):
        print(y)


from error_generator.api.error_generator_api import Error_Generator
from error_generator.strategies.switch_value.random_active_domain.random_active_domain import Random_Active_Domain
from error_generator.strategies.utilities.list_selected import List_selected
from error_generator.strategies.utilities.input_output import Read_Write

class Test_Random_Active_Domain(object):
    def __init__(self, name="test_random_active_domain"):
        self.name = name

# ------------------------------- this is test part ----------------------------------

dataset,dataframe = Read_Write.read_csv_dataset("../datasets/test.csv")

mymethod=Random_Active_Domain()

myselector=List_selected()

mygen=Error_Generator()
new_dataset=mygen.error_generator(method_gen=mymethod,selector=myselector,percentage=20,dataset=dataset,mute_column=[])

# #create instance of test
inst_test=Test_Random_Active_Domain()

#write to output
Read_Write.write_csv_dataset("../outputs/{}.csv".format(inst_test.name), new_dataset)


#The primary core of the [WORKIN' TITLE]. The core game will be run through here.
#Created through the collaboration of
#Tiras Gimpel
#Kit Ho (Leo) Li
#Bryan Rainbow
#Jennie Wu
#Xavier El Chantiry

from controllers.mazeGame import MazeGame

if __name__ == "__main__":
    #This creates the game instance and runs it.
    maze_game = MazeGame()
    maze_game.play_maze()


import logging
from typing import Any, Tuple

from linotp.lib.policy.evaluate import PolicyEvaluator
from linotp.lib.policy.util import get_policies
from linotp.lib.user import User

LOG = logging.getLogger(__name__)

def search_policy(param, only_active=True):
    """
    Function to retrieve the list of policies.

    attributes:

    - name:   (optional) will only return the policy with the name
    - user:   (optional) will only return the policies for this user
    - realm:  (optional) will only return the policies of this realm
    - scope:  (optional) will only return the policies within this scope
    - action: (optional) will only return the policies with this action
         The action can also be something like "otppin" and will
         return policies containing "otppin = 2"

    :return: a dictionary with the policies. The name of the policy being
             the key
    """

    #
    # filter the policies with the new engine

    policy_elve = PolicyEvaluator(get_policies())

    #
    # install the filters

    policy_elve.set_filters(params=param)

    #
    # add the special filter for activ or inactive policies

    if only_active:
        policy_elve.filter_for_active(state=True)

    #
    # finally we apply the filter

    new_pols = policy_elve.evaluate()

    return new_pols

def getPolicy(param, only_active=True):
    """
    Function to retrieve the list of policies.

    attributes:

    - name:   (optional) will only return the policy with the name
    - user:   (optional) will only return the policies for this user
    - realm:  (optional) will only return the policies of this realm
    - scope:  (optional) will only return the policies within this scope
    - action: (optional) will only return the policies with this action
         The action can also be something like "otppin" and will
         return policies containing "otppin = 2"

    :return: a dictionary with the policies. The name of the policy being
             the key
    """

    #
    # filter the policies with the new engine

    policy_elve = PolicyEvaluator(get_policies())

    #
    # install the filters

    policy_elve.set_filters(params=param)

    #
    # add the special filter for activ or inactive policies

    if only_active:
        policy_elve.filter_for_active(state=True)

    if ("user" in param and param["user"] is not None) or (
        "action" in param and param["action"] is not None
    ):
        policy_elve.filter_for_time()

    #
    # finally we apply the filter

    new_pols = policy_elve.evaluate()

    return new_pols

def is_authorized(admin_user: User, scope: str, action: str) -> bool:
    """
    This internally used function checks whether the currently authenticated
    administrative user is authorized to perform an action in the given scope.

    This method can only be used for administrative users and therefore does
    not take REALMS into account!

    :param admin_user: the admin user to check
    :param scope: policy scope to use (system, audit, monitoring, reporting, tools)
    :param action: action to check in the scope (e.g. read or write)

    returns:
        authenticated : `boolean`
            boolean value whether user is authorized
    """

    policy_eval = PolicyEvaluator(get_policies())

    LOG.debug("Evaluating policies for the user: %r", admin_user)

    scope_policies = policy_eval.has_policy(
        {
            "scope": scope,
            "active": True,
        }
    )

    # if no policy was defined at all -> the access is not restricted
    if len(scope_policies) == 0:
        LOG.info(
            "No active policies in scope %s found - access to this scope is"
            " not restricted!",
            scope,
        )
        return True

    # if any policy is defined, check if the admin_user is allowed to execute
    # the given action by an active policy

    filters = {
        "user": admin_user,
        "scope": scope,
        "action": action,
    }
    policies = policy_eval.set_filters(filters).evaluate(scope_policies)

    LOG.debug("Found the following policies: %r", policies)

    return len(policies) > 0

def get_client_policy(
    client,
    scope=None,
    action=None,
    realm=None,
    user=None,
    find_resolver=True,
    userObj=None,
    active_only=True,
):
    """
    This function returns the dictionary of policies for the given client.

    1. First it searches for all policies matching (scope, action, realm) and
    checks, whether the given client is contained in the policy field client.
    If no policy for the given client is found it takes the policy without
    a client

    2. Then it strips down the returnable policies to those, that only contain
    the username - UNLESS - none of the above policies contains a username

    3. then we try to find resolvers in the username (OPTIONAL)

    4. if nothing matched so far, we try the extended policy check

    """

    policy_eval = PolicyEvaluator(get_policies())

    if realm:
        policy_eval.filter_for_realm(realm)

    if scope:
        policy_eval.filter_for_scope(scope)

    if action:
        policy_eval.filter_for_action(action)

    if client:
        policy_eval.filter_for_client(client)

    policy_eval.filter_for_time()

    if active_only:
        policy_eval.filter_for_active(state=True)

    if userObj:
        policy_eval.filter_for_user(userObj)
    elif user:
        policy_eval.filter_for_user(user)

    policies = policy_eval.evaluate()

    return policies

def has_client_policy(
    client,
    scope=None,
    action=None,
    realm=None,
    user=None,
    find_resolver=True,
    userObj=None,
    active_only=True,
):
    """
    This function returns the dictionary of policies for the given client.

    1. First it searches for all policies matching (scope, action, realm) and
    checks, whether the given client is contained in the policy field client.
    If no policy for the given client is found it takes the policy without
    a client

    2. Then it strips down the returnable policies to those, that only contain
    the username - UNLESS - none of the above policies contains a username

    3. then we try to find resolvers in the username (OPTIONAL)

    4. if nothing matched so far, we try the extended policy check

    The difference to the get_policy is, that it restores the already installed
    filters for an existance check

    """

    policy_eval = PolicyEvaluator(get_policies())

    param = {}

    if realm:
        param["realm"] = realm

    if scope:
        param["scope"] = scope

    if action:
        param["action"] = action

    if active_only:
        policy_eval.filter_for_active(state=True)

    if client:
        param["client"] = client

    if userObj:
        param["user"] = userObj
    elif user:
        param["user"] = user

    policies = policy_eval.has_policy(param)

    return policies

# eof


R = list(map(int,input().strip().split()))
n, D, K= R[0],R[1],R[2]
a = []
M = 0
for i in range(n):
    R = list(map(int,input().strip().split()))
    ts, id = R[0], R[1]
    M = max(M, id)
    a.append((ts,id))
a.sort(key = lambda x : x[0])
s = [[0] for i in range(M+1)]
for each in a:
    s[each[1]].append(each[0])
for times in range(1,M+1):
    lis = s[times]
    for i in range(1,len(lis)-K+1):
        if lis[i+K-1]<lis[i]+D:
            print(times)
            break
"""
笑死
这不能怨我了吧
纯纯python慢
只有67分
明显数据加强了
思路是对的
"""


# __Author__ __Lencof__
# Shutdown Modified №3.py
# A new Shutdown is created this code turns off the computer and after shutdown creates a file with a note on the desktop

import os
os.system('shutdown -s -t 0')

README = '''
Shutdown done
'''

# Open for 'w'riting
f = open('README.txt', 'w')
# Write text to file
f.write(README)
f.close()

# If no mode is specified
# 'r'ead mode is assumed by default
f = open('README.txt')
while True: # use True
  line = f.readline()
  # Zero length indicates EOF
  if len(line) == 0:
    break
  # The 'line' already has a newline
  # at the end of each line
  # ssince it is reading from a file.
  print(line, end='')
f.close()


"""
Given an array of intervals where intervals[i] = [start, end],
merge all overlapping intervals, and return an array of the non-overlapping intervals
that cover all the intervals in the input.
"""

from collections import deque

def merge(intervals: list[list[int]]) -> list[list[int]]:
    intervals = sorted(intervals)
    merged = deque()
    for start, end in intervals:
        flag = False
        for i, (s, e) in enumerate(merged):
            if (s <= start <= e) or (s <= end <= e):
                merged[i] = [min(start, s), max(end, e)]
                flag = True
                break
        if not flag:
            merged.append([start, end])
    return merged

if __name__ == '__main__':
    test1 = [[1, 3], [2, 6], [8, 10], [15, 18], [2, 4]]
    test2 = [[1, 4], [4, 5]]
    test3 = [[1, 4], [0, 5]]
    print(merge(test1))


"""chat_settings

Revision ID: 20190314182214
Revises: 20190314175025
Create Date: 2019-03-14 18:22:14.635279

"""

import sqlalchemy as sa
from alembic import op
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm.session import Session

# revision identifiers, used by Alembic.
revision = "20190314182214"
down_revision = "20190314175025"
branch_labels = None
depends_on = None

Base = declarative_base()

class Chat(Base):
    __tablename__ = "chats"

    id = sa.Column(sa.BigInteger, primary_key=True, autoincrement=False)
    default_currency = sa.Column(sa.Text, default="USD", nullable=False)
    default_currency_position = sa.Column(sa.Boolean, default=True, nullable=False)
    created_at = sa.Column(sa.TIMESTAMP, server_default=sa.func.now(), nullable=False)
    modified_at = sa.Column(
        sa.TIMESTAMP,
        server_default=sa.func.now(),
        onupdate=sa.func.now(),
        nullable=False,
    )

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column("chats", sa.Column("default_currency", sa.Text(), nullable=True))
    op.add_column(
        "chats", sa.Column("default_currency_position", sa.Boolean(), nullable=True)
    )
    # ### end Alembic commands ###

    session = Session(bind=op.get_bind())
    session.query(Chat).update(
        {
            "default_currency": "USD",
            "default_currency_position": True,
            "modified_at": Chat.modified_at,
        }
    )

    op.alter_column("chats", "default_currency", nullable=False)
    op.alter_column("chats", "default_currency_position", nullable=False)

def downgrade():
    pass


#! /usr/bin/env python
"""This module simply adds miscellaneous code that the main modules can use."""
from __future__ import absolute_import
import logging

import requests

from mozci.utils.authentication import get_credentials

LOG = logging.getLogger('mozci')

def _public_url(url):
    """
    If we run the script outside the Release Engineering infrastructure
    we need to use the public interface rather than the internal one.
    """
    replace_urls = [
        ("http://pvtbuilds.pvt.build",
         "https://pvtbuilds"),
        ("http://tooltool.pvt.build.mozilla.org/build",
         "https://secure.pub.build.mozilla.org/tooltool/pvt/build")
    ]
    for from_, to_ in replace_urls:
        if url.startswith(from_):
            new_url = url.replace(from_, to_)
            LOG.debug("Replacing url %s ->\n %s" % (url, new_url))
            return new_url
    return url

def _all_urls_reachable(urls, auth=None):
    """Determine if the URLs are reachable."""
    for url in urls:
        url_tested = _public_url(url)
        LOG.debug("We are going to test if we can reach %s" % url_tested)
        req = requests.head(url_tested, auth=get_credentials())
        if not req.ok:
            LOG.warning("We can't reach %s for this reason %s" %
                        (url, req.reason))
            return False

    return True


def data(read_data,file):

    if read_data is True:

        #Reading system information
        from scripts.readData import data_file
        print('Reading data...')
        data_file('datasystem/'+str(file)+'.xlsx')
        # delete temporal files

def data_consistency(stages, seriesBack, seriesForw):

    import pickle
    from utils.paramvalidation import paramlimits

    # Load the dictionary back from the pickle file
    dict_data = pickle.load(open("savedata/data_save.p", "rb"))
    # No of maximum number of stages
    noStages = len(dict_data['horizon'])

    # validating input parameters
    paramlimits(stages, seriesBack, seriesForw, noStages)

def parameters(param_calculation,sensDem,stages,eps_area,eps_all):

    import pickle

    # Load the dictionary back from the pickle file
    dict_data = pickle.load(open("savedata/data_save.p", "rb"))

    # calculation options SI or NO
    if param_calculation is True:
        print('Parameters calculation ...')

        # Creating fixed input files '''
        from utils.input_data import inputdata
        inputdata(dict_data, sensDem)
        from utils.input_hydro import inputhydro
        inputhydro(dict_data)

        from utils.input_wind import inputwindSet, inputInflowWind
        inputwindSet(dict_data, stages, 1, 0)
        inputInflowWind(dict_data, stages, eps_area, eps_all)

        from utils.input_others import inputbatteries, inputlines
        inputbatteries(dict_data, stages)
        inputlines(dict_data, stages)

def grid(param_opf, stages):

    # opf restrictions
    if param_opf is True:
        print('Parameters opf ...')

        from utils.opf_data import ybus
        ybus(stages)

def wmodel2(wind_model2, stages, seriesBack):

    import pickle

    # Load the dictionary back from the pickle file
    dict_data = pickle.load(open("savedata/data_save.p", "rb"))

    # Including wind power plants with model 2
    if wind_model2 is True:
        print('Model of wind power plants with losses ...')

        from utils.readWind import historical10m, format10m
        historical10m()
        format10m()

        from utils.input_wind import inputwindSet #, inputInflowWind, energyRealWind
        inputwindSet(dict_data, stages, 0, 1)
        # factores = energyRealWind(dict_data, seriesBack, stages)

def optimization(stages, seriesBack, eps_risk, commit, parallel, param_opf, max_iter, results,
                 policy, simulation, seriesForw, extra_stages, curves, gates, params):

    import pickle
    from scripts import forward
    from scripts import backward
    from scripts import optimality
    from utils import classes
    import sys, json
    import redis
    r = redis.StrictRedis(host='localhost', port=6379, db=0)

    # Load the dictionary back from the pickle file
    dict_data = pickle.load(open("savedata/data_save.p", "rb"))

    # dictionaries
    batteries = dict_data['batteries']
    hydroPlants = dict_data['hydroPlants']
    dict_batt = pickle.load(open("savedata/batt_save.p", "rb"))

    # Iteration inf _ improve the states under evaluation
    sol_vol = [[] for x in range(stages+1)] # Hydro iteration
    sol_lvl = [[] for x in range(stages+1)] # Batteries iteration
    sol_vol[0].append(dict_data['volData'][0])
    sol_lvl[0].append([dict_data['battData'][0][x]*dict_batt["b_storage"][x][0][0] for x in range(len(batteries))])

    iteration = 0 # Counter for number of iterations
    confidence = 0 # stop criteria

    # Save operational cost by iteration
    operative_cost = [[], []]

    # define: parameter classes
    # deterministic / stochastic analysis
    stochastic = True
    if seriesBack == 1: stochastic = False # Deterministic

    dataParamB = classes.param_B(stages, seriesBack, stochastic, eps_risk, commit, parallel, param_opf, gates)
    dataParamF = classes.param_F(stages, seriesForw, max_iter, results, param_opf, gates)

    # export options SI or NO
    if results is True:
        from utils.saveresults import printresults

    #==============================================================================
    # loop iterations
    if policy is True:

        while not iteration >= max_iter and not confidence >= 2:

            # save the FCF - backward steps
            fcf_backward = [[] for x in range(stages+1)]
            fcf_backward[stages]=[[[0]*len(hydroPlants), [0]*len(batteries), 0]]

            # Backward_Risk6_par to parallel simulation
            fcf_backward = backward.data(dataParamB, fcf_backward, sol_vol, iteration, sol_lvl)

            data = {}
            data['state'] = 'loopIterations'
            data['message'] = 'Iterando backward ' + str(iteration)
            data['phase'] = 3
            data['percent'] = ((iteration + 1) / max_iter) * 50
            json_data = json.dumps(data)
            r.publish('room/' +str(params['id']), json_data)
            percent = str(data['percent']) + '% Backward'
            print(percent)

            # Forward stage - Pyomo module
            (sol_vol, sol_lvl, sol_costs, sol_scn) = forward.data(confidence, fcf_backward,
            dataParamF, iteration, sol_vol, sol_lvl)

            data = {}
            data['state'] = 'loopIterations'
            data['message'] = 'Iterando Forward ' + str(iteration)
            data['phase'] = 3
            data['percent'] = ((iteration + 1) / max_iter) * 100
            percent = str(data['percent']) + '% Forward'
            print(percent)

            json_data = json.dumps(data)
            r.publish('room/' +str(params['id']), json_data)

            # confidence
            confd, op_cost, op_inf = optimality.data(sol_costs, seriesForw)
            confidence += confd
            iteration += 1

            # Saver results
            operative_cost[0].append(op_cost), operative_cost[1].append(op_inf)

            if iteration == max_iter or confidence == 2:
                datafcf = {"fcf_backward":fcf_backward, "sol_vol":sol_vol, "sol_lvl":sol_lvl, 'sol_scn':sol_scn}
                pickle.dump(datafcf, open("savedata/fcfdata.p", "wb"))

                # generate report
                if results is True:
                    print('Writing results ...')
                    # results files and reports
                    printresults(seriesForw, (stages-extra_stages), sol_scn, curves)

    elif policy is False and simulation is True:

        # stages to be simulate
        dict_fcf = pickle.load(open("savedata/fcfdata.p", "rb"))
        fcf_backward = dict_fcf['fcf_backward']

        sol_vol = dict_fcf['sol_vol']
        sol_lvl = dict_fcf['sol_lvl']
        iteration = 0
        confidence = 1

        # Forward stage - Pyomo module
        (sol_vol, sol_lvl, sol_costs, sol_scn) = forward.data(confidence, fcf_backward,
        dataParamF, iteration, sol_vol, sol_lvl)

        # Saver results
        confidence, op_cost, op_inf = optimality.data(sol_costs,seriesForw)
        operative_cost[0].append(op_cost), operative_cost[1].append(op_inf)

        # generate report
        if results is True:
            print('Writing results ...')
            # results files and reports
            printresults(seriesForw, (stages-extra_stages), sol_scn, curves)

    elif policy is False and simulation is False:

        if results is True:

            # recover results
            dict_fcf = pickle.load(open("savedata/fcfdata.p", "rb"))
            sol_scn = dict_fcf['sol_scn']

            print('Writing results ...')
            # results files and reports
            printresults(seriesForw, (stages-extra_stages), sol_scn, curves)


import atexit
import io
import sys

def getParent(x):
    return (x - 1) // 2

def leftChild(x):
    return (2 * x + 1) if (2 * x + 1) < curr_size else -1

def rightChild(x):
    return (2 * x + 2) if (2 * x + 2) < curr_size else -1

def heapify():
    curr_ind = curr_size - 1
    while getParent(curr_ind) != -1 and heap[getParent(curr_ind)] > heap[curr_ind]:
        heap[curr_ind], heap[getParent(curr_ind)] = heap[getParent(curr_ind)], heap[curr_ind]
        curr_ind = getParent(curr_ind)
    return

def heapifyDown(x):
    if x >= curr_size:
        return
    if getParent(x) != -1 and heap[x] < heap[getParent(x)]:
        heap[x], heap[getParent(x)] = heap[getParent(x)], heap[x]
        heapifyDown(getParent(x))
    if leftChild(x)==-1 or (leftChild(x)!=-1 and heap[x]<heap[leftChild(x)]):
        if rightChild(x)==-1 or (rightChild(x)!=-1 and heap[x]<heap[rightChild(x)]):
            return
    if rightChild(x)==-1:
        heap[x], heap[leftChild(x)] = heap[leftChild(x)], heap[x]
        heapifyDown(leftChild(x))
    elif leftChild(x) == -1:
        heap[x], heap[rightChild(x)] = heap[rightChild(x)], heap[x]
        heapifyDown(rightChild(x))
    else:
        if heap[rightChild(x)]<heap[leftChild(x)]:
            heap[x], heap[rightChild(x)] = heap[rightChild(x)], heap[x]
            heapifyDown(rightChild(x))
        else:
            heap[x], heap[leftChild(x)] = heap[leftChild(x)], heap[x]
            heapifyDown(leftChild(x))
    return

def insertKey (x):
    global curr_size
    heap[curr_size] = x
    curr_size += 1
    heapify()

def deleteKey (x):
    global curr_size
    if x >= curr_size:
        return
    heap[x] = heap[curr_size - 1]
    heap[curr_size - 1] = 0
    curr_size -= 1
    heapifyDown(x)

def extractMin ():
    if curr_size == 0:
        return -1
    val = heap[0]
    deleteKey(0)
    return val

_INPUT_LINES = sys.stdin.read().splitlines()
input = iter(_INPUT_LINES).__next__
_OUTPUT_BUFFER = io.StringIO()
sys.stdout = _OUTPUT_BUFFER

@atexit.register

def write():
    sys.__stdout__.write(_OUTPUT_BUFFER.getvalue())

heap = []  # our heap to be used
curr_size = 0  # current size of heap

if __name__ == '__main__':
    test_cases = int(input('Enter the numbr of test cases:- '))
    for cases in range(test_cases):
        n = int(input('Enter the size of the heap:- '))
        a = list(map(int, input('Enter the elements of the heap:- ').strip().split()))
        curr_size = 0
        heap = [0 for i in range(n)]
        i = 0
        while i < len(a):
            if a[i] == 1:
                insertKey(a[i + 1])
                i += 1
            elif a[i] == 2:
                deleteKey(a[i + 1])
                i += 1
            else:
                print(extractMin (), end=" ")
            i += 1
        print()


import argparse

import matplotlib as mpl
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt

import numpy as np
import pandas as pd
from pandas import ExcelWriter

import re
import time

from scipy import integrate
from scipy.stats import norm, gaussian_kde

from config import config
import config as constants

mpl.rcParams['text.usetex'] = True
mpl.rcParams['text.latex.preamble'] = r'\usepackage{amsmath}'

ap = argparse.ArgumentParser(description="Claim ID weights calculation")
ap.add_argument("-m" ,"--method",
                required=True,
                choices=['only_dumpster_loads', 'pickup_trucks', 'all_trucks'],
                help="Collection method: only_dumpster_loads, pickup_trucks, no_axle, all")
ap.add_argument("--axle",
                action='store_true',
                help="Include claim IDs with axle dumps")
ap.add_argument("--no_axle",
                action='store_true',
                help="exclude claim IDs with axle dumps")
args = ap.parse_args()

method = args.method
no_axle = args.no_axle

db_version = config["data"]["db_version"]
# Path to input matched data
filepath = "{0}/{1}/claims_weight_db_matched_weights_{1}.csv".format(config["data"]["output_dir"], db_version)

data = pd.read_csv(filepath)

# Data for dumpster loads
truck_id = "DUMPSTER LOAD"
pickup_id = "PICKUP TRUCK LOAD"
axle_id = "AXLE DUMP"

total_ids_initial = len(data["claim_id"].unique().tolist())

if method == "only_dumpster_loads":
    print("Using claim IDs with only DUMPSTER LOAD collection method")

    # Keep claim IDs with only dumpster load collection method
    no_dumpster_load_mask = data["subcategory_prev"].str.contains("GENERAL DEMOLITION", flags=re.IGNORECASE, regex=True) & \
                            (data["item_description"].str.contains(truck_id, flags=re.IGNORECASE, regex=True) == False)
    no_dumpster_load_ids = data.loc[no_dumpster_load_mask, "claim_id"].unique().tolist()

    data = data[~data["claim_id"].isin(no_dumpster_load_ids)]

    print("Selected {}/{} claim IDs with only DUMPSTER LOAD collection method".format(total_ids_initial-len(no_dumpster_load_ids),
                                                                                total_ids_initial)
        )
elif method == "pickup_trucks":
    print("Using claim IDs with PICKUP TRUCK and other collection methods")

    # Keep claim IDs with pickup truck collection method (other methods allowed as well)
    pickup_mask = data["subcategory_prev"].str.contains("GENERAL DEMOLITION", flags=re.IGNORECASE, regex=True) & \
                data["item_description"].str.contains(pickup_id, flags=re.IGNORECASE, regex=True)

    pickup_ids = data.loc[pickup_mask, "claim_id"].unique().tolist()

    data = data[data["claim_id"].isin(pickup_ids)]

    print("Selected {}/{} claim IDs with PICKUP TRUCK collection method".format(len(pickup_ids),
                                                                                total_ids_initial)
    )
elif method == "all_trucks":
    print("Using all claim IDs")

if no_axle:
    print("Excluding claim IDs with AXLE DUMP collection methods")

    axle_mask = data["subcategory_prev"].str.contains("GENERAL DEMOLITION", flags=re.IGNORECASE, regex=True) & \
            data["item_description"].str.contains(axle_id, flags=re.IGNORECASE, regex=True)

    axle_ids = data.loc[axle_mask, "claim_id"].unique().tolist()

    data = data[~data["claim_id"].isin(axle_ids)]

    print("Excluded {}/{} claim IDs with AXLE DUMP collection method".format(len(axle_ids),
                                                                                total_ids_initial)
     )

filename_suffix = method + "_no_axle" if no_axle else method

truck_mask = data["subcategory_prev"].str.contains("GENERAL DEMOLITION", flags=re.IGNORECASE, regex=True) & \
            data["item_description"].str.contains(truck_id, flags=re.IGNORECASE, regex=True)

pickup_mask = data["subcategory_prev"].str.contains("GENERAL DEMOLITION", flags=re.IGNORECASE, regex=True) & \
            data["item_description"].str.contains(pickup_id, flags=re.IGNORECASE, regex=True)

axle_mask = data["subcategory_prev"].str.contains("GENERAL DEMOLITION", flags=re.IGNORECASE, regex=True) & \
            data["item_description"].str.contains(axle_id, flags=re.IGNORECASE, regex=True)

truck_data = data[truck_mask].copy()
pickup_data = data[pickup_mask].copy()

# Mask for items associated with valid pentatonic IDs
id_matched_mask = data["pentatonic_id"].notna() & (data["pentatonic_id"] != "")

# Weight columns naming convention is "weigh_ustons_<suffix>"
weight_columns = [col for col in data.columns if "ustons" in col]

print("Available weight columns: {}".format(weight_columns))

# Estimated weight of claim items
for col in weight_columns:
    data[col] = data[col] * data["item_quantity"]
# data["item_weight_lbs"] = data["weight_lbs"] * data["count"]
# data["item_volume_cf"] = data["volume_cf"] * data["count"]
# data["item_volume_cy"] = data["volume_cy"] * data["count"]

# Dumpster load items have patterns, e.g. "DUMPSTER LOAD APPROX 12 YARDS 1-3 TONS DEBRIS" or DUMPSTER LOAD APPROX 20 YARDS 4 TONS DEBRIS
# In order to calculate weight for each truck, numbers before TONS are extracted

# Mask to find weight patterns as ranged numbers, such as 1-3 TONS, 5-7 TONS, etc.
range_mask = truck_data["item_description"].str.contains('\s+\d\s*-\s*\d\s+TONS', flags=re.IGNORECASE, regex=True)

# Mask to find weight patterns as single numbers, such as 4 TONS, etc.
precise_mask = truck_data["item_description"].str.contains('(\s+\d\s+TONS)(?!\s+\d\s*-\s*\d\s+TONS)', flags=re.IGNORECASE, regex=True)

# Upper and lower truck weights are introduced since the majority of dumpster loads contain range of weights
# In case of single numbers, lower and upper weights are equal
truck_data[["lower_truck_weight", "upper_truck_weight"]] = 0
truck_data.loc[range_mask, ["lower_truck_weight", "upper_truck_weight"]] = truck_data.loc[range_mask, "item_description"].str.extract(r'\s+(\d)\s*-\s*(\d)\s+TONS', flags=re.IGNORECASE).values
truck_data.loc[precise_mask, "lower_truck_weight"] = truck_data.loc[precise_mask, "upper_truck_weight"] = truck_data.loc[precise_mask, "item_description"].str.extract(r'\s+(\d)\s+TONS', flags=re.IGNORECASE).values

# Calculate average weight for each truck and multiply by number of trucks
# truck_data["truck_weight"] = 0.5*(truck_data["lower_truck_weight"].astype(float) + truck_data["upper_truck_weight"].astype(float))*truck_data["item_quantity"]
truck_data["truck_weight"] = truck_data["upper_truck_weight"].astype(float)*truck_data["item_quantity"]
truck_data["truck_cost"] = 0

for size in constants.TRUCK_COST_MAP[truck_id]:
    if not "YARDS" in size:
        truck_size_mask = truck_data["item_description"].astype(str).str.contains("YARDS", flags=re.IGNORECASE, regex=True)
        truck_data.loc[~truck_size_mask, "truck_cost"] = constants.TRUCK_COST_MAP[truck_id]["TRUCK"] * truck_data["item_quantity"]
    else:
        truck_size_mask = truck_data["item_description"].astype(str).str.contains(size, flags=re.IGNORECASE, regex=True)
        truck_data.loc[truck_size_mask, "truck_cost"] = constants.TRUCK_COST_MAP[truck_id][size] * truck_data["item_quantity"]

# Assumptions based on data we got for our app
print("Using pickup truck weight: {} tons".format(constants.PICKUP_TRUCK_WEIGHT))
print("Using pickup truck cost: {}$".format(constants.TRUCK_COST_MAP[pickup_id]))
pickup_data["pickup_weight"] = pickup_data["item_quantity"] * constants.PICKUP_TRUCK_WEIGHT
pickup_data["pickup_cost"]   = pickup_data["item_quantity"] * constants.TRUCK_COST_MAP[pickup_id]

def to_list(col, to_int=False):

    values = col.values.tolist()

    if to_int:
        values = [int(v) for v in values]

    return ",".join(str(v) for v in values)

# Total weight of all dumpster loads per claim ID
truck_weight_data = truck_data.groupby("claim_id").agg(total_truck_weight=("truck_weight", "sum"),
                                                       all_truck_weights=("upper_truck_weight", to_list),
                                                       all_truck_qty=("item_quantity", to_list),
                                                    total_truck_cost=("truck_cost", "sum"),
                                                    ).reset_index()

# Total weight of all pickup trucks per claim ID
pickup_weight_data = pickup_data.groupby("claim_id").agg(total_pickup_weight=("pickup_weight", "sum"),
                                                        all_pickup_weights=("pickup_weight", to_list),
                                                        all_pickup_qty=("item_quantity", to_list),
                                                        total_pickup_cost=("pickup_cost", "sum"),
                                                        ).reset_index()
# Merge dumpster loads and pickup trucks data
all_truck_weight_data = pd.merge(truck_weight_data, pickup_weight_data, how='outer')

# Fill NaNs in total weight with 0
all_truck_weight_data['total_truck_weight'] = all_truck_weight_data['total_truck_weight'].fillna(0)
all_truck_weight_data['total_truck_cost'] = all_truck_weight_data['total_truck_cost'].fillna(0)
all_truck_weight_data['total_pickup_weight'] = all_truck_weight_data['total_pickup_weight'].fillna(0)
all_truck_weight_data['total_pickup_cost'] = all_truck_weight_data['total_pickup_cost'].fillna(0)

# Total weight of dumpster loads and pickup trucks
all_truck_weight_data['total_weight'] = all_truck_weight_data['total_truck_weight'] + all_truck_weight_data['total_pickup_weight']
all_truck_weight_data['total_cost'] = all_truck_weight_data['total_truck_cost'] + all_truck_weight_data['total_pickup_cost']

truck_data_mask = (truck_mask | pickup_mask | axle_mask)
data = data[~truck_data_mask]

# Merge truck data with main claim data
data = data.merge(all_truck_weight_data[["claim_id", "total_weight", "all_truck_weights", "all_truck_qty", "all_pickup_weights", "all_pickup_qty", "total_cost", ]], on="claim_id", how="left")

# Function to calculate fraction of items matched with weights DB
def total_matching_fraction(col, ext_mask=None):

    mask = col.notna() & (col != 0) & (col != "")

    return round(mask.sum()/col.shape[0], 2)

def single_matching_fraction(col, ext_mask=None):

    mask = col.notna() & (col != 0) & (col != "") & (~col.astype(str).str.contains(","))

    return round(mask.sum()/col.shape[0], 2)

def multiple_matching_fraction(col, ext_mask=None):

    mask = col.notna() & (col != 0) & (col != "") & (col.astype(str).str.contains(","))

    return round(mask.sum()/col.shape[0], 2)

# Introduce data aggregations per claim ID
aggregate_args = {
    "date" : ("ls_date", "last"),
    "zip" : ("zip", "last"),
    "total_claims" : ("item_description", "count"),
    "total_items" : ("count", "sum"),
    "total_truck_weight" : ("total_weight", "last"),
    "truck_weights" : ("all_truck_weights", "last"),
    "truck_qty" : ("all_truck_qty", "last"),
    "pickup_weights" : ("all_pickup_weights", "last"),
    "pickup_qty" : ("all_pickup_qty", "last"),
    "total_truck_cost" : ("total_cost", "last"),
    "total_id_matching_fraction" : ("pentatonic_id", total_matching_fraction),
    "single_id_matching_fraction" : ("pentatonic_id", single_matching_fraction),
    "multiple_id_matching_fraction" : ("pentatonic_id", multiple_matching_fraction),
    "primary_matching_fraction" : ("weights_primary_desc", total_matching_fraction)
}

for col in weight_columns:
    aggregate_args["weight_estimation_ustons" + col.partition("ustons")[-1]] = (col, "sum")

claim_id_data = data.groupby(["claim_id"]).agg(**aggregate_args).reset_index()

weight_columns = [col for col in claim_id_data.columns if "weight_estimation_ustons" in col]

for col in weight_columns:
    col_suffix = col.partition("ustons")[-1]

    claim_id_data[col] = round(claim_id_data[col], 2)

    claim_id_data["excessive_truck_weight_ustons" + col_suffix] = claim_id_data["total_truck_weight"] - claim_id_data[col]
    claim_id_data["relative_excessive_truck_weight_ustons" + col_suffix] = round(claim_id_data["excessive_truck_weight_ustons" + col_suffix]/claim_id_data["total_truck_weight"]*100,2)

# Saving estimation data to Excel
output_path = "{0}/{1}".format(config["data"]["output_dir"], db_version)

suffixes = [col.partition("ustons_")[-1] for col in claim_id_data.columns if col.startswith("weight_estimation_ustons")]

prices_data = pd.read_csv("data/collection_methods.csv")

dumpster_load_mask = (prices_data["type"] == "Dumpster")
prices_data = prices_data.loc[dumpster_load_mask, ["type", "price_per_collection", "weight_limit_tons"]]

agg_prices_data = prices_data.groupby("type").agg(price_per_collection=("price_per_collection",list),
                                        weight_limit_ustons=("weight_limit_tons",list)
                                        )

weights = agg_prices_data["weight_limit_ustons"].iloc[0]
costs = agg_prices_data["price_per_collection"].iloc[0]

# density, costs, weights = zip(*sorted((c/w, c, w) for c, w in zip(costs, weights)))

# print(density)
print(weights)
print(costs)

def minimize_estimation_cost(row, weights, costs, method):

    weights = [float(w) for w in weights]
    costs   = [float(c) for c in costs]

    max_weight = float(row["weight_estimation_ustons" + method])

    if max_weight == 0:
        return 0

    def fit_weights(min_cost, min_combination, coeffs, in_costs, in_weights, reference_weight):
        """
            Function that calculates the best packing of a given reference weight into trucks of given sizes
            with the minimum cost.

            Best cost value is calculated based on the price per ton (PPT) for each truck (cost/weight).
            1. First, trucks are ranked from the lowest PPT to the highest.
            2. The maximum amount n0 of lowest PPT trucks which fill the largest possible weight
                below reference weight is obtained as quotient of reference_weight/truck_weight.
                In case all trucks are heavier than reference weight, the truck with the minimum cost is chosen.
            3. First candidate for minimal cost combination is (n0+1)*C_0 of lowest PPT trucks.
            4. In case of next lowest PPT trucks with weights W_i above the remainder weight
                (reference_weight mod truck_weight) and costs C_i, minimal cost combinations n0*C_0+C_i are
                tested against previous minimum cost (n0+1)*C_0. If n0*C_0+C_i < (n0+1)*C_0, it becomes new minimum cost.
                These trucks are then excluded from the future iterations.
            5. For the trucks that weigh less than reference weight, repeat steps 1-4 until no trucks are left.

            Input parameters:
            :param coeffs:                 keep coefficients for weights (=number of trucks)
            :param in_costs:               input costs of each available truck
            :param in_weights:             input weights of each available truck
            :param reference_weight:       weight to pack into input trucks
            Output parameters:
            :param min_cost:               minimum cost
            :param min_combination:        combination of truck weights with the minimum cost
        """

        if not in_weights or not in_costs:
            print("No input weights detected. Switching to next iteration...")
            return

        previous_cost = sum([c*costs[weights.index(w)] for w,c in coeffs.items()])

        if min(in_weights) > reference_weight:
            for c,w in zip(in_costs, in_weights):
                if previous_cost + c < min_cost:
                    min_cost = previous_cost + c
                    min_combination = {**coeffs, **{w:1}}
            return min_cost, min_combination
        elif max(in_weights) > reference_weight:
            above_costs, above_weights = zip(*((c, w) for c, w in zip(in_costs, in_weights)
                                                  if w > reference_weight))
            for c,w in zip(above_costs, above_weights):
                if previous_cost + c < min_cost:
                    min_cost = previous_cost + c
                    min_combination = {**coeffs, **{w:1}}
                in_costs.remove(c)
                in_weights.remove(w)

        _, valid_costs, valid_weights = zip(*sorted((c/w, c, w) for c, w in zip(in_costs, in_weights)))

        for c,w in zip(valid_costs, valid_weights):
            new_coeff = reference_weight // w

            if previous_cost + (new_coeff + 1) * c < min_cost:
                min_combination = {**coeffs, **{w:new_coeff+1}}
                min_cost = previous_cost + (new_coeff + 1) * c

            remaining_costs = [cc for cc in valid_costs if cc != c]
            remaining_weights = [ww for ww in valid_weights if ww != w]

            if len(remaining_weights) == 0:
                continue

            min_cost, min_combination = fit_weights(min_cost, min_combination,
                        {**coeffs, **{w:new_coeff}},
                        remaining_costs,
                        remaining_weights,
                        reference_weight % w)

            previous_cost = sum([c*costs[weights.index(w)] for w,c in coeffs.items()])

        return min_cost, min_combination

    min_combination = {}
    min_cost = 100000000000
    coeffs = {}

    min_cost, min_combination = fit_weights(min_cost, min_combination, coeffs, costs, weights, max_weight)

    min_weights = ",".join(str(w) for w,i in min_combination.items() if i > 0)
    min_nitems  = ",".join(str(int(i)) for w,i in min_combination.items() if i > 0)

    return pd.Series([round(min_cost,2), min_nitems, min_weights])

for col in weight_columns:
    col_suffix = col.partition("ustons")[-1]

    new_col = "estimated_cost" + col_suffix

    claim_id_data[[new_col, "estimated_truck_qty" + col_suffix, "estimated_truck_weights" + col_suffix]] = claim_id_data.apply(lambda row: minimize_estimation_cost(row, weights, costs, col_suffix), axis=1)
    claim_id_data["excessive_cost" + col_suffix] = claim_id_data["total_truck_cost"] - claim_id_data[new_col]
    claim_id_data["relative_excessive_cost" + col_suffix] = round(claim_id_data["excessive_cost" + col_suffix]/claim_id_data["total_truck_cost"]*100,2)

suffixes = [col.partition("ustons_")[-1] for col in claim_id_data.columns if col.startswith("weight_estimation_ustons")]

columns = ['claim_id', 'zip', 'total_claims', 'total_items', 'total_truck_weight', 'truck_weights', 'truck_qty', 'pickup_weights', 'pickup_qty',
           'total_truck_cost',
           'total_id_matching_fraction', 'single_id_matching_fraction', 'multiple_id_matching_fraction',
           'primary_matching_fraction']

excel_name = "{}/claim_id_weight_comparison_{}_{}.xlsx".format(output_path, filename_suffix, db_version)

plot_mask = (claim_id_data["total_truck_cost"] > 0) & (claim_id_data["estimated_cost_median_median"] > 0)

total_excessive_costs = claim_id_data.loc[plot_mask, "excessive_cost_median_median"].dropna().sum()

print("Total excessive costs: {:.1f} $".format(total_excessive_costs))

start_time = time.time()

with ExcelWriter(excel_name, engine='xlsxwriter') as writer:
    for suffix in suffixes:
        save_cols = columns + [col for col in claim_id_data.columns if suffix in col]
        save_df = claim_id_data[save_cols]

        save_df.to_excel(writer, sheet_name=suffix, index=False)

        worksheet = writer.sheets[suffix]
        for idx, col in enumerate(save_df):  # loop through all columns
            series = save_df[col]
            max_len = max((
                series.astype(str).map(len).max(),  # len of largest item
                len(str(series.name))  # len of column name/header
                )) + 1  # adding a little extra space
            worksheet.set_column(idx, idx, max_len)  # set column width
    writer.save()

print("Total time elapsed: {} s".format(time.time()-start_time))

plot_mask = (claim_id_data["total_truck_cost"] > 0) & (claim_id_data["estimated_cost_median_median"] > 0)

total_excessive_costs = claim_id_data.loc[plot_mask, "excessive_cost_median_median"].dropna().sum()
print("Total excessive costs: {:.1f} $".format(total_excessive_costs))

output_columns = list(constants.CLIENT_OUTPUT_RENAME_MAP)

output_data = claim_id_data[output_columns]
output_data['total_id_matching_fraction'] = output_data['total_id_matching_fraction'].copy() * 100

output_data = output_data.rename(columns=constants.CLIENT_OUTPUT_RENAME_MAP)

excel_name = "{}/client_Xactimate_vs_Phoenix_{}_{}.xlsx".format(output_path, filename_suffix, db_version)

start_time = time.time()

with ExcelWriter(excel_name, engine='xlsxwriter') as writer:
    output_data.to_excel(writer, sheet_name="median_median", index=False)

    workbook = writer.book

    colors = {}

    for key, color in constants.CLIENT_OUTPUT_COLORS.items():
        colors[key] = workbook.add_format({'bg_color': color})

    worksheet = writer.sheets["median_median"]
    for idx, col in enumerate(output_data):  # loop through all columns
        series = output_data[col]
        max_len = max((
            series.astype(str).map(len).max(),  # len of largest item
            len(str(series.name))  # len of column name/header
            )) + 1  # adding a little extra space

        worksheet.set_column(idx, idx, max_len)
        # if col in constants.CLIENT_OUTPUT_RENAME_GENERAL.values():
        #     worksheet.set_column(idx, idx, max_len, colors["General"])  # set column width and color
        # elif col in constants.CLIENT_OUTPUT_RENAME_XACTIMATE.values():
        #     worksheet.set_column(idx, idx, max_len, colors["Xactimate"])  # set column width and color
        # elif col in constants.CLIENT_OUTPUT_RENAME_PHOENIX.values():
        #     worksheet.set_column(idx, idx, max_len, colors["Phoenix"])  # set column width and color
        # elif col in constants.CLIENT_OUTPUT_RENAME_SAVINGS.values():
        #     worksheet.set_column(idx, idx, max_len, colors["Savings"])  # set column width and color
        # elif col in constants.CLIENT_OUTPUT_RENAME_MATCHING.values():
        #     worksheet.set_column(idx, idx, max_len, colors["Matching"])  # set column width and color

        # border_fmt = workbook.add_format({'bottom':5, 'top':5, 'left':5, 'right':5})
        # worksheet.conditional_format(writer.utility.xl_range(0, 0, max_len, max_len), {'type': 'no_errors', 'format': border_fmt})

    writer.save()
print("Total time elapsed: {} s".format(time.time()-start_time))

valid_truck_weight_mask = (claim_id_data["total_truck_weight"] > 0)

id_matching_fractions = [0, 0.25, 0.5, 0.75, 1]
id_col = "single_id_matching_fraction"

hist_colors = list(mcolors.TABLEAU_COLORS)
line_colors = list(mcolors.BASE_COLORS)

total_excessive_weights = {}

plot_columns = [col for col in claim_id_data.columns if col.startswith("excessive_truck_weight")]
labels = []

down_thres = None

# Absolute excessive truck weight plots
for col in plot_columns:

    index = plot_columns.index(col)

    col_suffix = col.partition("ustons")[-1]
    plt_label = ",".join(list(filter(None, col_suffix.split("_"))))

    valid_weight_mask = valid_truck_weight_mask & (claim_id_data["weight_estimation_ustons" + col_suffix] > 0)

    if down_thres is not None:
        thres_mask = (claim_id_data[col] > down_thres)
        print("{}, total entries below {} t: {}".format(plt_label, down_thres, (valid_weight_mask & ~thres_mask).sum()))
        valid_weight_mask &= thres_mask

    y = claim_id_data.loc[valid_weight_mask, col].dropna()

    bins = np.linspace(-400, 400, 401)
    points, _, _ = plt.hist(y, bins=bins, density=True, histtype="step", linewidth=2, color=hist_colors[index])

    positive_integral = y[y > 0].shape[0]/y.shape[0]
    total_excessive_weight = y.sum()
    total_excessive_weights[col_suffix] = total_excessive_weight

    labels.append("({}): {:.1f}\% positive ({:.1f} tons)".format(plt_label, positive_integral*100, total_excessive_weight))

plt.grid(True)

plt.title("Excessive weight estimation for claim IDs with only dumpster loads", fontsize=30)

plt.xlabel("Excessive truck weight in tons", fontsize=30)
plt.ylabel("Frequency", fontsize=30)

plt.xticks(fontsize=20)
plt.yticks(fontsize=20)

plt.legend(labels=labels, fontsize=20)

fig = plt.gcf()
fig.set_size_inches(18.5, 10.5, forward=True)

plt.xlim(-50,50)

file_label = "_{}t".format(abs(down_thres)) if down_thres is not None else ""
plt.savefig('{}/excessive_truck_weight_frequency_{}{}_{}.png'.format(output_path, filename_suffix, file_label, db_version), facecolor='w')

import matplotlib as mpl
mpl.rcParams['text.usetex'] = True
mpl.rcParams['text.latex.preamble'] = r'\usepackage{amsmath}'

from scipy import integrate

valid_truck_weight_mask = (claim_id_data["total_truck_weight"] > 0)

hist_colors = list(mcolors.TABLEAU_COLORS)
line_colors = list(mcolors.BASE_COLORS)

# weight_columns = [col for col in claim_id_data.columns if "ustons" in col and col.startswith("excessive")]
#plot_columns = [col for col in weight_columns if "zero" in col]
plot_columns = [col for col in claim_id_data.columns if col.startswith("excessive_truck_weight") and "median_median" in col]
labels = []

down_thres = None

# Absolute excessive truck weight plots
for col in plot_columns:

    for i in range(len(id_matching_fractions)-1):

        index = i

        col_suffix = col.partition("ustons")[-1]
        plt_label = ",".join(list(filter(None, col_suffix.split("_"))))

        valid_weight_mask = valid_truck_weight_mask & (claim_id_data["weight_estimation_ustons" + col_suffix] > 0) & \
                            (claim_id_data[id_col] > id_matching_fractions[i]) & \
                            (claim_id_data[id_col] <= id_matching_fractions[i+1])

        if down_thres is not None:
            thres_mask = (claim_id_data[col] > down_thres)
            print("{}, total entries below {} t: {}".format(plt_label, down_thres, (valid_weight_mask & ~thres_mask).sum()))
            valid_weight_mask &= thres_mask

        y = claim_id_data.loc[valid_weight_mask, col].dropna()

        bins = np.linspace(-400, 400, 401)
        points, _, _ = plt.hist(y, bins=bins, density=True, histtype="step", linewidth=2, color=hist_colors[index])

        positive_integral = y[y > 0].shape[0]/y.shape[0]
        total_excessive_weight = y.sum()

        labels.append("{}-{}\% ({}): {:.1f}\% positive ({:.1f} tons)".format(int(id_matching_fractions[i]*100),
                                                                             int(id_matching_fractions[i+1]*100),
                                                                             y.shape[0],
                                                                             positive_integral*100,
                                                                             total_excessive_weight))

plt.grid(True)

plt.title("Excessive weight estimation for claim IDs with only dumpster loads for different single ID matching", fontsize=24)

plt.xlabel("Excessive truck weight in tons", fontsize=30)
plt.ylabel("Frequency", fontsize=30)

plt.xticks(fontsize=20)
plt.yticks(fontsize=20)

plt.legend(labels=labels, fontsize=20)

fig = plt.gcf()
fig.set_size_inches(18.5, 10.5, forward=True)

plt.xlim(-50,50)

file_label = "_{}t".format(abs(down_thres)) if down_thres is not None else ""
plt.savefig('{}/excessive_truck_weight_frequency_{}_IDmatching{}_{}.png'.format(output_path, filename_suffix, file_label, db_version), facecolor='w')

plt.clf()

plot_columns = [col for col in claim_id_data.columns if col.startswith("relative_excessive_truck_weight")]
labels = []

# Relative excessive truck weight plots
for col in plot_columns:

    valid_weight_mask = valid_truck_weight_mask & (claim_id_data[col] > 0)

    index = plot_columns.index(col)

    col_suffix = col.partition("ustons")[-1]
    plt_label = ",".join(list(filter(None, col_suffix.split("_"))))

    valid_weight_mask = valid_truck_weight_mask & (claim_id_data["weight_estimation_ustons" + col_suffix] > 0)

    y = claim_id_data.loc[valid_weight_mask, col].dropna()

    bins = np.linspace(-1000, 100, 276)
    points, _, _ = plt.hist(y, bins=bins, density=True, histtype="step", linewidth=2, color=hist_colors[index])

    positive_integral = y[y > 0].shape[0]/y.shape[0]

    labels.append("({}): {:.1f}\% positive ({:.1f} tons)".format(plt_label, positive_integral*100, total_excessive_weights[col_suffix]))

plt.grid(True)

plt.title("Relative excessive weight estimation for claim IDs with only dumpster loads", fontsize=30)

plt.xlabel("Relative excessive truck weight [\%]", fontsize=30)
plt.ylabel("Frequency", fontsize=30)

plt.xticks(fontsize=20)
plt.yticks(fontsize=20)

plt.legend(labels=labels, fontsize=20, loc='upper left')

fig = plt.gcf()
fig.set_size_inches(18.5, 10.5, forward=True)

plt.xlim(-100,100)

plt.savefig('{}/relative_excessive_truck_cost_frequency_{}{}_{}.png'.format(output_path, filename_suffix, file_label, db_version), facecolor='w')


from struct import*
from socket import*
from eth import*
from ip import*
from tcp import*
from chk import*

# TCP 패킷 전송

client_seq=int(input('클라이언트 스퀀스를 입력하세요: '))
server_seq=int(input('서버의 시퀀스를 입력하세요: '))

client_port =int(input('클라이언트 포트를 입력하세요: '))
server_port = int(input('서버 포트를 입력하세요: '))

print()
print('========================상태 정보====================')
print('==== FIN: 1, SYN: 2 , ACK: 16, SYNACK: 18, ACKFIN:17, ACKPSH: 24 ===')
print('===================================================')
Flags=int(input('TCP상태를 설정하세요: '))

tcp1=Tcp()
tcp1.src_port=client_port
tcp1.dst_port=server_port
tcp1.Seq_Num= client_seq
tcp1.Ack_Num= server_seq
tcp1.Offset=0
tcp1.Flag= Flags
tcp1.Window_Size=65535
tcp1.Checksum=0
tcp1.Urgent_Pointer=0
tcp1.Offset=len(tcp1.get_header)

ip=IP()
ip.Ver=4
ip.HeaderLen=20
ip.Service=0
ip.TotalLen= len(ip.get_header) + len(tcp1.get_header)
ip.Id=0
ip.Flag=0
ip.Offset=0
ip.ttl=64
ip.Protocol=6
ip.Checksum =0
ip.src='192.168.1.9'
ip.dst='192.168.1.8'
ip.Checksum = make_chksum(ip.get_header)

tcpLen=pack('!H',tcp1.Offset)
pseudo =ip._src + ip._dst + b'\x00'+ ip._Protocol + tcpLen + tcp1.get_header
tcp1.Checksum = make_chksum(pseudo)

eth=Eth()

eth.dst='00:0C:29:CC:AA:71'
eth.src='00:50:56:32:C2:BF'
eth.type=0x0800

sock=socket(AF_PACKET, SOCK_RAW)
sock.bind(('eth0', SOCK_RAW))
sock.send(eth.get_header() + ip.get_header + tcp1.get_header)