from flask import (
    Blueprint, request, g, redirect, url_for, flash, render_template, session
)
from werkzeug.exceptions import abort
from app.db import get_db
from app.util import get_item_by_id, generate_bill, pay_bill, save_message

bp = Blueprint('cart', __name__)

@bp.route('/view_cart')
def view_cart():
    if not g.user:
        items_by_id = session.get('cart', None)
        return render_template( 'cart/cart.html', items=items_by_id )
    return redirect( url_for('menu.index') )

@bp.route('/add_to_cart/item_<int:item_id>')
def add_to_cart(item_id):
    ''' adds the item with the given id to the order '''
    i = get_item_by_id(item_id)
    if i:
        item_id = str(item_id)
        item_details = { 'name' : i['name'], 'description' : i['description'], \
                         'cost' : i['cost'], 'diet' : i['diet'], 'id' : item_id, \
                         'spicy' : i['spicy'], 'total_cost' : i['cost'], 'qty' : 1 }
        if 'cart' not in session:
            session['cart'] = [ item_details ]
        else:
            item_idx = next((idx for idx, s in enumerate(session['cart']) if s['id'] == item_id), None)
            if item_idx is not None:
                session['cart'][item_idx]['qty'] += 1
                session['cart'][item_idx]['total_cost'] += i['cost']
            else:
                session['cart'].append(item_details)
            session.modified = True

    return redirect( url_for('menu.index') )

@bp.route('/make_order/total_<float:total>')
def make_order(total):
    ''' store customer order details to the database '''
    # ensure user has selected a table first
    if 'tableNo' not in session:
        flash("You must select a table before you can place an order.")
        return redirect( url_for('index') )
    if 'cart' in session:
        db = get_db()
        custIP = session.get('custIP', request.environ.get('HTTP_X_REAL_IP', request.remote_addr))
        orderId = db.execute(
            'INSERT INTO custOrder'
            ' (custIP, totalCost, tableNo)'
            ' VALUES (?, ?, ?)',
            (custIP, total, session['tableNo'])
        ).lastrowid
        db.commit()
        if orderId is not None:
            for i in session['cart']:
                db.execute(
                    'INSERT INTO orderDetail'
                    ' (itemId, orderId, quantity)'
                    ' VALUES (?, ?, ?)',
                    (int(i['id']), orderId, i['qty'])
                )
                db.commit()
            session.pop('cart', None)
            flash("Order submitted!")
    return redirect( url_for('cart.view_cart') )

@bp.route('/update_cart/item_<int:id>/action_<action>')
def update_cart(id, action):
    ''' updates the order for the item with the given id and action to perform '''
    if 'cart' in session:
        item_id = str(id)
        item_idx = next((idx for idx, i in enumerate(session['cart']) if i['id'] == item_id), None)
        if item_idx is not None:
            if action in ['inc', 'dec']:
                updateQuantity(item_idx, action)
            elif action == 'remove':
                del session['cart'][item_idx]
                session.modified = True
    return redirect( url_for('cart.view_cart') )

def updateQuantity(item_idx, action):
    ''' updates the quantity of the item at the given item_idx '''
    cost = session['cart'][item_idx]['cost']
    qty = session['cart'][item_idx]['qty']
    if action == 'inc':
        if qty < 30:
            session['cart'][item_idx]['qty'] += 1
            session['cart'][item_idx]['total_cost'] += cost
            session.modified = True
    else:
        if qty > 1:
            session['cart'][item_idx]['qty'] -= 1
            session['cart'][item_idx]['total_cost'] -= cost
            session.modified = True

@bp.route('/view_bill', methods=('GET', 'POST'))
def view_bill():
    ''' retrieves and groups the currently unpaid items to generate a bill '''
    itemsByName = {}
    tblNo = session.get('tableNo', None)
    custIP = session.get('custIP', request.environ.get('HTTP_X_REAL_IP', request.remote_addr))
    billItems = generate_bill(tblNo, custIP)
    if request.method == 'POST':
        billTotal = request.form['bill_total']
        request_bill(billItems, billTotal)
    else:
        if billItems is not None:
            itemsByName = groupBillItems(billItems)
    return render_template( 'cart/bill.html', items=itemsByName )

def groupBillItems(billItems):
    ''' group the bill items in a dictionary ensuring
        identical items are not shown separately
    '''
    itemsByName = {}
    for i in billItems:
        if i['name'] not in itemsByName:
            itemsByName[i['name']] = { 'desc' : i['description'], 'cost' : i['cost'] * i['quantity'], \
            'qty' : i['quantity'], 'diet' : i['diet'], 'spicy' : i['spicy'] }
        else:
            qty = itemsByName[i['name']]['qty'] + i['quantity']
            itemsByName[i['name']]['qty'] = qty
            itemsByName[i['name']]['cost'] = i['cost'] * qty
    return itemsByName

def request_bill(billItems, billTotal):
    ''' marks the orders associated with the given items as paid '''
    orderIDs = set([ i['id'] for i in billItems ])
    if orderIDs:
        # there are unpaid items
        pay_bill(orderIDs)
        msg = 'A customer from table {} has requested the bill totalling £{:.2f}'.format( \
        session.get('tableNo', None), float(billTotal) )
        save_message('Kitchen', msg)
        flash('Thank you, a member of the waiting staff will be with you shortly.')


import os

from migen import *

from litex.soc.interconnect import wishbone
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32

# Variants -----------------------------------------------------------------------------------------

CPU_VARIANTS = ["minimal", "lite", "standard", "full"]

# GCC Flags ----------------------------------------------------------------------------------------

GCC_FLAGS = {
    #                               /-------- Base ISA
    #                               |/------- Hardware Multiply + Divide
    #                               ||/----- Atomics
    #                               |||/---- Compressed ISA
    #                               ||||/--- Single-Precision Floating-Point
    #                               |||||/-- Double-Precision Floating-Point
    #                               imacfd
    "minimal":          "-march=rv32i     -mabi=ilp32",
    "lite":             "-march=rv32imc   -mabi=ilp32",
    "standard":         "-march=rv32imc   -mabi=ilp32",
    "full":             "-march=rv32imc   -mabi=ilp32",
}

# NEORV32 ------------------------------------------------------------------------------------------

class NEORV32(CPU):
    category             = "softcore"
    family               = "riscv"
    name                 = "neorv32"
    variants             = CPU_VARIANTS
    data_width           = 32
    endianness           = "little"
    gcc_triple           = CPU_GCC_TRIPLE_RISCV32
    linker_output_format = "elf32-littleriscv"
    nop                  = "nop"
    io_regions           = {0x8000_0000: 0x8000_0000} # Origin, Length.

    # GCC Flags.
    @property
    def gcc_flags(self):
        flags =  GCC_FLAGS[self.variant]
        flags += " -D__neorv32__ "
        return flags

    def __init__(self, platform, variant="standard"):
        self.platform     = platform
        self.variant      = variant
        self.human_name   = f"NEORV32-{variant}"
        self.reset        = Signal()
        self.ibus         = idbus = wishbone.Interface()
        self.periph_buses = [idbus] # Peripheral buses (Connected to main SoC's bus).
        self.memory_buses = []      # Memory buses (Connected directly to LiteDRAM).

        # # #

        class Open(Signal) : pass

        # CPU LiteX Core Complex Wrapper
        self.specials += Instance("neorv32_litex_core_complex",
            # Parameters.
            #p_CONFIG      = 2,
            #p_DEBUG       = False,

            # Clk/Rst.
            i_clk_i       = ClockSignal("sys"),
            i_rstn_i      = ~(ResetSignal() | self.reset),

            # JTAG.
            i_jtag_trst_i = 0,
            i_jtag_tck_i  = 0,
            i_jtag_tdi_i  = 0,
            o_jtag_tdo_o  = Open(),
            i_jtag_tms_i  = 0,

            # Interrupt.
            i_mext_irq_i  = 0,

            # I/D Wishbone Bus.
            o_wb_adr_o    = Cat(Signal(2), idbus.adr),
            i_wb_dat_i    = idbus.dat_r,
            o_wb_dat_o    = idbus.dat_w,
            o_wb_we_o     = idbus.we,
            o_wb_sel_o    = idbus.sel,
            o_wb_stb_o    = idbus.stb,
            o_wb_cyc_o    = idbus.cyc,
            i_wb_ack_i    = idbus.ack,
            i_wb_err_i    = idbus.err,
        )

        # Add Verilog sources
        self.add_sources(platform, variant)

    def set_reset_address(self, reset_address):
        self.reset_address = reset_address
        assert reset_address == 0x0000_0000

    @staticmethod
    def add_sources(platform, variant):
        cdir = os.path.abspath(os.path.dirname(__file__))
        # List VHDL sources.
        sources = {
            "core" : [
                # CPU & Processors Packages/Cores.
                "neorv32_package.vhd",
                "neorv32_fifo.vhd",

                # CPU components.
                "neorv32_cpu.vhd",
                    "neorv32_cpu_alu.vhd",
                        "neorv32_cpu_cp_bitmanip.vhd",
                        "neorv32_cpu_cp_cfu.vhd",
                        "neorv32_cpu_cp_fpu.vhd",
                        "neorv32_cpu_cp_muldiv.vhd",
                        "neorv32_cpu_cp_shifter.vhd",
                    "neorv32_cpu_bus.vhd",
                    "neorv32_cpu_control.vhd",
                        "neorv32_cpu_decompressor.vhd",
                    "neorv32_cpu_regfile.vhd",

                # Processor components.
                "neorv32_top.vhd",
                    "neorv32_icache.vhd",
                    "neorv32_busswitch.vhd",
                    "neorv32_bus_keeper.vhd",
                    "neorv32_wishbone.vhd",
                    "neorv32_mtime.vhd",
                    "neorv32_sysinfo.vhd",
                    "neorv32_debug_dm.vhd",
                    "neorv32_debug_dtm.vhd",
            ],

            "core/mem": [
                "neorv32_imem.default.vhd",
                "neorv32_dmem.default.vhd",
            ],

            "system_integration": [
                "neorv32_litex_core_complex.vhd",
            ],
        }

        # Download VHDL sources (if not already present).
        for directory, vhds in sources.items():
            for vhd in vhds:
                if not os.path.exists(os.path.join(cdir, vhd)):
                    os.system(f"wget https://raw.githubusercontent.com/stnolting/neorv32/main/rtl/{directory}/{vhd} -P {cdir}")

        def configure_litex_core_complex(filename, variant):
            # Read Wrapper.
            lines = []
            f = open(filename)
            for l in f:
                lines.append(l)
            f.close()

            # Configure.
            _lines = []
            for l in lines:
                if "constant CONFIG" in l:
                    config = {
                        "minimal"  : "0",
                        "lite"     : "1",
                        "standard" : "2",
                        "full"     : "3"
                    }[variant]
                    l = f"\tconstant CONFIG : natural := {config};\n"
                _lines.append(l)
            lines = _lines

            # Write Wrapper.
            f = open(filename, "w")
            for l in lines:
                f.write(l)
            f.close()

        configure_litex_core_complex(
            filename = os.path.join(cdir, "neorv32_litex_core_complex.vhd"),
            variant  = variant,
        )

        # Convert VHDL to Verilog through GHDL/Yosys.
        from litex.build import tools
        import subprocess
        cdir = os.path.dirname(__file__)
        ys = []
        ys.append("ghdl --ieee=synopsys -fexplicit -frelaxed-rules --std=08 --work=neorv32 \\")
        for directory, vhds in sources.items():
            for vhd in vhds:
                ys.append(os.path.join(cdir, vhd) + " \\")
        ys.append("-e neorv32_litex_core_complex")
        ys.append("chformal -assert -remove")
        ys.append("write_verilog {}".format(os.path.join(cdir, "neorv32_litex_core_complex.v")))
        tools.write_to_file(os.path.join(cdir, "neorv32_litex_core_complex.ys"), "\n".join(ys))
        if subprocess.call(["yosys", "-q", "-m", "ghdl", os.path.join(cdir, "neorv32_litex_core_complex.ys")]):
            raise OSError("Unable to convert NEORV32 CPU to verilog, please check your GHDL-Yosys-plugin install.")
        platform.add_source(os.path.join(cdir, "neorv32_litex_core_complex.v"))

    def do_finalize(self):
        assert hasattr(self, "reset_address")


