#!/usr/bin/env python

# -*- coding: utf-8 -*-
"""
udocker unit tests: CurlHeader
"""

from unittest import TestCase, main
from unittest.mock import patch
from io import StringIO
from udocker.utils.curl import CurlHeader
import collections

collections.Callable = collections.abc.Callable
BUILTINS = "builtins"

class CurlHeaderTestCase(TestCase):
    """Test CurlHeader() http header parser."""

    def test_01_init(self):
        """Test01 CurlHeader() constructor."""
        curl_header = CurlHeader()
        self.assertFalse(curl_header.sizeonly)
        self.assertIsInstance(curl_header.data, dict)
        self.assertEqual("", curl_header.data["X-ND-HTTPSTATUS"])
        self.assertEqual("", curl_header.data["X-ND-CURLSTATUS"])

    def test_02_write(self):
        """Test02 CurlHeader().write()."""
        buff = ["HTTP/1.1 200 OK",
                "Content-Type: application/octet-stream",
                "Content-Length: 32", ]
        curl_header = CurlHeader()
        for line in buff:
            curl_header.write(line)
        status = curl_header.data["content-type"]
        self.assertEqual(status, "application/octet-stream")
        status = curl_header.data["X-ND-HTTPSTATUS"]
        self.assertEqual(status, "HTTP/1.1 200 OK")

        curl_header = CurlHeader()
        for line in buff:
            curl_header.write(line)
        buff_out = curl_header.getvalue()
        self.assertTrue("HTTP/1.1 200 OK" in buff_out)

        line = ""
        curl_header = CurlHeader()
        curl_header.sizeonly = True
        self.assertEqual(-1, curl_header.write(line))

    @patch.object(CurlHeader, 'write')
    def test_03_setvalue_from_file(self, mock_write):
        """Test03 CurlHeader().setvalue_from_file()."""
        fakedata = StringIO('XXXX')
        with patch(BUILTINS + '.open') as mopen:
            mopen.return_value.__iter__ = (
                lambda self: iter(fakedata.readline, ''))
            curl_header = CurlHeader()
            self.assertTrue(curl_header.setvalue_from_file("filename"))
            self.assertTrue(mock_write.called_with('XXXX'))

    def test_04_getvalue(self):
        """Test04 CurlHeader().getvalue()."""
        curl_header = CurlHeader()
        curl_header.data = "XXXX"
        status = curl_header.getvalue()
        self.assertEqual(status, curl_header.data)

if __name__ == '__main__':
    main()


import numpy as np
import random
import dataFormatting

def perceptron(i_x, i_y, r, T):
    _x = i_x
    _y = i_y

    # initialize w as 0's
    w = [0] * len(_x[0])

    for e in range(T):
        #shuffle data
        row_indices = list(range(len(_x)))
        random.shuffle(row_indices)
        shuffled_x = [_x[i] for i in row_indices]
        shuffled_y = [_y[i] for i in row_indices]

        #for each example xy
        for index, xRow in enumerate(shuffled_x):

            #if wrong prediction - update w
            if np.sign(np.dot(xRow,w)) * shuffled_y[index] <= 0:
                temp = [x * shuffled_y[index] for x in xRow] # multiplies x by -1 or 1
                temp2 = [z * r for z in temp] # factors in r
                w = [a + b for a, b in zip(w, temp2)] # updates w

    return w

def votedPerceptron(i_x, i_y, r, T):
    _x = i_x
    _y = i_y

    # initialize w as list
    w = []
    # first element is all 0's
    w.append([0] * len(_x[0]))

    #initialize m as 0
    m = 0
    #initialize c as a list
    c = []
    c.append(0)

    for e in range(T):
        #for each example xy
        for index, xRow in enumerate(_x):

            #if wrong prediction - update w
            if np.sign(np.dot(xRow,w[m])) * _y[index] <= 0:
                temp = [x * _y[index] for x in xRow] # multiplies x by -1 or 1
                temp2 = [z * r for z in temp] # factors in r
                w.append([a + b for a, b in zip(w[m], temp2)]) # adds new w to list of w's
                m = m + 1 # update m
                c.append(1)

            # if correct prediction - add one to c
            else:
                c[m] = c[m] + 1

    return combine_matrix_rows_with_list(w, c)

def averagePerceptron(i_x, i_y, r, T):
    _x = i_x
    _y = i_y

    # initialize w and a as 0's
    w = [0] * len(_x[0])
    a = [0] * len(_x[0])

    for e in range(T):
        #shuffle data
        row_indices = list(range(len(_x)))
        random.shuffle(row_indices)
        shuffled_x = [_x[i] for i in row_indices]
        shuffled_y = [_y[i] for i in row_indices]

        #for each example xy
        for index, xRow in enumerate(shuffled_x):

            #if wrong prediction - update w
            if np.sign(np.dot(xRow,w)) * shuffled_y[index] <= 0:
                temp = [x * shuffled_y[index] for x in xRow] # multiplies x by -1 or 1
                temp2 = [z * r for z in temp] # factors in r
                w = [a + b for a, b in zip(w, temp2)] # updates w
            # update a with w
            a = [z + b for z, b in zip(a, w)]

    return a

# helper function for the return value of votedPerceptron
def combine_matrix_rows_with_list(matrix, x):
    combined_list = []
    for i, row in enumerate(matrix):
        if i < len(x):
            combined_list.append((row, x[i]))
        else:
            combined_list.append((row, None))  # If there are not enough elements in x, use None for the missing value.
    return combined_list

# used for both perceptron and average perceptron
# x and y are for test data, w is weight vector from perceptron
def evaluatePerceptron(x, y, w):
    wrongCount = 0

    #for each example xy
    for index, xRow in enumerate(x):

        #if wrong prediction - add 1 to wrong count
        if np.sign(np.dot(xRow,w)) * y[index] <= 0:
            wrongCount = wrongCount + 1

    # returns error of weight vector
    return wrongCount/len(y)

# x and y are for test data, vp is voted perceptron values for weight vectors and counts
# vp is in form: [([weight vector], count), (([weight vector], count))]
def evaluateVotedPerceptron(x, y, vp):
    wrongCount = 0

    #for each example xy
    for index, xRow in enumerate(x):
        prediction = 0

        # for each weight vector and count
        for weight in vp:

            # adds up prediction signs
            prediction = prediction + weight[1] * np.sign(np.dot(xRow,weight[0]))

        #if wrong prediction - add 1 to wrong count
        if prediction * y[index] <= 0:
            wrongCount = wrongCount + 1

    # returns error of weight vector
    return wrongCount/len(y)

xData = dataFormatting.trainX
yData = dataFormatting.trainY

xTest = dataFormatting.testX
yTest = dataFormatting.testY

learningRate = 0.5
numEpochs = 10

print("all calls use learning rate of 0.5 and T of 10\n")
print("Running normal perceptron 100 times and getting average error...")
averageError = 0
for i in range(100):
    normalWeights = perceptron(xData, yData, learningRate, numEpochs)
    error = evaluatePerceptron(xTest, yTest, normalWeights)
    averageError = averageError + error

averageError = round(averageError/100, 5)
print("the average error is: {}\n".format(averageError))

print("Running voted perceptron 20 times and getting average error...")
averageError = 0
for i in range(20):
    votedWeights = votedPerceptron(xData, yData, learningRate, numEpochs)
    error = evaluateVotedPerceptron(xTest, yTest, votedWeights)
    averageError = averageError + error

averageError = round(averageError/20, 5)
print("the average error is: {}\n".format(averageError))

print("Running average perceptron 100 times and getting average error...")
averageError = 0
for i in range(100):
    averageWeights = averagePerceptron(xData, yData, learningRate, numEpochs)
    error = evaluatePerceptron(xTest, yTest, averageWeights)
    averageError = averageError + error

averageError = round(averageError/100, 5)
print("the average error is: {}\n".format(averageError))

print("the weight vector from one call to perceptron is: {}\n".format(perceptron(xData, yData, learningRate, numEpochs)))
print("the weight vector from one call to averagePerceptron is: {}\n".format(averagePerceptron(xData, yData, learningRate, numEpochs)))
print("the weight vector and counts from one call to votedPerceptron is:\n")

votedValues = votedPerceptron(xData, yData, learningRate, numEpochs)

# rounds values to 8 digits for better looking output
votedValues = [([round(value, 8) for value in tup[0]], tup[1]) for tup in votedValues]
print(votedValues)

f = open("Perceptron/votedOutput.txt", "w")
f.write(str(votedValues))
f.close()

print("the voted perception output is also contained in the file votedOutput.txt")


import sys
import json

# Get arguments
semanticLabelPath = sys.argv[1]
changelogPath = sys.argv[2]
if len(sys.argv)>3:
  version = sys.argv[3]
else:
  version = None

# read semantic labels
with open(semanticLabelPath, 'r') as semanticLabelFile:
  semanticLabels = json.load(semanticLabelFile)

# print version changelog function
def printVersionChangelog(log: dict, version: str):
  sys.stdout.write("## Version " + version + "\n\n")
  for label in (semanticLabels["major"] + semanticLabels["minor"] + semanticLabels["patch"] + ["other"]):
    if label in log[version]:
      sys.stdout.write("### " + label + "\n\n")
      for change in log[version][label]:
        sys.stdout.write("* " + change + "\n")
      sys.stdout.write("\n")

# read changelog json
with open(changelogPath, 'r') as changelogFile:
  changelog = json.load(changelogFile)

sys.stdout.write("# CHANGELOG\n\n")
if version is not None:
  printVersionChangelog(changelog, version)
else:
  for ver in list(changelog.keys())[::-1]:
    printVersionChangelog(changelog, ver)


def solution(answers):
    result = []
    scores = [0, 0, 0]

    for idx, answer in enumerate(answers):
        if [1,2,3,4,5][idx % 5] == answer:
            scores[0] += 1

        if [2,1,2,3,2,4,2,5][idx % 8] == answer:
            scores[1] += 1

        if [3,3,1,1,2,2,4,4,5,5][idx % 10] == answer:
            scores[2] += 1

    # 이렇게 하면, 점수가 가장 높은 학생의 순번을 오름차순으로 넣을 수 있고,
    # 점수가 동일한 학생이더라도 오름차순으로 넣을 수 있다.
    max_score = max(scores)
    for idx, score in enumerate(scores):
        if max_score == score:
            result.append(idx + 1)

    return result

print(solution([1,2,3,4,5]))
print(solution([1,3,2,4,2]))


itemLotParam_mapTemplate = {
    "ID": "0",  # set to Row ID of the lot
    "Name": "",  # set to name used in yapped
    "lotItemId01": "0",  # set to EquipParam* ID of item
    "lotItemId02": "0",
    "lotItemId03": "0",
    "lotItemId04": "0",
    "lotItemId05": "0",
    "lotItemId06": "0",
    "lotItemId07": "0",
    "lotItemId08": "0",
    # set lotItemCategory01 to type of item:
    # 0 - None
    # 1 - Good
    # 2 - Weapon
    # 3 - Protector
    # 4 - Accessory
    # 5 - Ashes
    "lotItemCategory01": "1",  # 1 because all our notes are Goods
    "lotItemCategory02": "0",
    "lotItemCategory03": "0",
    "lotItemCategory04": "0",
    "lotItemCategory05": "0",
    "lotItemCategory06": "0",
    "lotItemCategory07": "0",
    "lotItemCategory08": "0",
    "lotItemBasePoint01": "1000",
    "lotItemBasePoint02": "0",
    "lotItemBasePoint03": "0",
    "lotItemBasePoint04": "0",
    "lotItemBasePoint05": "0",
    "lotItemBasePoint06": "0",
    "lotItemBasePoint07": "0",
    "lotItemBasePoint08": "0",
    "cumulateLotPoint01": "0",
    "cumulateLotPoint02": "0",
    "cumulateLotPoint03": "0",
    "cumulateLotPoint04": "0",
    "cumulateLotPoint05": "0",
    "cumulateLotPoint06": "0",
    "cumulateLotPoint07": "0",
    "cumulateLotPoint08": "0",
    "getItemFlagId01": "0",
    "getItemFlagId02": "0",
    "getItemFlagId03": "0",
    "getItemFlagId04": "0",
    "getItemFlagId05": "0",
    "getItemFlagId06": "0",
    "getItemFlagId07": "0",
    "getItemFlagId08": "0",
    "getItemFlagId": "0",  # set this to the same flag as the base lot
    "cumulateNumFlagId": "0",
    "cumulateNumMax": "0",
    "lotItem_Rarity": "-1",
    "lotItemNum01": "1",  # set this to the desired quantity of the item
    "lotItemNum02": "0",
    "lotItemNum03": "0",
    "lotItemNum04": "0",
    "lotItemNum05": "0",
    "lotItemNum06": "0",
    "lotItemNum07": "0",
    "lotItemNum08": "0",
    "enableLuck01": "0",
    "enableLuck02": "0",
    "enableLuck03": "0",
    "enableLuck04": "0",
    "enableLuck05": "0",
    "enableLuck06": "0",
    "enableLuck07": "0",
    "enableLuck08": "0",
    "cumulateReset01": "0",
    "cumulateReset02": "0",
    "cumulateReset03": "0",
    "cumulateReset04": "0",
    "cumulateReset05": "0",
    "cumulateReset06": "0",
    "cumulateReset07": "0",
    "cumulateReset08": "0",
    "GameClearOffset": "0",
    "canExecByFriendlyGhost": "0",
    "canExecByHostileGhost": "0",
    "PAD1": "0",
    "PAD2": "0"
}


