import fpdf
import json
import requests
import os
import sys
import time
from PIL import Image
# python3 -m pip install --upgrade pip
# python3 -m pip install --upgrade Pillow

fpdf.set_global("SYSTEM_TTFONTS", os.path.join(os.path.dirname(__file__),'fonts'))
# using NotoSans from https://www.google.com/get/noto/
# solution from here: https://stackoverflow.com/a/57360249/12616125 (otherwise there could be a UnicodeEncoding Error, fpdf uses latin-1

def getJson(manifest):
	try:
		myJson = requests.get(manifest).content
		#myJson.encode('utf-8')
		#myJson = myJson.encode('latin-1', 'replace').decode('latin-1')
		#print(myJson)
		myDict = json.loads(myJson)
		return myDict
	except:
		print('No valid input.')
		return None

def getImage(imageId, count, width):
	url = imageId+'/full/'+width+',/0/default.jpg'
	with open(str(count)+'.jpg', 'wb') as f:
		f.write(requests.get(url).content)

def writeMeta(metadata, pdf):
	pdf.set_font('NotoSans', 'B', 16)
	pdf.cell(40, 10, 'Metadata')
	pdf.ln(h = '10')
	pdf.set_font('NotoSans', '', 12)
	for entry in metadata:
		pdf.multi_cell(180, 10, entry['label']+': '+entry['value'])

def makeFrontpage(manifestDict, label):
	pdf = fpdf.FPDF()
	#pdf.set_doc_option('core_fonts_encoding', 'utf-8')
	pdf.add_font('NotoSans', style='', fname='NotoSans-Regular.ttf', uni=True)
	pdf.add_font('NotoSans', style='B', fname='NotoSans-Bold.ttf', uni=True)
	#pdf.add_font('NotoSans', style='I', fname='NotoSans-Italic.ttf', uni=True)
	#pdf.add_font('NotoSans', style='BI', fname='NotoSans-BoldItalic.ttf', uni=True)
	pdf.add_page()
	description = None
	headline = None
	attributionL = None
	lizenz = None
	description = manifestDict['description']
	headline = manifestDict['label']
	#print("headline: "+headline)
	pdf.set_font('NotoSans', '', 16)
	if headline is not None:
		pdf.multi_cell(180, 10, headline)
		#pdf.ln(h = '10')
	if label != '':
		print("label: "+label)
		pdf.set_font('NotoSans', 'B', 16)
		pdf.multi_cell(180, 10, label)
	pdf.set_font('NotoSans', '', 12)
	pdf.cell(40, 10, manifest)
	pdf.ln(h = '10')
	if description is not None:
		pdf.multi_cell(180, 10, description)
	attributionL = manifestDict['attribution'].split('<br/>')
	if attributionL is not None:
		for chunk in attributionL:
			#print("Attribution: "+chunk)
			pdf.multi_cell(180, 10, chunk)
			#pdf.ln(h = '10')
	if lizenz is not None:
		print("Lizenz: "+lizenz)
		pdf.multi_cell(180, 10, manifestDict['license'])
		#pdf.ln(h = '10')
	metadata = None
	try:
		metadata = manifestDict['metadata']
		if metadata is not None:
			writeMeta(metadata, pdf)
	except:
		pass
	finally:
		return pdf

def addImagesToPdf(manifestDict, width):
	f = makeFrontpage(manifestDict, '')
	sequences = manifestDict['sequences']
	canvases = sequences[0]['canvases']
	count = 1
	for canvas in canvases:
		imageId = canvas['images'][0]['resource']['service']['@id']
		getImage(imageId, count, width)
		print('Processing image '+str(count)+' of '+str(len(canvases)))
		imageName = str(count)+'.jpg'
		form = imageSizing(imageName)
		imageWidth = form[0]
		imageHeight = form[1]
		orientation = form[2]
		marginWidth = form[3]
		marginHeight = form[4]
		f.add_page(orientation)
		f.image(imageName, marginWidth, marginHeight, imageWidth, imageHeight)
		os.remove(str(count)+'.jpg')
		count += 1
	title = manifestDict['label']
	#pdf.output(dest='S').encode('latin-1','ignore')
	print('Processing file...')
	f.output(title+'.pdf', 'F')

def getImageIdRange(manifestDict, canvasId):
	sequences = manifestDict['sequences']
	canvases = sequences[0]['canvases']
	count = 0
	while canvases[count]['@id'] != canvasId:
		count += 1
		if count > len(canvases):
			print('Canvas-ID could not be found!')
			break
	imageId = canvases[count]['images'][0]['resource']['service']['@id']
	return imageId

def getRange(manifestDict, rangeId, width):
	sequences = manifestDict['sequences']
	structures = manifestDict['structures']
	for structure in structures:
		if rangeId == structure['@id']:
			# not working for the very first with label: content
			if len(structure['canvases']) > 0:
				f = makeFrontpage(manifestDict, structure['label'])
				count = 1
				for canvas in structure['canvases']:
					imageId = getImageIdRange(manifestDict, canvas)
					getImage(imageId, count, width)
					print('Processing image '+str(count)+' of '+str(len(structure['canvases'])))
					imageName = str(count)+'.jpg'
					form = imageSizing(imageName)
					imageWidth = form[0]
					imageHeight = form[1]
					orientation = form[2]
					marginWidth = form[3]
					marginHeight = form[4]
					f.add_page(orientation)
					f.image(imageName, marginWidth, marginHeight, imageWidth, imageHeight)
					os.remove(str(count)+'.jpg')
					count += 1
				title = manifestDict['label'] + structure['label']
				print('Processing file...')
				f.output(title+'.pdf', 'F')

def customPageNumbers(manifestDict, start, end, width):
	f = makeFrontpage(manifestDict, '- pages '+str(start)+' to '+str(end))
	sequences = manifestDict['sequences']
	canvases = sequences[0]['canvases']
	if start > len(canvases) or end > len(canvases):
		print("The numbers you have entered are too high for the specified document.")
	else:
		canvasSlice = canvases[start-1:end]
		count = 1
		for canvas in canvasSlice:
			imageId = canvas['images'][0]['resource']['service']['@id']
			getImage(imageId, count, width)
			print('Processing image '+str(count)+' of '+str(len(canvasSlice)))
			imageName = str(count)+'.jpg'
			form = imageSizing(imageName)
			imageWidth = form[0]
			imageHeight = form[1]
			orientation = form[2]
			marginWidth = form[3]
			marginHeight = form[4]
			f.add_page(orientation)
			f.image(imageName, marginWidth, marginHeight, imageWidth, imageHeight)
			os.remove(str(count)+'.jpg')
			count += 1
		title = manifestDict['label']+',pages'+str(start)+'-'+str(end)
		print('Processing file...')
		f.output(title+'.pdf', 'F')

def imageSizing(imageName):
    # from https://stackoverflow.com/questions/43767328/python-fpdf-not-sizing-correctly
	cover = Image.open(imageName)
	width, height = cover.size

    # convert pixel in mm with 1px=0.264583 mm
	width, height = float(width * 0.264583), float(height * 0.264583)

    # given we are working with A4 format size
	pdf_size = {'P': {'w': 210, 'h': 297}, 'L': {'w': 297, 'h': 210}}

    # get page orientation from image size
	orientation = 'P' if width < height else 'L'

    #  make sure image size is not greater than the pdf format size
	width = width if width < pdf_size[orientation]['w'] else pdf_size[orientation]['w']
	height = height if height < pdf_size[orientation]['h'] else pdf_size[orientation]['h']

	marginHeight = 0
	marginWidth = 0

	# if the height of an image is less than a4, center the image vertically
	if height < pdf_size[orientation]['h']:
		# creating upper and bottom margin
		marginHeight = (pdf_size[orientation]['h'] - height) / 2.0

	# same with the width
	if width < pdf_size[orientation]['w']:
		marginWidth = (pdf_size[orientation]['w'] - width) / 2.0

	return [width, height, orientation, marginWidth, marginHeight]

start = time.time()

if len(sys.argv) >= 1:
	manifest = sys.argv[1] # the manifest.json url
	manifestDict = getJson(manifest)

	if len(sys.argv) == 2:
		print('No width provided! Using a default width of 1000 pixels.')
		width = '1000'
		addImagesToPdf(manifestDict, width)
	else:
		width = sys.argv[2] # width of the image in pixels

		if len(sys.argv) == 3:
			addImagesToPdf(manifestDict, width)

		if len(sys.argv) == 4:
			rangeId = sys.argv[3] # ID of a range like "https://iiif.ub.uni-leipzig.de/0000030884/range/LOG_0011"
			getRange(manifestDict, rangeId, width)

		if len(sys.argv) == 5:
			try:
				startPage = int(sys.argv[3]) # starting page of your custom section
				endPage = int(sys.argv[4]) # ending page
				if startPage > endPage:
					print("The starting page can't have a higher value than the ending page!")
				else:
					customPageNumbers(manifestDict, startPage, endPage, width)
			except:
				print("No valid numbers for the pages have been entered!")
else:
	print('No Json provided!')

end = time.time()
print('Done! Time used: '+str(end - start)+' seconds.')

# Jsons for testing:
# https://iiif.ub.uni-leipzig.de/0000000001/manifest.json (https://papyrusebers.de/), wegen Proportionen
# https://iiif.bodleian.ox.ac.uk/iiif/manifest/e800b13a-6699-49ae-9bc2-c9b8c35b7a25.json, wegen Kodierung der Metadaten und den Html Tags


# -*- coding: utf-8 -*-
"""
@author: Md Mosharaf Hossain
"""

import random
import numpy as np
import torch
import argparse
import json
from torch.utils.data import DataLoader
from transformers import (
    T5Tokenizer
)

from model import PInterp
from data import PIDataset
from config import Config
import utils

def set_seed(seed):
  random.seed(seed)
  np.random.seed(seed)
  torch.manual_seed(seed)
  if torch.cuda.is_available():
    torch.cuda.manual_seed_all(seed)

argParser = argparse.ArgumentParser()
argParser.add_argument("-c", "--config_path", help="path of the configuration file", required=True)
args        = argParser.parse_args()
config_path = args.config_path

# Step 1: Read parameters and set a seed ----------------------------------------------------
with open(config_path) as json_file_obj:
	params = json.load(json_file_obj)

params = Config(params)
set_seed(params.seed)

# Step 2: Get appropriate device ------------------------------------------------------------
if torch.cuda.is_available()==True and params.use_gpu:
    device = torch.device("cuda:"+str(params.device))
else:
    device = torch.device("cpu")

# Step 3: Read test dataset for evaluation--------------------------------------------------
test_data = utils.read_data(params.data_path["test"])

# Step 4: Get tokenizer --------------------------------------------------------------------
tokenizer = T5Tokenizer.from_pretrained(params.T5_path[params.T5_type])

# Step 5: Initialize model and load with the trained weights--------------------------------
map_location = 'cuda:{}'.format(params.device) if params.use_gpu else 'cpu'
state = torch.load(params.best_model_path, map_location=map_location)

model = PInterp(params, device, tokenizer)
model.load_state_dict(state['model'])
model.to(device)
model.eval()
print(f"Model is loaded from {params.best_model_path}")

# Step 5: Prepare the datasets for data loader -------------------------------------------------
test_dataset = PIDataset(tokenizer, test_data, params)

test_size = len(test_dataset)
batch_num = int(np.ceil(test_size/params.batch_size))
print(f"test_size: {test_size}, batch_num: {batch_num}")