#!/usr/local/bin/python
#-*- coding:utf8 -*-

#http://docs.python.org/library/operator.html

def div(x, y):
    return x / y

def main():
    x = 6
    import pdb; pdb.set_trace()
    for i in [3, 2, 1, 0]:
        x = div(x, i)
    return x

if __name__ == '__main__':
    main()

#python -m pdb pdbtest.py

#step s    ステップ進む
#list l    現在位置確認
#p var     変数(var)の確認
#return    returnされるところまで処理実行
#continue  最後まで処理を実行
#break x   x行にbreakpoint
#break     ブレークポイントの確認
#clear x   ブレークポイントの削除
#enable x  ブレークポイントの有効
#disable x ブレークポイントの無効
#up        スタックフレームの移動
#down      スタックフレームの移動
#quit      終了


import requests
import tensorflow as tf
from google.cloud import storage
import numpy as np
import pandas as pd
import os
import glob
from sklearn.compose import make_column_transformer
from sklearn.preprocessing import MinMaxScaler, OneHotEncoder
from sklearn.model_selection import train_test_split

def transform(age_input, bmi_input, children_input, sex_input, smoker_input, region_input):
  #declare intrinsic value
  age_max = 64
  age_min = 18
  bmi_max = 53.13
  bmi_min = 15.96
  children_max = 5
  children_min = 0

  #DECLARE VARIABEL
  #age
  age	= float((age_input-age_min) / (age_max-age_min))
  #bmi
  bmi	= float((bmi_input-bmi_min)/(bmi_max-bmi_min))
  #children
  children = float((children_input-children_min)/(children_max-children_min))
  #sex
  sex_female	= 0.0
  sex_male	= 0.0
  if (sex_input=='female'):
    sex_female = float(1)
  else: sex_male = float(1)
  #smoker
  smoker_no	= 0.0
  smoker_yes = 0.0
  if (smoker_input == "no"):
    smoker_no = float(1)
  else: smoker_yes = float(1)
  #region
  region_northeast = 0.0
  region_northwest = 0.0
  region_southeast = 0.0
  region_southwest = 0.0
  if region_input == "northeast":
    region_northeast = float(1)
  elif region_input == "northwest":
    region_northwest = float(1)
  elif region_input == "southeast":
    region_southeast = float(1)
  else :
    region_southwest = float(1)

  return np.array([[age, bmi, children, sex_female,sex_male,smoker_no, smoker_yes,
                  region_northeast,region_northwest,region_southeast,region_southwest]])

def predict(requests):
    request_json = requests.get_json()
    age = float(request_json['age'])
    bmi = float( request_json['bmi'])
    children = int(request_json['children'])
    sex = request_json['sex']
    smoker = request_json['smoker']
    region = request_json['region']

    hasil_transform = transform(age,bmi,children,sex,smoker,region)

    ## LOAD MODEL DARI BUCKET
    storage_client = storage.Client()
    bucket = storage_client.get_bucket('bangkit-cap0134-model')
    # ## MEMBUAT DIREKTORI TEMP/MYMODEL UNTUK PENGGUNAAN SEMENTARA
    # file_path = '/tmp/my_model'
    # # pastikan directory ada
    # os.makedirs(os.path.dirname(file_path), exist_ok=True)

    model_3 = tf.keras.Sequential([
    tf.keras.layers.Dense(100),
    tf.keras.layers.Dense(10),
    tf.keras.layers.Dense(1)
    ])

    blob_weight1 = bucket.blob('my_model/variables/variables.data-00000-of-00001')
    blob_weight2 = bucket.blob('my_model/variables/variables.index')

    blob_weight1.download_to_filename('/tmp/variables.data-00000-of-00001')
    blob_weight2.download_to_filename('/tmp/variables.index')

    model_3.load_weights('/tmp/variables')

    hasil_prediksi = model_3.predict(hasil_transform)
    hasil_prediksi_string = str(hasil_prediksi[0][0])

    return(hasil_prediksi_string)


#!/usr/bin/env python
"""
Created on Thu Dec  3 13:40:51 2020

@author: andrei
"""
import numpy as np
import os
import time
from multiprocessing import Pool
import step_length_moduled
from jobs_module import job_submitted
from read_write_module import read_srf_source, read_stat_name, write_par_source_i

def mkdir_p(dir):
    '''make a directory (dir) if it doesn't exist'''
    if not os.path.exists(dir):
        os.mkdir(dir)

def run_process(process):
    os.system('python {}'.format(process))

# Main script#############
iters = 10

source_file = '../../../StatInfo/SOURCE_SRF.txt'
nShot, S, sNames = read_srf_source(source_file)

station_file = '../../../StatInfo/STATION_dh_4km.txt'
nRec, R, statnames = read_stat_name(station_file)

print('finish creating geometrical correlation')
mkdir_p('../../Vel_es/Vel_es_i')
mkdir_p('../../Vel_ob/Ves_ob_i')
mkdir_p('../../Vel_opt/Vel_ob_i')
mkdir_p('Dump')

ishot_arr = np.linspace(1, nShot, nShot).astype('int')
# ishot_arr=[1]
############################################################
for it in range(1, iters + 1):
    fi = open('iNumber.dat', 'w')
    (np.int64(it)).tofile(fi)
    fi.close()
    print('iNumber=' + str(it))
    #Load the initial model from Model/Models/
    if (it == 1):
        #        os.system('cp ../../../Model/Models/vs3dfile.s ../../../Model/Models/vs3dfile_in.s')
        #        os.system('cp ../../../Model/Models/vp3dfile.p ../../../Model/Models/vp3dfile_in.p')
        #        os.system('cp ../../../Model/Models/rho3dfile.d ../../../Model/Models/rho3dfile_in.d')

        os.system('cp ../../../Model/Models/vs3dfile_2020.s ../../../Model/Models/vs3dfile_in.s')
        os.system('cp ../../../Model/Models/vp3dfile_2020.p ../../../Model/Models/vp3dfile_in.p')
        os.system('cp ../../../Model/Models/rho3dfile_2020.d ../../../Model/Models/rho3dfile_in.d')

    #Load the current model as updated model from the previous iteration in /Dump
    #Make sure the /Dump folder existed to all store data for the current model (Except the synthetic waveform stored in Dump_DD).
    if (it > 1):
        os.system('cp %s' % 'Dump/vs3dfile_iter_' + str(it - 1) + '.s ../../../Model/Models/vs3dfile_in.s')
        os.system('cp %s' % 'Dump/vp3dfile_iter_' + str(it - 1) + '.p ../../../Model/Models/vp3dfile_in.p')
        os.system('cp %s' % 'Dump/rho3dfile_iter_' + str(it - 1) + '.d ../../../Model/Models/rho3dfile_in.d')

    print('Generate synthetic data for pyflex pick:')
    os.system('cp ../../../Model/Models/vs3dfile_in.s Model/vs3dfile_opt.s')
    os.system('cp ../../../Model/Models/vp3dfile_in.p Model/vp3dfile_opt.p')
    os.system('cp ../../../Model/Models/rho3dfile_in.d Model/rho3dfile_opt.d')

    #Remove the kernels and waveform for each individual source from the previous iteration run:
    os.system('rm -r All_shots/*')
    os.system('rm -r ../../Vel_es/*')
    dir_es = '../../Vel_es/Vel_es_i'
    mkdir_p(dir_es)

    #    for ishot in range(1,nShot+1):
    for ishot_id in range(0, len(ishot_arr)):
        ishot = ishot_arr[ishot_id]
        dir_es = '../../Vel_es/Vel_es_' + str(ishot)
        mkdir_p(dir_es)
        dir_opt = '../../Vel_opt/Vel_ob_' + str(ishot)
        mkdir_p(dir_opt)

    job_file = 'fdrun-mpi_Allshot_opt_moduled.sl'
    job_submitted(job_file)
    print('fw emod3d for all sources')

    # input('-->')
    print('Pyflex pick!')
    job_file = 'adj_pyflex_moduled.sl'
    job_submitted(job_file)
    # input('-->back to sum kernels update')
    print('Calculate kernels for all shots')

    #Parallelize the kernel calculations for 2 groups of sources
    #via Master_iterations_part_1_multi_taper.py in PART1/Kernel/Iter/iter1/ e.t.c.
    #In PART1: there're also folders: AdjSims  FwdSims  Kernels for forward/adjoint simulations and kernel calculation.
    for ipart in range(1, 3):

        fi = open('ipart.dat', 'w')
        (np.int64(ipart)).tofile(fi)
        fi.close()
        print('ipart=' + str(ipart))
        #Pass the i_part number (1 or 2) to the corresponding path:
        os.system('mv %s' % 'ipart.dat ../../../PART' + str(ipart) + '/Kernels/Iters/iter1/')

    print('parallel kernel calculation')
    processes = ('Master_iterations_part_1_moduled.py', 'Master_iterations_part_2_moduled.py')
    pool = Pool(processes=2)
    #    processes = ('Master_iterations_part_1_multi_taper.py', 'Master_iterations_part_2_multi_taper.py','Master_iterations_part_3_multi_taper.py', 'Master_iterations_part_4_multi_taper.py')
    #    pool = Pool(processes=4)
    pool.map(run_process, processes)
    #Save the kernels and Hessians as GP_shoti.txt, GS_shoti.txt and HP_shoti.txt, HS_shoti.txt in All_shots:
    print('Finish copy data and kernels')

####Finish parallel calculation of the kernels:
    #Sum kernels and precondition by the approcimated Hessians:
    #Save the summed kernels and Hessians as GP.txt, GS.txt and HP.txt, HS.txt in the running folder (Kernel/Iter/iter1/):
    os.system('python sum_gradients_moduled.py')
    #os.system('python Sum_Gradients_nShot_vsp_save_hessian.py')
    print('finish summing kernels')

    #    #################################
    #L-BFGS gradients calculation (Zhu, 2015).
    #Save gradient in /Dump as Gradp_iter_i.txt and Grads_iter_i.txt
    os.system('python precondition_gradient_L_BFGS_moduled.py')
    print('finish precoditioning kernels')

    ##############################
    #Misfit according to the current model.
    job_file5 = 'observed_misfit.sl'
    job_submitted(job_file5)
    #Save misfit and number of window picked to /Dump as err_iter_i.dat and nwin_iter_i.dat
    f_err0 = open('err_obs.dat', 'r');    Err = np.fromfile(f_err0, dtype=np.float64);    print('Err=' + str(Err))
    os.system('cp err_obs.dat Dump/err_iter_' + str(it) + '.dat')
    f = open('nwin.dat', 'r');    nwin = int(np.fromfile(f, dtype='int64'));    f.close()
    os.system('cp nwin.dat Dump/nwin_iter_' + str(it) + '.dat')
    #Check multi-taper misfit and number of windows picked for the current iteration:
    print('[Err,nwin]=' + str([Err, nwin]))

    #Calculate the optimal step length for updating:
    print('Set the update step length')

    if (it > 2):#Start L-BFGS step-length search if iteration>2.
        #Update model with steplength = 1, save in Model/ as vs3dfile_opt.s, vp3dfile_opt.p and rho3dfile_opt.d:
        job_file = 'model_optimizing_bfgs.sl'
        job_submitted(job_file)
        print('forward simulation with perturbed model')
        #Forward simulation according to the updated model to generate synthetic waveform
        job_file = 'fdrun-mpi_Allshot_opt_moduled.sl'
        job_submitted(job_file)
        print('fw emod3d for all sources')
        #Misfit calculation for the current updated model:
        job_file = 'optimized_misfit.sl'
        job_submitted(job_file)
        print('optimize misfit')
        f_err = open('err_opt.dat', 'r');
        Err2 = np.fromfile(f_err, dtype=np.float64);
        os.system("rm err_opt.dat")
        print('Err2=' + str(Err2))

        #Put constrain on the L-BSGS update: go back to steepest decent method if the update by L-BFGS is too small or misfit does not decrease:
        if (np.abs(Err - Err2) > 0.01 * Err and Err2 < Err):
            # Save the optimal steplength and updated model for the next iteration in /Dump as step_iter_i.dat and
            # vs3dfile_iter_i.s, vp3dfile_iter_i.p and rho3dfile_iter_i.d
            print('Finish update model')
            os.system('mv %s' % 'Model/vs3dfile_opt.s Dump/vs3dfile_iter_' + str(it) + '.s')
            os.system('mv %s' % 'Model/vp3dfile_opt.p Dump/vp3dfile_iter_' + str(it) + '.p')
            os.system('mv %s' % 'Model/rho3dfile_opt.d Dump/rho3dfile_iter_' + str(it) + '.d')

            os.system('mv %s' % 'st.dat Dump/step_iter_' + str(it) + '.dat')
        else:
            #Go back to the stepest decent method if L-BFGS steplength does not sastify the update:
            print('Search for optimal step length')
            opt_step_L2, flag = step_length_moduled.step_length(Err, S, nShot, sNames, it)
            #opt_step_L2, flag = Step_length_moduled.Step_length_new(Err, S, nShot, sNames, it) #for smaller step length.
    else: #Go back to the stepest decent method if iterations<=2.
        print('Search for optimal step length')
        opt_step_L2, flag = step_length_moduled.step_length(Err, S, nShot, sNames, it)
        # opt_step_L2, flag = Step_length_moduled.Step_length_new(Err, S, nShot, sNames, it) #for smaller step length.
    #Save the optimal steplength and updated model for the next iteration in /Dump as step_iter_i.dat and
    #vs3dfile_iter_i.s, vp3dfile_iter_i.p and rho3dfile_iter_i.d
    print('Finish iteration')