level_5 = [
    {
        "id": "Level5_SceneA",
        "text": "[[cyan]]"
                "You studied well, got enough of sleep and even got extra points on the exam, bringing your total \n"
                "grade to an A+. There is nothing you can't do. It's time to think about college. Your perfect \n"
                "grade opens up few doors for you and even 100% scholarship in any university. What's your pick?"
                "[[resetColor]]",
        "links": [
            {
                "label": "Ivy league all the way!",
                "id": "Level6_SceneA"
            }, {
                "label": "Arizona is good and luckily not far from home",
                "id": "Level6_SceneB"
            }, {
                "label": "College name does not matter, as long as it's in my hometown",
                "id": "Level6_SceneC"
            }, {
                "label": "Studying drained me out. I want to relax and think what I want to do with my life",
                "id": "Level6_SceneD"
            }
        ]
    }, {
        "id": "Level5_SceneB",
        "text": "[[cyan]]"
                "You were not completely ready for the test, but you did good. You got decent amount of sleep and \n"
                "got a B+ on the test. Not too bad, mate! What do you think about college??"
                "[[resetColor]]",
        "links": [
            {
                "label": "Pick the best college that you got accepted to",
                "id": "Level6_SceneB"
            }, {
                "label": "I want to stay in town close to my family and friends",
                "id": "Level6_SceneC"
            }, {
                "label": "College? I am done studying for now",
                "id": "Level6_SceneD"
            }
        ]
    }, {
        "id": "Level5_SceneC",
        "text": "[[cyan]]"
                "You  woke up relaxed and refreshed, but you got a C in the test. It could have been better, but now \n"
                "is not the time to fix on the past. Decide what you want to do next in your life."
                "[[resetColor]]",
        "links": [
            {
                "label": "I need a degree, at least that's what my parent say",
                "id": "Level6_SceneC"
            }, {
                "label": "I should take a year to try something else",
                "id": "Level6_SceneD"
            }
        ]
    }, {
        "id": "Level5_SceneD",
        "text": "[[cyan]]"
                "Wow, literature junkie over here! It is the right answer and teacher let you to take the test. \n"
                "Unfortunately, there was not enough time, so you got C. What do you do next?"
                "[[resetColor]]",
        "links": [
            {
                "label": "More studying, yay - college all the way",
                "id": "Level6_SceneC"
            }, {
                "label": "Gap year is all I need",
                "id": "Level6_SceneD"
            }
        ]
    }, {
        "id": "Level5_SceneE",
        "text": "[[cyan]]"
                "Wrong! You had not have enough time to finish the test and lost some points because you were later. \n"
                "That's a D. That really leaves you without options for now. "
                "[[resetColor]]",
        "links": [
            {
                "label": "Take a gap year to catch up",
                "id": "Level6_SceneD"
            }
        ]
    }, {
        "id": "Level5_SceneF",
        "text": "[[cyan]]"
                "You are the last one to leave the party. Time has passed fast, it's 7 am, you go home and fell \n"
                "asleep. Few hours later, you realize that you missed your literature test. You got an F. That \n"
                "really leaves you without options for now."
                "[[resetColor]]",
        "links": [
            {
                "label": "Take a gap year to catch up",
                "id": "Level6_SceneD"
            }
        ]
    }
]


import logging
from copy import deepcopy

"""
INFORMACOES OBRIGATORIAS NOS LOGS
client, id, service
"""

from aws_xray_sdk.core import patch_all

FORMAT = "[%(levelname)s] | %(message)s"

class RequiredParametersException(Exception):
    pass

class Logger(object):

    def __init__(self, logger_name=None, logger_level='ERROR', enable_xray=False):
        """
        Cria uma nova instância de Logger

        Parameters:
        -----------
        logger_name: str
            Nome do logger que será criado

        logger_level: str
            Nível mínimo de log que será impresso na tela. Os níveis de log seguem uma hierarquia fixa e são ordenados por criticidade:
            (OBS: o nível NOTSET é um pseudo-nível que indica que não há restrições de log, podendo ser impressos até mesmo logs de sistema)
            (OBS2: O nível OFF é outro pseudo-nível que desabilita a impressão dos logs por meio desta classe)

            OFF < NOTSET < DEBUG < INFO < WARNING (ou WARN) < ERROR < CRITICAL (ou FATAL)

        enable_xray: boolean
            Flag que habilita o xray para lambdas
        """
        self.logger_name = logger_name
        self.logger_level = logger_level
        self.logger = self.__create_logger(enable_xray)
        self.__extra_fields = {}

    @property
    def extra_fields(self):
        return self.__extra_fields

    @extra_fields.setter
    def extra_fields(self, extra_fields={}):
        self.__extra_fields = extra_fields

    def critical(self, message, **kwargs):
        self.__print_log(message, logging.CRITICAL, **kwargs)

    def error(self, message, **kwargs):
        self.__print_log(message, logging.ERROR, **kwargs)

    def warn(self, message, **kwargs):
        self.__print_log(message, logging.WARNING, **kwargs)

    def info(self, message, **kwargs):
        self.__print_log(message, logging.INFO, **kwargs)

    def debug(self, message, **kwargs):
        self.__print_log(message, logging.DEBUG, **kwargs)

    def __create_logger(self, enable_xray=False):
        logger = logging.getLogger(self.logger_name or __name__)
        logger.propagate = False

        if enable_xray:
            patch_all()

        if not logger.handlers and self.logger_level != 'OFF':
            logger.setLevel(self.logger_level)
            formatter = logging.Formatter(FORMAT)
            ch = logging.StreamHandler()
            ch.setLevel(self.logger_level)
            ch.setFormatter(formatter)
            logger.addHandler(ch)

        return logger

    def __print_log(self, message, logger_level, **kwargs):
        local_extra_fields = deepcopy(self.extra_fields)
        local_extra_fields.update(kwargs)

        extra_fields_message = self.__dict_to_string(local_extra_fields)
        log_message = f'{message} | {extra_fields_message}' if extra_fields_message != '' else message

        if self.logger_level != "OFF":

            if logger_level == logging.CRITICAL:
                self.logger.critical(log_message)
            elif logger_level == logging.ERROR:
                self.logger.error(log_message)
            elif logger_level == logging.WARNING:
                self.logger.warning(log_message)
            elif logger_level == logging.INFO:
                self.logger.info(log_message)
            elif logger_level == logging.DEBUG:
                self.logger.debug(log_message)

    def __dict_to_string(self, dictionary):
        return ' | '.join([f'{key} = {value}' for key, value in dictionary.items()])


import FWCore.ParameterSet.Config as cms

cmgDiTauCorFactory = cms.PSet(
    # leg1 and leg2 are dummy collections here
    leg1Collection = cms.InputTag(''),
    leg2Collection = cms.InputTag(''),
    metCollection = cms.InputTag('recoilCorrectedMET'),
    diObjectCollection = cms.InputTag('cmgDiTauSel')
)

cmgDiTauCor = cms.EDFilter(
    "DiTauUpdatePOProducer",
    cfg = cmgDiTauCorFactory.clone(),
    cuts = cms.PSet()
    )


import os
import pandas as pd
from printError import printErr

def reader(FileName):
    """Reads data from files with various extensions. Currently only working for csv extension

    :param FileName: Name of file from where data should be read
    :type FileName: str
    :return: A dataframe containing data from file
    :rtype: pandas.dataframe
    """
    # Check extension of given filename
    nameAsList = FileName.split('.')
    fileExt = nameAsList[-1]

    # Use proper function to handle given file
    if fileExt == 'csv':
        return pd.read_csv(FileName)
    else:
        printErr('File type not compatible', 3)

def comparison(FileName, VolumeDistribution, outFolder):
    """Produces a sorted .xlsx file, where one can compare the volume distribution of sample with some known drugs

    :param FileName: Name/Path of dataset containg name and volume distribution data of known drugs
    :type FileName: str
    :param VolumeDistribution: volume distribution of the sample
    :type VolumeDistribution: float
    :param outFolder: Folder to save all of output data (graphs, comparison data, computational result)
    :type outFolder: str
    """
    # Creating data heads
    nameHead = ['Name', 'NAME', 'name']

    # Reading data from file
    df1 = reader(FileName)

    # Setting and checking data heads
    (name, volume) = df1.keys()
    for i in nameHead:
        if name == i:
            break
    else:
        raise KeyError('Name data not found! Check Header')

    # Appending the sample volume distribution to the data read
    df2 = pd.DataFrame({name: ['Sample'],
                        volume: [VolumeDistribution]})

    df1 = df1.append(df2, ignore_index=True)

    outFile = os.path.join(outFolder, 'Drug_Comparison.xlsx')

    # Sorting the data and exporting it
    sorted_df = df1.sort_values(by=['V'], ascending=True)
    sorted_df.to_excel(outFile,
                       sheet_name='Comparison Sheet')


# Dice Game

import random
import math

# Ask if there are two players or one player playing against the computer
while True:
    try:
        num_of_players = int(input("Do you want to play a one-player or two-player game? Please type 1 or 2: "))
        print("You chose a {} player game".format(num_of_players))
        break
    except ValueError:
        print("Oops!  Thats not a valid answer. please try again...")

# Ask player for their chosen name
player1 = input("Player what would like to be called? ")

# Set player 2 default as computer
player2 = "Computer"

# If the players want to play with 2 players ask player 2 for their name
if num_of_players == 2:
    player2 = input("Player 2 what you like to be called? ")

# Print the players names
print("Let's start playing {} and {}!".format(player1, player2))

# Create a roll dice function
def roll_dice():
    return random.randint(1, 6)

# Set player 1's dice rolls and total
p1_roll_one = roll_dice()
p1_roll_two = roll_dice()
p1_total_roll = p1_roll_one + p1_roll_two

# Print the roll results to the player
print("{} you rolled a {} and a {} to create a total of {}".format(player1, p1_roll_one, p1_roll_two, p1_total_roll))

# Set player 2's dice rolls and total
p2_roll_one = rollDice()
p2_roll_two = rollDice()
p2_total_roll = p2_roll_one + p2_roll_two

# Print the roll results to the player
print("{} rolled a {} and a {} to create a total of {}".format(player2, p2_roll_one, p2_roll_two, p2_total_roll))

# Work out who wins and display winner
if p1_total_roll > p2_total_roll:
    print("{} wins!".format(player1))
elif p2_total_roll > p1_total_roll:
    print("{} wins!".format(player2))
else:
    print("It's a draw!")


from kivy.uix.textinput import TextInput
from kivy.clock import Clock
from kivy.base import EventLoop