# Step 6: Generate text for the test dataset-------------------------------------------------
test_output = []
test_loader = DataLoader(test_dataset, batch_size=params.batch_size, shuffle=False)
print(f"Test loader: {len(test_loader)}")

for batch_idx, batch in enumerate(test_loader):

    if params.use_multi_gpus:
        test_batch_output = model.module.predict(batch)
    else:
        test_batch_output = model.predict(batch)
    test_output.extend(test_batch_output)

utils.save_prediction_pi_formatted(test_output, params.num_return_sequences, params.output_path["test"])


import asyncio
from datetime import datetime
from elasticsearch import Elasticsearch, AsyncElasticsearch
from elasticsearch.helpers import async_streaming_bulk
import os

from dotenv import load_dotenv

load_dotenv()

# 非同期Elasticsearchクライアントのインスタンスを作成
async_es = AsyncElasticsearch(
    [
        f"http://{os.getenv('TARGET_ELASTICSEARCH_HOST')}:{os.getenv('TARGET_ELASTICSEARCH_PORT')}"
    ],
    basic_auth=(
        os.getenv("TARGET_ELASTICSEARCH_USERNAME"),
        os.getenv("TARGET_ELASTICSEARCH_PASSWORD"),
    ),
    request_timeout=60 * 60 * 24 * 7,
)

# 同期Elasticsearchクライアントのインスタンスを作成
es = Elasticsearch(
    [
        f"http://{os.getenv('TARGET_ELASTICSEARCH_HOST')}:{os.getenv('TARGET_ELASTICSEARCH_PORT')}"
    ],
    basic_auth=(
        os.getenv("TARGET_ELASTICSEARCH_SOFUE_WRITE_DATA_USERNAME"),
        os.getenv("TARGET_ELASTICSEARCH_SOFUE_WRITE_DATA_PASSWORD"),
    ),
    request_timeout=60 * 60 * 24 * 7,
)

async def create_index_and_insert_bulk(index_name, docs):
    # インデックスを作成
    if not es.indices.exists(index=index_name):
        es.indices.create(index=index_name)

    # async_streaming_bulkを使ってバルクインサート
    async for ok, response in async_streaming_bulk(async_es, docs):
        action, result = response.popitem()
        doc_id = result["_id"]
        if not ok:
            print(f"Failed to {action} document {doc_id}: {result}")
        else:
            print(f"Successfully {action} document {doc_id}")

async def main():
    # インデックス名とドキュメントデータ
    index_name = "sofue-test-index"

    docs = [
        {
            "_op_type": "create",
            "_index": index_name,
            "_source": {
                "timestamp": datetime.utcnow(),
                "message": f"message {i}"
            },
        }
        for i in range(10)
    ]

    # バルクインサート
    await create_index_and_insert_bulk(index_name, docs)

    # createメソッドを使って追加のドキュメントをインサート
    doc = {"timestamp": datetime.utcnow(), "message": "additional message"}
    res = es.index(index=index_name, body=doc)
    print("Created document:", res["_id"])

    # 非同期クライアントを閉じる
    await async_es.close()

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())


import tkinter as tk
import requests
import urllib
from io import BytesIO
from src.utils import helper, store
from src.constants import UI, WS
from src.models import L300_model
from src.modules.custom import PLabel, ToolTip
from uuid import getnode
from PIL import ImageTk, Image
from src.utils import scryto
import urllib
import sys
from datetime import datetime, timedelta
import time

class P300(tk.Frame):
    def __init__(self, parent, p300=None, parentTab=None, *args, **kwargs):
        super(P300, self).__init__(parent, *args, **kwargs)
        self.parent = parent
        self.parentTab = parentTab
        self.cell_width = 360
        self.top_height = 203
        self.bot_height = 25
        self.botBg = "#F4ECF7"
        self.p300 = p300
        self.setData(p300)

        self.initGUI()

    def setData(self, p300):
        self.PP300 = self.p300["PP300"] if "PP300" in p300 else 0
        self.PV301 = self.p300["PV301"] if "PV301" in p300 else ""
        self.PN303 = self.p300["PN303"] if "PN303" in p300 else 0
        self.PV307 = self.p300["PV307"] if "PV307" in p300 else ""
        self.PO322 = self.p300["PO322"] if "PO322" in p300 else {}
        self.FT300 = self.p300["FT300"] if "FT300" in p300 else 0
        if "live" in self.PO322:
            patern = (
                "%Y-%m-%dT%H:%M:%S.%fZ"
                if "." in self.PO322["live"]["time"]
                else "%Y-%m-%dT%H:%M:%SZ"
            )
            self.liveTime = datetime.strptime(self.PO322["live"]["time"], patern)

    def initGUI(self):
        ww = self.cell_width + 5
        wh = 5 + self.top_height + self.bot_height
        self.wrapper = tk.Frame(
            self, relief=tk.FLAT, bd=1, bg="#fff", width=ww, height=wh
        )
        self.wrapper.pack(fill=tk.BOTH)
        self.initTOP()
        self.initBOTTOM()

    def initTOP(self):
        self.top = tk.Frame(
            self.wrapper,
            bd=0,
            relief=tk.FLAT,
            bg="#999",
            width=self.cell_width,
            height=self.top_height,
        )
        self.top.pack(side=tk.TOP)
        try:
            response = requests.get(self.PV307)
            im = Image.open(BytesIO(response.content))
        except requests.exceptions.MissingSchema:
            im = Image.open(helper._IMAGES_PATH + "splash2.png")
        #
        nW, nH, pdx, pdy = self.calcSizeAndPad(im.size)
        resized = im.resize((nW, nH), Image.ANTIALIAS)
        imgMedia = ImageTk.PhotoImage(resized)
        self.topImage = tk.Label(self.top, image=imgMedia, bg="#f2f2f2", cursor="hand2")
        self.topImage.photo = imgMedia
        #
        self.topImage.pack(padx=pdx, pady=pdy)

    def calcSizeAndPad(self, size):
        """
        if showFrame is `vertical`:
            if ratio(h) > :9:
                `calcByH`
            else:
                `calcByW`
        elif showFrame is `horizontal`:
            if ratio(w) > :16:
                `calcByW`
            else:
                `calcByH`
        """
        w, h = size
        r = w / h
        if w > h and r >= 16 / 9:
            return self.calcSizeByWidth(r)
        else:
            return self.calcSizeByHeight(r)

    def calcSizeByWidth(self, r):
        nW = self.cell_width
        nH = int(nW / r)
        pdx = 0
        pdy = int((self.top_height - nH) / 2)
        return nW, nH, pdx, pdy

    def calcSizeByHeight(self, r):
        nH = self.top_height
        nW = int(nH * r)
        pdx = int((self.cell_width - nW) / 2)
        pdy = 0
        return nW, nH, pdx, pdy

    def initBOTTOM(self):
        self.bottom = tk.Frame(
            self.wrapper,
            bd=5,
            relief=tk.FLAT,
            bg=self.botBg,
            width=self.cell_width,
            height=self.bot_height,
        )
        self.bottom.pack(side=tk.BOTTOM, fill=tk.X)
        # label
        self.lbl_name = PLabel(
            self.bottom,
            text=urllib.parse.unquote(self.PV301),
            justify=tk.LEFT,
            elipsis=22,
            bg=self.botBg,
            font=UI.TXT_FONT,
            fg="#000",
        )
        ToolTip(self.lbl_name, urllib.parse.unquote(self.PV301))
        self.lbl_name.pack(side=tk.LEFT)

        if self.parentTab.keyManager.existedKey(self.PP300):
            self.packCheckExisted()
        else:  # not existed check least of 3 hrs
            threeHrs = 3 * 60 * 60
            if self.getDifferenceTimeFromNowToLive() <= threeHrs:
                self.packBtnGetKey()
            else:
                self.packWaitTimeGetKey()

    def getDifferenceTimeFromNowToLive(self):
        now = datetime.utcnow().timestamp()
        live = self.liveTime.timestamp()
        return live - now

    def packBtnGetKey(self):
        # get key
        self.btnGetKey = tk.Button(
            self.bottom,
            text="Get Key",
            relief=tk.FLAT,
            command=self.genarateKeyAndSave,
            font=UI.TXT_FONT,
            cursor="hand2",
            bg="#ff2d55",
            fg="#fff",
        )
        self.btnGetKey.configure(width=7)
        self.btnGetKey.pack(side=tk.RIGHT, padx=1, pady=1)

    def packCheckExisted(self):
        # already
        imChk = ImageTk.PhotoImage(Image.open(f"{helper._ICON_PATH}check-green-s.png"))
        self.lblExisted = tk.Label(
            self.bottom, image=imChk, cursor="hand2", bg=self.botBg
        )
        self.lblExisted.image = imChk
        self.lblExisted.pack(side=tk.RIGHT, padx=5, pady=5)
        ToolTip(self.lblExisted, "Already key")

    def packWaitTimeGetKey(self):
        offset = datetime.now() - datetime.utcnow()
        timeTooltip = self.liveTime - timedelta(hours=3) + offset
        timeTooltipStr = datetime.strftime(timeTooltip, "%d/%m/%Y %H:%M")
        # already
        imChk = ImageTk.PhotoImage(Image.open(f"{helper._ICON_PATH}ic-wait.png"))
        self.lblExisted = tk.Label(
            self.bottom, image=imChk, cursor="hand2", bg=self.botBg, text="Waiting"
        )
        self.lblExisted.image = imChk
        self.lblExisted.pack(side=tk.RIGHT, padx=5, pady=5)
        ToolTip(self.lblExisted, "Can get key from: " + timeTooltipStr)

    def genarateKeyAndSave(self):
        if not self.parentTab.keyManager.existedKey(self.PP300):
            l300 = self.insertL300()
            URL, STREAMKEY = self.makeRTMP(l300)
            self.parentTab.saveKeyStream(
                {
                    "id": l300["PL300"],
                    "label": urllib.parse.unquote(self.PV301),
                    "key_a": URL,
                    "key_b": STREAMKEY,
                    "PLAY": l300["PLAY"],
                    "P300": self.p300,
                }
            )
        #
        self.btnGetKey.pack_forget()
        self.packCheckExisted()

    def insertL300(self):
        l300 = L300_model()
        ADDRESS, LAT, LONG = self.getLocation()
        liveObj = self.PO322["live"] if "live" in self.PO322 else {}
        fl300 = liveObj["FL300"] if "FL300" in liveObj else 0
        AV107 = store._get("NO133")["NV133_P"] if None != store._get("NO133") else ""

        rs = l300.live_inserttabL300(
            {
                "FO100": store.getCurrentActiveBusiness(),  # fo100 doanh nghiep
                "PN303": self.PN303,
                "LV302": helper.getMyIP(),  # IP
                "LV303": AV107,  # phone
                "FT300": self.FT300,
                "PL300": fl300,  # nếu đã có FL300 (đã lấy key) thì truyền lại FL300, (p300.PO322.live.FL300)
                "ADDRESS": ADDRESS,
                "LAT": LAT,
                "LONG": LONG,
                "UUID": hex(getnode()),  # UUID của thiết bị mobile
                "NV124": store._get("NV124"),  # Quốc Gia
                "SRC": "WEB",
                "pvLOGIN": store._get("NV101"),
            }
        )
        return rs[WS.ELEMENTS] if rs[WS.STATUS] == WS.SUCCESS else []

    def makeRTMP(self, l300):
        FO100BU = store.getCurrentActiveBusiness()
        ADDRESS, LAT, LONG = self.getLocation()
        URL = f'rtmp://{l300["EDGE"]}/{l300["APP"]}/'
        STREAMKEY = (
            f'{FO100BU}.{l300["TOKEN"]}?token={l300["TOKEN"]}&SRC=WEB&FO100={FO100BU}&PL300={l300["PL300"]}&LN301={l300["LN301"]}&LV302={l300["LV302"]}'
            + f'&LV303={l300["LV303"]}&LL348={l300["LL348"]}&UUID={hex(getnode())}&NV124={store._get("NV124")}'
            + (
                f"&PN303={self.p300['PN303']}"
                if self.PN303 == 15
                else f"&LAT={LAT}&LONG={LONG}"
            )
        )

        return URL, STREAMKEY

    def getLocation(self):
        locObj = (
            store._get("NO123")
            if store._get("NO123")
            else store._get("NO122")
            if store._get("NO122")
            else None
        )
        ADDRESS = locObj["ADDRESS"] if "ADDRESS" in locObj else ""
        LAT = locObj["coordinates"][1]
        LONG = locObj["coordinates"][0]
        return ADDRESS, LAT, LONG