# defining the variables
# conversion of days to units
def days_to_units(num_of_days, conversion_unit):
    """ return f"{num_of_days} days are  {num_of_days * to_seconds} {s_unit}"
    print(custom_message)"""
    if conversion_unit == "hours":
        return f"{num_of_days} have  {num_of_days * 24} {conversion_unit}"
    elif conversion_unit == "sec":
        return f"{num_of_days} have  {num_of_days * 24 * 60 * 60} {conversion_unit}"
    else:
        print("your conversion unit is not supported")

# user input for the program
# def validate_execute():
#     if user_var.isdigit():
#         user_input = int(user_var)
#         if user_input > 0:
#             calculate_days = days_to_units(user_input, "user input of the pring")
#             print(calculate_days)
#         elif user_input == 0:
#             print("you entered the 0, which is not valid")
#     else:
#         print("you entered string which is not valid input")

def validate_execute(days_units_dic):
    try:  # trying to handle error in general
        user_input_days = int(days_units_dic["days"])
        if user_input_days > 0:
            calculate_days = days_to_units(user_input_days, days_units_dic["unit"])
            print(calculate_days)
        elif user_input_days == 0:
            print("you entered the 0, which is not valid")
        else:
            print("you entered the negative number which is not valid")
    except ValueError:
        print("you entered string which is not valid input")

user_input_message = "Hey user, enter the num of days and conversion unit like 20:hours \n"


# @Time    : 2023/5/4 16:25
# @Author  : ygd
# @FileName: leetcode 146.py
# @Software: PyCharm

'''
leetcode 146
146. LRU 缓存
mid
https://leetcode.cn/problems/lru-cache/
'''

class DLinkedNode:
    def __init__(self, key=0, value=0):
        self.key = key
        self.value = value
        self.pre = None
        self.next = None

class LRUCache:
    def __init__(self, capacity):
        self.cache = dict()
        self.head = DLinkedNode()
        self.tail = DLinkedNode()
        self.head.next = self.tail
        self.tail.pre = self.head
        self.capacity = capacity
        self.size = 0

    def get(self, key):
        if key not in self.cache:
            return -1
        node = self.cache[key]
        self.moveToHead(node)
        return node.value

    def put(self, key, value):
        if key not in self.cache:
            node = DLinkedNode(key, value)
            self.cache[key] = node
            self.addToHead(node)
            self.size += 1
            if self.size > self.capacity:
                removed = self.removeTail()
                self.cache.pop(removed.key)
                self.size -= 1
        else:
            node = self.cache[key]
            node.value = value
            self.moveToHead(node)

    def addToHead(self, node):
        node.pre = self.head
        node.next = self.head.next
        self.head.next.pre = node
        self.head.next = node

    def removeNode(self, node):
        node.pre.next = node.next
        node.next.pre = node.pre

    def moveToHead(self, node):
        self.removeNode(node)
        self.addToHead(node)

    def removeTail(self):
        node = self.tail.pre
        self.removeNode(node)
        return node


import time
import netaddr
import logging

from threading import Thread
from web_service import ws_event
from ryu.lib import ofctl_v1_3
from ryu.lib.dpid import dpid_to_str
from ryu.ofproto import ether

from base.parameters import BusinessType, DefaultBusinessType
from base.parameters import server_tcp_port, ROUTE_TASK_HANDLE_INTERVAL
from base.parameters import FLOW_IDLE_TIMEOUT, FLOW_HARD_TIMEOUT, ROUTE_FLOW_PRIORITY
from base.parameters import MULTICAST_FLOW_IDLE_TIMEOUT, MULTICAST_FLOW_HARD_TIMEOUT
from link_monitor import link_monitor_main
from fault_recovery import fault_recovery_main
# from route_manage.RouteManage import system_performance_logger

FORMAT = '%(name)s[%(levelname)s]%(message)s'
logging.basicConfig(format=FORMAT)
logger = logging.getLogger(__name__)

logger.setLevel(logging.INFO)

class RouteTaskHandler(list):
    """
        handle route task in queue with window ROUTE_TASK_HANDLE_INTERVAL.
        merge requests for performance improvement.
    """
    def __init__(self, route_manage):
        super(RouteTaskHandler, self).__init__()

        self.route_manage = route_manage
        self.rt_interval = ROUTE_TASK_HANDLE_INTERVAL

        self._init_thread()

    def _init_thread(self):
        """init RouteTaskHandler thread."""
        logger.info('route task handler thread start with interval %fs', self.rt_interval)
        gc_thread = Thread(target=self._handle_task)
        gc_thread.setDaemon(True)
        gc_thread.start()

    def _handle_task(self):
        """
            handle the whole task queue, calculate route and deploy flow table.
        """
        while True:
            now_time = time.time()
            for i in list(range(len(self))):
                # get next undo task.
                entry = self[0]

                if entry.timestamp < now_time:
                    if isinstance(entry, RouteTaskEntry) or \
                       isinstance(entry, NATRouteTaskEntry):
                        # handle unicast request task.
                        link_list, link_cost = entry.route_calc()
                        if link_list is None:
                            logger.error("route path calculate failed/ no path exist.")
                            break

                        entry.deploy_flow_table(link_list, link_cost)
                        # system_performance_logger.handle_req_finish(time.time())
                        '''
                        Fault recovery
                        '''

                        # Update the request information and its route path information for fault_recovery
                        # self.route_manage.route_info_maintainer.update(self.route_manage, fault_recovery_main,
                        #                                                entry, link_list)
                    elif isinstance(entry, MulticastTaskEntry):
                        # handle multicast request task.
                        link_list, link_cost = entry.route_calc()
                        if link_list is None:
                            break

                        entry.deploy_flow_table(link_list, link_cost)

                    # pop task when is done.
                    self.pop(0)
                else:
                    # when all task timeout done.
                    break

            time.sleep(self.rt_interval)

    def update_entry(self, task_entry):
        """update route task entry."""
        self.append(task_entry)

class TaskEntryBase(object):
    """
        task entry base class, all task entry inherited from here.
    """
    def __init__(self, route_type, src_dpid, src_ip, src_port_no,
                 dst_dpid, dst_ip, dst_port_no, route_manage):
        # value in checker should not be None
        checker = [route_type, src_dpid, src_ip, dst_dpid, dst_ip]
        assert sum(1 for i in checker if i is None) == 0

        self.route_type = route_type
        self.src_dpid = src_dpid
        self.src_ip = src_ip
        self.src_port_no = src_port_no
        self.dst_dpid = dst_dpid
        self.dst_ip = dst_ip
        self.dst_port_no = dst_port_no
        self.timestamp = time.time()
        self.route_manage = route_manage
        pass

    def __str__(self):
        logger.exception("task entry string unset.")
        return None

    # @system_performance_logger.timer
    def route_calc(self):
        """calculate route for unicast request.

        :return:
        """
        if self.src_dpid == self.dst_dpid:
            link_list = [self.src_dpid]
            link_cost = 0
            # self.request_cache[(src_ip, dst_ip)][1] = link_list
            logger.info("src:%s, dst:%s, both connect to dpid:%s",
                        self.src_ip, self.dst_ip, self.src_dpid)
        else:
            self.route_manage.algorithm.update_link_status(link_monitor_main.global_link_table)
            try:
                business_type = BusinessType[self.route_manage.servers[self.dst_ip]]
            except KeyError:
                business_type = BusinessType[DefaultBusinessType]
            self.route_manage.algorithm.run(self.src_dpid, self.dst_dpid, business_type)
            link_list, link_cost = self.route_manage.algorithm.get_link(self.src_dpid,
                                                                        self.dst_dpid)
            # self.request_cache[(src_ip, dst_ip)][1] = link_list
            logger.info("src:%s, dst:%s, deploy link:%s, link cost:%s",
                        self.src_ip, self.dst_ip, link_list, link_cost)
        return link_list, link_cost

    def deploy_flow_table(self, link_list, link_cost):
        """Deploy flow tables of switches in both way, from the end of link_list to the start

        :param link_list: path list from source to destination
        :param link_cost: path cost
        :return:
        """
        pass

    @staticmethod
    def flow_mod(datapath, src_ip, dst_ip, inport, outport):
        """deploy flow table

        :param datapath: switch datapath
        :param src_ip: source ip address for matching
        :param dst_ip: destination ip address for matching
        :param inport: data in port number for matching
        :param outport: data out port number
        """
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP, in_port=inport,
                                ipv4_src=str(src_ip), ipv4_dst=str(dst_ip))

        actions = [parser.OFPActionOutput(outport)]

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]

        mod = parser.OFPFlowMod(datapath=datapath, priority=ROUTE_FLOW_PRIORITY,
                                idle_timeout=FLOW_IDLE_TIMEOUT,
                                hard_timeout=FLOW_HARD_TIMEOUT,
                                command=ofproto.OFPFC_ADD,
                                match=match, instructions=inst)
        datapath.send_msg(mod)

    def to_dict(self):
        pass