class TxtInput(TextInput):
	# Enable right click
	# Enforce single active selection / copy-paste menu
	# ---- BEGIN ----

	last_selected= dict(instance=None, hidden=True) # Indicates if a selection exists

	# Disable long touch -- for like, when you drag to cancel menu from showing
	def long_touch(self, dt): pass

	# Enable copy-paste menu on right click. Also disable selection when click occurs outside input.
	def on_touch_down(self, touch):
		if self.last_selected['instance'] and \
		not self.last_selected['instance'].collide_point(*touch.pos):
				self.hide_old()

		if self.collide_point(*touch.pos):
			if touch.button == "right":
				return self.show_copy_paste(touch)
		return super().on_touch_down(touch)

	# Override to enforce single active selection / copy-paste menu
	# Note that showing the context menu causes a loss in focus
	def _on_textinput_focused(self, instance, value, *largs):
		from kivy.base import EventLoop
		from kivy import Config
		_is_desktop = Config.getboolean('kivy', 'desktop')

		win = EventLoop.window
		# self.cancel_selection() # changed
		# self._hide_cut_copy_paste(win) # changed

		if value:
			self.hide_old() # changed
			self.assign_last(instance=self, hidden=False) # changed

			if (not (self.readonly or self.disabled) or _is_desktop and
					self._keyboard_mode == 'system'):
				self._trigger_cursor_reset()
				self._editable = True
			else:
				self._editable = False
		else:
			self._do_blink_cursor_ev.cancel()
			self._hide_handles(win)

	# Helper function
	@classmethod
	def hide_old(cls):
		win = EventLoop.window
		if cls.last_selected['hidden'] is False:
			cls.last_selected['instance']._hide_cut_copy_paste(win)
			cls.last_selected['instance'].cancel_selection()
			cls.assign_last(hidden=True)

	# Helper function
	@classmethod
	def assign_last(cls, instance=None, hidden=None):
		tmp= cls.last_selected
		if instance is not None:
			tmp['instance']= instance
		if hidden is not None:
			tmp['hidden']= hidden

	# Helper function
	def show_copy_paste(self, touch):
		if self.focus and self.selection_text:
			pos= self.to_local(*touch.pos, relative=False)
			self._show_cut_copy_paste(pos, EventLoop.window)
			self.assign_last(instance=self, hidden=False)
			return False
		return False

	# ---- END ----

	# Bugfix for focus_previous not working: https://github.com/kivy/kivy/issues/6560
	def keyboard_on_key_down(self, window, keycode, text, modifiers):
		from kivy.base import EventLoop
		from kivy.clock import Clock
		import sys
		_is_osx = sys.platform == 'darwin'

		# Keycodes on OS X:
		ctrl, cmd = 64, 1024
		key, key_str = keycode
		win = EventLoop.window

		# This allows *either* ctrl *or* cmd, but not both.
		modifiers = set(modifiers) - {'capslock', 'numlock'}
		is_shortcut = (modifiers == {'ctrl'} or (
		_is_osx and modifiers == {'meta'}))
		is_interesting_key = key in (list(self.interesting_keys.keys()) + [27])

		modifiers= list(modifiers) # changed
		if not self.write_tab and super(TextInput,
			self).keyboard_on_key_down(window, keycode, text, modifiers):
			return True

		if not self._editable:
			# duplicated but faster testing for non-editable keys
			if text and not is_interesting_key:
				if is_shortcut and key == ord('c'):
					self.copy()
			elif key == 27:
				self.focus = False
			return True

		if text and not is_interesting_key:

			self._hide_handles(win)
			self._hide_cut_copy_paste(win)
			win.remove_widget(self._handle_middle)

			# check for command modes
			# we use \x01INFO\x02 to get info from IME on mobiles
			# pygame seems to pass \x01 as the unicode for ctrl+a
			# checking for modifiers ensures conflict resolution.

			first_char = ord(text[0])
			if not modifiers and first_char == 1:
				self._command_mode = True
				self._command = ''
			if not modifiers and first_char == 2:
				self._command_mode = False
				self._command = self._command[1:]

			if self._command_mode:
				self._command += text
				return

			_command = self._command
			if _command and first_char == 2:
				from_undo = True
				_command, data = _command.split(':')
				self._command = ''
				if self._selection:
					self.delete_selection()
				if _command == 'DEL':
					count = int(data)
					if not count:
						self.delete_selection(from_undo=True)
					end = self.cursor_index()
					self._selection_from = max(end - count, 0)
					self._selection_to = end
					self._selection = True
					self.delete_selection(from_undo=True)
					return
				elif _command == 'INSERT':
					self.insert_text(data, from_undo)
				elif _command == 'INSERTN':
					from_undo = False
					self.insert_text(data, from_undo)
				elif _command == 'SELWORD':
					self.dispatch('on_double_tap')
				elif _command == 'SEL':
					if data == '0':
						Clock.schedule_once(lambda dt: self.cancel_selection())
				elif _command == 'CURCOL':
					self.cursor = int(data), self.cursor_row
				return

			if is_shortcut:
				if key == ord('x'):  # cut selection
					self._cut(self.selection_text)
				elif key == ord('c'):  # copy selection
					self.copy()
				elif key == ord('v'):  # paste clipboard content
					self.paste()
				elif key == ord('a'):  # select all
					self.select_all()
				elif key == ord('z'):  # undo
					self.do_undo()
				elif key == ord('r'):  # redo
					self.do_redo()
			else:
				is_sdl2 = (EventLoop.window.__class__.__module__ ==
						   'kivy.core.window.window_sdl2')
				if is_sdl2:
					# we expect to get managed key input via on_textinput
					return
				if self._selection:
					self.delete_selection()
				self.insert_text(text)
			# self._recalc_size()
			return

		if is_interesting_key:
			self._hide_cut_copy_paste(win)
			self._hide_handles(win)

		if key == 27:  # escape
			self.focus = False
			return True
		elif key == 9:  # tab
			self.insert_text(u'\t')
			return True

		k = self.interesting_keys.get(key)
		if k:
			key = (None, None, k, 1)
			self._key_down(key)


# CRC
def crc(incoming):
    # convert to bytearray
    hex_data = incoming.decode("hex")
    msg = bytearray(hex_data)
    check = 0
    for i in msg:
        check = _addToCRC(i, check)
    return hex(check)

def _addToCRC(b, crc):
    if (b < 0):
        b += 256
    for i in range(8):
        odd = ((b^crc) & 1) == 1
        crc >>= 1
        b >>= 1
        if (odd):
            crc ^= 0x8C # this means crc ^= 140
    return crc


#!/usr/bin/python3
"""define a class representing a rectangle"""

class Rectangle:
    """ class that hold the width and height of a rectangle
    :attribute width: (int)
    :attribute height: (int)

    :method width: getter -> int
    :method width: setter -> void

    :method height: getter -> int
    :method height: setter -> void
    """
    def __init__(self, width=0, height=0):
        if type(width) is not int:
            raise TypeError("width must be an integer")
        elif width < 0:
            raise ValueError("width must be >= 0")
        elif type(height) is not int:
            raise TypeError("height must be an integer")
        elif height < 0:
            raise ValueError("height must be >= 0")
        else:
            self.__width = width
            self.__height = height

    @property
    def width(self):
        return self.__width

    @width.setter
    def width(self, value):
        if not isinstance(value, int):
            raise TypeError("width must be an integer")
        if value < 0:
            raise ValueError("width must be >= 0")
        self.__width = value

    @property
    def height(self):
        return self.__height

    @height.setter
    def height(self, value):
        if not isinstance(value, int):
            raise TypeError("height must be an integer")
        if value < 0:
            raise ValueError("height must be >= 0")
        self.__height = value


import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html

def cargarArchivo(ruta):
    return pd.read_csv(ruta)

emisiones = cargarArchivo("DATOS/Emisiones_limpio.csv")

print(emisiones.head())

entidades = emisiones["ENTIDAD"].unique()

lista_entidades = []

for i in entidades:
    lista_entidades.append(["Femenino", i, emisiones[(emisiones["SEXO"] == "Femenino") & (emisiones["ENTIDAD"] == i)]["NUMERO DE ASEGURADOS"].sum()])
    lista_entidades.append(["Masculino", i, emisiones[(emisiones["SEXO"] == "Masculino") & (emisiones["ENTIDAD"] == i)]["NUMERO DE ASEGURADOS"].sum()])

df_entidades = pd.DataFrame(lista_entidades, columns=["SEXO", "ENTIDAD", "OCURRENCIAS"])

fig_entidades = px.bar(df_entidades, x="ENTIDAD", y="OCURRENCIAS", color="SEXO", barmode="group",
             title="Número de asegurados por entidad y sexo")
fig_entidades.update_layout(xaxis_title="", yaxis_title="Número de asegurados", legend_title="")

comisiones = cargarArchivo("DATOS/Comisiones_limpio.csv")

polizas = comisiones["MODALIDAD DE LA POLIZA"].unique()

lista_polizas = []

for i in polizas:
    lista_polizas.append(["Femenino", i, comisiones[(comisiones["SEXO"] == "Femenino") & (comisiones["MODALIDAD DE LA POLIZA"] == i)]["NUMERO DE ASEGURADOS"].sum()])
    lista_polizas.append(["Masculino", i, comisiones[(comisiones["SEXO"] == "Masculino") & (comisiones["MODALIDAD DE LA POLIZA"] == i)]["NUMERO DE ASEGURADOS"].sum()])

df_polizas = pd.DataFrame(lista_polizas, columns=["SEXO", "MODALIDAD DE LA POLIZA", "OCURRENCIAS"])

fig_polizas = go.Figure

import pandas as pd
import plotly.express as px
import dash
import dash_core_components as dcc
import dash_html_components as html

# Cargar los datos
emisiones = pd.read_csv("DATOS/Emisiones_limpio.csv")
comisiones = pd.read_csv("DATOS/Comisiones_limpio.csv")

# Crear la aplicación de Dash
app = dash.Dash(__name__)

# Crear el layout
app.layout = html.Div(children=[
    html.H1(children='Número de asegurados por entidad y sexo'),
    dcc.Graph(
        id='entidades',
        figure=px.bar(df_entidades, x="ENTIDAD", y="OCURRENCIAS", color="SEXO", barmode="group",
                      title="Número de asegurados por entidad y sexo")
    ),
    html.H1(children='Número de asegurados por modalidad de la póliza y sexo'),
    dcc.Graph(
        id='polizas',
        figure=px.bar(df_polizas, x="MODALIDAD DE LA POLIZA", y="OCURRENCIAS", color="SEXO", barmode="group",
                      title="Número de asegurados por modalidad de la póliza y sexo")
    )
])

# Iniciar la aplicación de Dash
if __name__ == '__main__':
    app.run_server(debug=True)


# -*- coding: utf-8 -*-
"""
Created on Thu Mar 16 15:40:21 2023

@author: Yue
"""

import pandas as pd

def estimate_lambda(df_sales, resample='d'):
    df_sales['date'] = pd.to_datetime(df_sales['下单时间'])
    # 以日期作为索引
    df_sales = df_sales.set_index('date')
    # 取其中一种产品，按日求和得到各字段每日总和
    daily_sales_sum = df_sales[df_sales['ProductName']=='中长款无毛领羽绒服'].resample(resample).sum(numeric_only=True)
    # 每日销量总和的均值即为需求到达率
    daily_sales_sales_avg = daily_sales_sum['销量'].mean()
    return daily_sales_sales_avg

def estimate_c_L(df_purchase):
    df_purchase['date'] = pd.to_datetime(df_purchase['下单日期'])
    # 以日期作为索引
    df_purchase = df_purchase.set_index('date')
    # 取其中一种产品
    product = df_purchase[df_purchase['ProductName']=='中长款无毛领羽绒服']
    c = (product['单价'] * product['采购数量']).sum() / product['采购数量'].sum()
    # L为每日平均提前期的加权平均，权重为当日采购数量
    L = (product['提前期'] * product['采购数量']).sum() / product['采购数量'].sum()
    return c, L

if __name__ == '__main__':
    df_sales = pd.read_csv('销量表(1).csv', encoding='gbk')
    daily_sales_sales_avg = estimate_lambda(df_sales)
    print('需求到达率:', daily_sales_sales_avg)

    df_purchase = pd.read_csv('完整供应表(1).csv', encoding='gbk')
    c, L = estimate_c_L(df_purchase)
    print('采购成本:', c)
    print('提前期:', L)


# bmi_calc.py

def interface():
    print("BMI Calculator")
    k = 0
    while k == 0:
        print("Options:")
        print("  1 - Metric (kg/m)")
        print("  2 - Imperial (lb/in)")
        print("  9 - Quit")
        choice = input("Enter your option: ")
        if choice == '1':
            k = 1
            analysis(1)
        elif choice == '2':
            k = 2
            analysis(2)
        elif choice == '9':
            k = 1
            return
        else:  # other number
            k = 0
            print("That's not an option. Select a different number.")

def data_input():
    weight_input = input("Enter weight: ")
    weight_input = weight_input.split(" ")
    data_input.weight = float(weight_input[0])
    height_input = input("Enter height: ")
    height_input = height_input.split(" ")
    data_input.height = float(height_input[0])
    check_input(data_input.weight, data_input.height)