#!/usr/bin/env python3

from copy import deepcopy
from functools import partial
import multiprocessing as mp
import multiprocessing.connection as mp_conn
from casadi import *
from utils import Config, NumericParameters, SymbolicParameters, ref_path
from typing import Callable, List, Tuple

class Solver(object):
    def __init__(self, config: Config):
        self.construct_solver(config)

    def construct_solver(self, config: Config):
        num_obs = config.num_obs

        # +++ Optimal Control Problem Formulation +++

        # Vehicle State Vector

        # Vehicle position along fixed frame x-axis
        vehicle_state_x = SX.sym("vehicle_state_x")
        # Vehicle position along fixed frame y-axis
        vehicle_state_y = SX.sym("vehicle_state_y")
        # Vehicle orientation angle, RHS off x-axis
        vehicle_state_theta = SX.sym("vehicle_state_theta")
        # Virtual state that represents path parameter
        vehicle_state_pthprm = SX.sym("vehicle_state_pthprm")
        # Vehicle speed (forward velocity)
        vehicle_state_vel = SX.sym("vehicle_state_vel")
        # Vehicle steering angle (virtual central wheel)
        vehicle_state_steer = SX.sym("vehicle_state_steer")
        # Vehicle body frame longitudinal velocity
        vehicle_state_lon_vel = SX.sym("vehicle_state_lon_vel")
        # Vehicle body frame lateral velocity
        vehicle_state_lat_accel = SX.sym("vehicle_state_lat_accel")

        vehicle_state_vector = vertcat(
            vehicle_state_x,
            vehicle_state_y,
            vehicle_state_theta,
            vehicle_state_lon_vel,
            vehicle_state_vel,
            vehicle_state_pthprm,
            vehicle_state_steer,
        )
        vehicle_state_x_i = 0
        vehicle_state_y_i = 1
        vehicle_state_theta_i = 2
        vehicle_state_lon_vel_i = 3
        vehicle_state_vel_i = 4
        vehicle_state_pthprm_i = 5
        vehicle_state_steer_i = 6

        vehicle_state_n = SX.size(vehicle_state_vector)
        self.vehicle_state_n = vehicle_state_n[0]

        # Control Vector

        # System Control - Forward Speed
        control_accel = SX.sym("_control_accel")
        # System Control - Steering angle
        control_steer = SX.sym("control_steer")
        # System Control - Virtual Input
        control_vir = SX.sym("control_vir")

        control_vector = vertcat(control_accel, control_steer, control_vir)

        control_accel_i = 0
        control_steer_i = 1
        control_vir_i = 2

        control_n = SX.size(control_vector)
        self.control_n = control_n[0]

        # System Model

        # Formulas for kinematic bicycle model, see https://dingyan89.medium.com/simple-understanding-of-kinematic-bicycle-model-81cac6420357

        # Second parameter to atan is fraction of CoG to back of vehicle
        # Currently assumed to be at center of vehicle
        beta = atan2(tan(control_steer), 2)
        inertial_x_velocity = vehicle_state_vel * cos(beta + vehicle_state_theta)
        inertial_y_velocity = vehicle_state_vel * sin(beta + vehicle_state_theta)
        yaw_rate = (vehicle_state_vel * cos(beta) * tan(control_steer)) / config.body.L
        lon_accel = control_accel
        accel = control_accel

        # The right hand side of the dynamics equation, i.e. the derivative of the state vector
        rhs = vertcat(
            inertial_x_velocity,  # Derivative of _vehicle_state_x
            inertial_y_velocity,  # Derivative of _vehicle_state_y
            yaw_rate,  # Derivative of _vehicle_state_theta
            lon_accel,  # Derivative of _vehicle_state_lon_vel
            accel,  # Derivative of _vehicle_state_vel
            control_vir,  # Derivative of _vehicle_state_pthprm
            control_steer,  # NOT Derivative of _vehicle_state_steer, steering is set directly
        )

        # Nonlinear mapping Function f(x,u)
        f = Function("f", [vehicle_state_vector, control_vector], [rhs])

        # +++ NLP Formulation +++

        # NLP Variables - See Mohamed W. Mehrez playlist for details: https://www.youtube.com/watch?v=RrnkPrcpyEA&list=PLK8squHT_Uzej3UCUHjtOtm5X7pMFSgAL

        # Control decision variables NLP

        U = SX.sym("U", control_n[0], config.opt.N)
        # State decision variables of NLP
        X = SX.sym("X", vehicle_state_n[0], (config.opt.N + 1))
        # Parameters of NLP, see definition below
        P = SymbolicParameters(config)

        obj = 0  # Objective function that we will be building up
        g = SX([])  # Functional constraints vector that we will be adding to
        lbg = []  # Decision variables lower bounds
        ubg = []  # Decision variables upper bounds

        # Current steering angle
        steer_old = P.x0[vehicle_state_steer_i]
        reference_speed = config.body.desired_fwd_vel
        ref_spline_a = P.center_a
        ref_spline_b = P.center_b
        left_spline_a = P.left_a
        left_spline_b = P.left_b
        right_spline_a = P.right_a
        right_spline_b = P.right_b
        # Current longitudinal accel
        lon_accel_old = P.lon_accel
        # x-axis positions of obstacles
        x_obs = P.obs_x
        # y-axis positions of obstacles
        y_obs = P.obs_y
        rx_obs = P.obs_rx
        ry_obs = P.obs_ry
        theta_obs = P.obs_theta

        st = X[:, 0]  # initial state
        # Enforce that initial state decisions variables are equal to the vehicle's measured state passed in the parameters
        g = vertcat(g, st[:] - P.x0)  # initial condition constraints
        lbg = vertcat(lbg, DM.zeros(vehicle_state_n[0], 1))
        ubg = vertcat(ubg, DM.zeros(vehicle_state_n[0], 1))

        for k in range(config.opt.N):
            # State decisions variables at step k in the precition horizon
            st = X[:, k]
            # Control decisions variables at step k in the precition horizon
            con = U[:, k]

            # Get symbolic representation of minimum distance from obstacle parameters
            min_dist = 100000
            for i in range(num_obs):
                # get rotation matrix back from ellipsis angle, here implemented is the inverse is here
                rot_theta = blockcat(
                    [
                        [np.cos(theta_obs[i]), np.sin(theta_obs[i])],
                        [-np.sin(theta_obs[i]), np.cos(theta_obs[i])],
                    ]
                )

                footprint = config.body.footprint
                # ego representation as 3 circles
                center_1 = vertcat(
                    st[0] + footprint.circle_placement * cos(st[2]),
                    st[1] + footprint.circle_placement * sin(st[2]),
                )
                center_2 = vertcat(st[0], st[1])
                center_3 = vertcat(
                    st[0] - footprint.circle_placement * cos(st[2]),
                    st[1] - footprint.circle_placement * sin(st[2]),
                )

                # rotate ego and obstacle pos so that ellipsis axis are allignt with x and y axis to calculate if ego center is in ellipsis
                ego_pos_rot_1 = mtimes(rot_theta, center_1)
                ego_pos_rot_2 = mtimes(rot_theta, center_2)
                ego_pos_rot_3 = mtimes(rot_theta, center_3)
                ellipsis_pos = vertcat(x_obs[i], y_obs[i])
                obs_pos_rot = mtimes(rot_theta, ellipsis_pos)

                # add safetydistance to axis', to take care of the fact, that just ego center is concidered
                safetyDistance = footprint.circle_radius + footprint.safety
                rx_axis = rx_obs[i] + safetyDistance
                ry_axis = ry_obs[i] + safetyDistance

                # calculate if circle centerpoints are in ellipsis plus radius
                c1 = (ego_pos_rot_1[0] - obs_pos_rot[0]) ** 2 / rx_axis ** 2 + (
                    ego_pos_rot_1[1] - obs_pos_rot[1]
                ) ** 2 / ry_axis ** 2
                c2 = (ego_pos_rot_2[0] - obs_pos_rot[0]) ** 2 / rx_axis ** 2 + (
                    ego_pos_rot_2[1] - obs_pos_rot[1]
                ) ** 2 / ry_axis ** 2
                c3 = (ego_pos_rot_3[0] - obs_pos_rot[0]) ** 2 / rx_axis ** 2 + (
                    ego_pos_rot_3[1] - obs_pos_rot[1]
                ) ** 2 / ry_axis ** 2

                c = fmin(c1, fmin(c2, c3))
                min_dist = fmin(min_dist, c)

            # Enforce that ego center is outside all obstacles
            g = vertcat(g, min_dist)
            lbg = vertcat(lbg, 1)
            ubg = vertcat(ubg, inf)

            # Get symbolic representation of reference point
            u = st[vehicle_state_pthprm_i]

            bound_c = config.boundary
            # Create halfplanes via the vectors that point from path_param along
            # the bound to the ego position. Enforce that the ego position is inside
            # those halfplanes
            if bound_c.strat == "halfplane":
                st_x = st[vehicle_state_x_i]
                st_y = st[vehicle_state_y_i]
                x0, y0, _ = ref_path(
                    left_spline_a, left_spline_b, st[vehicle_state_pthprm_i]
                )
                x1, y1, _ = ref_path(
                    right_spline_a, right_spline_b, st[vehicle_state_pthprm_i]
                )
                left_const = (
                    (x1 - x0) * st_x
                    - (x1 - x0) * x0
                    + (y1 - y0) * st_y
                    - (y1 - y0) * y0
                )
                x1, y1, _ = ref_path(
                    left_spline_a, left_spline_b, st[vehicle_state_pthprm_i]
                )
                x0, y0, _ = ref_path(
                    right_spline_a, right_spline_b, st[vehicle_state_pthprm_i]
                )
                right_const = (
                    (x1 - x0) * st_x
                    - (x1 - x0) * x0
                    + (y1 - y0) * st_y
                    - (y1 - y0) * y0
                )
                g = vertcat(g, left_const)
                lbg = vertcat(lbg, 0)
                ubg = vertcat(ubg, inf)
                g = vertcat(g, right_const)
                lbg = vertcat(lbg, 0)
                ubg = vertcat(ubg, inf)

            # Get a directional vector for each bound using a small lookahead
            # and enforce that the ego is on the correct side of that vector
            elif bound_c.strat == "side":
                la = bound_c.side.lookahead
                pad = bound_c.side.padding
                left_x, left_y, _ = ref_path(P.left_a, P.left_b, u)
                left_x1, left_y1, _ = ref_path(P.left_a, P.left_b, u + la)
                left_side = (st[0] - left_x) * (left_y1 - left_y) - (st[1] - left_y) * (
                    left_x1 - left_x
                )
                right_x, right_y, _ = ref_path(P.right_a, P.right_b, u)
                right_x1, right_y1, _ = ref_path(P.right_a, P.right_b, u + la)
                right_side = (st[0] - right_x) * (right_y1 - right_y) - (
                    st[1] - right_y
                ) * (right_x1 - right_x)
                g = vertcat(g, left_side)
                lbg = vertcat(lbg, pad)
                ubg = vertcat(ubg, inf)
                g = vertcat(g, right_side)
                lbg = vertcat(lbg, -inf)
                ubg = vertcat(ubg, -pad)

            elif bound_c.strat != "none":
                raise ValueError(f"Unrecognized boundary.strat '{bound_c.strat}'")

            x_ref, y_ref, yaw_ref = ref_path(P.center_a, P.center_b, u)
            # No idea what this calcuation is and we don't currently use it. Somehow characterized yaw error
            objYaw = (
                1
                - sin(st[vehicle_state_theta_i]) * sin(yaw_ref)
                - cos(st[vehicle_state_theta_i]) * cos(yaw_ref)
            )
            # Squared distance to reference point
            objPos = (x_ref - st[0]) ** 2 + (y_ref - st[1]) ** 2
            # Squared parametric distance to route completion
            objPathParam = (st[vehicle_state_pthprm_i] - 1) ** 2
            # Squared velocity error
            objRefVel = (st[vehicle_state_vel_i] - reference_speed) ** 2

            # Calculations for higher order body frame position derivatives as shown in https://www.sciencedirect.com/science/article/pii/S2405896319304185
            # Note that these metrics needs to be maintained as per SAE comfortable driving guidelines
            lon_jerk = (con[control_accel_i] - lon_accel_old) / config.opt.T
            lon_accel_old = con[control_accel_i]
            lat_accel = (
                (st[vehicle_state_lon_vel_i] ** 2) * con[control_steer_i]
            ) / config.body.L
            steer_delta = (con[control_steer_i] - steer_old) / config.opt.T
            lat_jerk = (
                2 * con[control_accel_i] * con[control_steer_i]
                + st[vehicle_state_lon_vel_i] * steer_delta
            ) * (st[vehicle_state_lon_vel_i] / config.body.L)
            objLatJerk = lat_jerk ** 2

            # side_pen = if_else(
            #     side < 0, 2 ** (sqrt(objPos) - 10), 2 ** (sqrt(objPos) - 1)
            # )
            # These 3 lines of code take up most of the time tuning weights, find out how to automate this process?
            w_obs = config.opt.weights.obstacle
            obj_obs = (
                w_obs.pos * objPos
                + w_obs.path_param * objPathParam
                + w_obs.ref_vel * objRefVel
                # How we penalize the state if it is decided to be close to an obstacle
                #   note that we add a repulsive field term around the obstacle, see plot here: https://www.wolframalpha.com/input/?i=plot+1%2F%28%281%2F4%29*x%29+from+0+to+5
                + w_obs.obs_dist * (1 / min_dist)
                + w_obs.lat_jerk * objLatJerk
                # + side_pen
            )
            w_free = config.opt.weights.free
            obj_free = (
                w_free.pos * objPos
                + w_free.path_param * objPathParam
                + w_free.ref_vel * objRefVel
                + w_free.lat_jerk * objLatJerk
            )
            non_stop_obj = if_else(
                # Switch how we penailize the state in step k depending on whether or not it is decided to be close to an obstacle
                min_dist < config.opt.obstacle_switch_dist,
                obj_obs,
                # How we penalize the state if it is not close to an obstacle
                obj_free,
                True,
            )

            # If the state is 70% done with the local route, stop by penalizing our speed and travel forward
            w_stop = config.opt.weights.stop
            obj_stop = (
                w_stop.pos * objPos
                + fabs(st[vehicle_state_vel_i])
                + con[control_accel_i]
            )
            obj += if_else(
                st[vehicle_state_pthprm_i] > config.opt.stop_switch_frac,
                obj_stop,
                non_stop_obj,
            )
            # self._obj += non_stop_obj
            # end_speed = if_else(self._st[self._vehicle_state_pthprm_i] > 0.9, self._st[self._vehicle_state_vel_i], 0)
            # self._g = vertcat(self._g, end_speed)
            # self._lbg = vertcat(self._lbg, 0)
            # self._ubg = vertcat(self._ubg, 0)

            # Bounds on body frame metrics as specififed by SAE
            bounds = config.body.bounds
            g = vertcat(g, lat_accel)
            lbg = vertcat(lbg, DM(bounds.lat_accel_l))
            ubg = vertcat(ubg, DM(bounds.lat_accel_u))
            g = vertcat(g, lon_jerk)
            lbg = vertcat(lbg, DM(bounds.lon_jerk_l))
            ubg = vertcat(ubg, DM(bounds.lon_jerk_u))

            # Calculate the next step state by solving the dynamics function ODE using RK4: https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods
            k1 = f(st, con)
            k2 = f(st + k1 * config.opt.T / 2, con)
            k3 = f(st + k2 * config.opt.T / 2, con)
            k4 = f(st + k3 * config.opt.T, con)
            gradientRK4 = (k1 + 2 * k2 + 2 * k3 + k4) / 6
            # Note that the steering state component is set directly, so ODE is only solved for the other components
            st_next_RK4 = (
                st[0:vehicle_state_steer_i]
                + config.opt.T * gradientRK4[0:vehicle_state_steer_i]
            )
            # And the steering state is taken directly from the f function
            st_next_RK4 = vertcat(st_next_RK4, k1[vehicle_state_steer_i])
            # Now, we just enforce that the next state adheres to the dynaimcs by enforcing that their difference is zero
            #   This programming of the dynamics is called multiple shooting
            st_next = X[:, k + 1]
            g = vertcat(g, st_next - st_next_RK4)
            lbg = vertcat(lbg, DM.zeros(vehicle_state_n[0], 1))
            ubg = vertcat(ubg, DM.zeros(vehicle_state_n[0], 1))

        # Now we populate the lower and upper bounds for every decision variable (state and control decision variables)
        N = config.opt.N
        lbx = DM.zeros(vehicle_state_n[0] * (N + 1) + control_n[0] * N, 1)
        ubx = DM.zeros(vehicle_state_n[0] * (N + 1) + control_n[0] * N, 1)

        # constraint on X position
        end_of_state_vars = vehicle_state_n[0] * (N + 1)
        lbx[vehicle_state_x_i : end_of_state_vars : vehicle_state_n[0], 0] = -inf
        ubx[vehicle_state_x_i : end_of_state_vars : vehicle_state_n[0], 0] = inf

        # constraint on Y position
        lbx[vehicle_state_y_i : end_of_state_vars : vehicle_state_n[0], 0] = -inf
        ubx[vehicle_state_y_i : end_of_state_vars : vehicle_state_n[0], 0] = inf

        # constraint on yaw angle
        lbx[
            vehicle_state_theta_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = -inf
        ubx[
            vehicle_state_theta_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = inf

        # constraint on lon velocity (state)
        lbx[
            vehicle_state_lon_vel_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = bounds.vel_l
        ubx[
            vehicle_state_lon_vel_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = bounds.vel_u

        # constraint on fwd velocity (state)
        lbx[
            vehicle_state_vel_i : end_of_state_vars : vehicle_state_n[0], 0
        ] = bounds.vel_l
        ubx[
            vehicle_state_vel_i : end_of_state_vars : vehicle_state_n[0], 0
        ] = bounds.vel_u

        # constraint on virtual state
        lbx[
            vehicle_state_pthprm_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = 0
        ubx[
            vehicle_state_pthprm_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = 1

        # constraint on steering angle (state) (0->a,5)
        lbx[
            vehicle_state_steer_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = bounds.steer_l
        ubx[
            vehicle_state_steer_i : end_of_state_vars : vehicle_state_n[0],
            0,
        ] = bounds.steer_u

        # constraint on accel input (a->end)
        lbx[
            end_of_state_vars
            + control_accel_i : vehicle_state_n[0] * (N + 1)
            + control_n[0] * N : control_n[0],
            0,
        ] = bounds.lon_accel_l
        ubx[
            end_of_state_vars
            + control_accel_i : vehicle_state_n[0] * (N + 1)
            + control_n[0] * N : control_n[0],
            0,
        ] = bounds.lon_accel_u

        # constraint on steering input (a->end)
        lbx[
            end_of_state_vars
            + control_steer_i : vehicle_state_n[0] * (N + 1)
            + control_n[0] * N : control_n[0],
            0,
        ] = bounds.steer_l
        ubx[
            end_of_state_vars
            + control_steer_i : vehicle_state_n[0] * (N + 1)
            + control_n[0] * N : control_n[0],
            0,
        ] = bounds.steer_u

        # constraint on virtual input (a->end)
        lbx[
            end_of_state_vars
            + control_vir_i : vehicle_state_n[0] * (N + 1)
            + control_n[0] * N : control_n[0],
            0,
        ] = 0
        ubx[
            end_of_state_vars
            + control_vir_i : vehicle_state_n[0] * (N + 1)
            + control_n[0] * N : control_n[0],
            0,
        ] = 1

        # Lastly, we just pack up everything we setup into a NLP, see https://web.casadi.org/docs/#nonlinear-programming

        # Make the decision variables a column vector
        opt_variables = reshape(X, vehicle_state_n[0] * (N + 1), 1)
        opt_variables = vertcat(opt_variables, reshape(U, control_n[0] * N, 1))

        nlp_prob = {
            "f": obj,
            "x": opt_variables,
            "g": g,
            "p": P.sx,
        }

        # Solver options
        opts = {
            "ipopt.max_iter": config.opt.max_iters,
            "ipopt.print_level": 0,
            "print_time": 0,
            "ipopt.acceptable_tol": 1e-8,
            "ipopt.acceptable_obj_change_tol": 1e-6,
        }

        self.solver = partial(
            nlpsol("solver", "ipopt", nlp_prob, opts),
            lbx=lbx,
            ubx=ubx,
            lbg=lbg,
            ubg=ubg,
        )

    def __call__(self, init, p):
        return self.solver(x0=init, p=p)

class SolverContainer(object):
    """
    Constructs a solver for each possible number of obstacles
    """

    def __init__(self, config: Config):
        self._solvers = {}
        self.max_num_obs = config.max_num_obs
        for num_obs in range(self.max_num_obs + 1):
            num_obs_config = deepcopy(config)
            num_obs_config.num_obs = num_obs
            self._solvers[num_obs] = Solver(num_obs_config)

    def __call__(self, p: NumericParameters):
        num_obs = len(p.obs_x)
        if num_obs > self.max_num_obs:
            raise ValueError(f"Observed {num_obs} obstacles, max is {self.max_num_obs}")
        return self._solvers[num_obs](init=p.init, p=p.P)

class SolverProc(mp.Process):
    TERM = "term"

    def __init__(self, solver: Callable, conn: mp_conn.Connection):
        super(SolverProc, self).__init__()
        self.conn = conn
        self.solver = solver

    def run(self):
        while True:
            job = self.conn.recv()
            if job == self.TERM:
                self.conn.send(self.TERM)
                return
            # TODO: Add profiling for this call
            self.conn.send(self.solver(job))

class ParallelSolver(object):
    """
    Runs multiple solvers in parallel and synchronizes the best
        solution between them
    """

    def __init__(self, config: Config):
        config.opt.max_iters = config.opt.online_max_iters
        self._online_solver = SolverContainer(config)

        self.N = config.opt.N
        self.vehicle_state_n = self._online_solver._solvers[0].vehicle_state_n
        self.control_n = self._online_solver._solvers[0].control_n

        self._exploring = not config.parallel.active
        self.explore_sol = None
        self.explore_copy = config.parallel.copy_warm
        self.online_sol = None

        self.prev_yaw = 0

        explore_config = deepcopy(config)
        explore_config.opt.max_iters = config.opt.explore_max_iters
        self.conn, conn = mp.Pipe()
        self.proc = SolverProc(
            partial(
                SolverContainer(explore_config),
            ),
            conn,
        )
        self.proc.start()

    def _get_init(self, yaw: float) -> Tuple[DM, DM]:
        """
        Checks to see if the exploring solver has a solution. If it does,
            and solution is better than the current online solution,
            returns the exploring solution. Otherwise, returns the online solution.

        Params:
            - yaw: Current yaw angle of the ego

        Returns:
            - x_warm: State decision variables to initialize the iterative solver with
            - u_warm: Control decision variables to initialize the iterative solver with
        """
        if self.conn.poll():
            self.explore_sol = self.conn.recv()
            self._exploring = False
        if self.online_sol is None:
            return DM.zeros(self.vehicle_state_n * (self.N + 1)), DM.zeros(
                self.control_n * self.N
            )
        if self.explore_sol is None or self.online_sol["f"] < self.explore_sol["f"]:
            sol = self.online_sol
        else:
            sol = self.explore_sol
            self.explore_sol = None

        N = self.N
        x = sol["x"][: self.vehicle_state_n * (N + 1)]
        x_warm = DM.zeros(self.vehicle_state_n * (self.N + 1))
        # Set first N states based on moving prev solution forward by 1 step
        x_warm[: self.vehicle_state_n * N] = x[
            self.vehicle_state_n : self.vehicle_state_n * (N + 1)
        ]
        # Set last state to last state of prev solution
        x_warm[self.vehicle_state_n * N :] = x[self.vehicle_state_n * N :]

        # If odom switched yaw sign, we also need to switch initial
        # optimization variable assignments for yaw, or else solver
        # will have a hard time numerically
        if abs(yaw - self.prev_yaw) > 6:
            for n in range(N + 1):
                x_warm[n * self.vehicle_state_n + 2] *= -1

        u = sol["x"][self.vehicle_state_n * (N + 1) :]
        u_warm = DM.zeros(self.control_n * self.N)
        # Set first N-1 controls based on moving prev solution forward by 1 step
        u_warm[: self.control_n * (N - 1)] = u[self.control_n : self.control_n * N]
        # Set last control to last control of prev solution
        u_warm[self.control_n * (N - 1) :] = u[self.control_n * (N - 1) :]

        self.prev_yaw = yaw

        return x_warm, u_warm

    def terminate(self):
        self.conn.send(SolverProc.TERM)
        while self.conn.recv() != SolverProc.TERM:
            continue
        self.proc.terminate()

    def __call__(self, p: NumericParameters):
        x_warm, u_warm = self._get_init(yaw=p.x0[2])
        if not self._exploring:
            self._exploring = True
            x_warm_explore = deepcopy(x_warm)
            u_warm_explore = deepcopy(u_warm)
            x_warm_explore[
                self.explore_copy
                * self.vehicle_state_n : self.vehicle_state_n
                * (self.N + 1)
            ] = 0
            u_warm_explore[
                self.explore_copy * self.control_n : self.control_n * self.N
            ] = 0
            explore_p = deepcopy(p)
            explore_p.init = vertcat(x_warm_explore, u_warm_explore)
            self.conn.send(explore_p)

        p.init = vertcat(x_warm, u_warm)
        self.online_sol = self._online_solver(p)
        return self.online_sol["x"]


import requests
from decouple import config

''' У Яндекс.Диска есть очень удобное и простое API. Для описания всех его методов существует
Полигон. Нужно написать программу, которая принимает на вход путь до файла на компьютере и
сохраняет на Яндекс.Диск с таким же именем. Все ответы приходят в формате json;
Загрузка файла по ссылке происходит с помощью метода put и передачи туда данных;
Токен можно получить кликнув на полигоне на кнопку "Получить OAuth-токен".'''

token = config('token', default='')

class YandexDisk:

    def __init__(self, token):
        self.token = token

    def get_headers(self):
        return {
            'Content-Type': 'application/json',
            'Authorization': 'OAuth {}'.format(self.token)
        }

    def get_files_list(self):
        files_url = 'https://cloud-api.yandex.net/v1/disk/resources/files'
        headers = self.get_headers()
        response = requests.get(files_url, headers=headers)
        return response.json()

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

    def upload_file_to_disk(self, path_to_file, file_name):
        result = self._get_upload_link(path_to_file=path_to_file)
        url = result.get('href')
        response = requests.put(url, data=open(file_name, 'rb'))
        response.raise_for_status()
        # if response.status_code == 201:
        #     print("Success")

if __name__ == '__main__':
    # Получить путь к загружаемому файлу и токен от пользователя
    path_to_file = '/text.txt'
    token = config('token', default='')
    file_name = 'text.txt'
    uploader = YandexDisk(token=token)
    result = uploader.upload_file_to_disk(path_to_file, file_name)


from __future__ import annotations

from typing import List, Optional, Union

from google.protobuf.json_format import MessageToDict, ParseDict
from grpc import RpcError

from .channel import V1, Channel
from .exceptions import ContainerServiceException
from .v1.api_pb2 import (
    ContainerFilter,
    ContainerStatusRequest,
    ListContainersRequest,
    RemoveContainerRequest,
)
from .v1.api_pb2_grpc import RuntimeServiceStub
from .v1alpha2.api_pb2 import ContainerFilter as V1Alpha2ContainerFilter
from .v1alpha2.api_pb2 import ContainerStatusRequest as V1Alpha2ContainerStatusRequest
from .v1alpha2.api_pb2 import ListContainersRequest as V1Alpha2ListContainersRequest
from .v1alpha2.api_pb2 import RemoveContainerRequest as V1Alpha2RemoveContainerRequest
from .v1alpha2.api_pb2_grpc import RuntimeServiceStub as V1Alpha2RuntimeServiceStub

class Containers:
    def __init__(self, channel: Channel) -> None:
        self.channel = channel
        self.stub: Union[RuntimeServiceStub, V1Alpha2RuntimeServiceStub] = (
            RuntimeServiceStub(channel.channel)
            if channel.version == V1
            else V1Alpha2RuntimeServiceStub(channel.channel)
        )

    def list_containers(self, filter: Optional[dict] = None) -> List[dict]:
        if self.channel.version == V1:
            request: Union[ListContainersRequest, V1Alpha2ListContainersRequest] = ListContainersRequest(
                filter=ParseDict(filter, ContainerFilter()) if filter else None
            )
        else:
            request = V1Alpha2ListContainersRequest(
                filter=ParseDict(filter, V1Alpha2ContainerFilter()) if filter else None
            )

        try:
            response = self.stub.ListContainers(request)
            return MessageToDict(response).get("containers", [])
        except RpcError as e:
            raise ContainerServiceException(e.code(), e.details()) from e

    def get_container(self, container_id: str) -> Optional[dict]:
        try:
            response = self.stub.ContainerStatus(
                ContainerStatusRequest(container_id=container_id)
                if self.channel.version == V1
                else V1Alpha2ContainerStatusRequest(container_id=container_id)
            )
            return MessageToDict(response).get("status")
        except RpcError as e:
            raise ContainerServiceException(e.code(), e.details()) from e

    def remove_container(self, container_id: str) -> None:
        try:
            self.stub.RemoveContainer(
                RemoveContainerRequest(container_id=container_id)
                if self.channel.version == V1
                else V1Alpha2RemoveContainerRequest(container_id=container_id)
            )
        except RpcError as e:
            raise ContainerServiceException(e.code(), e.details()) from e


from torch.utils.data import Dataset

class FashionHowDataset(Dataset):
    def __init__(self, dataset):
        self.diag = dataset["diag"]
        self.cordi = dataset["cordi"]
        self.rank = dataset["rank"] if "rank" in dataset else None

    def __len__(self):
        return len(self.diag)

    def __getitem__(self, idx):
        diag = self.diag[idx]
        cordi = self.cordi[idx]

        if self.rank == None :
            return diag, cordi
        else :
            rank = self.rank[idx]
            return diag, cordi, rank


import Chemins
from Utils import UTILS_Adaptations
from Utils.UTILS_Traduction import _
import wx
from Ctrl import CTRL_Bouton_image
from Ctrl import CTRL_Bandeau
from Ol import OL_Villes

class Dialog(wx.Dialog):
    def __init__(self, parent, modeImportation=False):
        wx.Dialog.__init__(self, parent, -1, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)
        self.panel_saisie = wx.Panel(self, -1)

        titre = _(u"Villes et codes postaux")
        if modeImportation == True :
            intro = _(u"Vous pouvez ici rechercher une ville ou un code postal grâce à la barre de recherche. Cliquez sur 'Importer la ville' pour importer la ville saisie ou sélectionnée.")
        else:
            intro =_(u"Vous pouvez ici rechercher une ville ou un code postal. La barre de recherche vous permet d'effectuer une recherche sur une partie du nom ou du code postal.")
        self.SetTitle(titre)
        self.ctrl_bandeau = CTRL_Bandeau.Bandeau(self, titre=titre, texte=intro, hauteurHtml=30, nomImage="Images/32x32/Carte.png")
        self.ctrl_villes = OL_Villes.ListView(self, id=-1, style=wx.LC_REPORT|wx.SUNKEN_BORDER|wx.LC_SINGLE_SEL|wx.LC_HRULES|wx.LC_VRULES)
        self.ctrl_villes.MAJ()

        self.ctrl_barreRecherche = OL_Villes.CTRL_Outils(self, listview=self.ctrl_villes)

        self.staticbox_saisie_staticbox = wx.StaticBox(self.panel_saisie, -1, _(u"Insertion manuelle d'une ville dans le champ Adresse"))
        self.label_cp = wx.StaticText(self.panel_saisie, -1, "Code postal :")
        self.ctrl_cp = wx.TextCtrl(self.panel_saisie, -1, "")
        self.label_ville = wx.StaticText(self.panel_saisie, -1, "Ville :")
        self.ctrl_ville = wx.TextCtrl(self.panel_saisie, -1, "")

        self.bouton_ajouter = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Ajouter.png"), wx.BITMAP_TYPE_ANY))
        self.bouton_modifier = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Modifier.png"), wx.BITMAP_TYPE_ANY))
        self.bouton_supprimer = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Supprimer.png"), wx.BITMAP_TYPE_ANY))

        self.bouton_aide = CTRL_Bouton_image.CTRL(self, texte=_(u"Aide"), cheminImage="Images/32x32/Aide.png")
        self.bouton_importer = CTRL_Bouton_image.CTRL(self, texte=_(u"Importer la ville"), cheminImage="Images/32x32/Fleche_bas.png")
        self.bouton_annuler = CTRL_Bouton_image.CTRL(self, texte=_(u"Fermer"), cheminImage="Images/32x32/Fermer.png")

        if modeImportation == False :
            self.panel_saisie.Show(False)
            self.bouton_importer.Show(False)

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.Ajouter, self.bouton_ajouter)
        self.Bind(wx.EVT_BUTTON, self.Modifier, self.bouton_modifier)
        self.Bind(wx.EVT_BUTTON, self.Supprimer, self.bouton_supprimer)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonImporter, self.bouton_importer)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAide, self.bouton_aide)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAnnuler, self.bouton_annuler)

    def __set_properties(self):
        self.ctrl_cp.SetMinSize((60, -1))
        self.ctrl_cp.SetToolTip(wx.ToolTip(_(u"Saisissez ici un code postal")))
        self.ctrl_ville.SetToolTip(wx.ToolTip(_(u"Saisissez ici le nom d'une ville")))
        self.bouton_ajouter.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour ajouter une ville")))
        self.bouton_modifier.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour modifier la ville sélectionnée dans la liste")))
        self.bouton_supprimer.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour supprimer la ville sélectionnée dans la liste")))
        self.bouton_aide.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour obtenir de l'aide")))
        self.bouton_importer.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour importer la ville saisie manuellement ou sélectionnée dans la liste")))
        self.bouton_annuler.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour fermer")))
        self.SetMinSize((480, 600))

    def __do_layout(self):
        grid_sizer_base = wx.FlexGridSizer(rows=4, cols=1, vgap=10, hgap=10)
        grid_sizer_base.Add(self.ctrl_bandeau, 0, wx.EXPAND, 0)

        grid_sizer_saisie = wx.GridSizer(rows=1, cols=1, vgap=0, hgap=0)
        staticbox_saisie = wx.StaticBoxSizer(self.staticbox_saisie_staticbox, wx.VERTICAL)

        grid_sizer_recherche = wx.FlexGridSizer(rows=2, cols=2, vgap=5, hgap=5)
        grid_sizer_recherche.Add(self.ctrl_villes, 0, wx.LEFT|wx.RIGHT|wx.TOP|wx.EXPAND, 0)

        grid_sizer_droit = wx.FlexGridSizer(rows=5, cols=1, vgap=5, hgap=5)
        grid_sizer_droit.Add(self.bouton_ajouter, 0, 0, 0)
        grid_sizer_droit.Add(self.bouton_modifier, 0, 0, 0)
        grid_sizer_droit.Add(self.bouton_supprimer, 0, 0, 0)
        grid_sizer_recherche.Add(grid_sizer_droit, 1, wx.EXPAND, 0)

        grid_sizer_recherche.Add(self.ctrl_barreRecherche, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 0)
        grid_sizer_recherche.AddGrowableRow(0)
        grid_sizer_recherche.AddGrowableCol(0)

        grid_sizer_base.Add(grid_sizer_recherche, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)

        grid_sizer_saisie_2 = wx.FlexGridSizer(rows=1, cols=4, vgap=5, hgap=5)
        grid_sizer_saisie_2.Add(self.label_cp, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 0)
        grid_sizer_saisie_2.Add(self.ctrl_cp, 0, 0, 0)
        grid_sizer_saisie_2.Add(self.label_ville, 0, wx.LEFT|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5)
        grid_sizer_saisie_2.Add(self.ctrl_ville, 0, wx.EXPAND, 0)
        grid_sizer_saisie_2.AddGrowableRow(0)
        grid_sizer_saisie_2.AddGrowableCol(3)
        staticbox_saisie.Add(grid_sizer_saisie_2, 1, wx.ALL|wx.EXPAND, 5)

        grid_sizer_saisie.Add(staticbox_saisie, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)

        self.panel_saisie.SetSizer(grid_sizer_saisie)
        grid_sizer_base.Add(self.panel_saisie, 1, wx.EXPAND, 0)

        # Boutons
        grid_sizer_boutons = wx.FlexGridSizer(rows=1, cols=4, vgap=10, hgap=10)
        grid_sizer_boutons.Add(self.bouton_aide, 0, 0, 0)
        grid_sizer_boutons.Add(self.bouton_importer, 0, 0, 0)
        grid_sizer_boutons.Add((20, 20), 0, wx.EXPAND, 0)
        grid_sizer_boutons.Add(self.bouton_annuler, 0, 0, 0)
        grid_sizer_boutons.AddGrowableRow(0)
        grid_sizer_boutons.AddGrowableCol(2)
        grid_sizer_base.Add(grid_sizer_boutons, 1, wx.ALL|wx.EXPAND, 10)
        self.SetSizer(grid_sizer_base)
        grid_sizer_base.Fit(self)
        grid_sizer_base.AddGrowableRow(1)
        grid_sizer_base.AddGrowableCol(0)
        self.Layout()
        self.CentreOnScreen()

    def Ajouter(self, event):
        self.ctrl_villes.Ajouter(None)

    def Modifier(self, event):
        self.ctrl_villes.Modifier(None)

    def Supprimer(self, event):
        self.ctrl_villes.Supprimer(None)

    def GetVille(self):
        selectionListe = self.ctrl_villes.Selection()
        saisie_cp = self.ctrl_cp.GetValue()
        saisie_ville = self.ctrl_ville.GetValue()
        if saisie_ville != "" and saisie_cp != "" :
            return saisie_cp, saisie_ville
        return self.ctrl_villes.Selection()[0].cp, self.ctrl_villes.Selection()[0].nom

    def OnBoutonImporter(self, event):
        selectionListe = self.ctrl_villes.Selection()
        saisie_cp = self.ctrl_cp.GetValue()
        saisie_ville = self.ctrl_ville.GetValue()
        if saisie_ville == "" and saisie_cp == "" and len(selectionListe) == 0 :
            dlg = wx.MessageDialog(self, _(u"Vous n'avez effectué aucune saisie manuelle ou sélection dans la liste !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        if saisie_ville != "" and saisie_cp == "":
            dlg = wx.MessageDialog(self, _(u"Vous avez saisi le nom d'une ville sans saisir le code postal !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        if saisie_ville == "" and saisie_cp != "":
            dlg = wx.MessageDialog(self, _(u"Vous avez saisi le code postal sans saisir le nom de la ville !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        self.EndModal(wx.ID_OK)

    def OnBoutonAide(self, event):
        from Utils import UTILS_Aide
        UTILS_Aide.Aide("Villesetcodespostaux")

    def OnBoutonAnnuler(self, event):
        self.EndModal(wx.ID_CANCEL)

if __name__ == "__main__":
    app = wx.App(0)
    #wx.InitAllImageHandlers()
    dialog_1 = Dialog(None, modeImportation=True)
    app.SetTopWindow(dialog_1)
    dialog_1.ShowModal()
    app.MainLoop()


from __future__ import annotations

import auto_prefetch
from django.conf import settings
from django.db import models
from django.urls import reverse
from slugger import AutoSlugField

from markdownx.models import MarkdownxField

class FlexPage(auto_prefetch.Model):
    """
    Definition of a FlexPage object
    """

    title = models.CharField(max_length=250)
    description = models.TextField(blank=True, null=True)
    public = models.BooleanField(default=False)
    created_by = auto_prefetch.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="flexpages",
    )
    slug = AutoSlugField(populate_from="title")
    content = MarkdownxField()
    created = models.DateField(auto_now_add=True)
    updated = models.DateField(auto_now=True)

    class Meta(auto_prefetch.Model.Meta):
        ordering = ("-created",)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse(
            "core_flexpage",
            kwargs={
                "slug": self.slug,
            },
        )

    def get_detail_url(self):
        return self.get_absolute_url()

class Contact(auto_prefetch.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()
    message = models.TextField(max_length=250)
    response = models.TextField(max_length=250, null=True, blank=True)
    responded = models.BooleanField(default=False)
    responded_on = models.DateField(null=True, blank=True)
    responded_by = auto_prefetch.ForeignKey(
        settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL
    )

    subscribe = models.BooleanField(
        verbose_name="Subscribe to our Newsletter", default=False
    )
    subscribed = models.BooleanField(default=False)

    created_on = models.DateField(auto_now_add=True)

    def __str__(self) -> str:
        return self.name

    def save(self, *args, **kwargs):
        not_allowed_strings = ["http://", "https://", "www.", "money", "$", "€"]
        if not any(x in self.message for x in not_allowed_strings):
            super().save(*args, **kwargs)


#!/usr/bin/python
import sys
import os
import json
import yaml
import requests

def usage():
 print ("Usage: ./tungctl.py create -f xxx.yaml")

if (not len(sys.argv)==4):
 usage()
 sys.exit(30)

if (not sys.argv[1]=='create' or not sys.argv[2]=='-f'):
 sys.exit(32)

yamlname = sys.argv[3]
with open(yamlname) as f:
 yamls = yaml.safe_load_all(f.read())
jsonname=yamlname.split('.')[0] + '.json'

## it's not the correct way to do so :(
controller_ip = os.popen ("ip -o route get 8.8.8.8 | awk '{print $7}'").read ().rstrip()
vnc_api_headers= {"Content-Type": "application/json", "charset": "UTF-8"}

def empty_func():
 pass

do_finally=empty_func

for js in yamls:
  if ('kind' in js.keys()):
   pass
  else:
   print ('kind is not spcified in yaml')
   sys.exit(31)

  kind = js["kind"]

  if (kind == "virtual-network"):
    name = js["name"]
    subnet = js["subnet"]
    prefix = js["prefix"]
    project = js["project"]

    jsonstring = """
    {"virtual-network":
     {
        "fq_name": [
            "default-domain",
            "%s",
            "%s"
        ],
        "network_ipam_refs": [
            {
                "attr": {
                    "ipam_subnets": [
                        {
                            "subnet": {
                                "ip_prefix": "%s",
                                "ip_prefix_len": %s
                            }
                        }
                    ]
                },
                "to": [
                    "default-domain",
                    "default-project",
                    "default-network-ipam"
                ]
            }
        ],
        "parent_type": "project"
     }
    }
    """ % (project, name, subnet, prefix)

    jsondict = json.loads(jsonstring)
    if ("gatewayless" in js.keys()):
      jsondict["virtual-network"]["virtual_network_refs"]=[{"to": ["default-domain", "default-project", "ip-fabric"]}]
    if ("route-target-list" in js.keys()):
      jsondict["virtual-network"]["route_target_list"]={"route_target": js["route-target-list"]}
    if ("external" in js.keys()):
      jsondict["virtual-network"]["router_external"]=True
    if ("network_policy_refs" in js.keys()):
      jsondict["virtual-network"]["network_policy_refs"]=[{"attr":{}, "to": policy_fqname.split(":")} for policy_fqname in js["network_policy_refs"]]
  elif (kind == "network-policy"):
    name=js["name"]
    project=js["project"]
    np_rule=js["network_policy_rule"]
    action=np_rule["action"]
    src_addr=np_rule["src_addresses"]
    dst_addr=np_rule["dst_addresses"]
    protocol=np_rule["protocol"]
    jsonstring = """
      {"network-policy":
       {
         "fq_name": [
           "default-domain",
           "%s",
           "%s"
         ],
         "network_policy_entries": {
           "policy_rule": [
             {
               "action_list": {
                 "simple_action": "%s"
               },
               "dst_addresses": [
                 {
                   "virtual_network": "%s"
                 }
               ],
               "src_addresses": [
                 {
                   "virtual_network": "%s"
                 }
               ],
               "protocol": "%s"
             }
           ]
         },
         "parent_type": "project"
       }
      }
    """ % (project, name, action, src_addr, dst_addr, protocol)
    jsondict = json.loads(jsonstring)
    if ("apply_service_list" in np_rule.keys()):
      jsondict["network-policy"]["network_policy_entries"]["policy_rule"][0]["action_list"]["apply_service"]=np_rule["apply_service_list"]
  elif (kind == "logical-router"):
    name=js["name"]
    project=js["project"]
    jsonstring = """
    {"logical-router":
      {
        "fq_name": [
          "default-domain",
          "%s",
          "%s"
        ],
        "parent_type": "project"
      }
    }
    """ % (project, name)
    jsondict = json.loads(jsonstring)
    if ("connected_interfaces" in js.keys()):
      jsondict["logical-router"]["virtual_machine_interface_refs"]=[]
      for uuid in js["connected_interfaces"]:
        r = requests.post ("http://{}:8082/id-to-fqname".format(controller_ip), data='{"uuid": "%s"}' % uuid, headers=vnc_api_headers)
        #print (r.text)
        fqname = json.loads(r.text)["fq_name"]
        jsondict["logical-router"]["virtual_machine_interface_refs"].append ({"uuid": uuid, "to": fqname})
  elif (kind == "bgp-router"):
    name=js["name"]
    neighbor_address=js["neighbor-address"]
    autonomous_system=js["autonomous-system"]
    router_id=js["router-id"]
    vendor=js["vendor"]
    jsonstring = """
    {"bgp-router":
      {
        "bgp_router_parameters": {
          "address": "%s",
          "autonomous_system": %s,
          "identifier": "%s",
          "vendor": "%s"
        },
        "fq_name": [
          "default-domain",
          "default-project",
          "ip-fabric",
          "__default__",
          "%s"
        ],
        "parent_type": "routing-instance"
      }
    }
    """ % (neighbor_address, autonomous_system, router_id, vendor, name)
    jsondict = json.loads(jsonstring)
  elif (kind == "service-instance"):
    name=js["name"]
    project=js["project"]
    left_virtual_network=js["left_virtual_network"]
    right_virtual_network=js["right_virtual_network"]
    service_template=js["service_template"]
    jsonstring = """
    {"service-instance":
      {
        "fq_name": [
          "default-domain",
          "%s",
          "%s"
        ],
        "parent_type": "project",
        "service_instance_properties": {
          "interface_list": [
            {
              "virtual_network": "%s"
            },
            {
              "virtual_network": "%s"
            }
          ],
          "left_virtual_network": "%s",
          "right_virtual_network": "%s"
        },
        "service_template_refs": [
          {
            "to": [
              "default-domain",
              "%s"
            ]
          }
        ]
      }
    }""" % (project, name, left_virtual_network, right_virtual_network, left_virtual_network, right_virtual_network, service_template)
    jsondict = json.loads(jsonstring)
  elif (kind == "virtual-machine-interface"):
    name=js["name"]
    project=js["project"]
    virtual_network=js["virtual-network"]
    jsonstring = """
    {"virtual-machine-interface":
      {
        "fq_name": [
          "default-domain",
          "%s",
          "%s"
        ],
        "parent_type": "project",
        "virtual_network_refs": [
          {
            "to": [
              "default-domain",
              "%s",
              "%s"
            ]
          }
        ]
      }
    }
    """ % (project, name, project, virtual_network)
    jsondict = json.loads(jsonstring)
    if ("uuid" in js.keys()):
      jsondict["virtual-machine-interface"]["uuid"]=js["uuid"]
    if ("mac-address" in js.keys()):
      jsondict["virtual-machine-interface"]["virtual_machine_interface_mac_addresses"]={"mac_address": [js["mac-address"]]}
    if ("virtual_machine_refs" in js.keys()):
      jsondict["virtual-machine-interface"]["virtual_machine_refs"]=[{"to": [js["virtual_machine_refs"]]}]

  elif (kind == "port-tuple"):
    name=js["name"]
    project=js["project"]
    jsonstring = """
    {"port-tuple":
      {
        "fq_name": [
          "default-domain",
          "%s",
          "%s",
          "%s"
        ],
        "parent_type": "service-instance"
      }
    }
    """ % (project, name, name)
    jsondict = json.loads(jsonstring)
    if ("connected_vmis" in js.keys()):
      def update_vmis_to_attach_to_port_tuple():
        port_tuple_refs=[{"to": ["default-domain", project, name, name]}]
        for uuid in js["connected_vmis"]:
          r = requests.get ("http://{}:8082/virtual-machine-interface/{}".format(controller_ip, uuid))
          #print (r.text)
          tmp_js = json.loads(r.text)
          tmp_js["virtual-machine-interface"]["port_tuple_refs"]=port_tuple_refs
          print (json.dumps(tmp_js))
          r = requests.put ("http://{}:8082/virtual-machine-interface/{}".format(controller_ip, uuid), data=json.dumps(tmp_js), headers=vnc_api_headers)
          print (r.text)
      do_finally = update_vmis_to_attach_to_port_tuple
  elif (kind == "virtual-machine"):
    name=js["name"]
    jsonstring = """
    {"virtual-machine":
      {
        "fq_name": [
          "%s"
        ]
      }
    }
    """ % (name)
    jsondict = json.loads(jsonstring)
    if ("uuid" in js.keys()):
      uuid=js["uuid"]
      jsondict["virtual-machine"]["uuid"]=js["uuid"]
    if ("virtual-machine-interface" in js.keys()):
      def update_vmis_to_attach_to_virtual_machine():
        virtual_machine_refs=[{"to": [name]}]
        uuid = js["virtual-machine-interface"]
        r = requests.get ("http://{}:8082/virtual-machine-interface/{}".format(controller_ip, uuid))
        tmp_js = json.loads(r.text)
        tmp_js["virtual-machine-interface"]["virtual_machine_refs"]=virtual_machine_refs
        print (json.dumps(tmp_js))
        r = requests.put ("http://{}:8082/virtual-machine-interface/{}".format(controller_ip, uuid), data=json.dumps(tmp_js), headers=vnc_api_headers)
        print (r.text)
      do_finally = update_vmis_to_attach_to_virtual_machine
  elif (kind == "instance-ip"):
    name=js["name"]
    project=js["project"]
    instance_ip_address=js["instance_ip_address"]
    virtual_machine_interface=js["virtual_machine_interface"]
    virtual_network=js["virtual_network"]
    jsonstring = """
    {"instance-ip":
      {
        "fq_name": [
          "%s"
        ],
        "instance_ip_address": "%s",
        "virtual_machine_interface_refs": [
          {
            "to": [
              "default-domain",
              "%s",
              "%s"
            ]
          }
        ],
        "virtual_network_refs": [
          {
            "to": [
              "default-domain",
              "%s",
              "%s"
            ]
          }
        ]
      }
    }
    """ % (name, instance_ip_address, project, virtual_machine_interface, project, virtual_network)
    jsondict = json.loads(jsonstring)
  elif (kind == "loadbalancer"):
    name=js["name"]
    project=js["project"]
    jsonstring = """
    {"loadbalancer":
      {
        "fq_name": [
          "default-domain", "%s", "%s"
        ],
        "parent_type": "project"
      }
    }
    """ % (project, name)
    jsondict = json.loads(jsonstring)
  elif (kind == "loadbalancer-listener"):
    name=js["name"]
    project=js["project"]
    loadbalancer_name=js["loadbalancer_name"]
    jsonstring = """
    {"loadbalancer-listener":
      {
        "fq_name": [
          "default-domain", "%s", "%s"
        ],
        "loadbalancer_refs": [
          {
            "to": [
              "default-domain",
              "%s",
              "%s"
            ]
          }
        ]
      }
    }
    """ % (project, name, project, loadbalancer_name)
    jsondict = json.loads(jsonstring)
  elif (kind == "loadbalancer-pool"):
    name=js["name"]
    project=js["project"]
    jsonstring = """
    {"loadbalancer-pool":
      {
        "fq_name": [
          "default-domain", "%s", "%s"
        ],
        "parent_type": "project"
      }
    }
    """ % (project, name)
    jsondict = json.loads(jsonstring)
  elif (kind == "loadbalancer-member"):
    name=js["name"]
    project=js["project"]
    loadbalancer_pool_name=js["loadbalancer_pool_name"]
    jsonstring = """
    {"loadbalancer-member":
      {
        "fq_name": [
          "default-domain", "%s", "%s", "%s"
        ],
        "parent_type": "loadbalancer-pool"
      }
    }
    """ % (project, loadbalancer_pool_name, name)
    jsondict = json.loads(jsonstring)

  jsonstring = json.dumps(jsondict)
  print (jsonstring)

  #with open (jsonname, 'w') as f:
  # f.write (json)

  r = requests.post ("http://{}:8082/{}s".format(controller_ip, kind), data=jsonstring, headers=vnc_api_headers)
  print (r.text)

  do_finally()


from datetime import date

class Task():
    def __init__(self, user=False, data={}):
        self.date = str(date.today())
        # For dummy generation without user
        if user == False:
            self.code = ''
        # For non-dummy generation
        else:
            self.code = user.generate_code('task', 6)
        self.active = True
        self.staff = ''
        self.due = str(date.today())
        self.deadline = ''
        self.property = data.get('property_code', '')
        self.message = data.get('message', '')
        self.next = ''

    # Class methods:

    def date_in_days(date_str):
        day = int(date_str[8:10])
        months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
        month = int(date_str[5:7])
        day += months[month - 1]
        year = int(date_str[0:4])
        day += year * 365
        return day

    def date_length(start_str, end_str):
        start_in_days = Task.date_in_days(start_str)
        end_in_days = Task.date_in_days(end_str)
        return end_in_days - start_in_days

    # Instance methods:

    def update(self, type, value):
        setattr(self, type, value)


# -*- coding: UTF-8 -*-
"""
Inotifywait事件监听模块

本模块功能：
    1. inotifywait进程的创建，该进程持续监听配置文件中指定
        文件或目录的变化事件（写关闭、修改、删除、移动、修改权限等）；
    2. 把收集的事件发送出去由其他（Master）模块处理。
"""
import subprocess
from json import dumps
import fs_global as Global
from fs_util import FileOP, Common, Singleton
from fs_logger import Logger
from fs_data import ConfigWrapper, StateInfo
from fs_message import Receiver

class Inotify(Singleton):

    def __init__(self):
        self.listen_file = '{0}/listen.ini'.format(Global.G_RUN_DIR)
        self.event_list = []
        self.inotify_process = None
        self.inotify_event = ''

    def steps(self):
        """ 初始化配置文件和参数 """
        self.inotify_event = ''
        try:
            self.init_listen_file()
            self.init_inotify_event()
            self.register_event()
        except Exception as e:
            Logger.error(e)
            return False
        else:
            return True

    def init_listen_file(self):
        """ 初始化监听的目录到文件中 """
        listen_list = ConfigWrapper.get_listen_path()
        if not listen_list:
            raise Exception('[fs_inotify] inotify listen path is NULL')
        Logger.info('[fs_inotify] inotify listen path:%s'
                    % dumps(listen_list, indent=4))

        """ 写入监听文件，由inotifywait监听 """
        FileOP.write_to_file(self.listen_file, '')
        [FileOP.write_append_file(self.listen_file, line)
         for line in listen_list]

    def init_inotify_event(self):
        """ 初始化inotifywait命令参数 """
        _get_global_value = ConfigWrapper.get_key_value
        is_delete = _get_global_value('event_delete')
        is_create = _get_global_value('event_create')
        is_close_write = _get_global_value('event_closewrite')
        is_move = _get_global_value('event_move')
        is_moved_to = _get_global_value('event_movedto')
        is_moved_from = _get_global_value('event_movedfrom')
        is_attrib = _get_global_value('event_attrib')
        _event_param = ''
        if is_delete == 'true':
            _event_param += '-e delete'
        if is_create == 'true':
            _event_param += ' -e create'
        if is_close_write == 'true':
            _event_param += ' -e close_write'
        if is_move == 'true':
            _event_param += ' -e move'
        if is_moved_to == 'true':
            _event_param += ' -e moved_to'
        if is_moved_from == 'true':
            _event_param += ' -e moved_from'
        if is_attrib == 'true':
            _event_param += ' -e attrib'
        if _event_param == '':
            raise Exception("[fs_inotify] ALL event type is false")
        self.inotify_event += _event_param

    def register_event(self):
        Receiver.bind(Global.G_INOTIFY_EVENT_MSGID, self._get_event_list)
        Receiver.bind(Global.G_INOTIFY_HEARTBEAT_MSGID, self._heartbeat)

    def _get_event_list(self, param=None):
        return self.event_list

    def _heartbeat(self, param=None):
        if self._get_inotify_pid() != -1:
            return True
        return False

    def _get_inotify_pid(self):
        try:
            if self.inotify_process.poll() is None:
                pid = self.inotify_process.pid
            else:
                pid = -1
        except:
            pid = -1
        return pid

    def _inotify_process(self, args=None):
        """ 开启inotifywait进程 """
        inotify_cmd = "{0} -rmq --format '%e %w%f' {1} --fromfile {2}".format(
            Global.G_INOTIFY_TOOL, self.inotify_event, self.listen_file)

        Logger.info("[fs_inotify] start %s" % inotify_cmd)
        self.inotify_process = subprocess.Popen([inotify_cmd],
                                                bufsize=10240,
                                                stdout=subprocess.PIPE,
                                                env={'LD_LIBRARY_PATH': Global.G_LIB_DIR},
                                                shell=True)
        Logger.info("[fs_inotify] filesync pid: %s" % Common.get_pid())
        Logger.info("[fs_inotify] inotifywait pid: %s" % self._get_inotify_pid())
        _proc_poll = self.inotify_process.poll
        _readline = self.inotify_process.stdout.readline
        _append = self.event_list.append

        while _proc_poll() is None:
            event_line = Common.stream_2_str(_readline()).strip()
            if event_line != "":
                _append(event_line)

    def start(self):
        Common.start_thread(target=self._inotify_process)

    def stop(self):
        try:
            if self.inotify_process.poll() is None:
                Logger.info("[fs_inotify] inotifywait(%s) exit"
                            % self.inotify_process.pid)
                self.inotify_process.kill()
        except:
            pass

    def reload(self):
        """ 重新加载 """
        self.stop()
        if self.steps():
            self.start()

    def status(self):
        pid = self._get_inotify_pid()
        StateInfo.set_inotify_pid(pid)


import csv
import datetime
from glob import glob
from os import stat

today = datetime.date.today()
ay = today.year - (1 if today.month < 4 else 0)
meibo = [(stat(f).st_ctime, f) for f in glob('RSMeibo_' + str(ay) + '*')]
meibo.sort(reverse=True)
print(*meibo, sep='\n')
meibo = meibo[0][1]

with open(meibo) as f:
    reader = csv.reader(f)
    for i in range(3):
        next(reader)
    meibo = []
    for row in reader:
        meibo.append(row[2:6])
    with open("maillist.txt", "w") as f:
        for row in meibo[1:]:
            print('"{0:s}" <s{1:s}@u.tsukuba.ac.jp>'.format(row[2], row[1][2:9]),
                  file=f)
    with open("meibo.txt", "w") as f:
        for row in meibo:
            print("{:9} {:1} {}\t{}\t".format(row[1], row[0], row[2], row[3]),
                  file=f)
    with open("meibo.csv", "w") as f:
        for row in meibo:
            print("{},{},{},{}".format(row[1], row[0], row[2], row[3]),
                  file=f)


from application.api.stock.Stock import Stock
from application.utility.number_utils import is_digit
from application.utility.converter import alchemy_encoder, parse_sql_result
from application.core.constants import DEFAULT_SCHEMA
import json
from datetime import datetime

dict_basic_operation = {
    'less' : ' {column} < {value} ',
    'eless' : ' {column} <= {value} ',
    'greater' : ' {column} > {value} ',
    'egreater' : ' {column} >= {value} ',
    'equal' : ' {column} = {value} ',
    'nequal' : ' {column} <> {value} ',
    'equals' : " {column} = '{value}' ",
    'like' : " {column} like '%%{value}%%' ",
    'ilike' : " {column} ilike '%%{value}%%' ",
}

dict_basic_two_operations = {
    'in_range' : ' {column} between {lower} and {upper}',
    'not_in_range' : ' {column} <= {lower} and {column} >= {upper}'
}

list_complex_operation = ['crosses', 'crosses_above', 'crosses_below']

"""[summary]
params contains:
- filters: list of filter item
- columns: list of column returned
"""
def screen_stock(params):
    data = []
    filters = params.get('filters')
    columns = params.get('columns')
    limit = params.get('limit') or 2000
    offset = params.get('offset') or 0
    sql_columns = build_sql_columns(columns)
    sql_filters = build_sql_filters(filters)
    sql = f'select {sql_columns} from {DEFAULT_SCHEMA}.stock_price where (1 = 1) {sql_filters} order by symbol offset {offset} limit {limit} ;'
    if limit == -1 and offset == -1:
        sql = f'select {sql_columns} from {DEFAULT_SCHEMA}.stock_price where (1 = 1) {sql_filters} order by symbol;'
    print(sql)
    data = Stock.execute(sql)
    return parse_sql_result(data)

def build_sql_filters(filters):
    sql = ''
    for item in filters:
        sql_filter = build_sql_filter(item)
        sql += f" and ({sql_filter}) "
    return sql

def build_sql_filter(item):
    filter_type = item.get('type')
    filter_value = parse_filter_value(item.get('value'))
    filter_operation = item.get('operation')
    if filter_operation in dict_basic_operation.keys():
        return dict_basic_operation.get(filter_operation).format(column=filter_type, value=filter_value)
    elif filter_operation in dict_basic_two_operations.keys():
        return dict_basic_two_operations.get(filter_operation).format(column=filter_type, lower=filter_value[0], upper=filter_value[1])
    elif filter_operation in list_complex_operation:
        return ''

def parse_filter_value(value):
    if is_digit(value):
        return float(value)
    elif isinstance(value, list):
        return [float(value[0]), float(value[1])]
    else:
        return f"{value}"

def build_sql_columns(columns):
    return ', '.join(columns)

def check_condition_notification(filter_list):
    res = False
    columns = []
    filters = []
    filter_list = json.loads(filter_list)
    # print(filter_list)
    for filter_item in filter_list:
        if filter_item.get('type') == 'stock_date':
            filter_item['value'] = datetime.today().strftime('%Y-%m-%d')
        columns.append(filter_item.get('type'))
    params = {
        'filters': filter_list,
        'columns': filters,
        'limit': -1,
        'offset': -1,
    }
    data = screen_stock(params)
    if len(data) > 0:
        res = True
    # print(res)
    return res


"""
credit_risk_app -- Arhum Zafar

A Streamlit web application that takes in a user's financial background and loan information
and returns whether the user will default on their loan.
"""

import streamlit as st
import pandas as pd
import pickle

# load in the trained model
pickle_in = open("classifier.pkl", "rb")
classifier = pickle.load(pickle_in)

# function that produces the default prediction
def prediction(age, income, emp_length, loan_amount, int_rate, default_history, credit_length, home_ownership, loan_intent):

    # features to reference later
    pho_Mortgage, pho_Rent, pho_Own, pho_Other = 0, 0, 0, 0
    intent_DC, intent_Education, intent_Home_Improvement, intent_Medical, intent_Personal, intent_Venture = 0, 0, 0, 0, 0, 0

    # Processing user inputs

    ## Default History
    if default_history == "Yes":
        default_history = 1
    else:
        default_history = 0

    ## Home Ownership
    if home_ownership == "Mortgage":
        pho_Mortgage = 1
    elif home_ownership == "Other":
        pho_Other = 1
    elif home_ownership == "Own":
        pho_Own = 1
    elif home_ownership == "Rent":
        pho_Rent = 1

    ## Loan Intent
    if loan_intent == "Debt Consolidation":
        intent_DC = 1
    elif loan_intent == "Education":
        intent_Education = 1
    elif loan_intent == "Home Improvement":
        intent_Home_Improvement = 1
    elif loan_intent == "Medical":
        intent_Medical = 1
    elif loan_intent == "Personal":
        intent_Personal = 1
    elif loan_intent == "Venture":
        intent_Venture = 1

    ## Loan Percent Income
    loan_percent_income = loan_amount / income

    # Creating a dataframe with the user's inputs
    user_inputs = pd.DataFrame([[age, income, emp_length, loan_amount, int_rate,
                                loan_percent_income, default_history, credit_length, pho_Mortgage, pho_Other,
                                pho_Own, pho_Rent, intent_DC, intent_Education, intent_Home_Improvement, intent_Medical,
                                intent_Personal, intent_Venture]])

    #make prediction
    prediction = classifier.predict(user_inputs)

    if prediction == 0:
        prediction = "Not Default"
    else:
        prediction = "Default"

    return prediction

# function that defines our app
def main():
    """Credit Risk App"""
    # front end elements of the web page
    html_temp = """

Credit Risk App

 arhum zafar

    """

    st.markdown(html_temp, unsafe_allow_html=True)

    st.title("Welcome!")
    st.subheader("Begin entering your financial information on the left.")
    st.subheader("The app will then predict whether you will default on your loan.")
    st.write("If there are no fields on the left, click the arrow in the upper left corner.")
    st.write("")
    st.write("")

    # define the user inputs
    age = st.sidebar.slider("Enter your age", 21, 99, 25)
    income = st.sidebar.slider("Income in Dollars:", 0, 150000, 55000)
    emp_length = st.sidebar.slider("Employment length in years", 0, 50, 5)
    int_rate = st.sidebar.slider("Interest Rate - between 5-15%", 5.0, 15.0, 10.0)
    loan_amount = st.sidebar.slider("Loan Amount in dollars:", 0, 100000, 15000)
    credit_length = st.sidebar.slider("Credit history length in years:", 0, 50, 5)
    default_history = st.sidebar.radio("Have you defaulted on a loan before?", ("Yes", "No"))
    home_ownership = st.sidebar.radio("Select your home ownership status:", ("Mortgage", "Rent", "Own", "Other"))
    loan_intent = st.sidebar.radio("Select your loan intent:", ("Debt Consolidation", "Education", "Home Improvement", "Medical",
    "Personal", "Venture"))

    # display the user inputs
    st.write("Your Age: ", int(age))
    st.write("Your Income: ", int(income))
    st.write("Employment Length: ", emp_length)
    st.write("Interest Rate: ", float(int_rate))
    st.write("Loan Amount: ", int(loan_amount))
    st.write("Credit history Length in years: ", int(credit_length))
    st.selectbox("Default History: ", default_history)
    st.selectbox("Home Ownership: ", home_ownership)
    st.selectbox("Loan Intent: ", loan_intent)
    result = ""

    if st.button("Predict"):
        result = prediction(age, income, emp_length, loan_amount, int_rate, default_history, credit_length, home_ownership, loan_intent)
        if result == "Default":
            st.write("")
            st.success("Unfortunately, you are likely to default on your loan.")
        else:
            st.write("")
            st.success("Congrats! You are not likely to default on your loan.")
            st.write("")

        st.write("Thank you for using the credit risk app!")

if __name__ == "__main__":
    main()