class RouteTaskEntry(TaskEntryBase):
    """data center inside route task entry

    :param route_type: ROUTE_TYPE_INTRA_TOPO
    :param src_dpid: source switch datapath id
    :param src_ip: source host ip address
    :param src_port_no: source switch port number
    :param dst_dpid: destination switch datapath id
    :param dst_ip: destination host ip address
    :param dst_port_no: destination switch port number
    """
    def __init__(self, route_type, src_dpid, src_ip, src_port_no,
                 dst_dpid, dst_ip, dst_port_no, route_manage):
        super(RouteTaskEntry, self).__init__(route_type, src_dpid, src_ip, src_port_no,
                                             dst_dpid, dst_ip, dst_port_no,
                                             route_manage)
        pass

    def __str__(self):
        return "RouteTaskEntry"

    def deploy_flow_table(self, link_list, link_cost):
        if len(link_list) == 1:
            dp = self.route_manage.switches.get_switch(link_list[0]).dp
            self.flow_mod(dp, self.dst_ip, self.src_ip, self.dst_port_no, self.src_port_no)
            self.flow_mod(dp, self.src_ip, self.dst_ip, self.src_port_no, self.dst_port_no)
            return True
        elif len(link_list) > 1:
            sw1 = self.route_manage.switches.get_switch(link_list[0])
            sw2 = self.route_manage.switches.get_switch(link_list[len(link_list) - 1])
            if len(link_list) == 2:
                self.flow_mod(sw2.dp, self.dst_ip, self.src_ip, self.dst_port_no, sw2.neighbors[sw1.dp.id][0])
                self.flow_mod(sw2.dp, self.src_ip, self.dst_ip, sw2.neighbors[sw1.dp.id][0], self.dst_port_no)
                self.flow_mod(sw1.dp, self.dst_ip, self.src_ip, sw1.neighbors[sw2.dp.id][0], self.src_port_no)
                self.flow_mod(sw1.dp, self.src_ip, self.dst_ip, self.src_port_no, sw1.neighbors[sw2.dp.id][0])
                return True
            else:
                links = []
                for num, dpid in enumerate(link_list):
                    sw = self.route_manage.switches.get_switch(dpid)
                    if num == 0:
                        self.flow_mod(sw.dp, self.src_ip, self.dst_ip,
                                      self.src_port_no, sw.neighbors[link_list[num+1]][0])

                        second_dpid = link_list[num+1]
                        first_port_no = sw.neighbors[second_dpid][0]
                        second_sw = self.route_manage.switches.get_switch(second_dpid)
                        second_port_no = second_sw.neighbors[dpid][0]
                        first_link = [dpid_to_str(sw.dp.id), first_port_no,
                                      dpid_to_str(second_sw.dp.id), second_port_no]
                        links.append(first_link)
                        continue
                    if num == len(link_list) - 1:
                        self.flow_mod(sw.dp, self.dst_ip, self.src_ip,
                                      self.dst_port_no, sw.neighbors[link_list[num-1]][0])
                        continue
                    self.flow_mod(sw.dp, self.src_ip, self.dst_ip,
                                  sw.neighbors[link_list[num-1]][0], sw.neighbors[link_list[num+1]][0])
                    self.flow_mod(sw.dp, self.dst_ip, self.src_ip,
                                  sw.neighbors[link_list[num+1]][0], sw.neighbors[link_list[num-1]][0])
                    # add ws_update event msg: middle links
                    current_dpid = dpid
                    next_dpid = link_list[num+1]
                    next_sw = self.route_manage.switches.get_switch(next_dpid)
                    current_port_no = sw.neighbors[next_dpid][0]
                    next_port_no = next_sw.neighbors[current_dpid][0]
                    current_link = [dpid_to_str(sw.dp.id), current_port_no,
                                    dpid_to_str(next_sw.dp.id), next_port_no]
                    links.append(current_link)

                # send GUI event
                if self.route_manage.algorithm_type == "GA":
                    self.route_manage.send_event_to_observers(ws_event.EventWebRouteSet(links))
                elif self.route_manage.algorithm_type == "Dij":
                    self.route_manage.send_event_to_observers(ws_event.EventWebRouteSetDij(links))
            self.flow_mod(sw2.dp, self.src_ip, self.dst_ip,
                          sw2.neighbors[link_list[len(link_list)-2]][0], self.dst_port_no)
            self.flow_mod(sw1.dp, self.dst_ip, self.src_ip,
                          sw1.neighbors[link_list[1]][0], self.src_port_no)
            return True
        else:
            logger.info("find path failed!")
            return False

    def to_dict(self):
        r = {'route_type': self.route_type,
             'src_dpid': self.src_dpid,
             'src_ip': self.src_ip,
             'src_port_no': self.src_port_no,
             'dst_dpid': self.dst_dpid,
             'dst_ip': self.dst_ip,
             'dst_port_no': self.dst_port_no}
        return r

class NATRouteTaskEntry(TaskEntryBase):
    def __init__(self, route_type, src_dpid, src_ip, src_port_no, dst_dpid, dst_ip, dst_port_no,
                 route_manage, gateway_ip, gateway_mac, server_mac, user_mac):
        super(NATRouteTaskEntry, self).__init__(route_type, src_dpid, src_ip, src_port_no,
                                                dst_dpid, dst_ip, dst_port_no,
                                                route_manage)
        self.gateway_ip = gateway_ip
        self.gateway_mac = gateway_mac
        self.server_mac = server_mac
        self.user_mac = user_mac
        pass

    def __str__(self):
        return "NATRouteTaskEntry"

    def update_attribute(self, dst_ip=None, dst_port_no=None, server_mac=None):
        if dst_ip:
            self.dst_ip = dst_ip
        if dst_port_no:
            self.dst_port_no = dst_port_no
        if server_mac:
            self.server_mac = server_mac
        pass

    def deploy_flow_table(self, link_list, link_cost):
        if len(link_list) > 1:
            sw1_dpid = link_list[0]
            sw2_dpid = link_list[len(link_list)-1]
            sw1 = self.route_manage.switches.get_switch(sw1_dpid)
            sw2 = self.route_manage.switches.get_switch(sw2_dpid)
            if len(link_list) == 2:
                self.flow_mod(sw2.dp, self.dst_ip, self.src_ip, self.dst_port_no, sw2.neighbors[sw1.dp.id][0])
                self.flow_mod(sw2.dp, self.src_ip, self.dst_ip, sw2.neighbors[sw1.dp.id][0], self.dst_port_no)
                self.flow_mod(sw1.dp, self.dst_ip, self.src_ip, sw1.neighbors[sw2.dp.id][0], self.src_port_no)
                self.flow_mod(sw1.dp, self.src_ip, self.dst_ip, self.src_port_no, sw1.neighbors[sw2.dp.id][0])
                return True
            else:
                links = []
                reverse_link_list = link_list[::-1]
                for num, dpid in enumerate(reverse_link_list):
                    sw = self.route_manage.switches.get_switch(dpid)
                    if num == 0:
                        if (sw.attribute == sw.AttributeEnum.access) and ((dpid, self.src_port_no) in
                                self.route_manage.fault_classifier.access_switch_to_user_ports):
                            self._user_to_server_flow_mod(sw.dp, self.src_ip, self.dst_ip,
                                                          sw.neighbors[reverse_link_list[num+1]][0],
                                                          self.gateway_ip, self.gateway_mac,
                                                          self.server_mac, self.user_mac)
                            self._server_to_user_flow_mod(sw.dp, self.src_ip, self.dst_ip, self.dst_port_no,
                                                          self.gateway_ip, self.gateway_mac,
                                                          self.server_mac, self.user_mac)
                        else:
                            self.flow_mod(sw.dp, self.src_ip, self.dst_ip,
                                          sw.neighbors[reverse_link_list[num+1]][0],
                                          self.dst_port_no)
                            self.flow_mod(sw.dp, self.dst_ip, self.src_ip,
                                          self.dst_port_no, sw.neighbors[reverse_link_list[num+1]][0])

                        second_dpid = reverse_link_list[num+1]
                        first_port_no = sw.neighbors[second_dpid][0]
                        second_sw = self.route_manage.switches.get_switch(second_dpid)
                        second_port_no = second_sw.neighbors[dpid][0]
                        first_link = [dpid_to_str(sw.dp.id), first_port_no,
                                      dpid_to_str(second_sw.dp.id), second_port_no]
                        links.append(first_link)
                        continue
                    if num == len(reverse_link_list) - 1:
                        if (sw.attribute == sw.AttributeEnum.access) and \
                                ((dpid, self.src_port_no) in
                                 self.route_manage.fault_classifier.access_switch_to_user_ports):
                            self._user_to_server_flow_mod(sw.dp, self.src_ip, self.dst_ip,
                                                          sw.neighbors[reverse_link_list[num-1]][0],
                                                          self.gateway_ip, self.gateway_mac,
                                                          self.server_mac, self.user_mac)
                            self._server_to_user_flow_mod(sw.dp, self.src_ip, self.dst_ip, self.src_port_no,
                                                          self.gateway_ip, self.gateway_mac,
                                                          self.server_mac, self.user_mac)
                        else:
                            self.flow_mod(sw.dp, self.src_ip, self.dst_ip,
                                          self.src_port_no, sw.neighbors[reverse_link_list[num-1]][0])
                            self.flow_mod(sw.dp, self.dst_ip, self.src_ip,
                                          sw.neighbors[reverse_link_list[num-1]][0], self.src_port_no)
                        continue
                    self.flow_mod(sw.dp, self.src_ip, self.dst_ip,
                                  sw.neighbors[reverse_link_list[num+1]][0],
                                  sw.neighbors[reverse_link_list[num-1]][0])
                    self.flow_mod(sw.dp, self.dst_ip, self.src_ip,
                                  sw.neighbors[reverse_link_list[num-1]][0],
                                  sw.neighbors[reverse_link_list[num+1]][0])
                    # add ws_update event msg: middle links
                    current_dpid = dpid
                    next_dpid = reverse_link_list[num+1]
                    next_sw = self.route_manage.switches.get_switch(next_dpid)
                    current_port_no = sw.neighbors[next_dpid][0]
                    next_port_no = next_sw.neighbors[current_dpid][0]
                    current_link = [dpid_to_str(sw.dp.id), current_port_no,
                                    dpid_to_str(next_sw.dp.id), next_port_no]
                    links.append(current_link)

                # send GUI event
                if self.route_manage.algorithm_type == "GA":
                    self.route_manage.send_event_to_observers(ws_event.EventWebRouteSet(links))
                elif self.route_manage.algorithm_type == "Dij":
                    self.route_manage.send_event_to_observers(ws_event.EventWebRouteSetDij(links))
            return True
        else:
            logger.info("find path failed!")
            return False

    @staticmethod
    def _user_to_server_flow_mod(datapath, user_ip, server_ip, outport,
                                 gateway_ip, gateway_mac, server_mac, user_mac):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # match by IP address of users and gateways
        format_match = {'dl_type': str(0x0800),
                        'nw_proto': 6,
                        'ipv4_src': str(user_ip),
                        'ipv4_dst': str(gateway_ip)}
        match = ofctl_v1_3.to_match(datapath, format_match)

        actions = [parser.OFPActionDecNwTtl(),
                   parser.OFPActionSetField(tcp_dst=int(server_tcp_port)),
                   parser.OFPActionSetField(ipv4_dst=netaddr.IPAddress(server_ip)),
                   parser.OFPActionSetField(eth_dst=netaddr.EUI(server_mac)),
                   parser.OFPActionOutput(outport)]

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]

        mod = parser.OFPFlowMod(datapath=datapath, flags=1,
                                priority=ROUTE_FLOW_PRIORITY, cookie=0,
                                buffer_id=ofproto.OFP_NO_BUFFER,
                                idle_timeout=FLOW_IDLE_TIMEOUT,
                                hard_timeout=FLOW_HARD_TIMEOUT,
                                command=ofproto.OFPFC_ADD,
                                match=match, instructions=inst)
        datapath.send_msg(mod)

    @staticmethod
    def _server_to_user_flow_mod(datapath, user_ip, server_ip, outport,
                                 gateway_ip, gateway_mac, server_mac, user_mac):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        # match by IP address of server and user
        format_match = {'dl_type': str(0x0800),
                        'nw_proto': 6,
                        'ipv4_src': str(server_ip),
                        'ipv4_dst': str(user_ip)}

        actions = [parser.OFPActionDecNwTtl(),
                   parser.OFPActionSetField(tcp_src=int(80)),
                   parser.OFPActionSetField(ipv4_src=netaddr.IPAddress(gateway_ip)),
                   parser.OFPActionSetField(eth_src=netaddr.EUI(gateway_mac)),
                   parser.OFPActionSetField(eth_dst=netaddr.EUI(user_mac)),
                   parser.OFPActionOutput(outport)]

        match = ofctl_v1_3.to_match(datapath, format_match)
        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]

        mod = parser.OFPFlowMod(datapath=datapath, flags=1,
                                priority=ROUTE_FLOW_PRIORITY, cookie=0,
                                buffer_id=ofproto.OFP_NO_BUFFER,
                                idle_timeout=FLOW_IDLE_TIMEOUT,
                                hard_timeout=FLOW_HARD_TIMEOUT,
                                command=ofproto.OFPFC_ADD,
                                match=match, instructions=inst)
        datapath.send_msg(mod)
        pass

    def to_dict(self):
        r = {'server_mac': self.server_mac,
             'gateway_ip': self.gateway_ip,
             'gateway_mac': self.gateway_mac,
             'route_type': self.route_type,
             'src_dpid': self.src_dpid,
             'src_ip': self.src_ip,
             'src_port_no': self.src_port_no,
             'dst_dpid': self.dst_dpid,
             'dst_ip': self.dst_ip,
             'dst_port_no': self.dst_port_no}
        return r