def check_input(w, h):
    # check if entered weight and height correct,
    print("Your weight and height were input as {} lbs/kg and {} in/m.".format(w, h))
    print("Is this correct?")
    check_choice = input("  1 - Yes, 2 - No\n")
    if check_choice == '1':
        print("On to your BMI calculation!")
    elif check_choice == '2':
        print("Please re-enter weight and height")
        data_input()
    else:
        print("Please pick 1 or 2!")
        check_input(w, h)

def analysis(n):
    data_input()
    analysis.bmi = bmi_calc(data_input.weight, data_input.height, n)
    bmi_output(analysis.bmi)

def bmi_calc(w, h, n):
    if n == 1:  # metric
        bmi = w/(h**2)
    elif n == 2:  # imperial
        bmi = 703*w/(h**2)
    print("Your BMI is {:0.2f}." .format(bmi))
    return bmi

def bmi_output(bmi):
    if bmi < 18.50:
        result = "underweight"
    elif 18.50 <= bmi < 24.99:
        result = "normal"
    elif 25 <= bmi < 29.99:
        result = "overweight"
    else:  # bmi >30
        result = "obese"
    print("Your BMI indicates that you are {}." .format(result))

if __name__ == "__main__":
    interface()


from __future__ import print_function

import math
import os
import random

import numpy as np
import torch
import torch.nn.functional as F
from PIL import ImageFilter

def seed_everything(seed: int):
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = True

def D(p, z, version='simplified'):  # negative cosine similarity
    if version == 'original':
        z = z.detach()  # stop gradient
        p = F.normalize(p, dim=1)  # l2-normalize
        z = F.normalize(z, dim=1)  # l2-normalize
        return -(p * z).sum(dim=1).mean()

    elif version == 'simplified':  # same thing, much faster. Scroll down, speed test in __main__
        return - F.cosine_similarity(p, z.detach(), dim=-1).mean()
    else:
        raise Exception

def knn_predict(feature, feature_bank, feature_labels, classes, knn_k):
    # compute cos similarity between each feature vector and feature bank ---> [B, N]
    sim_matrix = torch.mm(feature, feature_bank)
    # [B, K]
    sim_weight, sim_indices = sim_matrix.topk(k=knn_k, dim=-1)
    # [B, K]
    sim_labels = torch.gather(feature_labels.expand(feature.size(0), -1), dim=-1, index=sim_indices)
    # print(sim_weight.shape, sim_labels.shape)
    sim_weight = torch.ones_like(sim_weight)

    sim_weight = sim_weight / sim_weight.sum(dim=-1, keepdim=True)

    # counts for each class
    one_hot_label = torch.zeros(feature.size(0) * knn_k, classes, device=sim_labels.device)
    # [B*K, C]
    one_hot_label = one_hot_label.scatter(dim=-1, index=sim_labels.view(-1, 1), value=1.0)
    # weighted score ---> [B, C]
    # print(one_hot_label.shape)
    pred_scores = torch.sum(one_hot_label.view(feature.size(0), -1, classes) * sim_weight.unsqueeze(dim=-1), dim=1)
    # print(pred_scores.shape)
    pred_labels = pred_scores.argmax(dim=-1)
    return pred_scores, pred_labels

def weighted_knn(cur_feature, feature, label, num_classes, knn_k=100, chunks=10, norm='global'):
    # distributed fast KNN and sample selection with three different modes
    num = len(cur_feature)
    num_class = torch.tensor([torch.sum(label == i).item() for i in range(num_classes)]).to(
        feature.device) + 1e-10
    pi = num_class / num_class.sum()
    split = torch.tensor(np.linspace(0, num, chunks + 1, dtype=int), dtype=torch.long).to(feature.device)
    score = torch.tensor([]).to(feature.device)
    pred = torch.tensor([], dtype=torch.long).to(feature.device)
    feature = torch.nn.functional.normalize(feature, dim=1)
    with torch.no_grad():
        for i in range(chunks):
            torch.cuda.empty_cache()
            part_feature = cur_feature[split[i]: split[i + 1]]

            part_score, part_pred = knn_predict(part_feature, feature.T, label, num_classes, knn_k)
            score = torch.cat([score, part_score], dim=0)
            pred = torch.cat([pred, part_pred], dim=0)

        # balanced vote
        if norm == 'global':
            # global normalization
            score = score / pi
        else:  # no normalization
            pass
        score = score/score.sum(1, keepdim=True)

    return score  # , pred

def save_checkpoint(state, filename='checkpoint.pth.tar'):
    torch.save(state, filename)

def adjust_learning_rate(optimizer, epoch, args):
    """Decay the learning rate based on schedule"""
    lr = args.lr
    if args.cos:  # cosine lr schedule
        lr *= 0.5 * (1. + math.cos(math.pi * epoch / args.epochs))
    else:  # stepwise lr schedule
        for milestone in args.schedule:
            lr *= 0.1 if epoch >= milestone else 1.
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

def accuracy(output, target, topk=(1,)):
    """Computes the accuracy over the k top predictions for the specified values of k"""
    with torch.no_grad():
        maxk = max(topk)
        batch_size = target.size(0)

        _, pred = output.topk(maxk, 1, True, True)
        pred = pred.t()
        correct = pred.eq(target.view(1, -1).expand_as(pred))

        res = []
        for k in topk:
            correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True)
            res.append(correct_k.mul_(100.0 / batch_size))
        return res

def save_config(args, path):
    dict = vars(args)
    if not os.path.isdir(path):
        os.mkdir(os.path.abspath(path))
    with open(path + '/params.csv', 'w') as f:
        for key in dict.keys():
            f.write("%s\t%s\n" % (key, dict[key]))

class AverageMeter(object):
    """Computes and stores the average and current value"""

    def __init__(self, name, fmt=':f'):
        self.name = name
        self.fmt = fmt
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

    def __str__(self):
        fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})'
        return fmtstr.format(**self.__dict__)

class KCropsTransform:
    """Take K random crops of one image as the query and key."""

    def __init__(self, base_transform, K=2):
        self.base_transform = base_transform
        self.K = K

    def __call__(self, x):
        res = [self.base_transform(x) for i in range(self.K)]
        return res

class MixTransform:
    def __init__(self, strong_transform, weak_transform, K=2):
        self.strong_transform = strong_transform
        self.weak_transform = weak_transform
        self.K = K

    def __call__(self, x):
        res = [self.weak_transform(x) for i in range(self.K)] + [self.strong_transform(x) for i in range(self.K)]
        return res

class DMixTransform:
    def __init__(self, transforms, nums):
        self.transforms = transforms
        self.nums = nums

    def __call__(self, x):
        res = []
        for i, trans in enumerate(self.transforms):
            res += [trans(x) for _ in range(self.nums[i])]
        return res

class GaussianBlur(object):
    """Gaussian blur augmentation in SimCLR https://arxiv.org/abs/2002.05709"""

    def __init__(self, sigma=[.1, 2.]):
        self.sigma = sigma

    def __call__(self, x):
        sigma = random.uniform(self.sigma[0], self.sigma[1])
        x = x.filter(ImageFilter.GaussianBlur(radius=sigma))
        return x


#!/usr/bin/env python

# @file robot_motion_controller.py
# @brief This node allows to move the robot from the current to the target position.

import numpy as np
import random
import matplotlib.pyplot as plt
import time
import rospy
from std_msgs.msg import Int64MultiArray
from std_msgs.msg import Bool
from matplotlib import cm
from geometry_msgs.msg import Twist
import sys
import math
from nav_msgs.msg import Odometry
from tf.transformations import euler_from_quaternion

pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
vel = Twist()
vel.linear.x = 0
vel.linear.y = 0
vel.linear.z = 0
vel.angular.x = 0
vel.angular.y = 0
vel.angular.z = 0

number = 1
curr_x = 0
curr_y = 0

# Calculates the euclidean distance between two given points

def EuclidianDistance(x_goal, y_goal, x_real, y_real):
    euclidean_dist = math.sqrt(
        math.pow((x_goal-x_real), 2) + math.pow((y_goal-y_real), 2))

    return euclidean_dist

# Callback function for the robot position.

def odom_callback(data):

    global curr_x
    global curr_y

    curr_x = data.pose.pose.position.x
    curr_y = data.pose.pose.position.y

# Callback function for the target position.
# It computes the velocity to send to the cmd_vel topic, by considering an omniwheel robot.
# when the robot has arrived at desired position, publishes vel=0 and sets the "arrived" and
# current robot position parameters.

def traj_callback(data):

    global curr_x
    global curr_y
    global number

    target_pos = data.data
    target_x = target_pos[0]
    target_y = target_pos[1]

    while EuclidianDistance(target_x, target_y, curr_x, curr_y) >= 0.001:

        # omniwheel robot
        vel.linear.x = (target_x-curr_x)
        vel.linear.y = (target_y-curr_y)

        # Publish
        pub.publish(vel)

    # omniwheel robot
    vel.linear.x = 0
    vel.linear.y = 0

    # Publish
    pub.publish(vel)

    # Set command parameter
    rospy.set_param('all', [target_x, target_y, curr_x, curr_y, number])
    rospy.set_param('arrived', 1)

    number = number+1

    time.sleep(2)

# Ros node that subscribes to the target_pos and odom topic and publishes on the cmd_vel topic.

def robot_motion_controller():

    rospy.init_node('robot_motion_controlller', anonymous=True)

    rospy.Subscriber("target_pos", Int64MultiArray, traj_callback)

    rospy.Subscriber('odom', Odometry, odom_callback)

    rospy.spin()

    pass

if __name__ == '__main__':
    robot_motion_controller()


# Write a Python function that accepts a string and calculate the number of upper case letters and lower case letters.
# Sample String : 'The quick Brow Fox'
# Expected Output :
# No. of Upper case characters : 3
# No. of Lower case Characters : 12

def upperlower(string):
	u=0
	l=0
	for i in range(len(string)):
		if (ord(string[i])>=97 and ord(string[i])<=122):
			l+=1
		elif (ord(string[i])>=65 and ord(string[i])<=90):
			u+=1
	print("No. of Upper case characters :", u)
	print("No. of Lower case Characters :", l)
string='The quick Brow Fox'
upperlower(string)


import requests
import time
import execjs
import pandas as pd

folderCode = './data/'

class FundInfoCrawler:
    def __init__(self, plateCode):
        self.fileFundTrain = folderCode + plateCode + "/fundinfo.csv"

        fundTrainTemp = pd.read_csv(folderCode + plateCode + "/code.csv",header=None,dtype=object).values.tolist()[0]
        self.fundTrainCode = fundTrainTemp

    def getUrl(self, fscode):
        head = 'http://fund.eastmoney.com/pingzhongdata/'
        tail = '.js?v=' + time.strftime("%Y%m%d%H%M%S", time.localtime())
        return head+fscode+tail

    # 根据基金代码获取净值
    def getWorth(self, fscode):
        content = requests.get(self.getUrl(fscode))
        jsContent = execjs.compile(content.text)
        # 累计净值走势
        ACWorthTrend = jsContent.eval('Data_ACWorthTrend')
        ACWorth = []
        for dayACWorth in ACWorthTrend:
            ACWorth.append(dayACWorth[1])
        return ACWorth

    def getFundTrain(self):
        trainFundFile = open(self.fileFundTrain, 'w')
        for code in self.fundTrainCode:
            try:
                trainFund = self.getWorth(code)
            except:
                continue
            if len(trainFund) > 0:
                trainFundFile.write(code + ",")
                trainFundFile.write(",".join(list(map(str, trainFund))))
                trainFundFile.write("\n")
                print('{} data downloaded'.format(code))
        trainFundFile.close()


import torch
import numpy as np
import random
from data.Dataset import SingleImageDataset
from models.model import Model
from util.losses import LossG
from util.util import get_scheduler, get_optimizer, save_result
import yaml
from argparse import ArgumentParser
from tqdm import tqdm

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