class MulticastTaskEntry(TaskEntryBase):
    """multicast route task entry

    :param route_type: ROUTE_TYPE_INTRA_TOPO
    :param src_dpid: group source switch datapath id
    :param src_ip: group source host ip address
    :param src_port_no: source switch port number
    :param dst_dpid_set: group destination switch datapath id
    :param group_ip: group ip address
    """
    def __init__(self, route_type, src_dpid, src_ip, src_port_no,
                 dst_dpid_set, group_ip, route_manage):
        super(MulticastTaskEntry, self).__init__(route_type, src_dpid, src_ip, src_port_no,
                                                 dst_dpid=dst_dpid_set, dst_ip=group_ip, dst_port_no=None,
                                                 route_manage=route_manage)
        pass

    def __str__(self):
        return "MulticastTaskEntry"

    # @system_performance_logger.timer
    def route_calc(self):
        """calculate route for multicast request."""
        self.route_manage.multicast_algorithm.update_link_status(link_monitor_main.global_link_table)
        self.route_manage.multicast_algorithm.run(self.src_dpid, self.dst_dpid, BusinessType["VIDEO"])
        link_list = self.route_manage.multicast_algorithm.get_link()

        logger.info("src:%s, dst:%s, deploy multicast link:%s",
                    self.src_ip, self.dst_ip, link_list)
        link_cost = None
        return link_list, link_cost

    def deploy_flow_table(self, link_list, link_cost):
        # get formatted link list and reverse for deployment.
        format_link_list = self._format_link_list(link_list)
        format_link_list.reverse()

        # get group information.
        group_info = self.route_manage.multicast_group[self.dst_ip]

        for link in format_link_list:
            dpid = link.keys()[0]
            info = link.values()[0]
            switch = self.route_manage.switches[dpid]

            # get inport
            if info['root'] is False:
                in_port = switch.neighbors[info['former']][0]
            else:
                in_port = self.src_port_no

            # get outports
            outports = []
            if info['end']:
                # add destination outport.
                group_outports = group_info[dpid].keys()
                for port in group_outports:
                    outports.append(port)
                    pass
            if len(info['next']) != 0:
                # add outport to next switch.
                for dpid in info['next']:
                    outports.append(switch.neighbors[dpid][0])
                    pass

            # deploy flow table
            self.flow_mod(switch.dp, self.src_ip, self.dst_ip,
                          in_port, outports)
        pass

    @staticmethod
    def flow_mod(datapath, src_ip, dst_ip, inport, outport):
        """for multicast support

        :param outport: data out ports number list
        """
        assert isinstance(outport, list)

        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP, in_port=inport,
                                ipv4_src=str(src_ip), ipv4_dst=str(dst_ip))

        actions = []
        for port in outport:
            actions.append(parser.OFPActionOutput(port))

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]

        mod = parser.OFPFlowMod(datapath=datapath, priority=ROUTE_FLOW_PRIORITY,
                                idle_timeout=MULTICAST_FLOW_IDLE_TIMEOUT,
                                hard_timeout=MULTICAST_FLOW_HARD_TIMEOUT,
                                command=ofproto.OFPFC_ADD,
                                match=match, instructions=inst)
        datapath.send_msg(mod)

    @staticmethod
    def _format_link_list(link_list):
        """format multicast link list for flow table deployment.

        :param link_list: set of every unicast link list
        :return format_link_list: set of switch for flow table deployment

        such as:
        link_list = [[1, 2, 3, 4], [1, 2, 5, 6], [1, 2, 5, 7]]
        format_link_list = [{1: {'shared': True, 'end': False, 'root': True, 'former': None, 'next': [2]}},
                            {2: {'shared': True, 'end': False, 'root': False, 'former': 1, 'next': [3, 5]}},
                            {3: {'shared': False, 'end': False, 'root': False, 'former': 2, 'next': [4]}},
                            {5: {'shared': True, 'end': False, 'root': False, 'former': 2, 'next': [6, 7]}},
                            {4: {'shared': False, 'end': True, 'root': False, 'former': 3, 'next': []}},
                            {6: {'shared': False, 'end': True, 'root': False, 'former': 5, 'next': []}},
                            {7: {'shared': False, 'end': True, 'root': False, 'former': 5, 'next': []}}]
        """
        branch_len = []
        for branch in link_list:
            branch_len.append(len(branch))

        max_depth = max(branch_len)

        format_link_list = []
        format_link_list_dpid = []
        for depth in range(max_depth):
            for branch_num in range(len(link_list)):
                if depth > (len(link_list[branch_num]) - 1):
                    continue

                dpid = link_list[branch_num][depth]
                if dpid not in format_link_list_dpid:
                    format_link_list_dpid.append(dpid)
                    format_link_list.append(
                        {dpid: {'former': None,     # former dpid
                                'next': [],         # next dpids
                                'root': False,      # is root of tree or not
                                'shared': False,    # is shared branch or not
                                'end': False}})     # is end of branch or not
                else:
                    index = format_link_list_dpid.index(dpid)
                    format_link_list[index][dpid]['shared'] = True

                index = format_link_list_dpid.index(dpid)
                if depth > 0:
                    former_dpid = link_list[branch_num][depth-1]
                    format_link_list[index][dpid]['former'] = former_dpid
                    if depth < (len(link_list[branch_num])-1):
                        next_dpid = link_list[branch_num][depth+1]
                        if next_dpid not in format_link_list[index][dpid]['next']:
                            format_link_list[index][dpid]['next'].append(next_dpid)
                    else:
                        format_link_list[index][dpid]['end'] = True
                else:
                    format_link_list[index][dpid]['root'] = True
                    next_dpid = link_list[branch_num][depth+1]
                    if next_dpid not in format_link_list[index][dpid]['next']:
                        format_link_list[index][dpid]['next'].append(next_dpid)

        return format_link_list

    def to_dict(self):
        r = {'route_type': self.route_type,
             'src_dpid': self.src_dpid,
             'src_ip': self.src_ip,
             'src_port_no': self.src_port_no,
             'dst_dpid': self.dst_dpid,
             'dst_ip': self.dst_ip,
             'dst_port_no': self.dst_port_no}
        return r


from tkinter import Tk, Frame, Label, Button
from time import sleep

class Question:
    def __init__(self, question, answers, correctLetter):
        self.question = question
        self.answers = answers
        self.correctLetter = correctLetter

    def check(self, letter, view):
        global right
        if(letter == self.correctLetter):
            label = Label(view, text="Tunggu!")
            right += 1
        else:
            label = Label(view, text="Tunggu!")
        label.pack()
        view.after(500, lambda *args: self.unpackView(view))

    def getView(self, window):
        view = Frame(window)
        Label(view, text=self.question, font="Times 20").pack()
        Button(view, text=self.answers[0], command=lambda *args: self.check("A", view)).pack()
        Button(view, text=self.answers[1], command=lambda *args: self.check("B", view)).pack()
        return view

    def unpackView(self, view):
        view.pack_forget()
        askQuestion()

def askQuestion():
    global questions, window, index, button, right, number_of_questions
    if(len(questions) == index + 1):
        Label(window, text="Berdasarkan hasil analisa anda dinyatakan mengalami gejala covid tingkat:").pack()
        if (right == 3):
            Label(window, text="Serius!!!", fg='red', font="Times 24").pack()
            Label(window, text="Segeralah mencari bantuan medis!", font="Times 20").pack()
            Label(window, text="Jangan lupa tetap patuhi protokol kesehatan 5M", font="Times 20").pack()
        elif (right == 2):
            Label(window, text="Sedang!!!", fg='red', font="Times 24").pack()
            Label(window, text="Anda cukup melakukan perawatan mandiri di rumah ", font="Times 20").pack()
            Label(window, text="Dengan perbanyak mengonsumsi makanan yang sehat, perbanyak minum air putih dan meminum obat ringan", font="Times 20").pack()
            Label(window, text="Jangan lupa tetap patuhi protokol kesehatan 5M", font="Times 20").pack()
        elif (right == 1):
            Label(window, text="Ringan!!!", fg='red', font="Times 24").pack()
            Label(window, text="Anda cukup melakukan perawatan mandiri di rumah", font="Times 20").pack()
            Label(window, text="Dengan mengonsumsi makanan yang sehat dan meminum obat penurun demam", font="Times 20").pack()
            Label(window, text="Jangan lupa tetap patuhi protokol kesehatan 5M", font="Times 20").pack()
        else :
            Label(window, text="Tidak terdampak", fg='red', font="Times 24").pack()
            Label(window, text="Meskipun tidak ada gejala anda tetap harus menjaga imunitas tubuh dan perbanyak melakukan aktivitas olahraga", font="Times 20").pack()
            Label(window, text="Agar terhindar dari gejala Covid-19", font="Times 20").pack()
            Label(window, text="Jangan lupa tetap patuhi protokol kesehatan 5M", font="Times 20").pack()
        return window

    button.pack_forget()
    index += 1
    questions[index].getView(window).pack()

#pertanyaan
questions = []
file = open("questions.txt", "r")
line = file.readline()
while(line != ""):
    questionString = line
    answers = []
    for i in range (2):
        answers.append(file.readline())
    correctLetter = file.readline()
    correctLetter = correctLetter[:-1]
    questions.append(Question(questionString, answers, correctLetter))
    line = file.readline()
file.close()
index = -1
right = 0
number_of_questions = len(questions)

#Tittle
window = Tk()
window.geometry("800x400")
window.title("Aplikasi Sistem Pakar")

welcome=Label(window,text="Aplikasi Pendiagnosa Gejala Covid-19", bg='yellow', font="Times 20").pack()

#button
button = Button(window, text="Start", command=askQuestion)
button.pack()

window.mainloop()


# Дан массив из целых чисел. Необходимо найти максимальную сумму подряд стоящих элементов.
# Пример: [-2,1,-3,4,-1,2,1,-5,4], вывод: 6, пояснение: [4, -1, 2, 1]
# Пример: [1], вывод: 1, пояснение: [1]
# Пример: [5,4,-1,7,8], вывод: 23, пояснение: [5,4,-1,7,8]

array = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
max_sum = 0
for i in range(len(array)):
    sum = 0
    for j in range(i, len(array)):
        sum += array[j]
        max_sum = max(sum, max_sum)
print(max_sum)


import time
import requests
from HTMLParser import HTMLParser
from collectors.lib.collectorbase import CollectorBase

SPARK_STANDALONE_MODE = 'spark_standalone_mode'
SPARK_YARN_MODE = 'spark_yarn_mode'
SPARK_MESOS_MODE = 'spark_mesos_mode'

REST_API = {
    "YARN_APPS_PATH": "ws/v1/cluster/apps",
    "SPARK_APPS_PATH": "api/v1/applications",
    "SPARK_MASTER_STATE_PATH": "json",
    "SPARK_MASTER_APP_PATH": "app",
    "MESOS_MASTER_APP_PATH": "frameworks"
}

# request :
# <track_url>/api/v1/applications/<is name , must return from 'api/v1/application' >/jobs

# spark Job Metrics
# [
#     {
#         "jobId": 0,
#         "name": "saveAsTextFile at NativeMethodAccessorImpl.java:-2",
#         "submissionTime": "2016-03-31T03:05:43.301GMT",
#         "completionTime": "2016-03-31T03:05:47.080GMT",
#         "stageIds": [
#             0,
#             1
#         ],
#         "status": "RUNNING",
#         "numTasks": 20,
#         "numActiveTasks": 30,
#         "numCompletedTasks": 40,
#         "numSkippedTasks": 50,
#         "numFailedTasks": 60,
#         "numActiveStages": 70,
#         "numCompletedStages": 80,
#         "numSkippedStages": 90,
#         "numFailedStages": 100
#     }
# ]
JOB_METRICS = [
    'numTasks',
    'numActiveTasks',
    'numCompletedTasks',
    'numSkippedTasks',
    'numFailedTasks',
    'numActiveStages',
    'numCompletedStages',
    'numSkippedStages',
    'numFailedStages'
]

# spark stage metric
# [
#     {
#         "status": "COMPLETE",
#         "stageId": 0,
#         "attemptId": 0,
#         "numActiveTasks": 100,
#         "numCompleteTasks": 101,
#         "numFailedTasks": 102,
#         "executorRunTime": 103,
#         "inputBytes": 104,
#         "inputRecords": 105,
#         "outputBytes": 106,
#         "outputRecords": 107,
#         "shuffleReadBytes": 108,
#         "shuffleReadRecords": 109,
#         "shuffleWriteBytes": 110,
#         "shuffleWriteRecords": 111,
#         "memoryBytesSpilled": 112,
#         "diskBytesSpilled": 113,
#         "name": "reduceByKey at <stdin>:1",
#         "details": "",
#         "schedulingPool": "default",
#         "accumulatorUpdates": []
#     }
# ]
STAGE_METRICS = [
    'numActiveTasks',
    'numCompleteTasks',
    'numFailedTasks',
    'executorRunTime',
    'inputBytes',
    'inputRecords',
    'outputBytes',
    'outputRecords',
    'shuffleReadBytes',
    'shuffleReadRecords',
    'shuffleWriteBytes',
    'shuffleWriteRecords',
    'memoryBytesSpilled',
    'diskBytesSpilled'
]

# spark executor metric
# [
#     {
#         "id": "driver",
#         "hostPort": "10.0.2.15:33870",
#         "rddBlocks": 99,
#         "memoryUsed": 98,
#         "diskUsed": 97,
#         "activeTasks": 96,
#         "failedTasks": 95,
#         "completedTasks": 94,
#         "totalTasks": 93,
#         "totalDuration": 92,
#         "totalInputBytes": 91,
#         "totalShuffleRead": 90,
#         "totalShuffleWrite": 89,
#         "maxMemory": 278019440,
#         "executorLogs": {}
#     }
# ]

EXECUTOR_METRICS = [
    'rddBlocks',
    'memoryUsed',
    'diskUsed',
    'activeTasks',
    'failedTasks',
    'completedTasks',
    'totalTasks',
    'totalDuration',
    'totalInputBytes',
    'totalShuffleRead',
    'totalShuffleWrite',
    'maxMemory'
]

# spacke rdd metric
# [
#     {
#         "id": 6,
#         "name": "PythonRDD",
#         "numPartitions": 2,
#         "numCachedPartitions": 2,
#         "storageLevel": "Memory Serialized 1x Replicated",
#         "memoryUsed": 284,
#         "diskUsed": 0
#     }
# ]
RDD_METRCIS = [
    'numPartitions',
    'numCachedPartitions',
    'memoryUsed',
    'diskUsed'
]

class Spark(CollectorBase):
    def __init__(self, config, logger, readq):
        super(Spark, self).__init__(config, logger, readq)

        self.spark_cluster_mode = self.get_config('spark_cluster_mode', SPARK_STANDALONE_MODE)
        self.host = self.get_config('spark_host', "localhost")
        self.port = self.get_config('spark_port', 8080)
        self.spark_url = 'http://%s:%s' % (self.host, self.port)

    def __call__(self):
        try:
            spark_apps = self._get_running_apps()
            self._spark_job_metrics(spark_apps)
            self._spark_stage_metrics(spark_apps)
            self._spark_executor_metrics(spark_apps)
            self._spark_rdd_metrics(spark_apps)
            self._readq.nput("spark.state %s %s" % (int(time.time()), '0'))
        except Exception as e:
            self._readq.nput("spark.state %s %s" % (int(time.time()), '1'))
            self.log_exception('exception collecting spark metrics %s' % e)

    def _get_running_apps(self):
        self.log_info("Choose Spark Cluster Mode : %s" % self.spark_cluster_mode)
        if self.spark_cluster_mode is None:
            raise Exception('spark_cluster_node must not be none')

        if self.spark_cluster_mode == SPARK_STANDALONE_MODE:
            return self._standalone_init()

        elif self.spark_cluster_mode == SPARK_MESOS_MODE:
            running_apps = self._mesos_init()
            return self._get_spark_app_ids(running_apps)

        elif self.spark_cluster_mode == SPARK_YARN_MODE:
            running_apps = self._yarn_init()
            return self._get_spark_app_ids(running_apps)

        else:
            self._readq.nput("spark.state %s %s" % (int(time.time()), '1'))
            raise Exception('Invalid setting for spark_cluster_mode. Received %s.' % (self.spark_cluster_mode))

    def _spark_job_metrics(self, running_apps):
        try:
            for app_id, (app_name, tracking_url) in running_apps.iteritems():
                i = 0
                ts = time.time()

                for job in self.request(url_join_4(tracking_url, REST_API["SPARK_APPS_PATH"], app_name, 'jobs')):
                    i = i + 1
                    for metric in JOB_METRICS:
                        self._readq.nput('spark.job.%s %d %d host=%s name=%s id=%s' % (metric, ts, job[metric], self.host, app_name, job['jobId']))

                self._readq.nput('spark.job.count %d %d host=%s' % (ts, i, self.host))
        except Exception as e:
            self._readq.nput("spark.state %s %s" % (int(time.time()), '1'))
            self.log_exception('exception collecting spark job metrics %s' % e)

    def _spark_stage_metrics(self, running_apps):
        try:
            for app_id, (app_name, tracking_url) in running_apps.iteritems():
                i = 0
                ts = time.time()

                for stage in self.request(url_join_4(tracking_url, REST_API["SPARK_APPS_PATH"], app_name, 'stages')):
                    i = i + 1
                    for metric in STAGE_METRICS:
                        self._readq.nput('spark.stage.%s %d %d host=%s name=%s id=%s' % (metric, ts, stage[metric], self.host, app_name, stage['stageId']))

                self._readq.nput('spark.stage.count %d %d host=%s' % (ts, i, self.host))
        except Exception as e:
            self._readq.nput("spark.state %s %s" % (int(time.time()), '1'))
            self.log_exception('exception collecting spark stage metrics %s' % e)

    def _spark_executor_metrics(self, running_apps):
        try:
            for app_id, (app_name, tracking_url) in running_apps.iteritems():
                i = 0
                ts = time.time()

                for executor in self.request(url_join_4(tracking_url, REST_API["SPARK_APPS_PATH"], app_name, 'executors')):
                    i = i + 1
                    for metric in EXECUTOR_METRICS:
                        self._readq.nput('spark.executor.%s %d %d host=%s name=%s id=%s' % (metric, ts, executor[metric], self.host, app_name, executor['id']))

                self._readq.nput('spark.executor.count %d %d host=%s' % (ts, i, self.host))
        except Exception as e:
            self._readq.nput("spark.state %s %s" % (int(time.time()), '1'))
            self.log_exception('exception collecting spark stage metrics %s' % e)

    def _spark_rdd_metrics(self, running_apps):
        try:
            for app_id, (app_name, tracking_url) in running_apps.iteritems():
                i = 0
                ts = time.time()

                for rdd in self.request(url_join_4(tracking_url, REST_API["SPARK_APPS_PATH"], app_name, 'storage/rdd')):
                    i = i + 1
                    for metric in RDD_METRCIS:
                        self._readq.nput('spark.rdd.%s %d %d host=%s name=%s id=%s' % (metric, ts, rdd[metric], self.host, app_name, rdd['id']))

                self._readq.nput('spark.rdd.count %d %d host=%s' % (ts, i, self.host))
        except Exception as e:
            self._readq.nput("spark.state %s %s" % (int(time.time()), '1'))
            self.log_exception('exception collecting spark stage metrics %s' % e)

    def _standalone_init(self):
        # Return a dictionary of {app_id: (app_name, tracking_url)} for the running Spark applications
        jdata = self.request(url_join_2(self.spark_url, REST_API['SPARK_MASTER_STATE_PATH']))
        running_apps = {}

        if jdata.get('activeapps'):
            for app in jdata['activeapps']:
                app_id = app.get('id')
                app_name = app.get('name')

                # Parse through the HTML to grab the application driver's link
                app_url = self._get_standalone_app_url(app_id)

                if app_id and app_name and app_url:
                    running_apps[app_id] = (app_name, app_url)

        return running_apps

    def _yarn_init(self):
        running_apps = {}

        metrics_json = self.request(url_join_3(self.spark_url, REST_API['YARN_APPS_PATH'], "states=RUNNING&applicationTypes=SPARK"))
        if metrics_json.get('apps'):
            if metrics_json['apps'].get('app') is not None:

                for app_json in metrics_json['apps']['app']:
                    app_id = app_json.get('id')
                    tracking_url = app_json.get('trackingUrl')
                    app_name = app_json.get('name')

                    if app_id and tracking_url and app_name:
                        running_apps[app_id] = (app_name, tracking_url)

        return running_apps

    def _mesos_init(self):
        running_apps = {}

        metrics_json = self.request(url_join_2(self.spark_url, REST_API['MESOS_MASTER_APP_PATH']))
        if metrics_json.get('frameworks'):
            for app_json in metrics_json.get('frameworks'):
                app_id = app_json.get('id')
                tracking_url = app_json.get('webui_url')
                app_name = app_json.get('name')

                if app_id and tracking_url and app_name:
                    running_apps[app_id] = (app_name, tracking_url)

        return running_apps

    def _get_standalone_app_url(self, app_id):
        '''
        Return the application URL from the app info page on the Spark master.
        Due to a bug, we need to parse the HTML manually because we cannot
        fetch JSON data from HTTP interface.
        '''

        headers = {'Accept-Encoding': 'UTF-8'}
        try:
            url = url_join_3(self.spark_url, REST_API['SPARK_MASTER_APP_PATH'], "appId=" + app_id)
            app_page = requests.get(url , headers)
            # parser html and get app_detail_direct_link
            parser = SparkParser()
            parser.feed(app_page.text)
            parser.close()
            app_detail_ui_links = parser.href

            if app_detail_ui_links and len(app_detail_ui_links) == 1:
                return parser.href
            else :
                self.log_info ("Can not get any director link form spark standalone apps pages. Maybe parser would have problem: %s" % url)

        except Exception :
            self._readq.nput("spark.state %s %s" % (int(time.time()), '1'))
            self.log_exception("Can not access SPARK_MASTER_APP_PATH %s" % url)
            raise HTTPError(app_page)

    def _get_spark_app_ids(self, running_apps):
        '''
        Because appname in yarn doesn't as same as spark. so must be transform the name;
        Traverses the Spark application master in YARN to get a Spark application ID.
        Return a dictionary of {app_id: (app_name, tracking_url)} for Spark applications
        '''
        spark_apps = {}
        for app_id, (app_name, tracking_url) in running_apps.iteritems():
            response = self.request(url_join_2(tracking_url,REST_API["SPARK_APPS_PATH"]))

            for app in response:
                app_id = app.get('id')
                app_name = app.get('name')

                if app_id and app_name:
                    spark_apps[app_id] = (app_name, tracking_url)

        return spark_apps

    def request(self, url):
        headers = {'Content-Type': 'application/json'}
        resp = requests.get(url, headers=headers)
        if resp.status_code != 200:
            self.log_exception("spark collector can not access url : %s" % url)
            raise HTTPError(url)

        return resp.json()