def train_model(dataroot, callback=None):
    with open("conf/default/config.yaml", "r") as f:
        config = yaml.safe_load(f)

    cfg = config

    if dataroot is not None:
        cfg['dataroot'] = dataroot

    # set seed
    seed = cfg['seed']
    if seed == -1:
        seed = np.random.randint(2 ** 32 - 1, dtype=np.int64)
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    print(f'running with seed: {seed}.')

    # create dataset, loader
    dataset = SingleImageDataset(cfg)

    # define model
    model = Model(cfg)

    # define loss function
    criterion = LossG(cfg)

    # define optimizer, scheduler
    optimizer = get_optimizer(cfg, model.netG.parameters())

    scheduler = get_scheduler(optimizer,
                              lr_policy=cfg['scheduler_policy'],
                              n_epochs=cfg['n_epochs'],
                              n_epochs_decay=cfg['scheduler_n_epochs_decay'],
                              lr_decay_iters=cfg['scheduler_lr_decay_iters'])

    with tqdm(range(1, cfg['n_epochs'] + 1)) as tepoch:
        for epoch in tepoch:
            inputs = dataset[0]
            for key in inputs:
                inputs[key] = inputs[key].to(device)
            optimizer.zero_grad()
            outputs = model(inputs)
            losses = criterion(outputs, inputs)
            loss_G = losses['loss']
            log_data = losses
            log_data['epoch'] = epoch

            # update learning rate
            lr = optimizer.param_groups[0]['lr']
            log_data["lr"] = lr
            tepoch.set_description(f"Epoch {log_data['epoch']}")
            tepoch.set_postfix(loss=log_data["loss"].item(), lr=log_data["lr"])

            # log current generated entire image
            if epoch % cfg['log_images_freq'] == 0:
                img_A = dataset.get_A().to(device)
                with torch.no_grad():
                    output = model.netG(img_A)
                save_result(output[0], cfg['dataroot'])
                if callback is not None:
                    callback(output[0])

            loss_G.backward()
            optimizer.step()
            scheduler.step()

if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument("--dataroot", type=str)
    args = parser.parse_args()
    dataroot = args.dataroot

    train_model(dataroot)


import xml.etree.ElementTree as ET

def boxes_in_groundtruth(gt_image_path):

    ground_truth_boxes = []
    tree = ET.parse(gt_image_path)
    root = tree.getroot()
    for items in root.findall('object/bndbox'):
        xmin = items.find('xmin')
        ymin = items.find('ymin')
        xmax = items.find('xmax')
        ymax = items.find('ymax')
        ground_truth_boxes.append([int(xmin.text), int(ymin.text), int(xmax.text), int(ymax.text)])
        #print("Ground truth images",ground_truth_boxes)
    return ground_truth_boxes

def area_of_intersection(box_100,groud_truth_box):
    #print(box_100,groud_truth_box)
    x1 = max(box_100[0], groud_truth_box[0])
    x2 = min(box_100[2], groud_truth_box[2])
    y1 = max(box_100[1], groud_truth_box[1])
    y2 = min(box_100[3], groud_truth_box[3])
    #print(x1,x2,y1,y2)
    if (x2 - x1 < 0) or (y2 - y1 < 0):
        return 0
    else:
        #print((x2 - x1 + 1) * (y2 - y1 + 1))
        return (x2 - x1 ) * (y2 - y1)

def find_IOU(boxes_100,ground_truth_boxes):
    iou_qual_boxes=[]
    boxes_best_iou=[]
    for box_g in ground_truth_boxes:
        best_iou=0
        best_box=0
        area_groundtruth_box= (box_g[2]-box_g[0] )* (box_g[3]-box_g[1])
        #print(box_g)
        #print(area_groundtruth_box)
        for box in boxes_100:
            area_box_100=(box[2]-box[0] )* (box[3]-box[1])
            area_of_intersec = area_of_intersection(box, box_g)
            #print(area_of_intersec)
            area_of_union = area_box_100 + area_groundtruth_box - area_of_intersec
            #print(area_of_union)
            iou = float(area_of_intersec) / float(area_of_union)
            #print(iou)
            if iou > 0.5:
                iou_qual_boxes.append(box)
                if iou > best_iou:
                    best_iou = iou
                    best_box = box
        if best_iou != 0:
            boxes_best_iou.append(best_box)
    return iou_qual_boxes, boxes_best_iou

import cv2
import argparse
image= cv2.imread("./HW2_Data/JPEGImages/000009.jpg")
cv2.imshow("000009",image)
parser = argparse.ArgumentParser()
parser.add_argument("strategy", default="color", type=str,
                        help="Enter the strategy - color for color strategy, all for all strategies")
args = parser.parse_args()
selective_search = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
selective_search.setBaseImage(image)
RGB_image  = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
selective_search.addImage(RGB_image)
# graph_segmentation = cv2.ximgproc.segmentation.createGraphSegmentation()
# selective_search.addGraphSegmentation(graph_segmentation)
# color_strategy = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyColor()
# selective_search.addStrategy(color_strategy)

#Creating strategy using color similarity and texture similarity
if args.strategy == "color":
    strategy_color = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyColor()
    selective_search.addStrategy(strategy_color)
if args.strategy == "texture":
    strategy_texture = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyTexture()
    selective_search.addStrategy(strategy_texture)

# Creating strategy using all similarities (size,color,fill,texture)
elif args.strategy == "all":
    strategy_color = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyColor()
    strategy_fill = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyFill()
    strategy_size = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategySize()
    strategy_texture = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyTexture()
    strategy_multiple = cv2.ximgproc.segmentation.createSelectiveSearchSegmentationStrategyMultiple(
        strategy_color, strategy_fill, strategy_size, strategy_texture)
    selective_search.addStrategy(strategy_multiple)

selective_search.switchToSelectiveSearchFast()
get_boxes = selective_search.process()
print("Total proposals = ", len(get_boxes))
#print(get_boxes)
first_100_box= 100
boxes_100=[]
box_top_100=[]
for box in get_boxes[0:first_100_box]:
    box_top_100.append([box[0],box[1],box[0]+box[2],box[1]+box[3]])
for box in get_boxes:
    boxes_100.append([box[0],box[1],box[0]+box[2],box[1]+box[3]])
#print(boxes_100)
print (len(boxes_100))
#Get all ground truth images from annotated xml files
output_image_100= image.copy()
ground_truth_boxes= boxes_in_groundtruth("./HW2_Data/Annotations/000009.xml")
print("Number of Ground Truth Boxes = ", len(ground_truth_boxes))
for i in range(0,len(box_top_100)):
    x_top, y_top, x_bottom, y_bottom= box_top_100[i]
    #cv2.rectangle(image, start_point, end_point, color, thickness)
    cv2.rectangle(output_image_100, (x_top, y_top), (x_bottom, y_bottom), (0, 255, 0), 1, cv2.LINE_AA)
cv2.imshow("output_image_100", output_image_100)
cv2.imwrite("./Results/output_image_100_000009.png",output_image_100)
#cv2.waitKey(10000)
# cv2.destroyAllWindows()
IOU_qual_boxes, final_boxes = find_IOU(boxes_100, ground_truth_boxes)
print("Number of Qualified Boxes with IOU > 0.5 = ", len(IOU_qual_boxes))
#print("Qualified Boxes = ", IOU_qual_boxes)

output_img_iou_qualified = image.copy()
image_final = image.copy()

#Draw bounding boxes for iou_qualified_boxes
for i in range(0, len(IOU_qual_boxes)):
    top_x, top_y, bottom_x, bottom_y = IOU_qual_boxes[i]
    cv2.rectangle(output_img_iou_qualified, (top_x, top_y), (bottom_x, bottom_y), (0, 255, 0), 1, cv2.LINE_AA)