# Get Url and Parse form Spark standalone page
#

#
Application Detail UI

#

class SparkParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.temp = None
        self.href = None

    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            for name, value in attrs:
                if name == 'href':
                    self.temp = value

    def handle_data(self, data):
        if data == 'Application Detail UI':
            self.href = self.temp

class HTTPError(RuntimeError):
    def __init__(self, resp):
        RuntimeError.__init__(self, str(resp))
        self.resp = resp

def url_join_2(prefix, uri):
    return "%s%s" % (prefix, uri)

def url_join_3(prefix, uri, param):
    return "%s/%s?%s" % (prefix, uri, param)

def url_join_4(prefix, uri, appId, service):
    return "%s%s/%s/%s" % (prefix, uri, appId, service)


first_word, second_word = input().split()
final_result = 0

diff = (len(first_word) - len(second_word))
if diff > 0:
    second_word += chr(1) * diff
else:
    first_word += chr(1) * abs(diff)

for index in range(len(first_word)):
    current_result = ord(first_word[index]) * ord(second_word[index])
    final_result += current_result
    current_result = 0
print(final_result)

PYTHON FUNDAMENTALS/Text processing/Exercise/02. Character Multiplier.py


#!/usr/bin/env pypy3

import re
import sys
import time
from typing import List, Match, Optional
from copy import copy, deepcopy
from collections import defaultdict
from itertools import repeat
from functools import partial
from advent import sirange, srange, nddict
import pprint
import math
if type(__builtins__) is not dict or 'profile' not in __builtins__: profile=lambda f:f;
sys.setrecursionlimit(10000000)

ADVENTDAY="06"
test = False
debug = False
stdin = False
INFILENAME = f"inputs/{ADVENTDAY}.txt"
for arg in sys.argv:
    if arg == "--test":
        test = True
        INFILENAME = f"inputs/{ADVENTDAY}.test.txt"
    if arg == "--debug":
        debug = True
    if arg == "--stdin":
        stdin = True

NN = 2**16
print(f"NN = {NN}")
# Utilities
def rematch(pattern: str, s: str) -> Optional[Match]:
    return re.fullmatch(pattern, s)

def sirange(start: int, stop: int):
    stop += 1 if stop >= start else -1
    m = 1 if stop >= start else -1
    return range(start, stop, m)

def srange(start: int, stop: int):
    m = 1 if stop >= start else -1
    return range(start, stop, m)

def pp(stuff):
    print('-'*30)
    p = pprint.PrettyPrinter(indent=4, width=40, depth=3, compact=True)
    p.pprint(stuff)
    print('-'*30)

print(f"\n{'=' * 30}\n")

# Input parsing
input_start = time.time()
if stdin:
    lines: List[str] = [l.strip() for l in sys.stdin.readlines()]
else:
    with open(INFILENAME) as f:
        lines: List[str] = [l.strip() for l in f.readlines()]

input_end = time.time()

# Part 1
########################################################################################
print("Part 1:")

def part1() -> int:
    global ADVENTDAY, test, pp
    #G = defaultdict(int)
    G = []
    D = 6
    N = 1
    for f in [int(x) for x in lines[0].split(',')]:
        G.append(f)
    first = len(G)
    prev = len(G)
    S = []
    dd = 80
    if test:
        dd = 80
    else:
        dd = 256
    for d in range(0, dd, 2):
        print(f"day {d}")
        new = []
        for i,v in enumerate(G):
            if v <= 0:
                G[i] = 6 + abs(v)
                new.append(8+abs(v))
            else:
                G[i] -= 2
        G += new
    return len(G)

#print(part1())

D = defaultdict(int)

@profile
def c(f: int, d: int):
    global D
    if (f,d) in D:
        return D[(f,d)]
    if f > d or d == 0:
        D[(f,d)] = 1
        return 1
    if f == 0:
        D[(f,d)] = c(0, d - 7) + c(0, d - 9)
        return D[(f,d)]
    else:
        n = min(f,d)
        s = c(f-n,d-n)
        D[(f-n,d-n)] = s
        return s

@profile
def part2():
    global ADVENTDAY, test, pp, NN, D
    N = dict()
    GG = []
    for f in [int(x) for x in lines[0].split(',')]:
        GG.append(f)
    for f in range(6, 0, -1):
        N[f] = c(f, NN)
    T = 0
    for f in GG:
        T += N[f]
    print(len(D))
    rate = defaultdict(int)
    return T

def part22():
    global NN, D
    GG = defaultdict(int)
    for f in [int(x) for x in lines[0].split(',')]:
        GG[f] += 1
    for i in range(1,7):
        GG[0] += 1

print("Part 2:")
print(math.log(part2(),2))


# # ---------- filter()------------ #
# """
# filter - фильтрует по определенному критерию
# создать новый список четных чисел из исходного списка

# """
# l = [2,5,34,78889,9,44]
# new_l = list(filter(lambda n: n%2==0, [2,5,34,78889,9,44]))

# print(new_l)

# # ---------- map()------------ #
# """
# map - формирует новый *список* по определенному критерию
# """

# l = [2,5,34,78889,9,44]
# newl = list(map(lambda x: x*2, l))

# print(newl)

# ----------задание------------ #
"""
дан список чисел, необходимо создать новый список из строковых чисел

пример
[2,5,34,78889,9,44]
вывод
['2','5'...]

"""
# l = [2,5,34,78889,9,44]
# newl = list(map(lambda el: str(el),l))
# # #-------------тоже самое что и выше на одну строку-----------------------#
# # new_l = []
# # for el  in l:
# #     new_l.append(str(el))
# # #--------------------------------------------------------------------#
# print(newl)

# ----------задание------------ #
"""
дан список чисел
неоходимо сформировать новый список с простыми числами
* совет функцию
"""

#lambda x: действие при true if услове else действие при false
# def f(x):
#     if x<2:
#         return False
#     for i in range(2, int(x**0.5)+1):
#         if x % i == 0:
#             return False
#     return True

# l = [2,5,34,78889,9,44]
# new_l = list(filter(lambda el: f(el), l))
# # # # #-------------тоже самое что и выше на одну строку-----------------------#

# # new_list = []
# # for el in l:
# #     if f(el):
# #         new_list.append(el)
# # # # #--------------------------------------------------------------------#

# print(new_l)

# # ----------задание------------ #
# """
# дан список чисел
# посчитать сумму четных цифр
# * совет создать новый список

# """

# l = list(range(1, 25)) # [1,2,3...23,24]
# b = 0
# new_l = list(filter(lambda x: x % 2 == 0, l)) # сформируетсясписок четных чисел

# print(new_l)
# #----------1 способ подсчета суммы-------------#
# for i in new_l:
#     b = b + i
# #-----------------------#\

# #----------2 способ подсчета суммы-------------#
# b = sum(new_l)
# #-----------------------#\

#-------------------reduce()------------------------#
# #----------3 способ подсчета суммы-------------#
# from functools import reduce
# b = reduce(lambda x, x1: x+x1, new_l)

# print(b)

# # ----------задание------------ #
# """
# дан список чисел
# посчитать произведение двузначных чисел # 10 45 87
# * совет создать новый список

# """
# #------мини-задание-------#
# """
# написать лямбда функцию для формирования случайных чисел в списке
# """
# import random as r
# l = []
# func = lambda x: [r.randint(1, 100) for el in range(r.randint(1, 10))]
# l = func(l)

# b = 1
# new_l = list(filter(lambda x: 10 <= x <= 100, l))
# # new_l = list(filter(lambda x: len(str(x))==2, l)) # 2 способ

# print(new_l)
# # # #----------1 способ подсчета произведения-------------#
# # for i in new_l:
# #     b = b * i
# # #--------------------------------------------------------#
# from functools import reduce
# b = reduce(lambda x,x1: x*x1, new_l)

# print(b)

#------------------------------строки-----------------------------------#

"""
"строка" - ['c','т'...'a']
'строка'
''' строка''' сюда же   """ """
"""
# s = "это строка"
# print(s[2])
# for symbol in s:
#     print(symbol)

# s = 'string'
# print(s.find('s',1,3)) # -1 -не нашел такой элемент

# #------------------задание-----------------
# """
# Даны строка и слово для поиска. Посчитайте сколько раз в строке встречается
# искомое слово. Полученное число выведите на экран
# 1. найти слово в строке
# 2. посчитать кол-во повторений
# """
# s = 'cat is not a dog. cat is beautiful'
# word = 'cat'
# print(s.count(word))

# #------------------задание-----------------
# """
# Даны строка и символ для поиска. Посчитайте сколько раз в строке встречается
# искомое символ без учета регистра(может любым). Полученное число выведите на экран
# 1. найти слово в строке
# 2. посчитать кол-во повторений
# """
# s = 'cat is not a dog. cat is beautiful'
# word = 'c'
# #считаем как дано
# print(s.count(word))
# # выполнить проверку на регистр
# if word.isupper():
#     print(s.count(word.lower()), word.lower(), word)
# else:
#     print(s.count(word.upper()), word.upper(), word)

#--------------------------------задание-----------------#
"""
Строка состоит из символов X, Y и Z.
Определите длину самой длинной последовательности, состоящей из символов X. Хотя бы один символ X
находится в последовательности.

XYXXXXYZXXYZ
X - ПОДХОДИТ 1
XXXX - 4
XX - 2
НАИБОЛЬШАЯ 4
"""
# s = "XYXXXXYZXXYZXXXXXX"
# counter = 0
# max_count = 0
# for e in s:
#     if e == 'X':
#         counter += 1
#     else:
#         if counter > max_count:
#             max_count = counter
#         counter = 0
# if counter > max_count:
#     max_count = counter
# print(max_count)

# #------2 способ------#
# list_ = []
# count_list = []
# for i in 'XYXXXXYZXXYZ':
#     if i == 'X':
#         list_.append(i)
#     else:
#         print(list_)
#         count_list.append(len(list_))
#         list_.clear()

# print(max(count_list))

#

# #--------------------------------задание--------------------------------------#
"""
Строка состоит из символов X, Y и Z.
Определите длину самой длинной последовательности, состоящей из символов XYZ. Хотя бы одна XYZ
находится в последовательности.

XYXYZXXYZXYZXYZ
XYZ - ПОДХОДИТ 1
XYZXYZXYZ - 3

НАИБОЛЬШАЯ 3
*совет используйте метод replace
"""
string = 'XYXYZXXYZXYZXYZ'
new_str = string.replace('XYZ', '1')
print(new_str)
counter = 0
max_count = 0
for i in new_str:
    if i == '1':
        counter += 1
    else:
        if counter > max_count:
            max_count = counter
        counter = 0

if counter > max_count:
    max_count = counter
print(max_count)


from django.urls import path, include
from . import views
from rest_framework import routers

app_name = 'blog'

router = routers.DefaultRouter()
router.register('post', views.PostViewSet)
router.register('category', views.PostCategoryViewSet)
router.register('author', views.AuthorViewSet)

urlpatterns = [
    path('', include(router.urls)),
]


INF: int = 1000

def get_shortest_path(weights: list[list[int]], start_index: int = 0) -> tuple[set[tuple[int, int]], list[int]]:
    size: int = len(weights)
    result: list[set[tuple[int, int]]] = list(set())

    vnear: int = None
    f: set = set()
    touch: list[int] = size * [0]
    length: list[int] = size * [0]
    shortest_distances: list[int] = size * [0]

    for i in range(0, size):
        if i != start_index:
            touch[i] = start_index
            length[i] = weights[start_index][i]

    for times in range(0, size - 1):
        minimum: int = INF
        for i in range(0, size):
            if i != start_index and 0 <= length[i] < minimum:
                minimum = length[i]
                vnear: int = i
        if vnear is None:
            break
        edge: tuple[int, int] = (touch[vnear], vnear)
        f.add(edge)

        for i in range(1, size):
            if length[vnear] + weights[vnear][i] < length[i]:
                length[i] = length[vnear] + weights[vnear][i]
                touch[i] = vnear
        shortest_distances[vnear] = length[vnear]
        length[vnear] = -1

    return f, shortest_distances

def get_shortest_path_from_all_nodes(weights: list[list[int]]) -> list[tuple[set[tuple[int, int]], list[int]]]:
    size: int = len(weights)
    result: list[tuple[set[tuple[int, int]], list[int]]] = list()

    for start_index in range(0, size):
        f, shortest_distances = get_shortest_path(weights=weights, start_index=start_index)
        result.append((f, shortest_distances))

    return result

def is_promising(index: int, columns: list) -> bool:
    k_index: int = 0
    is_switch: bool = True

    while k_index < index and is_switch:
        if columns[index] == columns[k_index] or abs(columns[index] - columns[k_index]) == index - k_index:
            is_switch = False
        k_index += 1

    return is_switch

def queens(index: int, columns: list, depth: int):
    results: list[list[int]] = list()
    queens_recursive(index=index, columns=columns, depth=depth, current_depth=0, results=results)

    print(f"Number of solutions: {len(results)}")

def queens_recursive(index: int, columns: list, depth: int, current_depth: int, results: list[list[int]]) -> int:
    if is_promising(index=index, columns=columns):
        if index == len(columns) - 1:
            results.append(columns)
            if current_depth == depth:
                print(columns)
            current_depth += 1
        else:
            for j in range(0, len(columns)):
                columns[index + 1] = j
                current_depth = queens_recursive(index=index + 1, columns=columns, depth=depth,
                                                 current_depth=current_depth, results=results)

    return current_depth

def main() -> None:
    weights: list[list[int]] = [[0, 7, 4, 6, 1],
                                [INF, 0, INF, INF, INF],
                                [INF, 2, 0, 5, INF],
                                [INF, 3, INF, 0, INF],
                                [INF, INF, INF, 1, 0]]

    f, distances = get_shortest_path(weights=weights)

    print(f"edges: {f}\ndistances: {distances}")

    size: int = 7
    columns: list[int] = size * [0]
    queens(index=-1, columns=columns, depth=1)

if __name__ == "__main__":
    main()


"""
https://leetcode.com/problems/course-schedule/
"""

from typing import List
from collections import deque, defaultdict

class Solution:
    def canFinish(
            self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        """
        Use BFS to perform topological sort.
        """
        todo, nodesWithPre = defaultdict(list), {}
        for curr, pre in prerequisites:  # Build from input.
            todo[pre].append(curr)
            nodesWithPre[curr] = nodesWithPre.get(curr, 0) + 1

        # Put all nodes which have empty pre nodes into the queue.
        queue = deque([i for i in range(numCourses) if i not in nodesWithPre])
        while queue:
            pre = queue.popleft()
            for curr in todo[pre]:
                nodesWithPre[curr] -= 1
                if not nodesWithPre[curr]:  # The current node has no pre.
                    queue.append(curr)

            todo.pop(pre)

        return not todo


# 残差网络(ResNet)
# 适用于粒子分辨 train_type=particle

import torch
import torch.nn as nn
from torch.nn import functional as F

class Residual(nn.Module):
    def __init__(self,input_channels,num_channels,use_1x1conv=False,strides=1):
        super().__init__()
        self.conv1 = nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1, stride=strides)
        self.conv2 = nn.Conv2d(num_channels, num_channels, kernel_size=3, padding=1)
        if use_1x1conv:
            self.conv3 = nn.Conv2d(input_channels, num_channels, kernel_size=1, stride=strides)
        else:
            self.conv3 = None
        self.bn1 = nn.BatchNorm2d(num_channels)
        self.bn2 = nn.BatchNorm2d(num_channels)

    def forward(self,X):
        Y = F.relu(self.bn1(self.conv1(X)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            X = self.conv3(X)
        Y += X
        return F.relu(Y)

class ResNet_old(nn.Module):
    def __init__(self,input_channel,input_size_x,input_size_y,output_size,init_weights=False):
        super().__init__()
        def resnet_block(input_channels,num_channels,num_residuals,first_block=False):
            blk=[]
            for i in range(num_residuals):
                if i == 0 and not first_block:
                    blk.append(Residual(input_channels, num_channels, use_1x1conv=True, strides=2))
                else:
                    blk.append(Residual(num_channels, num_channels))
            return blk

        b1 = nn.Sequential(nn.Conv2d(input_channel, 64, kernel_size=3, padding=1), nn.BatchNorm2d(64), nn.ReLU(), nn.MaxPool2d(kernel_size=3, padding=1))
        b2 = nn.Sequential(*resnet_block(64, 64, 1, first_block=True))
        b3 = nn.Sequential(*resnet_block(64, 128, 1))
        b4 = nn.Sequential(*resnet_block(128, 256, 1))
        b5 = nn.Sequential(*resnet_block(256, 512, 1))

        self.features=nn.Sequential(
            b1,b2,b3,b4,b5,
            nn.AdaptiveAvgPool2d((1,1)),
            nn.Flatten()
        )
        x=torch.randn(1,input_channel,input_size_x,input_size_y)
        linear_input_size=self.features(x).size(-1)
        # print(self.features(x).shape)
        self.classifer=nn.Sequential(
            nn.Linear(linear_input_size,output_size)
        )
        if init_weights:
            self._initialize_weights()

    def forward(self,x):
        x=self.features(x)
        x=self.classifer(x)
        return x

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0, 0.01)
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)


import pytest

from langchain_community.document_loaders.confluence import ConfluenceLoader

try:
    from atlassian import Confluence  # noqa: F401

    confluence_installed = True
except ImportError:
    confluence_installed = False

@pytest.mark.skipif(not confluence_installed, reason="Atlassian package not installed")
def test_load_single_confluence_page() -> None:
    loader = ConfluenceLoader(url="https://templates.atlassian.net/wiki/")
    docs = loader.load(page_ids=["33189"])

    assert len(docs) == 1
    assert docs[0].page_content is not None
    assert docs[0].metadata["id"] == "33189"
    assert docs[0].metadata["title"] == "An easy intro to using Confluence"
    assert docs[0].metadata["source"] == (
        "https://templates.atlassian.net/wiki/"
        "spaces/RD/pages/33189/An+easy+intro+to+using+Confluence"
    )

@pytest.mark.skipif(not confluence_installed, reason="Atlassian package not installed")
def test_load_full_confluence_space() -> None:
    loader = ConfluenceLoader(url="https://templates.atlassian.net/wiki/")
    docs = loader.load(space_key="RD")

    assert len(docs) == 14
    assert docs[0].page_content is not None

@pytest.mark.skipif(not confluence_installed, reason="Atlassian package not installed")
def test_confluence_pagination() -> None:
    loader = ConfluenceLoader(url="https://templates.atlassian.net/wiki/")
    # this will issue 2 requests; each with a limit of 3 until the max_pages of 5 is met
    docs = loader.load(space_key="RD", limit=3, max_pages=5)

    assert len(docs) == 5
    assert docs[0].page_content is not None

@pytest.mark.skipif(not confluence_installed, reason="Atlassian package not installed")
def test_pass_confluence_kwargs() -> None:
    loader = ConfluenceLoader(
        url="https://templates.atlassian.net/wiki/",
        confluence_kwargs={"verify_ssl": False},
    )

    assert loader.confluence.verify_ssl is False


import torch
import numpy as np
from torchvision import datasets, transforms
from base import BaseDataLoader

class MnistDataLoader(BaseDataLoader):
    """
    MNIST data loading demo using BaseDataLoader
    """
    def __init__(self, config):
        super(MnistDataLoader, self).__init__(config)
        self.data_dir = config['data_loader']['data_dir']
        self.data_loader = torch.utils.data.DataLoader(
            datasets.MNIST('../datasets', train=True, download=True,
                           transform=transforms.Compose([
                               transforms.ToTensor(),
                               transforms.Normalize((0.1307,), (0.3081,))
                           ])), batch_size=256, shuffle=False)
        self.x = []
        self.y = []
        for data, target in self.data_loader:
            self.x += [i for i in data.numpy()]
            self.y += [i for i in target.numpy()]
        self.x = np.array(self.x)
        self.y = np.array(self.y)

    def __next__(self):
        batch = super(MnistDataLoader, self).__next__()
        batch = [np.array(sample) for sample in batch]
        return batch

    def _pack_data(self):
        packed = list(zip(self.x, self.y))
        return packed

    def _unpack_data(self, packed):
        unpacked = list(zip(*packed))
        unpacked = [list(item) for item in unpacked]
        return unpacked

    def _update_data(self, unpacked):
        self.x, self.y = unpacked

    def _n_samples(self):
        return len(self.x)


# -*- coding: utf-8 -*-
"""
Created on Tue Nov 26 12:20:30 2019

Ej. 2.2: sumatoria de números.

@author: dai
"""
import leeDatos as ld
import numpy as np

#Prog. principal.
flec = open("Ej2_2_Sumatorias.txt", "r")
n= int(flec.readline()) #Cant. de valores para los arreglos.

#Lee los datos de los arreglos.
listaA= ld.lee_datos(flec,n)
a = np.array(listaA, dtype = 'float')
print("A: ",a)

listaB= ld.lee_datos(flec,n)
b = np.array(listaB, dtype = 'float')
print("B: ",b)
flec.close()

#Calcula la 1a. sumatoria
c = a * b
print("c: ",c)
print("1ra. sumatoria: ",c.sum())

#Calcula la 2nda. sumatoria
d= np.flip(b)   #Invierte el arreglo b
e = a*d
print ("d: ",d)
print("e: ",e)
print("2nda. sumatoria: ",e.sum())


def xyz(s):
    """Checks if the string 'xyz', not preceeded by '.', is contained in s."""
    # Check if the first 3 letters are 'xyz'
    if s[0:3] == 'xyz':
        return True
    # Check if the i-th character is 'x'
    for i in range(1, len(s)-2):
        if s[i] == 'x':
            # Check if the next 2 letters are 'yz' and the previous character isn't '.'
            if s[i+1:i+3] == 'yz' and s[i-1] != '.':
                return True
    return False

n = input("Enter string: ")
print(xyz(n))


"""
PPT Ejercicios propuestos, ej4
Numero primo, retornas true o false.
"""

def esPrimo(num):
    for i in range(2,num):
        if (num % i) == 0:
            return False
        return True

num = int(input("Ingrese numero a evaluar: "))
resultado = esPrimo(num)
print(resultado)

ARCHIVE_2022/Bastian-Guerra/Progamacion/Clases/Clase 6/PPT Ejercicios propuestos/ej4.py


import requests
from os import listdir

class YaUploader:
    def __init__(self, token: str):
        self.token = token

    def get_headers(self):
        return {
            'Authorization': f'OAuth {self.token}'
        }

    def _get_upload_url(self, file_path):
        upload_url = "https://cloud-api.yandex.net/v1/disk/resources/upload"
        headers = self.get_headers()
        params = {"path": file_path, "overwrite": "true"}
        response = requests.get(upload_url, headers=headers, params=params)
        response.raise_for_status()
        return response.json()

    def upload(self, path_to_dir, file_list):
        """Метод загружает файлы по списку file_list на яндекс диск"""
        for file_path in file_list:
            response_dict = self._get_upload_url(f'{path_to_dir}/{file_path}')
            upload_files_url = response_dict.get("href", "")
            with open(f'{path_to_dir}/{file_path}', 'rb') as file:
                response = requests.put(upload_files_url, files={"file": file})
                response.raise_for_status()
                if response.status_code == 201:
                    print('Status: OK')
        return 'Done'

def token_from_file():
    with open('token.txt') as t_file:
        token_f = t_file.read()
    return token_f

if __name__ == '__main__':
    path_to_dir = 'files'
    path_to_file = listdir(path_to_dir)
    token = token_from_file()
    uploader = YaUploader(token)
    result = uploader.upload(path_to_dir, path_to_file)
    print(result)