for i in range(0, len(ground_truth_boxes)):
    top_x, top_y, bottom_x, bottom_y = ground_truth_boxes[i]
    cv2.rectangle(output_img_iou_qualified, (top_x, top_y), (bottom_x, bottom_y), (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("Output_IOU_Qualified_Proposals", output_img_iou_qualified)
cv2.imwrite("./Results/Output_IOU_Qualified_Proposals_000009.png", output_img_iou_qualified)
#cv2.waitKey(1000)

print("Number of final boxes = ", len(final_boxes))
print("Final boxes = ", final_boxes)

# Recall is calculated as the fraction of ground truth boxes that overlap with at least one proposal box with
# Intersection over Union (IoU) > 0.5
recall = len(final_boxes) / len(ground_truth_boxes)
print("Recall is = ", recall)

# Draw bounding boxes for final_boxes
for i in range(0, len(final_boxes)):
    top_x, top_y, bottom_x, bottom_y = final_boxes[i]
    cv2.rectangle(image_final, (top_x, top_y), (bottom_x, bottom_y), (0, 255, 0), 1, cv2.LINE_AA)
for i in range(0, len(ground_truth_boxes)):
    top_x, top_y, bottom_x, bottom_y = ground_truth_boxes[i]
    cv2.rectangle(image_final, (top_x, top_y), (bottom_x, bottom_y), (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("Output_Final_Boxes", image_final)
cv2.imwrite("./Results/output_img_final_000009.png", image_final)
#cv2.waitKey(1000)


from retrying import retry
from topology_common.utils.threading import ThreadGroup
from time import sleep
from pytest import (
    mark,
    fixture
)
from topology_common.ops.vxlan.ft_vxlan_lib import (
    TrafficType,
    verify_mac_table
)

from topology_common.ops.vlans.vlan import configure_switch_vlan

from topology_common.ops.l3_common.ft_l3_lib import (
    AddressType
)

from fixtures import (
    env_setup_hs_sw_hs_hs_hs,
    l2_basic_phy,
    l3_basic_phy
)

__doc__ = """
Test Case Header:
=================
:Author: Anvita Mishra anvita.mishra@hpe.com
:TestId: 00000
:Release: 10_04
:TestName: test_ft_VxLAN_TrafficMultiAVPNVP
:Objective: Verify VXLAN encapsulation and decapsulation across
            multiple AVPs and NVPs with multiple traffic types.
            The NVPs are part of a multi-member ECMP group.
:Requirements:
    - 1 switch
    - 4 hosts
:TestDescription: This test-case verifies VXLAN encapsulation is working for
    different traffic types on AVP-->All direction and decapsulation for
    NVP-->All direction. This test-case also verifies ECMP load balancing
    behavior for Known Unicast Traffic

    1.  Setup the topology as shown and enable all interfaces.
    2.  Configure VXLAN on the switch
    3.  Send packet from AVP1 to all other hosts. Verify correct
        encapsulation at one NVP (one member of the ECMP group)
        and correct packet transmission at AVP2.
    4.  Send encapsulated packet from NVP1 to all and verify that
        the packet is correctly decapsulated at AVP1 for known unicast traffic
        and flooded to all AVPs for all other traffic types. Verify that the
        packet is not received at the NVP on the same tunnel.
    5.  Testing ECMP Load Balancing behavior by permuting the Source MAC
        bitwise and checking which member of the ECMP group receives traffic.
:PlanPriority: 3 - High
:TestPassCriteria: -
    1. Setup of the topology successfully created.
    2. Packet successfully transmitted from AVP1 to all other hosts.
    3. Source MAC from packet sucessfully learned
    4. Packet successfully transmitted from NVP1 to all other hosts.
    5. Source MAC from packet successfully learned.
    6. Packet Permutations successfully transmitted from AVP1 to all other hosts.
    7. ECMP Load Balancing behavior occurs as expected for each traffic type
:PlatformIndependent: Y
:SupportedPlatforms: 8325
Topology:
=========
.. ditaa::

+-----------+   +-----------+
|           |   |           |
|   h3      |   |   h4      |
|   NVP1    |   |   NVP2    |
|           |   |           |
+----+------+   +------+----+
     |                 |
+----+-----------------+-----+
|                            |
|           s1               |
|                            |
+----+------------------+----+
     |                  |
+----+------+    +------+---+
|           |    |          |
|   h1      |    |   h2     |
|   AVP1    |    |   AVP2   |
|           |    |          |
+-----------+    +----------+

"""

TOPOLOGY = """
# Nodes
[type=halon_0 name="OpenSwitch 1" target="true"] ops1
[type=host name="Host 1" image="ubuntuscapy_2.4:latest"] hs1
[type=host name="Host 2" image="ubuntuscapy_2.4:latest"] hs2
[type=host name="Host 3" image="ubuntuscapy_2.4:latest"] hs3
[type=host name="Host 4" image="ubuntuscapy_2.4:latest"] hs4

# Links
ops1:if01 -- hs1:eth1
ops1:if02 -- hs2:eth1
ops1:if03 -- hs3:eth1
ops1:if04 -- hs4:eth1
"""

# Global Variables
AVP_MAC = ""
NVP_MAC = ""
VNI = 1760
UDP_DPORT = 4789
UDP_SPORT = 1234
SRC_IP = ""
DST_IP = ""
OUTER_SRC_MAC = ""
OUTER_DST_MAC = ""
PKT_TYPE = ''

# Global fixed variables
STP_DEST_MAC = "01:80:c2:00:00:00"
BROADCAST_MAC = "ff:ff:ff:ff:ff:ff"
MULTICAST_MAC = "01:00:00:00:00:bb"
LLDP_MAC = "01:80:c2:00:00:0e"
AVP1_MAC = "00:00:00:00:00:11"
NVP1_MAC = "00:00:00:00:00:aa"
SW_MAC = ""

# NVP IPs and IPs
# IPs  and MACs only needed for NVPs h3 and h4
HOST3_MAC = ""
HOST4_MAC = ""
H3_IP = '30.0.0.100'
H4_IP = '40.0.0.100'

VTEP_PEER_IP = '20.0.0.2'

# Switch SVI IPs
S1_SVI_IP_1 = '30.0.0.1'
S1_SVI_IP_2 = '40.0.0.1'

# Switch Loopback IP
# Used for VxLAN tunnel Source IP
S1_LO_IP = '1.1.1.1'

MASK = '24'
DEST_MASK = '32'

VLAN1 = '10'
VLAN2 = '30'
VLAN3 = '40'
VNI_HEX = '0x6e0'
TUN_NUM = '1'

PKT_COUNT = 5
SNIFF_PKT_COUNT = 10

# Number of MACs to send for ECMP Loading
TOTAL_MACS = 50

# This timeout parameter is for sending 5 packets
TIMEOUT = 5

# This timeout parameter is for sending 50 packets
LONG_TIMEOUT = 15

# Global dict to store packet count
# Updated in parse_packet function
RECEIVED_PKT_DICT = {}

@fixture(scope='function')
def config(env_setup_hs_sw_hs_hs_hs, request, testlog):
    '''
    Fixture to get the global fixture for this topology and run the teardown

    :param env_setup_hs_sw_hs: global fixture for the topology
    :param request: request param from pytest fixture
    :param testlog: testlog fixture
    '''
    yield env_setup_hs_sw_hs_hs_hs

    testlog.log_step("Teardown")
    env_setup_hs_sw_hs_hs_hs.teardown()

@fixture(scope='function')
def get_switch_mac(topology):
    '''
    Helper function to get mac address from the switch
    '''
    global SW_MAC
    s = topology.get('ops1')
    result = s.libs.vtysh.show_system()
    SW_MAC = result['base_mac']
    yield

@fixture(scope='function')
def get_host_macs(topology):
    '''
    Helper function to get mac addresses for NVP hosts h3 and h4
    '''
    global HOST3_MAC, HOST4_MAC

    h3 = topology.get('hs3')
    h4 = topology.get('hs4')

    h3_port = h3.ports['eth1']
    h4_port = h4.ports['eth1']

    ifconfig = h3.libs.ip.get_ifconfig(h3_port)
    HOST3_MAC = ifconfig[h3_port]['hwaddr']

    ifconfig = h4.libs.ip.get_ifconfig(h4_port)
    HOST4_MAC = ifconfig[h4_port]['hwaddr']
    yield

@fixture(scope='function',
         ids=['l2_basic', 'stp', 'broadcast', 'multicast', 'lldp'],
         params=[TrafficType.l2_basic, TrafficType.stp,
                 TrafficType.broadcast, TrafficType.multicast,
                 TrafficType.lldp])
def traffic_permutation(request):
    """
    Set the global variables for traffic
    """
    global AVP_MAC, NVP_MAC, UDP_SPORT, SRC_IP, DST_IP, OUTER_SRC_MAC,\
        OUTER_DST_MAC, PKT_TYPE

    # Values common to all packet types
    SRC_IP = VTEP_PEER_IP
    DST_IP = S1_LO_IP
    OUTER_SRC_MAC = HOST3_MAC
    OUTER_DST_MAC = SW_MAC
    AVP_MAC = AVP1_MAC

    # NVP_MAC updated based on pkt_type
    NVP_MAC_dict = {TrafficType.l2_basic: NVP1_MAC,
                    TrafficType.stp: STP_DEST_MAC,
                    TrafficType.broadcast: BROADCAST_MAC,
                    TrafficType.multicast: MULTICAST_MAC,
                    TrafficType.lldp: LLDP_MAC}

    PKT_TYPE_dict = {TrafficType.l2_basic: 'l2_basic',
                     TrafficType.stp: 'stp',
                     TrafficType.broadcast: 'broadcast',
                     TrafficType.multicast: 'multicast',
                     TrafficType.lldp: 'lldp'}

    NVP_MAC = NVP_MAC_dict[request.param]
    PKT_TYPE = PKT_TYPE_dict[request.param]

    yield request.param

def generate_params(sw):
    """
    Return arguments required for every single permutation

    :param sw: Topology switch object
    :param permutation: Main pytest fixture for this test
    """

    # List of vlan ids to use for this permutation
    vlan_ids = []
    # Physical ports  required for this permutation per L3 interface
    phy_ports = []
    # L3 interfaces to be created
    l3_interfaces = 0
    # List of ip address for every host
    ip_address_hs = []
    # VxLAN interfaces to be created
    vxlan_ids = []
    # VNIs to be created
    vnis = {}
    # VTEP Peers to be created
    vtep_peers = []

    vlan_ids = [VLAN1, VLAN2, VLAN3]
    vxlan_ids = [TUN_NUM]
    vnis = {VNI: {'vlan': [VLAN1], 'vtep_peer': [VTEP_PEER_IP]}}
    l3_interfaces = 1
    phy_ports = [sw.vtysh_ports['if01'], sw.vtysh_ports['if02'],
                 sw.vtysh_ports['if03'], sw.vtysh_ports['if04']]
    ip_address_hs = [H3_IP, H4_IP]
    vtep_peers = [H3_IP, H4_IP]

    return {'vlan_ids': vlan_ids,
            'vxlan_ids': vxlan_ids,
            'vnis': vnis,
            'vtep_peers': vtep_peers,
            'l3_interfaces': l3_interfaces,
            'phy_ports': phy_ports,
            'ip_address_hs': ip_address_hs}

def configure_host_ips(h3, h4, ip_address_hs):
    """
    Configure host IPs for the NVPs (h3 and h4)
    AVPs do not need IPs assigned for test

    :param h3: A Topology host object
    :param h4: A Topology host object
    :param ip_address_hs: A list of ip addresses to configure h3 and h4
    """

    h3.libs.ip.flush_ip('eth1')
    h3.libs.ip.interface('eth1', up=False)

    h4.libs.ip.flush_ip('eth1')
    h4.libs.ip.interface('eth1', up=False)

    h3.libs.ip.interface(portlbl='eth1', addr="{}/{}".format(
        ip_address_hs[0], MASK), up=True)
    h4.libs.ip.interface(portlbl='eth1', addr="{}/{}".format(
        ip_address_hs[1], MASK), up=True)

def start_stop_scapy_on_hosts(hs, action='start'):
    """
    Function to start and stop scapy daemon on hosts

    :param hs: A Topology host object
    :param action: By default, the value is 'start'
            If set to any other value, scapy will exit
    """
    if action == 'start':
        hs.libs.scapy.start_scapy()
    else:
        hs.libs.scapy.exit_scapy()

def scapy_configuration_avp(hs, pkt_type=None, macsrc=None, macdst=None):
    """
    Function to configure scapy for packet in AVP->All direction

    :param hs: A Topology host object
    :param pkt_type: l2_basic, stp, broadcast, multicast, or lldp
    :param macsrc: Source MAC address
    :param macdst: Destination MAC address
    """
    # L2 header
    eth_header = hs.libs.scapy.ether()

    eth_header['src'] = '{}'.format(macsrc)
    eth_header['dst'] = '{}'.format(macdst)

    if isinstance(macsrc, list):
        eth_header['src'] = macsrc
    packet_list = []
    packet_struct = ""

    # If pkt_type is stp, need additional STP and LLC headers
    if pkt_type == 'stp':
        # Raw data
        stp_header = hs.libs.scapy.stp()
        llc_header = hs.libs.scapy.llc()
        packet_list = [eth_header, llc_header, stp_header]
        packet_struct = "Eth/LLC()/STP()"

    # For all other packet types, packet structure is same
    else:
        # Update raw_data with pkt_type
        raw_data = {'data': "{} packet from AVP end".format(pkt_type)}
        packet_list = [eth_header, raw_data]
        packet_struct = "Eth/data"

    packet = [packet_struct, packet_list]

    return packet

def scapy_configuration_nvp(hs, pkt_type=None,
                            inner_macsrc=None, inner_macdst=None, vni=None,
                            src_port=None, dst_port=None, src_IP=None,
                            dst_IP=None, outer_macsrc=None, outer_macdst=None):
    """
    Function to configure scapy for packet in NVP->All direction

    :param hs: A Topology host object
    :param pkt_type: l2_basic, stp, broadcast, multicast, or lldp
    :param inner_macsrc: Encapsulated packet source MAC address
    :param inner_macdst: Encapsulated packet destination MAC address
    :param vni: VNI value for VxLAN header
    :param src_port: UDP source port
    :param dst_port: UDP destination port
    :param src_IP: Source VTEP's IP
    :param dst_IP: Destination VTEP's IP
    :param inner_macsrc: Source VTEP's MAC address
    :param inner_macdst: Next hop MAC address
    """
    # Inner L2 header
    inner_eth_header = hs.libs.scapy.ether()
    inner_eth_header['prot'] = 'ENCAP_ETH'
    inner_eth_header['src'] = '{}'.format(inner_macsrc)
    inner_eth_header['dst'] = '{}'.format(inner_macdst)

    # VxLAN header
    vxlan_header = hs.libs.scapy.vxlan()
    vxlan_header['vni'] = vni
    vxlan_header['flags'] = 'Instance'
    # UDP header
    udp_header = hs.libs.scapy.udp()
    udp_header['sport'] = src_port
    udp_header['dport'] = dst_port
    # IP header
    ip_header = hs.libs.scapy.ip()
    ip_header['src'] = '{}'.format(src_IP)
    ip_header['dst'] = '{}'.format(dst_IP)
    # Outer L2 header
    outer_eth_header = hs.libs.scapy.ether()
    outer_eth_header['src'] = '{}'.format(outer_macsrc)
    outer_eth_header['dst'] = '{}'.format(outer_macdst)
    outer_eth_header['type'] = 0x0800
    # Inner L2 header
    inner_eth_header['src'] = '{}'.format(inner_macsrc)
    inner_eth_header['dst'] = '{}'.format(inner_macdst)

    # If pkt_type is stp, need additional STP and LLC headers
    if pkt_type == 'stp':
        stp_header = hs.libs.scapy.stp()
        llc_header = hs.libs.scapy.llc()
        packet_list = [outer_eth_header, ip_header, udp_header,
                       vxlan_header, inner_eth_header, llc_header, stp_header]
        packet_struct = "Eth/IP/UDP/VXLAN/ENCAP_ETH/LLC()/STP()"

    # For all other packet types, packet structure is same
    else:
        # Update raw_data with pkt_type
        raw_data = {'data': "{} packet from NVP end".format(pkt_type)}
        packet_list = [outer_eth_header, ip_header, udp_header,
                       vxlan_header, inner_eth_header, raw_data]
        packet_struct = "Eth/IP/UDP/VXLAN/ENCAP_ETH/data"

    packet = [packet_struct, packet_list]
    return packet

def start_traffic(hs, packet, count):
    """
    Start Traffic
    :param hs: Host hs.
    :param packet: Custom header to send.
    :param count: Number of packets to send
    """

    # Waiting 2 sec to give some time to sniffer to be ready
    sleep(2)
    iface = hs.ports['eth1']
    # Start Traffic
    hs.libs.scapy.sendp(packet[0], packet[1],
                        "iface='{}', count = {}, inter=0.2".format(iface, count))

def check_packet(packet, recipient_type, pkt_type, exp_src, exp_dst):
    """
    Helper function to determine how many packets are correctly received.
    Return packet_count

    :param packet: Dictionary of sniffed packets.
    :param recipient_type: String describing if recipient host is an AVP or NVP
    :param pkt_type: l2_basic, stp, broadcast, multicast, or lldp
    :param exp_src: String representing expected source MAC of packet
    :param exp_dst: String representing expected destination MAC of packet
    """
    packet_count = 0

    # If recipient is AVP, check for simple packet
    if ("AVP" in recipient_type):
        for pkt in packet.values():
            # Boolean to store if packet is correct. Set to False initially
            correctly_received = False

            # Check 1: Check src and dst MACs match expected
            if ((pkt['Ethernet']['src'] in exp_src) and
                    (pkt['Ethernet']['dst'] == exp_dst)):

                # Check 2: If packet type is LLDP, check raw string for "lldp"
                if (pkt_type == "lldp"):
                    # If "lldp" is present, set correctly_received to True
                    if ("lldp" in pkt['Ethernet']['Raw']['load']):
                        correctly_received = True

                # Packet type is not LLDP, so only Check 1 is required
                # Set correctly_received to True
                else:
                    correctly_received = True

            # Update total packet count with value of correctly_received
            packet_count += correctly_received

    # If recipient is NVP, then check for VXLAN encapsulated packet
    elif ("NVP" in recipient_type):
        for pkt in packet.values():
            # Boolean to store if packet is correct. Set to False initially
            correctly_received = False

            # Check 1: Check if VxLAN fields are correct
            if ((pkt['Ethernet']['IP']['src'] == S1_LO_IP) and
                (pkt['Ethernet']['IP']['dst'] == VTEP_PEER_IP) and
                (pkt['Ethernet']['IP']['UDP']['dport'] == str(UDP_DPORT)) and
                (pkt['Ethernet']['IP']['UDP']['VXLAN']['vni'] == VNI_HEX) and
                (pkt['Ethernet']['IP']['UDP']['VXLAN']['Ethernet']['src'] in exp_src) and
                    (pkt['Ethernet']['IP']['UDP']['VXLAN']['Ethernet']['dst'] == exp_dst)):

                # Check 2: If packet type is LLDP, check raw string for "lldp"
                if (pkt_type == "lldp"):
                    # If "lldp" is present, set correctly_received to True
                    if ("lldp" in pkt['Ethernet']['IP']['UDP']['VXLAN']['Ethernet']['Raw']['load']):
                        correctly_received = True
                # Packet type is not LLDP, so only Check 1 is required
                # Set correctly_received to True
                else:
                    correctly_received = True

            # Update total packet count with value of correctly_received
            packet_count += correctly_received

    return packet_count

def parse_packet(packet, recipient_type, pkt_type, exp_src, exp_dst, step):
    """
    Function to parse received packets and check if the packet values
    match expected values

    :param packet: Dictionary of sniffed packets.
    :param recipient_type: String describing if host is an AVP or NVP
    :param pkt_type: l2_basic, stp, broadcast, multicast, or lldp
    :param expected_pkts: Boolean stating if we expect packets
    :param exp_src: Expected source MAC of packet
    :param exp_dst: Expected destination MAC of packet
    :param step: Step fixture
    """

    packet_count = 0
    expected_packet_count = PKT_COUNT

    # Calling check_packet helper function to determine how many packets are
    # correctly received. Function returns packet_count
    packet_count = check_packet(
        packet, recipient_type, pkt_type, exp_src, exp_dst)

    # Print packet count at each host
    print("Packet count at {} was {}".format(recipient_type, packet_count))

    # Store packet_counts in global dict RECEIVED_PKT_DICT
    # Dict needed for ECMP check
    RECEIVED_PKT_DICT[recipient_type] = packet_count

def sniff_traffic(hs, count, timeout, recipient_type, pkt_type,
                  exp_src, exp_dst, testlog):
    """
    Sniff traffic on given interface
    :param hs: Host hs.
    :param count: Count of packets to be sniffed
    :param timeout: timeout value
    :param recipient_type: AVP or NVP
    :param pkt_type: l2_basic, stp, broadcast, multicast, or lldp
    :param step: Step fixture
    """
    iface = hs.ports['eth1']

    # If host is NVP, sniff using a filter that checks for UDP packets
    if ("NVP" in recipient_type):
        packet = hs.libs.scapy.sniff2("iface='{}', count={}, timeout={}, "
                                      " filter='port 4789 and (!icmp or !ip6)', "
                                      " prn=lambda x:x.show()".format(
                                          iface, count, timeout), True)
        parse_packet(packet, recipient_type, pkt_type,
                     exp_src, exp_dst, testlog)
    # If host is AVP, sniff using a filter that checks for Ethernet packets
    elif ("AVP" in recipient_type):
        packet = hs.libs.scapy.sniff2("iface='{}', count={}, "
                                      " timeout={}, filter='!icmp or !ip6', "
                                      " prn=lambda x:x.show()".format(
                                          iface, count, timeout), True)
        parse_packet(packet, recipient_type, pkt_type,
                     exp_src, exp_dst, testlog)

def print_transmission_results(pkts_expected_dict,
                               expected_pkt_count, testlog):
    """
    Helper function to display results of packet transmission

    :param pkts_expected_dict: Dictionary of Booleans representing if packets
          are expected at each host (Keys: Host Names, Values: True/False)
    :param expected_pkt_count: Number of packets expected
    :param testlog: Testlog fixture
    """

    # Global Dictionary representing packet count received at each host
    # (Keys: Host Names, Values: Packet Count)
    global RECEIVED_PKT_DICT

    testlog.log_subheader("Results:")

    # If packets are expected at ECMP group
    if (pkts_expected_dict["ECMP group"]):
        # Ensure that one NVP received traffic but not both (XOR)
        assert ((RECEIVED_PKT_DICT["NVP1 (h3)"] == expected_pkt_count) ^
                (RECEIVED_PKT_DICT["NVP2 (h4)"] == expected_pkt_count)), \
            "Packets expected at ECMP group, but incorrectly received. " + \
            "Check packet count at the NVPs"
        testlog.log_info("Packets correctly received at the ECMP group. " +
                         "Only one NVP received traffic")
    # Packets were not expected at the ECMP group
    else:
        testlog.log_info("Packets were not expected at the ECMP group")

    # If packets are expected at AVP1 and packets were received
    if (pkts_expected_dict["AVP1"]) and ("AVP1 (h1)" in RECEIVED_PKT_DICT.keys()):
        # Check received packet count matches expected packet count
        assert ((RECEIVED_PKT_DICT["AVP1 (h1)"] == expected_pkt_count)),\
            "Packets expected at AVP1, but incorrectly received. " + \
            "Check packet count at the AVP1"
        testlog.log_info("Packets correctly received at AVP1")
    # Packets were not expected at AVP1
    else:
        testlog.log_info("Packets were not expected at AVP1")

    # If packets are expected at AVP2 and packets were received
    if (pkts_expected_dict["AVP2"]) and ("AVP2 (h2)" in RECEIVED_PKT_DICT.keys()):
        # Check received packet count matches expected packet count
        assert ((RECEIVED_PKT_DICT["AVP2 (h2)"] == expected_pkt_count)),\
            "Packets expected at AVP2, but incorrectly received. " + \
            "Check packet count at the AVP2"
        testlog.log_info("Packets correctly received at AVP2")
    # Packets were not expected at AVP2
    else:
        testlog.log_info("Packets were not expected at AVP2")

def check_load_balancing(testlog):
    """
    Helper function to parse RECEIVED_PKT_DICT and report on
    if NVP1 or NVP2 is chosen

    :param testlog: testlog fixture
    """

    # Global Dictionary representing packet count received at each host
    # (Keys: Host Names, Values: Packet Count)
    global RECEIVED_PKT_DICT

    testlog.log_step("Final ECMP Load Balancing Results")
    NVP1_count = RECEIVED_PKT_DICT["NVP1 (h3)"]
    NVP2_count = RECEIVED_PKT_DICT["NVP2 (h4)"]
    NVP1_percent = (NVP1_count/TOTAL_MACS)*100
    NVP2_percent = (NVP2_count/TOTAL_MACS)*100

    print("NVP1 was chosen {} out of {} times, which is {:.2f}% of the time\n".format(
        NVP1_count, TOTAL_MACS, NVP1_percent))
    print("NVP2 was chosen {} out of {} times, which is {:.2f}% of the time\n".format(
        NVP2_count, TOTAL_MACS, NVP2_percent))

    # Check ECMP Load Balancing if expected
    if (PKT_TYPE == "l2_basic"):
        # Check if at least 40% of total packets were received at one host
        # Check that total NVP1_count and NVP2_count equals the number of packets
        assert((NVP1_percent >= 0.4) or (NVP2_percent >= 0.4) and
               ((NVP1_count + NVP2_count) == TOTAL_MACS)),\
            "ECMP Load Balancing Failed for Known Unicast Traffic"

        step_desc = "ECMP Load Balancing check passed for Known Unicast traffic"
        testlog.log_info(step_desc)
    else:
        # Check that all of the packets are only received at one NVP and
        # zero packets are received at the other NVP
        assert(((NVP1_count == 0) and (NVP2_count == TOTAL_MACS)) or
               (NVP2_count == 0) and (NVP1_count == TOTAL_MACS)), \
            "Load Balancing was not expected, but packets were not" +\
            " received correctly for {} traffic".format(PKT_TYPE)

        step_desc = "Load Balancing is not expected for {} traffic. ".format(PKT_TYPE) + \
                    "All traffic was directed to the BUM Next Hop"
        testlog.log_info(step_desc)

@mark.timeout(1000)
def test_ft_VxLAN_TrafficMultiAVPNVP(topology,
                                     testlog,
                                     config,
                                     get_switch_mac,
                                     get_host_macs,
                                     traffic_permutation,
                                     l2_basic_phy,
                                     l3_basic_phy):
    """
    Test sends different types of traffic between 4 hosts connected
    through VxLAN tunnel.

    Build a topology of one switch and four hosts and connect
    the hosts to the switches.
    Setup a VxLAN between switches and VLANs between ports
    and switches.
    """

    """
    Step: Create the topology as shown
    Result: Topology created successfully
    """
    testlog.log_step("Set up the switch and hosts")
    s1 = topology.get('ops1')
    h1 = topology.get('hs1')
    h2 = topology.get('hs2')
    h3 = topology.get('hs3')
    h4 = topology.get('hs4')

    argv = generate_params(s1)

    """
    Step: Configure the topology as shown
    Result: Topology has been configured successfully
    """
    # Configuring VLAN and four interfaces on switch 1
    testlog.log_subheader("Creating L2 Interfaces")
    config.create_l2_interface_type(s1,
                                    l2_basic_phy['l2_iface'],
                                    False, False,
                                    [argv['phy_ports'][0]],
                                    argv['vlan_ids'][0],
                                    None, testlog)

    config.create_l2_interface_type(s1,
                                    l2_basic_phy['l2_iface'],
                                    False, False,
                                    [argv['phy_ports'][1]],
                                    argv['vlan_ids'][0],
                                    None, testlog)

    testlog.log_subheader("Creating SVIs")
    # Creating SVI interfaces of if03 and if04
    config.create_l2_interface_type(s1,
                                    l2_basic_phy['l2_iface'],
                                    False, False,
                                    [argv['phy_ports'][2]],
                                    argv['vlan_ids'][1],
                                    None, testlog)

    config.create_l2_interface_type(s1,
                                    l2_basic_phy['l2_iface'],
                                    False, False,
                                    [argv['phy_ports'][3]],
                                    argv['vlan_ids'][2],
                                    None, testlog)

    configure_switch_vlan(s1,
                          argv['vlan_ids'][1],
                          S1_SVI_IP_1 + '/' + MASK,
                          [argv['phy_ports'][2]])

    configure_switch_vlan(s1,
                          argv['vlan_ids'][2],
                          S1_SVI_IP_2 + '/' + MASK,
                          [argv['phy_ports'][3]])

    testlog.log_subheader("Creating Switch Loopback Interface")
    # Creating a loopback interface on s1
    config.create_l3_loopback(s1,
                              '0',
                              S1_LO_IP + '/' + MASK)

    testlog.log_subheader("Configure Host IPs")
    configure_host_ips(h3, h4, argv['ip_address_hs'])

    testlog.log_subheader("Configuring IP Routes from NVPs to 20.0.0.2")
    config.switch_add_route(s1, VTEP_PEER_IP, DEST_MASK, H3_IP)
    config.switch_add_route(s1, VTEP_PEER_IP, DEST_MASK, H4_IP)

    """
    Step: Configure VxLAN interface on switch 1
    Result: VxLAN interface has been configured successfully
    """
    testlog.log_step("Configure VXLAN")
    config.configure_vxlan(s1,
                           TUN_NUM,
                           S1_LO_IP,
                           argv['vnis'])
    testlog.log_subheader("Current Running Configuration")
    s1.libs.vtysh.show_running_config()

    """
    Step:   Generate traffic type using Scapy on all hosts
    Result: Traffic successfully created
    """
    testlog.log_step("Start Scapy on hosts")
    # Starting scapy
    start_stop_scapy_on_hosts(h1)
    start_stop_scapy_on_hosts(h2)
    start_stop_scapy_on_hosts(h3)
    start_stop_scapy_on_hosts(h4)

    """
    Step:   Use scapy to configure the traffic from AVP to all hosts
    Result: Packet created
    """
    # Configure Scapy on hs1 for AVP-->All traffic
    step_desc = "Configure traffic from AVP1"
    testlog.log_step(step_desc)

    cur_src_MAC = AVP_MAC
    cur_dst_MAC = NVP_MAC
    packet_avp = scapy_configuration_avp(h1, pkt_type=PKT_TYPE,
                                         macsrc=cur_src_MAC, macdst=cur_dst_MAC)

    """
    Step:   Transmit the traffic from AVP to all hosts and
            parse the captured packet to check
            if the packet is received as expected
    Result: Traffic transmitted successfully and
            Correct values received
    """

    # Updating step_desc based on traffic type
    if (PKT_TYPE == "l2_basic"):
        step_desc = "Transmit from AVP1 (Packet Type: Unknown Unicast)\n" + \
                    "\t     Intended Receivers: AVP2, NVP1/NVP2"
    else:
        step_desc = "Transmit from AVP1 (Packet Type: {})\n".format(PKT_TYPE) + \
                    "\t     Intended Receivers: AVP2, NVP1/NVP2"

    testlog.log_step(step_desc)

    # Dictionary of Booleans for each host
    # True means Packet expected at host and False: Packets not expected at host
    pkts_expected_dict = {"AVP1": False, "AVP2": True, "ECMP group": True}
    # Sending traffic from AVP h1 to all other hosts
    with ThreadGroup() as ctx:
        # Sniffing on hs2 (AVP)
        ctx.run(sniff_traffic, hs=h2, count=SNIFF_PKT_COUNT, timeout=TIMEOUT,
                recipient_type="AVP2 (h2)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        # Sniffing on hs3 (NVP)
        ctx.run(sniff_traffic, hs=h3, count=SNIFF_PKT_COUNT, timeout=TIMEOUT,
                recipient_type="NVP1 (h3)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        # Sniffing on hs4 (NVP)
        ctx.run(sniff_traffic, hs=h4, count=SNIFF_PKT_COUNT, timeout=TIMEOUT,
                recipient_type="NVP2 (h4)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        ctx.run(start_traffic, hs=h1, packet=packet_avp, count=PKT_COUNT)

    # Checking Transmission Results
    print_transmission_results(pkts_expected_dict, PKT_COUNT, testlog)

    print(RECEIVED_PKT_DICT)
    RECEIVED_PKT_DICT.clear()

    """
    Step:   Check if MAC is learnt as expected
    Result: Source MAC is present in switch MAC table
    """
    testlog.log_step("Check MAC Learning")
    # Verifying if MAC A was learned on if01
    verify_mac = retry(
        stop_max_attempt_number=3,
        wait_fixed=1000)(verify_mac_table)
    verify_mac(sw1=s1, mac=cur_src_MAC, exp_port=argv['phy_ports'][0],
               exp_vlan=VLAN1, vtep_peer=None)

    # Update src MAC and dst MAC based on packet type
    dst_MAC_dict = {"l2_basic": AVP1_MAC, "stp": STP_DEST_MAC,
                    "broadcast": BROADCAST_MAC, "multicast": MULTICAST_MAC,
                    "lldp": LLDP_MAC}

    cur_src_MAC = NVP1_MAC
    cur_dst_MAC = dst_MAC_dict[PKT_TYPE]

    """
    Step:   Use scapy to configure the traffic for NVP to all hosts
    Result: Packet created
    """
    step_desc = "Configure traffic from NVP1"
    testlog.log_step(step_desc)

    # Configure Scapy on hs1 for NVP-->All traffic
    packet_nvp = scapy_configuration_nvp(h3, pkt_type=PKT_TYPE,
                                         inner_macsrc=cur_src_MAC,
                                         inner_macdst=cur_dst_MAC, vni=VNI,
                                         src_port=UDP_SPORT, dst_port=UDP_DPORT,
                                         src_IP=SRC_IP, dst_IP=DST_IP,
                                         outer_macsrc=OUTER_SRC_MAC,
                                         outer_macdst=OUTER_DST_MAC)

    """
    Step:   Transmit the traffic from NVP to all hosts and
            parse the captured packet to check
            if the packet is received as expected
    Result: Traffic transmitted successfully and
            Correct values received
    """
    # Updating step_desc based on traffic type
    if (PKT_TYPE == "l2_basic"):
        step_desc = "Transmit from NVP1 (Packet Type: Known Unicast)\n" + \
                    "\t     Intended Receivers: AVP1"
    else:
        step_desc = "Transmit from NVP1 (Packet Type: {})\n".format(PKT_TYPE) + \
                    "\t     Intended Receivers: AVP1, AVP2"
    testlog.log_step(step_desc)

    # If broadcast, multicast or BPDU, packet is flooded to both AVPs
    pkts_expected_dict = {"AVP1": True, "AVP2": True, "ECMP group": False}

    # If l2 basic, packet is known unicast packet and only received at AVP1
    if (PKT_TYPE == "l2_basic"):
        pkts_expected_dict = {"AVP1": True, "AVP2": False, "ECMP group": False}

    # Sending traffic from NVP1 h3 to all other hosts
    with ThreadGroup() as ctx:
        # Sniffing on h1 (AVP1)
        ctx.run(sniff_traffic, hs=h1, count=SNIFF_PKT_COUNT, timeout=TIMEOUT,
                recipient_type="AVP1 (h1)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        # Sniffing on h2 (AVP2)
        ctx.run(sniff_traffic, hs=h2, count=SNIFF_PKT_COUNT, timeout=TIMEOUT,
                recipient_type="AVP2 (h2)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        # Sniffing on h4 (NVP2)
        ctx.run(sniff_traffic, hs=h4, count=SNIFF_PKT_COUNT, timeout=TIMEOUT,
                recipient_type="NVP2 (h4)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        ctx.run(start_traffic, hs=h3, packet=packet_nvp, count=PKT_COUNT)

    # Checking Transmission Results
    print_transmission_results(pkts_expected_dict, PKT_COUNT, testlog)
    print(RECEIVED_PKT_DICT)
    RECEIVED_PKT_DICT.clear()

    """
    Step:   Check if MAC is learnt as expected
    Result: Source MAC is present in switch MAC table
    """

    testlog.log_step("Check MAC Learning")
    # Verifying if NVP1_MAC was learned on interface vxlan 1
    verify_mac(sw1=s1, mac=cur_src_MAC, exp_port="vxlan1",
               exp_vlan=VLAN1, vtep_peer=VTEP_PEER_IP)

    """
    Step:   Transmit the traffic from NVP to all hosts and
            parse the captured packet to check
            if the packet is received as expected
    Result: Traffic transmitted successfully and
            Correct values received
    """
    # Updating step_desc based on traffic type
    step_desc = "Transmit from AVP1. Permuting Source MAC to Test ECMP Load Balancing"
    testlog.log_step(step_desc)

    # If broadcast, multicast or BPDU, packet is sent to AVP2 and ECMP group
    pkts_expected_dict = {"AVP1": False, "AVP2": True, "ECMP group": True}

    # If l2 basic, packet is known unicast packet and only received at ECMP group
    if (PKT_TYPE == "l2_basic"):
        pkts_expected_dict = {"AVP1": True, "AVP2": False, "ECMP group": True}

    # Creating a list of potential source MACs
    lst_source_macs = ['00:00:00:00:00:{}'.format(
        i) for i in range(21, 21+TOTAL_MACS)]
    cur_src_MAC = lst_source_macs
    cur_dst_MAC = NVP_MAC

    packet_avp_lst = scapy_configuration_avp(h1, pkt_type=PKT_TYPE,
                                             macsrc=cur_src_MAC, macdst=cur_dst_MAC)

    with ThreadGroup() as ctx:
        # Sniffing on hs2 (AVP)
        ctx.run(sniff_traffic, hs=h2, count=TOTAL_MACS+10, timeout=LONG_TIMEOUT,
                recipient_type="AVP2 (h2)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        # Sniffing on hs3 (NVP)
        ctx.run(sniff_traffic, hs=h3, count=TOTAL_MACS+10, timeout=LONG_TIMEOUT,
                recipient_type="NVP1 (h3)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        # Sniffing on hs4 (NVP)
        ctx.run(sniff_traffic, hs=h4, count=TOTAL_MACS+10, timeout=LONG_TIMEOUT,
                recipient_type="NVP2 (h4)", pkt_type=PKT_TYPE,
                exp_src=cur_src_MAC, exp_dst=cur_dst_MAC, testlog=testlog)
        ctx.run(start_traffic, hs=h1, packet=packet_avp_lst, count=1)

    print(RECEIVED_PKT_DICT)

    # Call check_load_balancing helper function to
    check_load_balancing(testlog)

    RECEIVED_PKT_DICT.clear()
    testlog.log_step("Stop Scapy on hosts")
    # Stopping scapy
    start_stop_scapy_on_hosts(h1, action='stop')
    start_stop_scapy_on_hosts(h2, action='stop')
    start_stop_scapy_on_hosts(h3, action='stop')
    start_stop_scapy_on_hosts(h4, action='stop')


import unittest
from src.customer import Customer
from src.coffee_shop import CoffeeShop
from src.drink import Drink
from src.food import Food

class TestCustomer(unittest.TestCase):

    def setUp(self):
        self.customer = Customer("John Smith", 50.00, 28, 100)
        # self.drink1 = Drink("Latte", 2.50, 5)
        # self.drink2 = Drink("Mocha", 3.50, 10)
        # self.food = Food("Burger", 8.00, 50)

        self.stock = [
                    {   "type": "drink",
                        "name" : "Latte",
                        "price": 2.50,
                        "energy": 5
                        },
                    {   "type": "drink",
                        "name" : "Mocha",
                        "price": 3.50,
                        "energy": 10
                        },
                    {   "type": "food",
                        "name" : "Burger",
                        "price": 8.00,
                        "energy": 50
                        }
                ]
        self.coffee_shop = CoffeeShop("the Prancing Pony", 200.00, self.stock)

    def test_buy_a_drink(self):

        self.customer.buy_a_drink(self.coffee_shop, self.stock[0])
        self.assertEqual(self.customer.wallet, 47.50)
        self.assertEqual(self.coffee_shop.till, 202.50)

    def test_age(self):

        self.customer = Customer("Underage Child", 6.70, 13, 200)
        self.customer.buy_a_drink(self.coffee_shop, self.stock[0])
        self.assertEqual(self.customer.wallet, 6.70)
        self.assertEqual(self.coffee_shop.till, 200.00)

    def test_energy_increased_by_caffeine_level(self):
        self.customer.buy_a_drink(self.coffee_shop, self.stock[0])
        self.assertEqual(105, self.customer.energy_level)

    def test_refuse_sale_high_energy(self):
        self.customer.buy_a_drink(self.coffee_shop, self.stock[1])
        self.customer.buy_a_drink(self.coffee_shop, self.stock[1])
        self.assertEqual(110, self.customer.energy_level)

    def test_rejuvenation_level_change(self):
        self.customer.buy_food(self.coffee_shop, self.stock[2])
        self.assertEqual(50, self.customer.energy_level)


import json
import argparse
import sys

parser = argparse.ArgumentParser()
parser.add_argument('--input', type=str, required=True)
parser.add_argument('--baseline', type=str, required=True)
parser.add_argument('--keys', type=str, required=True, help='Comma-separated list of keys to compare')
parser.add_argument('--tolerance', type=float, default=0.9)

args = parser.parse_args()

args.keys = args.keys.split(',')

input = json.load(open(args.input))
baseline = json.load(open(args.baseline))

fail = False
for key in args.keys:
    print('Checking key:', key)
    input_value = input['run'][key]
    baseline_value = baseline['run'][key]
    print("input value: ", input_value)
    print("baseline value: ", baseline_value)

    # only 'higher is better'-type scenarios currently supported
    if input_value < 0.9 * baseline_value:
        print('FAILED\n')
        fail = True
    else:
        print('PASSED\n')

if fail:
    sys.exit(1)
else:
    sys.exit(0)