"""

FGCN Model Implementation in Pytorch
© Sagnik Roy, 2021

"""

from blocks import *
import random
import torch
import torch.nn as nn
from torchsummary import summary

torch.manual_seed(42)
random.seed(42)

class MFCF(nn.Module):

    def __init__(self, in_channels = 50,
                 out_channels = 32,
                 kernel_size = (1, 1),
                 stride = 1,
                 padding = 0):

        super(MFCF, self).__init__()
        self.pcba1h = PCBA(in_channels, out_channels, kernel_size, stride, padding)
        self.pcba1l = PCBA(1, out_channels, kernel_size, stride, padding)
        self.cba1h = CBA(in_channels, out_channels, kernel_size, stride, padding)
        self.cba1l = CBA(1, out_channels, kernel_size, stride, padding)
        self.pcba2h = PCBA(out_channels*2, out_channels*2, kernel_size, stride, padding)
        self.ucba2l = UCBA(out_channels*2, out_channels*2, kernel_size, stride, padding)
        self.cba2h = CBA(out_channels*2, out_channels*2, kernel_size, stride, padding)
        self.cba2l = CBA(out_channels*2, out_channels*2, kernel_size, stride, padding)
        self.ucba3l = UCBA(out_channels*2, out_channels, kernel_size, stride, padding)
        self.cba3h = CBA(out_channels*2, out_channels, kernel_size, stride, padding)

    def forward(self, h_data, l_data):

        h1h = self.cba1h(h_data)
        h1l = self.pcba1h(h_data)
        l1h = self.cba1l(l_data)
        l1l = self.pcba1l(l_data)

        h1 = torch.cat((h1h, l1h), dim = 1)
        l1 = torch.cat((h1l,l1l), dim = 1)

        h2h = self.cba2h(h1)
        h2l = self.pcba2h(h1)
        l2h = self.ucba2l(l1)
        l2l = self.cba2l(l1)

        h2 = h2h + l2h
        l2 = h2l + l2l

        h3 = self.cba3h(h2)
        l3 = self.ucba3l(l2)

        return h3 + l3

class FG_Conv(nn.Module):

    def __init__(self,
                 in_channels = 64,
                 out_channels = 16,
                 kernel_size = (3, 3),
                 stride = 1,
                 padding = 1,
                 momentum = 0.9,
                 dropout = 0.1):

        super().__init__()
        self.p1 = [Conv(in_channels, out_channels, kernel_size, stride, padding) for _ in range(4)]
        self.p2 = [Conv(out_channels, out_channels, kernel_size, stride, padding) for _ in range(4)]
        self.p3 = [Conv(out_channels, out_channels, kernel_size, stride, padding) for _ in range(4)]
        self.bad = BAD(out_channels, momentum, dropout)

    def forward(self, x):

        x1 = self.p1[0](x)
        x2 = self.p1[1](x)
        x3 = self.p1[2](x)
        x4 = self.p1[3](x)

        c1 = torch.cat((x1, x2, x3, x4), dim = 1)

        x1 = self.p2[0](self.bad(x1))
        x2 = self.p2[1](self.bad(x2))
        x3 = self.p2[2](self.bad(x3))
        x4 = self.p2[3](self.bad(x4))

        c2 = torch.cat((x1, x2, x3, x4), dim = 1)

        x1 = self.p3[0](self.bad(x1))
        x2 = self.p3[1](self.bad(x2))
        x3 = self.p3[2](self.bad(x3))
        x4 = self.p3[3](self.bad(x4))

        c3 = torch.cat((x1, x2, x3, x4),dim = 1)

        return torch.cat((c1, c2, c3), dim = 1)

class SPBr(nn.Module):

    def __init__(self,
                 in_channels = 64,
                 out_channels = 64,
                 kernel_size = (1, 1),
                 stride = 1,
                 padding = 0,
                 momentum = 0.9,
                 dropout = 0.1):
        super().__init__()

        self.c1 = Conv(in_channels, out_channels, kernel_size, stride, padding)
        self.c2 = Conv(out_channels, out_channels, kernel_size, stride, padding)
        self.c3 = Conv(out_channels, out_channels, kernel_size, stride, padding)
        self.bad = BAD(out_channels, momentum, dropout)

    def forward(self, x):

        x1 = self.c1(x)
        x2 = self.c2(self.bad(x1))
        x3 = self.c3(self.bad(x2))

        return torch.cat((x1, x2, x3), dim = 1)

class FGCN(nn.Module):
    def __init__(self,
                 num_classes,
                 channels = 64,
                 w0 = 1.0,
                 w1 = 1.0,
                 H = 100,
                 W = 100):
        super().__init__()
        self.w0 = w0
        self.w1 = w1
        self.mfcf_block = MFCF(channels)
        self.fg_conv = FG_Conv(in_channels = 32)
        self.spbr = SPBr(channels)
        self.c0 = Conv(192, channels, (1, 1), 1, 0)
        self.c1 = Conv(channels, num_classes, (1, 1), 1, 0)
        self.fc = nn.Linear(W*H*num_classes, num_classes)

    def forward(self, h_data, l_data):
        mfcf_op = self.mfcf_block(h_data, l_data)
        fg_conv_op = self.fg_conv(mfcf_op)
        spbr_op = self.spbr(h_data)

        wad_op = self.w0 * spbr_op + self.w1 * fg_conv_op

        conv_op = self.c1(self.c0(wad_op))
        output = self.fc(nn.Flatten()(conv_op))

        return output

if __name__ == "__main__":
    model = FGCN(num_classes = 10, H = 200, W = 150)
    summary(model, [(64,200,150), (1,200,150)], device = "cpu")


import sys
import numpy as np
from itertools import chain

entries = list()

with open('5.input.txt', 'r') as fh:
	entries = fh.read().split('\n')

max_x = 0
max_y = 0

processed_entries = list()

# Clean up data

for e in entries:
	elist = list(chain.from_iterable([i.split(',') for i in e.split(' -> ')]))
	elist = [int(x) for x in elist]
	processed_entries.append(elist)
	x1,y1,x2,y2 = elist
	# Find bounds for numpy array
	if x1 > max_x:
		max_x = x1
	if x2 > max_x:
		max_x = x2
	if y1 > max_y:
		max_y = y1
	if y2 > max_y:
		max_y = y2

arr = np.zeros((int(max_x) + 1, int(max_y) + 1))

for p in processed_entries:
	x1,y1,x2,y2 = p

	if x1 == x2:
		# Horizontal
		draw_length = abs(y1 - y2)
		if y1 > y2:
			ystart = y2
		else:
			ystart = y1
		for y in range(draw_length + 1):
			arr[ystart + y, x1] += 1
	elif y1 == y2:
		# Vertical
		draw_length = abs(x1 - x2)
		if x1 > x2:
			xstart = x2
		else:
			xstart = x1
		for x in range(draw_length + 1):
			arr[y1, xstart + x] += 1
	else:
		# Diaganol
		draw_length_x = abs(x1 - x2)
		draw_length_y = abs(y1 - y2)
		draw_length = abs(x1 - x2)   # Only 45 degree lines len(x) == len(y)
		if x1 < x2:
			xstart = x1
			ystart = y1
			if y1 < y2:
				for x in range(draw_length + 1):
					arr[ystart + x, xstart + x] += 1
			else:
				# y2 < y1
				for x in range(draw_length + 1):
					arr[ystart - x, xstart + x] += 1
		else:
			xstart = x2
			ystart = y2
			if y1 < y2:
				for x in range(draw_length + 1):
					arr[ystart - x, xstart + x] += 1
			else:
				# y2 < y1
				for x in range(draw_length + 1):
					arr[ystart + x, xstart + x] += 1

print(arr)
points = np.argwhere(arr > 1)
print(points)
print(len(points))


import asyncio
import aiohttp
import json
import pprint
from config import TOKEN, IP, PORT

class WebhookEmulator:
    __slots__ = ['loop', 'session', 'token', 'offset', 'printer']

    def __init__(self, loop, token):
        self.loop = loop
        self.session = None
        self.token = token
        self.offset = None
        self.printer = pprint.PrettyPrinter(indent=2)

    async def connect(self):
        self.session = aiohttp.ClientSession()
        print('Connected!')

    async def __call__(self, *args, **kwargs):
        telegram_url = 'https://api.telegram.org/bot{token}/getUpdates'.format(token=self.token)
        await self.connect()

        while True:
            print('check for updates')
            await asyncio.sleep(1)
            params = {'offset': self.offset, 'timeout': 20} if self.offset else {'timeout': 20}
            async with self.session.get(url=telegram_url, params=params) as response:
                updates = await response.json()
                print(json.dumps(updates, indent=4, ensure_ascii=False))
                if updates['result']:
                    await self.send_to_bot(updates)

    async def send_to_bot(self, data):
        email_bot_url = 'https://{ip}:{port}/updates/{token}'.format(
            ip=IP,
            port=PORT,
            token=self.token
        )
        async with self.session.post(url=email_bot_url, ssl=False, json=data) as resp:
            if resp.status == 200:
                self.offset = max(update['update_id'] for update in data['result']) + 1

def main():
    if not TOKEN:
        raise Exception('Can\'t find bot token in environment (BOT_TOKEN) --> Failed to start')
    print("Emulator Started")
    loop = asyncio.get_event_loop()
    emulator = WebhookEmulator(loop, TOKEN)
    try:
        loop.run_until_complete(emulator())
    except KeyboardInterrupt:
        loop.stop()


import time, sys, smbus
from HT16K33 import HT16K33, HT16K33_LED_MATRIX, HT16K33_7_SEGMENT

mode = 0

if mode == 0:

    ledMatrix = HT16K33_LED_MATRIX(0x70, [8,8], adafruit = True)
    ledMatrix.fill_matrix(1)
    ledMatrix.show_matrix()
    time.sleep(2)
    ledMatrix.set_brightness(4)
    ledMatrix.display_status('ON', 1) # turn blinking on at 1Hz
    time.sleep(4)
    ledMatrix.display_status('ON', 0) # turn blinking off

    ledMatrix.matrix = [0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0,
                        0, 1, 1, 0, 0, 1, 1, 0,
                        0, 1, 1, 0, 0, 1, 1, 0,
                        0, 0, 0, 0, 0, 0, 0, 0,
                        0, 1, 0, 0, 0, 0, 1, 0,
                        0, 0, 1, 1, 1, 1, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0]
    ledMatrix.show_matrix()
    #ledMatrix.show_matrix_adafruit_backpack()
    time.sleep(2)
    ledMatrix.invert_matrix()
    ledMatrix.show_matrix()
    time.sleep(2)
    ledMatrix.invert_matrix()
    ledMatrix.show_matrix()
    time.sleep(2)

    """#Keyscan demo
    ledMatrix.set_interrupt(True, 'HIGH')
    startTime = time.time()
    loopLength = 10

    while (time.time()-startTime)<loopLength:
        print(ledMatrix.read_keyscan())
        time.sleep(0.2)"""

    #Turn HT16K33 off
    ledMatrix.set_interrupt(False, 'HIGH')
    ledMatrix.display_status('OFF')
    ledMatrix.set_system_oscillator('OFF')

elif mode == 1:

    sevenSegment = HT16K33_7_SEGMENT(0x70)
    sevenSegment.set_brightness(7)
    sevenSegment.set_justification("LEFT")
    sevenSegment.write_numbers(-256.7)
    time.sleep(2)
    sevenSegment.write_numbers(91.3)
    time.sleep(2)
    sevenSegment.write_numbers(17.96)
    time.sleep(2)
    sevenSegment.write_numbers(None) # clear display
    time.sleep(2)
    sevenSegment.write_numbers(-8.5)
    time.sleep(2)

    # turn colon on and off every 1 second
    for i in range(0,5):
        sevenSegment.write_numbers(1004)
        time.sleep(1)
        sevenSegment.write_numbers(1004, True)
        time.sleep(1)

    #Turn HT16K33 off
    sevenSegment.write_numbers(None)
    sevenSegment.display_status('OFF')
    sevenSegment.set_system_oscillator('OFF')


"""""
        This script includes various functions used when a block is validated and created

        Author: Guillaume A. Khayat
        Date: 2022/02/17
"""""
# Importing global parameters
from Util.Cls.Block import Block
from Util.Fcts.sigFuncs import verifF
from collections import Counter

def orderBckchain(bckChainL, orderedBckChainInt):
    """""
        This function creates a list of block hashes by order
        The first hash in the produced list is the hash of the last block of the blockchain (only non-parent block)
        and the last hash in the produced list is the hash of the initial block of the blockchain
        As only the government can create blocks, this function does not treat the situation
        where there are forks (it only flags it)
            - Input:
                    - bckChainL: list of dict, python object from reading the JSON that saves
                                    all the blocks of the blockchain
                    - orderedBckChainInt: list, the produced list of the ordered hashes will be appended to this list
    """""
    bckHashes = tuple(map(lambda item: item['Bhash'], bckChainL))
    bckPrevHashes = tuple(map(lambda item: item['BprevHash'], bckChainL))
    diffLists = list(set(bckHashes) - set(bckPrevHashes))
    if len(diffLists) > 1:
        print("Forks in the Blockchain")
        return
    lastBck = diffLists[0]
    if len(bckChainL) < 2:
        orderedBckChainInt.append(bckChainL[0]['Bhash'])
        # return list( bckChainL[0]['Bhash'] )
    else:
        lastBckL = list(filter(lambda item: item['Bhash'] == lastBck, bckChainL))
        if len(lastBckL) > 1:
            print("SOMETHING IS WRONG WITH BLOCK LIST")
            return
        orderedBckChainInt.append( lastBckL[0]['Bhash'] )
        # del bckChainL[bckChainL.index(lastBckL[0])]
        # orderBckChain(bckChainL, orderedBckChainInt)
        orderBckchain(bckChainL[0:bckChainL.index(lastBckL[0])] + bckChainL[(bckChainL.index(lastBckL[0])+1):len(bckChainL)], orderedBckChainInt)

def verVotesFromBck(voteIDs, votesAll, vrAll):
    """""
        This function verifies if any vote of a vote list is not valid. It is destined to verify if a block is valid
        by verifying that all votes included in the block are valid.
            - Input:
                - voteIDs: list of strings, each string is the vote ID. List of vote IDs to be verified
                - votesAll: list of dicts, list of all posted votes
                - vrAll: list of dicts, list of all voting rights created by the government
            - Output:
                - Boolean:
                    - True if all votes are valid
                    - False if ANY of the votes is not valid
    """""
    if len(voteIDs) == 0:
        return True
    voteDicts = list(filter(lambda a: a['Vid'] in voteIDs, votesAll))
    # Check 1: does the block include several votes from the same voting right?
    vVRl = list(map(lambda a: a['Vvr'], voteDicts))
    cntVid = Counter(vVRl)
    if max(list(cntVid.values())) > 1:
        print("The block includes several votes from the same voting right")
        return False
    # Check 2: Are the votes valid (eLv)?
    vVRll = list(map(lambda a: list(filter(lambda b: b['VRhash'] == a['Vvr'], vrAll)), voteDicts))
    vVRl = [vr for vrL in vVRll for vr in vrL]
    # list(map(lambda a: , vVRl))
    boolVerif = list(map(lambda a, b: verifF(b['VRsigL'], b['VRsigPubKeyL'], b['VRsigNonceECpts'], a['eLv']), voteDicts, vVRl))
    if any(boolVerif) == False:
        blckBool = False
    else:
        blckBool = True
    return blckBool

def bckListDictToBlock(bckDictL):
    return tuple(map(lambda item: Block(item['BprevHash'], item['Vids']) , bckDictL))

def bckListBlockToDict(bckBlockL):
    return tuple(map(lambda item: {
        'Bhash': item.Bhash,
        'BprevHash': item.BprevHash,
        'Vids': item.Vids
    } , bckBlockL))

def bckToDict(blk):
    return (
        {
            "Bhash": blk.Bhash,
            "BprevHash": blk.BprevHash,
            "Vids": blk.Vids
        }
    )

def verBckchain(bckchainDictL, votesAll, vrAll):
    """""
            This fuction orders and verifies what blocks of a blockchain are valid.
            - Input:
                - bckchainDictL: the blockchain, list of dict. Each dict is a block of the blockchain to verify
                - votesAll: list of dicts, list of all posted votes
                - vrAll: list of dicts, list of all voting rights created by the government
            - Output:
                - Dict:
                    - ordBckchain: list of dict, the same blockchain as provided in the input but ordered
                                    (first element is the initial block & last element is the last and only child block)
                    - ordVldBckchain: list of dict, the ordered valid blockchain
                                        All blocks are valid, the last dict of the list if the last valid block
                                        of the full blockchain provided in the input
                    - nonValBck:
                        - if there is any non valid block, the index of the first non valid block
                            of the ordered blockchain
                        - if all blocks are valid, the length of the blockchain
    """""
    orderedBckchainL = []
    orderBckchain(bckchainDictL, orderedBckchainL)
    orderedBckchainL.reverse()
    bckchainDictL.sort(key=lambda i: orderedBckchainL.index(i['Bhash']))
    boolBlocks = tuple(map(lambda a: verVotesFromBck(a['Vids'], votesAll, vrAll), bckchainDictL))
    try:
        valBcks = boolBlocks.index(False)
    except:
        valBcks = len(bckchainDictL)
    return {'ordBckchain': bckchainDictL, 'ordVldBckchain': bckchainDictL[0:valBcks], 'nonValBck': valBcks}


from kombu import Queue, Exchange
BROKER_URL = 'amqp://guest:guest@app.maimiaotech.com:5672//'
CELERY_RESULT_BACKEND = 'amqp://guest:guest@app.maimiaotech.com:5672'
#    BROKER_URL = 'amqp://guest:guest@mm_246:5672//'
#    CELERY_RESULT_BACKEND = 'amqp://guest:guest@mm_246:5672'

CELERY_ROUTES = {'syb_test_wrapper': {'queue': 'syb_test'}
}
CELERY_ACKS_LATE = True
CELERYD_PREFETCH_MULTIPLIER=1
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_ENABLE_UTC = True

CELERYD_LOG_FORMAT='%(asctime)s %(levelname)-2s %(name)s.%(funcName)s:%(lineno)-5d %(message)s'
CELERYD_TASK_LOG_FORMAT='%(asctime)s %(levelname)-2s %(name)s.%(funcName)s:%(lineno)-5d %(message)s %(task_name)s(%(task_id)s) %(message)s'


import os
import tempfile
import traceback

from sdkit import Context
from sdkit.utils import load_tensor_file, log, get_nested_attr

"""
The VAE model overwrites the state_dict of model.first_stage_model.

We keep a copy of the original first-stage state_dict when a SD model is loaded,
and restore that copy if the custom VAE is unloaded.
"""

def load_model(context: Context, **kwargs):
    vae_model_path = context.model_paths.get("vae")

    try:
        vae = load_tensor_file(vae_model_path)
        vae = vae["state_dict"] if "state_dict" in vae else vae

        if context.test_diffusers:
            from diffusers.pipelines.stable_diffusion.convert_from_ckpt import (
                convert_ldm_vae_checkpoint,
                create_vae_diffusers_config,
            )

            # the ckpt converter requires the VAE dict in the original SD style
            vae_converted = {}
            for key, value in vae.items():
                vae_converted["first_stage_model." + key] = value

            vae = vae_converted

            model = context.models["stable-diffusion"]
            m = model["default"]
            image_size = m.vae.sample_size

            original_config = model["config"]
            vae_config = create_vae_diffusers_config(original_config, image_size=image_size)
            vae_dict = convert_ldm_vae_checkpoint(vae, vae_config)

            log.info("Loading diffusers vae")
        else:
            vae_dict = {k: v for k, v in vae.items() if k[0:4] != "loss"}

        if context.half_precision:
            for key in vae_dict.keys():
                vae_dict[key] = vae_dict[key].half()

        _set_vae(context, vae_dict)

        del vae_dict
        return {}  # we don't need to access this again
    except Exception as e:
        log.error(traceback.format_exc())
        log.error(f"Could not load VAE: {vae_model_path}")
        raise e

def move_model_to_cpu(context: Context):
    pass

def unload_model(context: Context, **kwargs):
    base_vae = _get_base_model_vae(context)
    _set_vae(context, base_vae)

def _set_vae(context: Context, vae: dict):
    if "stable-diffusion" not in context.models:
        return

    model = context.models["stable-diffusion"]

    if context.test_diffusers:
        m = model["default"]

        if hasattr(m.vae, "_hf_hook"):  # update the buffered weights directly
            for k, v in vae.items():
                mod_name, v_type = k.rsplit(".", 1)
                try:
                    mod = get_nested_attr(m.vae, mod_name)
                except Exception as e:
                    log.error(f"Couldn't get module: {k}")
                    raise e

                mod._hf_hook.weights_map[v_type].data = v.to("cpu")
        else:
            m.vae.load_state_dict(vae, strict=False)
    else:
        model.first_stage_model.load_state_dict(vae, strict=False)

def _get_base_model_vae(context: Context):
    base_vae = os.path.join(tempfile.gettempdir(), "sd-base-vae.safetensors")
    return load_tensor_file(base_vae)


from dataclasses import dataclass

import requests

from protostar.self.protostar_directory import VersionManager, Version

class LatestVersionRemoteChecker:
    """
    Call a remote endpoint to figure out if the new Protostar version is available.
    """

    PROTOSTAR_REPO = "https://github.com/software-mansion/protostar"

    @dataclass
    class Result:
        latest_release_tag: str
        latest_version: Version
        changelog_url: str

    @staticmethod
    async def check() -> "LatestVersionRemoteChecker.Result":
        headers = {"Accept": "application/json"}
        response = requests.get(
            f"{LatestVersionRemoteChecker.PROTOSTAR_REPO}/releases/latest",
            headers=headers,
            timeout=8,
        )
        response_dict = response.json()
        latest_release_tag = response_dict["tag_name"]
        latest_version = VersionManager.parse(latest_release_tag)
        changelog_url = "https://github.com" + response_dict["update_url"]
        return LatestVersionRemoteChecker.Result(
            latest_version=latest_version,
            latest_release_tag=latest_release_tag,
            changelog_url=changelog_url,
        )


#Three ways to compute a sum of elements in list

List=[1,2,3]
N=len(List)-1

#using for-loop
def func1(li):
    ans=0
    for i in li:
        ans+=i
    return ans

#using while-loop
def func2(li):
    ans=0
    i=0
    while i<len(li):
        ans += li[i]
        i+=1
    return ans

#using recursion
def func3(li,n):
    if n==0:
        return li[n]
    else:
        return li[n]+func3(li,n-1)

print(func1(List))
print(func2(List))
print(func3(List,N))


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

from PIL import ImageGrab, Image
import datetime

def save():
    im = ImageGrab.grabclipboard()
    if isinstance(im, Image.Image):
        im.save(str("SAVE DIRECTORY HERE")+str(datetime.datetime.today()).replace(" ","-").replace(":","-")+'.jpg')
        print('saved')
    else:
        print('no image')

from pynput.keyboard import Key, Listener

def on_press(key):
    try:
        if key.char == "Key.ctrl_r":
            save()
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:

        it= "{0}".format(
            key)
        if it == "Key.ctrl_r":
            save()

if __name__ == '__main__':

    with Listener(
        on_press = on_press,
    ) as listener:
        listener.join()


import cv2
import numpy as np

def count_point(img):
    count_1 = 0
    for y in range(0, len(img)):
        for x in range(0, len(img[0])):
            #  9 26 69
            if abs(img[y][x][0] - 9) < 10 and \
                    abs(img[y][x][1] - 26) < 10 and \
                    abs(img[y][x][2] - 70) < 10:
                img[y][x] = [0, 0, 0]
            else:
                count_1 += 1
                # print(img[y][x], end=" ")
        # print()
    print("Counr = ", count_1)

def read_img_p_count(filename):
    basepath = "../storage/ScreenShot/"
    img = cv2.imread(filename)
    count_point(img)
    return img

if __name__ == '__main__':
    basepath = "../storage/ScreenShot/"
    img = read_img_p_count('UseDisable.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    cv2.namedWindow('sss')
    cv2.moveWindow("sss", 0, 0)
    cv2.namedWindow('ddd')
    cv2.moveWindow("ddd", 100, 100)

    cv2.imshow("sss", img)

    count_point(img)

    cv2.imshow("ddd", img)
    cv2.waitKey()


r = int(input('what is the radius? '))   #ask for input
#print(range(r+1,0,-1))

for cir_top in range(r,0,-2):                    #for the top of the circle use range r to 0 (skipping steps to make it look pretty)
    y1 = int((r**(2)-cir_top**(2))**(.5))    #solving for y = sqrt(r^2-x^2) where x is defined by the range
    print(" "*(r+1-y1)+'x'+" "*(2*y1)+'x')   #print the top half

for cir in range(0,r+1,2):      #for the bottom use range 0 to r
    y = int((r**(2)-cir**(2))**(.5))     # same thing as top half
    print(" "*(r+1-y)+'x'+" "*(2*y)+'x')   #print bottom half


# -*- coding: utf-8 -*-
"""
Author: Tomasz Neska
Date: 06/03/2020
Description: Project 2 - utilising three different methods it evaluates the effects of time step and accuracy on the
behaviour of the simple harmonic oscillator
"""
# initialisation
import string
from math import *
import numpy as np
import matplotlib.pyplot as plt
import random
import time
import cmath
import json
from scipy import optimize

plt.rcParams.update({'font.size': 14})
plt.style.use('default')
figure = plt.figure()
plt.rcParams.update({'errorbar.capsize': 2})

class SHO(object):
    def __init__(self, time_step, max_time, b=0.0, m=0.0, k=0.0, init_x=0.0, init_v=0.0, fileNameSave="data.txt",
                 fileNameLoad="data.txt"):
        self.fileNameSave = fileNameSave
        self.fileNameLoad = fileNameLoad
        self.b = b
        self.m = m
        self.k = k
        self.h = time_step
        self.init_v = init_v
        self.init_x = init_x
        self.no_steps = int(np.rint(max_time / time_step))
        self.natural_angular_frequency = np.sqrt(self.k / self.m)
        if self.b != 0:
            self.gamma = self.b / self.m
            self.quality_factor = self.natural_angular_frequency / self.gamma
        self.analytic_series_pos = []
        self.analytic_series_vel = []
        self.analytic_energy = []
        self.__coefficients = []
        self.solver()
        self.analytic_solution()
        self.data = []
        self.b_critical = 2 * np.sqrt(self.k * self.m)

        self.Euler_data = []
        self.B_Euler_data = []
        self.Verlet_data = []
        self.Euler_Cromer_data = []
        self.analytical_data = []
        self.time = np.array(range(0, self.no_steps, 1)) * self.h
        self.disturbed_Verlet_data = []

    def runSimulation(self):
        self.Euler_integrator()
        self.Better_Euler_integrator()
        self.Verlet_integrator()
        self.Euler_Cromer_integrator()
        print("Simulation has been executed")

    def getCoefficients(self):
        return self.__coefficients

    def Euler_integrator(self):
        position_series = [self.init_x]
        velocity_series = [self.init_v]
        for counter in range(1, self.no_steps, 1):
            v_n = velocity_series[len(velocity_series) - 1]
            x_n = position_series[len(position_series) - 1]
            a_n = (-self.b / self.m) * v_n + (-self.k / self.m) * x_n

            position_series.append(x_n + self.h * v_n)
            velocity_series.append(v_n + self.h * a_n)

        self.Euler_data = [position_series, velocity_series, self.energy_function(position_series, velocity_series)]

    def Better_Euler_integrator(self):
        position_series = [self.init_x]
        velocity_series = [self.init_v]
        for counter in range(1, self.no_steps, 1):
            v_n = velocity_series[len(velocity_series) - 1]
            x_n = position_series[len(position_series) - 1]
            a_0 = (-self.b / self.m) * v_n + (-self.k / self.m) * x_n

            position_series.append(x_n + self.h * v_n + 0.5 * self.h ** 2 * a_0)
            velocity_series.append(v_n + self.h * a_0)

        self.B_Euler_data = [position_series, velocity_series, self.energy_function(position_series, velocity_series)]

    def Euler_Cromer_integrator(self):
        position_series = [self.init_x]
        velocity_series = [self.init_v]
        for counter in range(1, self.no_steps, 1):
            v_n = velocity_series[len(velocity_series) - 1]
            x_n = position_series[len(position_series) - 1]

            temp = v_n - (self.k * self.h / self.m) * x_n  # v_n+1
            velocity_series.append(temp)
            position_series.append(x_n + self.h * temp)

        self.Euler_Cromer_data = [position_series, velocity_series,
                                  self.energy_function(position_series, velocity_series)]
        print(np.array(self.Euler_Cromer_data))

    def Verlet_integrator(self):
        position_series = [self.init_x]
        velocity_series = [self.init_v]

        D = 2 * self.m + self.b * self.h
        B = ((self.b * self.h) - (2 * self.m)) / D
        A = 2 * (2 * self.m - (self.k * self.h ** 2)) / D

        a_0 = (-self.b / self.m) * self.init_v + (-self.k / self.m) * self.init_x
        x_1 = self.init_x + self.init_v * self.h + 0.5 * a_0 * self.h ** 2  # obtained using a Taylor expansion of order 2
        position_series.append(x_1)

        for counter in range(1, self.no_steps, 1):
            position_series.append(A * position_series[counter] + B * position_series[counter - 1])

        # calculating velocities using an approximation of O(h^2)
        # the velocity is estimated using the mean value theorem
        for counter in range(1, self.no_steps, 1):
            velocity_series.append(
                (position_series[counter + 1] - position_series[counter - 1]) / (2 * self.h))  # +O(h^2)
        position_series = position_series[:len(position_series) - 1]

        self.Verlet_data = [position_series, velocity_series, self.energy_function(position_series, velocity_series)]

    def energy_function(self, position, velocity):
        temp_pos = np.array(position)
        temp_vel = np.array(velocity)
        return 0.5 * self.m * temp_vel ** 2 + 0.5 * self.k * temp_pos ** 2

    def convert_array(self, array):
        # operates on 1 dimensional arrays
        temp = []
        for entry in array:
            temp.append(entry)

        return temp

    def analytic_solution(self):
        # creates the analytic solution position series
        t_0 = 0
        for counter in range(0, self.no_steps, 1):
            self.analytic_series_pos.append(self.ana_position(t_0))
            self.analytic_series_vel.append(self.ana_velocity(t_0))
            t_0 += self.h
        print("solution found")
        self.analytic_energy = self.energy_function(self.analytic_series_pos, self.analytic_series_vel)

    def solver(self):
        #
        print((self.k / self.m))
        print((self.b ** 2 / (4 * self.m ** 2)))
        #
        A = 0
        B = 0
        temp = (self.b ** 2 / (4 * self.m ** 2))
        if self.b == 0:
            marker = 1
            print("The analytic solution is a simple harmonic motion")
            omega = np.sqrt(self.k / self.m)
            A = self.init_v / omega
            B = self.init_x

            # x = A*sin(omega*t) + B*cos(omega*t)
            # v = omega A cos(omega t) - omega*B*sin(omega t)

            self.__coefficients = [omega, 0, marker, A, B]
        elif (self.k / self.m) > temp:  # imaginary
            print("The solution is a lightly damped oscillation")
            marker = 3

            p = -1 * self.b / 2 * self.m
            q = np.sqrt((self.k / self.m) - self.b ** 2 / (4 * self.m ** 2))
            # initial conditions
            A = (- self.init_x * p + self.init_v) / q
            B = self.init_x
            self.__coefficients = [p, q, marker, A, B]
        elif (self.k / self.m) == temp:
            print("The solution is a critically damped oscillation")
            marker = 2  # repeated real solutions
            K = -1 * self.b / 2 * self.m
            # initial conditions
            A = self.init_x
            self.__coefficients = [K, 0, marker, A, B]
        elif (self.k / self.m) < temp:  # overdamped oscillation
            marker = 4
            print("The solution is an overdamped oscillation")
            p = -1 * self.b / 2 * self.m + np.sqrt(-(self.k / self.m) + self.b ** 2 / (4 * self.m ** 2))
            q = -1 * self.b / 2 * self.m - np.sqrt(-(self.k / self.m) + self.b ** 2 / (4 * self.m ** 2))

            # initial conditions
            A = (q * self.init_x - self.init_v) / (q - p)
            B = self.init_x - A
            self.__coefficients = [p, q, marker, A, B]
        print(marker)

    def ana_position(self, t):
        k_1 = self.__coefficients[0]
        k_2 = self.__coefficients[1]
        marker = self.__coefficients[2]
        A = self.__coefficients[3]
        B = self.__coefficients[4]
        if marker == 1:  # no damping solution
            return A * np.sin(self.natural_angular_frequency * t) + B * np.cos(self.natural_angular_frequency * t)
        elif marker == 2:  # regular damping (complex)
            return A * np.exp(k_1 * t)
        elif marker == 3:  # repeated root
            return np.exp(k_1 * t) * (A * np.sin(k_2 * t) + B * np.cos(k_2 * t))
        elif marker == 4:  # two real distinct solutions
            return A * np.exp(k_1 * t) + B * np.exp(k_2 * t)

    def ana_velocity(self, t):
        k_1 = self.__coefficients[0]
        k_2 = self.__coefficients[1]
        marker = self.__coefficients[2]
        A = self.__coefficients[3]
        B = self.__coefficients[4]
        if marker == 1:  # no damping solution
            return A * k_1 * np.cos(k_1 * t) - B * k_1 * np.sin(k_1 * t)
        elif marker == 2:  # regular damping (complex)
            return A * k_1 * np.exp(k_1 * t)
        elif marker == 3:  # repeated root
            return k_1 * np.exp(k_1 * t) * (A * np.sin(k_2 * t) + B * np.cos(k_2 * t)) + np.exp(k_1 * t) * (
                    A * k_2 * np.cos(k_2 * t) - B * k_2 * np.sin(k_2 * t))
        elif marker == 4:  # two real distinct solutions
            return A * k_1 * np.exp(k_1 * t) + B * k_2 * np.exp(k_2 * t)

    def plot_data(self):  # plots all on separate graphs
        # analytical solution
        figure3 = plt.figure()
        axes_5 = figure3.add_subplot(121)
        axes_5.plot(self.analytic_series_pos, self.analytic_series_vel, label="Analytical")
        axes_5.set_xlabel("position/ m")  # edit later if the functions don't exist
        axes_5.set_ylabel("velocity/ ms^-1")  # as above
        # energy plotting
        axes_6 = figure3.add_subplot(122)
        axes_6.plot(self.time, self.analytic_energy)
        axes_6.set_xlabel("time/ s")
        axes_6.set_ylabel("energy/ J")
        figure3.legend()

        # Euler method
        # plotting
        figure = plt.figure()
        axes_1 = figure.add_subplot(121)
        axes_1.plot(self.Euler_data[0], self.Euler_data[1], label="Euler")
        axes_1.set_xlabel("position/ m")  # edit later if the functions don't exist
        axes_1.set_ylabel("velocity/ ms^-1")  # as above
        # energy plotting

        axes_2 = figure.add_subplot(122)
        axes_2.plot(self.time, self.Euler_data[2])
        axes_2.set_xlabel("time/ s")
        axes_2.set_ylabel("energy/ J")
        figure.legend()
        # end plotting

        # Better Euler method
        # plotting
        figure2 = plt.figure()
        axes_3 = figure2.add_subplot(121)
        axes_3.plot(self.B_Euler_data[0], self.B_Euler_data[1], label="Better Euler")
        axes_3.set_xlabel("position/ m")  # edit later if the functions don't exist
        axes_3.set_ylabel("velocity/ ms^-1")  # as above
        # energy plotting
        axes_4 = figure2.add_subplot(122)
        axes_4.plot(self.time, self.B_Euler_data[2])
        axes_4.set_xlabel("time/ s")
        axes_4.set_ylabel("energy/ J")
        figure2.legend()
        # end plotting

        # Verlet method
        figure4 = plt.figure()
        axes_7 = figure4.add_subplot(121)
        axes_7.plot(self.Verlet_data[0], self.Verlet_data[1], label="Verlet")
        axes_7.set_xlabel("position/ m")
        axes_7.set_ylabel("velocity/ ms^-1")
        # energy plotting
        axes_8 = figure4.add_subplot(122)
        axes_8.plot(self.time, self.Verlet_data[2])
        axes_8.set_xlabel("time/ s")
        axes_8.set_ylabel("energy/ J")
        figure4.legend()

        # Euler Cromer method
        figure5 = plt.figure()
        axes_9 = figure5.add_subplot(121)
        axes_9.plot(self.Euler_Cromer_data[0], self.Euler_Cromer_data[1], label="Euler Cromer Method")
        axes_9.set_xlabel("position/ m")
        axes_9.set_ylabel("velocity/ ms^-1")
        # energy plotting
        axes_10 = figure5.add_subplot(122)
        axes_10.plot(self.time, self.Euler_Cromer_data[2])
        axes_10.set_xlabel("time/ s")
        axes_10.set_ylabel("energy/ J")
        figure5.legend()

    def plot_single(self):
        figure = plt.figure()
        axes_1 = figure.add_subplot(121)
        axes_1.set_xlabel("position/ m")
        axes_1.set_ylabel("velocity/ ms^-1")
        # energy_function
        energy = []
        axes_2 = figure.add_subplot(122)
        axes_2.set_xlabel("time/ s")
        axes_2.set_ylabel("Energy/ J")

        axes_1.plot(self.Euler_data[0], self.Euler_data[1], label="Euler")
        axes_2.plot(self.time, self.Euler_data[2])

        axes_1.plot(self.B_Euler_data[0], self.B_Euler_data[1], label="Improved Euler")
        axes_2.plot(self.time, self.B_Euler_data[2])

        axes_1.plot(self.Verlet_data[0], self.Verlet_data[1], label="Verlet")
        axes_2.plot(self.time, self.Verlet_data[2])

        axes_1.plot(self.Euler_Cromer_data[0], self.Euler_Cromer_data[1], label="Euler Cromer")
        axes_2.plot(self.time, self.Euler_Cromer_data[2])

        axes_1.plot(self.analytic_series_pos, self.analytic_series_vel, label="Analytic solution")
        axes_2.plot(self.time, self.analytic_energy)
        figure.legend()

    def save_data(self):
        # all files are saved as json dictionaries in the format "name of method": [position, velocity, energy]
        # the header of the file headers named appropriately contains the
        temp = [self.analytic_series_pos, self.analytic_series_vel, self.convert_array(self.analytic_energy)]

        data = {}
        data["Analytic"] = temp
        data["Euler"] = [self.Euler_data[0], self.Euler_data[1], self.convert_array(self.Euler_data[2])]
        data["Better Euler"] = [self.B_Euler_data[0], self.B_Euler_data[1], self.convert_array(self.B_Euler_data[2])]
        data["Verlet"] = [self.Verlet_data[0], self.Verlet_data[1], self.convert_array(self.Verlet_data[2])]
        data["Euler Cromer"] = [self.Euler_Cromer_data[0], self.Euler_Cromer_data[1],
                                self.convert_array(self.Euler_Cromer_data[2])]
        data["coefficients"] = [self.h, self.no_steps, self.b, self.m, self.k, self.init_x,
                                self.init_v]  # h, T, b, m, k, x, v

        with open(self.fileNameSave, 'w') as outfile:
            json.dump(data, outfile)
        outfile.close()

    def load_data(self):
        try:
            with open(self.fileNameLoad) as json_file:
                data = json.load(json_file)
                self.Euler_data = data["Euler"]
                self.B_Euler_data = data["Better Euler"]
                self.Verlet_data = data["Verlet"]
                self.analytic_series_pos = data["Analytic"][0]
                self.analytic_series_vel = data["Analytic"][1]
                self.analytic_energy = data["Analytic"][2]
                self.Euler_Cromer_data = data["Euler Cromer"]
                self.h, self.no_steps, self.b, self.m, self.k, self.init_x, self.init_v = data["coefficients"]
                print(self.h)
                print(self.no_steps)
                print(self.b)
                print(self.m)
                print(self.k)
                print(self.init_x)
                print(self.init_v)

            json_file.close()
            return True
        except:
            print("The file was not found")
            return False

    def find_accuracy(self):
        # finds the accuracy of the simulation by using the analytic energy as a baseline
        # this assigns a number of "fictitious energy" and also graphs the growth of the errors with time
        figure = plt.figure()
        axes_1 = figure.add_subplot(111)
        axes_1.set_ylabel("Energy error/ J")
        axes_1.set_xlabel("time/ s")
        fict_energy = []
        baseline = np.array(self.analytic_energy)

        # Euler's method
        temp = np.abs(np.array(self.Euler_data[2]) - baseline)
        axes_1.plot(self.time, temp, label="Euler")
        fict_energy.append(np.sum(temp))
        # Better Euler
        temp = np.abs(np.array(self.B_Euler_data[2]) - baseline)
        axes_1.plot(self.time, temp, label="Improved Euler")
        fict_energy.append(np.sum(temp))
        # Cromer
        temp = np.abs(np.array(self.Euler_Cromer_data[2]) - baseline)
        axes_1.plot(self.time, temp, label="Euler Cromer")
        fict_energy.append(np.sum(temp))
        # Verlet
        temp = np.abs(np.array(self.Verlet_data[2]) - baseline)
        axes_1.plot(self.time, temp, label="Verlet")
        fict_energy.append(np.sum(temp))
        temp = 0
        print("Euler: " + str(fict_energy[0]) + " J")
        print("Improved Euler: " + str(fict_energy[1]) + "J")
        print("Euler Cromer: " + str(fict_energy[2]) + "J")
        print("Verlet: " + str(fict_energy[3]) + "J")
        figure.legend()
        axes_1.set_title("h = " + str(self.h))

    def const_dist_Verlet_integrator(self, force, min, max):
        position_series = [self.init_x]
        velocity_series = [self.init_v]

        D = 2 * self.m + self.b * self.h
        B = (self.b * self.h - 2 * self.m) / D
        A = 2 * (2 * self.m - self.k * self.h ** 2) / D

        a_0 = (-self.b / self.m) * self.init_v + (-self.k / self.m) * self.init_x
        x_1 = self.init_x + self.init_v * self.h + 0.5 * a_0 * self.h ** 2  # obtained using a Taylor expansion of order 2
        position_series.append(x_1)

        for counter in range(1, self.no_steps, 1):
            if (counter * self.h > min) and (counter * self.h < max):
                position_series.append(
                    A * position_series[counter] + B * position_series[counter - 1] + (force / self.m * self.h ** 2))
            else:
                position_series.append(A * position_series[counter] + B * position_series[counter - 1])

        # calculating velocities using an approximation of O(h^2)
        # the velocity is estimated using the mean value theorem
        # the velocity is independent of the equation of motion. It just utilises the definition of velocity. If h is small
        # enough this approximation holds true
        for counter in range(1, self.no_steps, 1):
            velocity_series.append(
                (position_series[counter + 1] - position_series[counter - 1]) / (2 * self.h))  # +O(h^2)
        position_series = position_series[:len(position_series) - 1]

        self.disturbed_Verlet_data = [position_series, velocity_series,
                                      self.energy_function(position_series, velocity_series)]

    def funct_dist_Verlet_integrator(self, min, max, Amp, freq):
        position_series = [self.init_x]
        velocity_series = [self.init_v]

        D = 2 * self.m + self.b * self.h
        B = (self.b * self.h - 2 * self.m) / D
        A = 2 * (2 * self.m - self.k * self.h ** 2) / D

        a_0 = (-self.b / self.m) * self.init_v + (-self.k / self.m) * self.init_x
        x_1 = self.init_x + self.init_v * self.h + 0.5 * a_0 * self.h ** 2  # obtained using a Taylor expansion of order 2
        position_series.append(x_1)

        for counter in range(1, self.no_steps, 1):
            if (counter * self.h > min) and (counter * self.h < max):
                position_series.append(
                    A * position_series[counter] + B * position_series[counter - 1] + (
                            Amp * np.sin(freq * counter * self.h) / self.m * self.h ** 2))
            else:
                position_series.append(A * position_series[counter] + B * position_series[counter - 1])

        # calculating velocities using an approximation of O(h^2)
        # the velocity is estimated using the mean value theorem
        # the velocity is independent of the equation of motion. It just utilises the definition of velocity. If h is small
        # enough this approximation holds true
        for counter in range(1, self.no_steps, 1):
            velocity_series.append(
                (position_series[counter + 1] - position_series[counter - 1]) / (2 * self.h))  # +O(h^2)
        position_series = position_series[:len(position_series) - 1]

        self.disturbed_Verlet_data = [position_series, velocity_series,
                                      self.energy_function(position_series, velocity_series)]

    def push_testing(self, min, max, force, amp, freq):
        # constant force
        self.const_dist_Verlet_integrator(force, min, max)
        constant_data = self.disturbed_Verlet_data

        # sinusoidal force
        self.funct_dist_Verlet_integrator(min, max, amp, freq)
        function_data = self.disturbed_Verlet_data

        figure = plt.figure()
        axes_1 = figure.add_subplot(111)
        axes_1.plot(self.time, constant_data[0], label="constant force")
        # axes_1.plot(self.time, function_data[0], label="sinusoidal force")
        axes_1.plot(self.time, self.Verlet_data[0], label="undisturbed")
        # axes_1.plot(self.time, self.analytic_series_pos, label="analytical solution")
        figure.legend()

    def search(self, arr, x):
        '''
        variable name               type                    description
        i                           integer                 counter
        arr                         list                    array
        x                           float                   the value being searched
        '''
        # linear search function
        for i in range(len(arr)):
            if arr[i] == x:
                return i
        return -1

    def resonance_Plot(self):
        def test_func(x, a, b):
            return a * np.sin(b * x)

        temp = np.sqrt(self.k / self.m)
        freq_array = []
        for counter in range(0, 40, 1):
            freq_array.append(counter * temp * 0.1)

        amplitude = []
        for freq in freq_array:
            # get the data sets for a specific frequency
            self.funct_dist_Verlet_integrator(0, self.no_steps * self.h, self.init_x, freq)
            temp = self.disturbed_Verlet_data[0]
            # calculate amplitude
            params, params_covariance = optimize.curve_fit(test_func, self.time, temp, p0=[2, 2])
            amplitude.append((params[0]))
            # append to the arrays
        # plot the results
        figure = plt.figure()
        axes_1 = figure.add_subplot(111)
        axes_1.set_xlabel("Frequency/ Hz")
        axes_1.set_ylabel("Amplitude/ m")
        axes_1.plot(freq_array, amplitude, "+b")

    def Critical(self):
        temp = self.b
        b = [0.5 * self.b_critical, self.b_critical, 2 * self.b_critical]
        data = []
        for entry in b:
            self.b = entry
            self.Verlet_integrator()
            data.append(self.Verlet_data)

        # Verlet method
        # phase plots
        figure4 = plt.figure()
        axes_7 = figure4.add_subplot(121)
        axes_7.plot(data[0][0], data[0][1], label="0.5b")
        axes_7.plot(data[1][0], data[1][1], label="b")
        axes_7.plot(data[2][0], data[2][1], label="2b")
        axes_7.set_xlabel("position (m)")
        axes_7.set_ylabel("velocity (ms^-1)")
        # energy plotting
        axes_8 = figure4.add_subplot(122)
        axes_8.plot(self.time, data[0][2])
        axes_8.plot(self.time, data[1][2])
        axes_8.plot(self.time, data[2][2])
        axes_8.set_xlabel("time (s)")
        axes_8.set_ylabel("energy (J)")
        # position plot
        figure = plt.figure()
        axes_1 = figure.add_subplot(111)
        axes_1.plot(self.time, data[0][0], label="0.5b")
        axes_1.plot(self.time, data[1][0], label="b")
        axes_1.plot(self.time, data[2][0], label="2b")
        axes_1.set_ylabel("Position (m)")
        axes_1.set_xlabel("Time (s)")
        figure4.legend()
        figure.legend()

        self.b = temp

    def thing(self):
        plt.plot(self.time, self.Verlet_data[0], label="Verlet")
        plt.plot(self.time, self.analytic_series_pos, label="analytic")
        plt.plot(self.time, self.Euler_Cromer_data[0], label="Eruler Cromer")
        plt.plot(self.time, self.Euler_data[0], label="Euler")
        plt.plot(self.time, self.B_Euler_data[0], label="Better euler")

        plt.legend()

def getData():  # edit this function

    fileName = float(input("Enter the name of the simulation (don't forget the format)"))
    m = float(input("Enter the value for the mass of the particle: "))
    k = float(input("Enter the value of the spring constant: "))
    b = float(input("Enter the value of the damping constant "))
    T = float(input("Enter the time you want the simulation to run: "))
    h = float(input("Enter the time step in seconds: "))
    init_x = float(input("Enter the initial position"))
    init_v = float(input("Enter the initial velocity"))

    return m, k, b, T, h, init_x, init_v

def main():
    option = 0
    while option != "8":
        option = input("Select an option:")
        print("1. Run simulation")
        print("2. Load old simulation")
        if option == "1" or option == "2":
            if option == "1":
                m, k, b, T, h, init_x, init_v = getData()
                os = SHO(h, T, b, m, k, init_x, init_v)
            elif option == "2":
                print("Enter the name of the file or type 'none' if you want to use default")
                name = input()
                if name == "none":
                    os = SHO(0, 0, 0, 0, 0, 0, 0)
                    os.load_data()
                else:
                    os = SHO(0, 0, 0, 0, 0, 0, 0, name)
                    check = os.load_data()
                    if not check:
                        print("Goodbye!")
                        return 0
            option = input("Select an option:")
            print("3. Run critical damping simulation")
            print("4. Run simulation with the force appplied")
            print("5. Plot all of it")
            print("6. Save the simulation")
            print("7. Plot Resonance Curves")
            print("8. Leave")
            if option == "3":
                os.Critical()
            elif option == "4":
                min = input("Minimum time: ")
                max = input("Maximum time: ")
                force = input("Force magnitude: ")
                Amp = input("Sinusoidal force amplitude: ")
                freq = input("Sinusoidal force frequency: ")
                os.push_testing(min, max, force, Amp, freq)
            elif option == "5":
                os.plot_data()
                os.plot_single()
            elif option == "6":
                os.save_data()
                print("File was saved as data.txt")
            elif option == "7":
                os.resonance_Plot()
        else:
            print("Goodbye!")

def main2():
    m = 5.44
    k = 0.93
    b = 0.1
    T = 400  # max time
    h = 0.001  # time step

    os = SHO(h, T, b, m, k, 10, 0)

    os.runSimulation()
    os.thing()

    # os.push_testing(45.6, 100, 5, 5, 0.062832)
    # os.push_testing(57, 100, 5, 5, 6.2832)

main2()
plt.show()


#!/usr/bin/python3
from mil_usb_to_can.sub8 import SimulatedCANDevice

from .packets import SEND_ID, CommandMessage, FeedbackMessage

class ActuatorBoardSimulation(SimulatedCANDevice):
    """
    Simulator for the communication of the actuator board.

    Attributes:
        status (Dict[int, bool]): The status of the valves. The keys are each of the valve IDs,
          and the values are the statues of whether the valves are open.
    """

    def __init__(self, *args, **kwargs):
        # Tracks the status of the 12 valves
        self.status = {i: False for i in range(12)}
        super().__init__(*args, **kwargs)

    def on_data(self, data, can_id) -> None:
        """
        Processes data received from motherboard / other devices. For each message received,
        the class' status attribute is updated if the message is asking to write, otherwise
        a feedback message is constructed and sent back.
        """
        # If from wrong ID, ignore
        if can_id != SEND_ID:
            return

        # First byte should be the identifier char for the command message
        assert ord(data[0]) == CommandMessage.IDENTIFIER

        # Parse message
        message = CommandMessage.from_bytes(data)

        # If message is writing a valve, store this change in the internal dictionary
        if message.write:
            self.status[message.address] = message.on

        # If message is a status request, send motherboard the status of the requested valve
        else:
            response = FeedbackMessage.create_feedback_message(
                address=message.address,
                on=self.status[message.address],
            )
            self.send_data(bytes(response))


# -*- coding: utf-8 -*-
#  This file is part of AC3ES Tools.
#
#  AC3ES Tools is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  AC3ES Tools is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with AC3ES Tools.  If not, see <http://www.gnu.org/licenses/>.
from ac3es.cli import BaseCliCommand
from ac3es.info import InfoFile
import json

class CliInfo(BaseCliCommand):

    def __init__(self):
        self.name = 'info'
        self.help = 'Try to identify files and print useful information'
        self.args = None

    def get_parser(self, subparsers):
        parser_info = subparsers.add_parser(self.name, help=self.help)
        parser_info.add_argument(
            'FILES',
            help="One or more file to get info",
            nargs="+"
        )
        parser_info.add_argument('--format', '-f',
                                 choices=['list', 'csv', 'json'],
                                 default='list',
                                 help='Print output in different file formats')

        return subparsers

    def run_cmd(self, args):
        self.args = args
        self.guess(args.FILES)

    def guess(self, file_list):
        info = InfoFile()
        stats = []
        for x in file_list:
            stats.append(info.detect(x))

        if self.args.format == 'json':
            print(json.dumps(stats, indent=2))
        elif self.args.format == 'csv':
            print("\t".join(map(str, stats[0].keys())))
            for line in stats:
                print("\t".join(map(str, line.values())))
        else:
            pad_len = 15
            if stats:
                pad_len = len(max(stats[0].keys(), key=len))

            for item in stats:
                for key, value in item.items():
                    print(key.rjust(pad_len, ' '), value)
                print()


def rIS(a, n):
    if n == 0:
        return
    rIS(a, n-1)
    val = a[n]
    while n > 0 and a[n-1] >= val:
        a[n] = a[n-1]
        n -= 1
    a[n] = val

def main():
    list = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    print("Unsorted list:", list)
    rIS(list, len(list) - 1)
    print("Sorted list:", list)

if __name__ == "__main__":
    main()


from random import randint, uniform
import math

import pygame
from pygame import Vector2

from settings import *
from data import Data

class Wall(pygame.sprite.Sprite):
    ''' Walls of the game'''
    def __init__(self, game, x, y):
        self.groups = game.all_sprites, game.walls
        pygame.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = pygame.Surface((TILESIZE, TILESIZE))
        self.image.fill(WALL)
        self.rect = self.image.get_rect()
        self.x = x
        self.y = y
        self.rect.x = x * TILESIZE
        self.rect.y = y * TILESIZE

class Mob(pygame.sprite.Sprite):
    '''Parent class for Mobs '''
    def __init__(self, game, groups, position, image, name):

        self.groups = groups
        pygame.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.data = Data()
        self.name = name
        self.image = image
        self.rect = self.image.get_rect()

        base_max_speed = MOBS[self.name]['MAX_SPEED']
        self.max_speed = base_max_speed + \
            uniform(-base_max_speed * 0.25, base_max_speed * 0.25)
        self.acceleration = MOBS[self.name]['ACCELERATION']

        self.position = position
        self.rect.topleft = position
        self.desired_velocity = Vector2(0, 0)
        self.velocity = Vector2(0, 0)
        self.avoidance = Vector2(0, 0)
        self.max_health = MOBS[self.name]['HEALTH']
        self.health = self.max_health
        self.mob_score = 0
        self.spawn_time = pygame.time.get_ticks()

        self.last_shot_time = 0

    def update(self):
        pass

    def move(self):
        if self.desired_velocity.magnitude() > 0:
            self.desired_velocity = self.desired_velocity.normalize()

        self.velocity -= self.velocity * DRAG * self.game.dt
        self.velocity += (self.desired_velocity + self.avoidance) * \
            self.acceleration * self.game.dt
        if self.velocity.magnitude() > self.max_speed:
            self.velocity.scale_to_length(self.max_speed)

        self.position += self.velocity * self.game.dt

        self.rect.x = self.position.x
        self.collide_with_walls('x')
        self.rect.y = self.position.y
        self.collide_with_walls('y')

    def collide_with_walls(self, dir):
        hits = pygame.sprite.spritecollide(self, self.game.walls, False)
        if len(hits) == 0:
            return

        if dir == 'x':
            if self.velocity.x > 0:
                self.position.x = hits[0].rect.left - self.rect.width
            if self.velocity.x < 0:
                self.position.x = hits[0].rect.right
            self.velocity.x = 0
            self.rect.x = self.position.x

        if dir == 'y':
            if self.velocity.y > 0:
                self.position.y = hits[0].rect.top - self.rect.height
            if self.velocity.y < 0:
                self.position.y = hits[0].rect.bottom
            self.velocity.y = 0
            self.rect.y = self.position.y

    def receive_damage(self, damage):
        self.health -= damage
        if self.health <= 0:
            self.health = 0
            self.game.score += self.mob_score
            self.data.dead_fx.play()
            self.kill()

    def draw_health(self):
        health = self.health / self.max_health
        bar_width = int(health * self.rect.width)
        health_bar = pygame.Rect(
            self.position.x, self.position.y - 7, bar_width, 5)
        pygame.draw.rect(self.game.screen, GREEN, health_bar)

    def avoid_mobs(self):
        towards_mobs = Vector2(0, 0)
        for mob in self.game.mobs:
            if mob != self:
                towards_mob = mob.position - self.position
                if 0 < towards_mob.magnitude() < AVOID_RADIUS:
                    towards_mobs += towards_mob / towards_mob.magnitude()

    def shoot_at(self, x, y, target_group):
        weapon = WEAPONS[self.weapon_name]

        time_since_last_shot = pygame.time.get_ticks() - self.last_shot_time
        if time_since_last_shot < weapon['FIRING_RATE']:
            return
        bullet_velocity = Vector2(x, y) - self.position
        if bullet_velocity.magnitude() > 0:
            bullet_velocity = bullet_velocity.normalize()

        for _ in range(weapon['AMMO_PER_SHOT']):
            Bullet(
                self.game,
                Vector2(self.rect.center),
                bullet_velocity,
                weapon['SPREAD'],
                weapon['TTL'],
                weapon['SPEED'],
                weapon['DAMAGE'],
                weapon['COLOR'],
                weapon['SIZE'],
                target_group
            )
            self.data.bullet_fx.play().set_volume(0.15)
        self.last_shot_time = pygame.time.get_ticks()

class Player(Mob):
    def __init__(self, game, position, image, map, name):

        super().__init__(game, (game.all_sprites, game.players), position, image, name)
        self.map = map
        self.weapon_name = 'GUN'
        self.weapon_img = self.data.gun_img
        self.max_speed = MOBS[self.name]['MAX_SPEED'] # We don't use default MOB speed

    def update(self):
        self.handle_input()
        self.move()

        # teleport player if is outside the window
        if self.position.x > WIDTH or self.position.x < 0:
            self.position.x, self.position.y = self.map.get_empty_position()
        if self.position.y > HEIGHT or self.position.y < 0:
            self.position.x, self.position.y = self.map.get_empty_position()

    def receive_damage(self, damage):
        self.health -= damage
        if self.health <= 0:
            self.health = 0
            self.kill()
            self.game.game_over()

    def teleport(self, new_position):
        self.position.x = new_position.x
        self.position.y = new_position.y
        self.rect.x = self.position.x
        self.rect.y = self.position.y

        # Avoiding keeping speed buff bug when teleporting
        self.max_speed = MOBS['PLAYER']['MAX_SPEED']

    def handle_input(self):
        mouse = pygame.mouse.get_pressed()
        if mouse[0]:
            x, y = pygame.mouse.get_pos()
            self.shoot_at(x, y, self.game.mobs)

        vx, vy = 0, 0
        key = pygame.key.get_pressed()
        if key[pygame.K_a]:
            vx = -1
        if key[pygame.K_d]:
            vx = 1
        if key[pygame.K_w]:
            vy = -1
        if key[pygame.K_s]:
            vy = 1

        self.desired_velocity = Vector2(vx, vy)

class Bee(Mob):
    def __init__(self, game, position, image, name, groups=()):

        super().__init__(game, (game.all_sprites, game.mobs) + groups,
                         position, image, name)

        self.damage = MOBS[name]['HIT_DAMAGE']
        self.vision_radius = MOBS[name]['VISION_RADIUS']
        self.mob_score = 10

    def update(self):
        towards_player = self.game.player.position - self.position
        if towards_player.magnitude() <= self.vision_radius:
            self.desired_velocity = towards_player
        else:
            self.desired_velocity = Vector2(uniform(-1, 1),
                                            uniform(-1, 1))
        self.avoid_mobs()
        self.move()
        if pygame.sprite.collide_rect(self, self.game.player):
            self.game.player.receive_damage(self.damage * self.game.dt)

        # Kill the mobs outside the window
        if self.position.x > WIDTH or self.position.x < 0:
            self.kill()
        if self.position.y > HEIGHT or self.position.y < 0:
            self.kill()

class BeeNest(Mob):
    def __init__(self, game, position, image, name):
        super().__init__(game, (game.all_sprites, game.nests,
                                game.mobs), position, image, name)

        self.spawn_frequency = MOBS[name]['SPAWN_FREQUENCY']  + randint(2000, 5000)
        self.last_spawn_time = 0
        self.max_population = MOBS[name]['MAX_POPULATION']
        self.population = pygame.sprite.Group()
        self.mob_score = 30

    def update(self):
        time_since_last_spawn = pygame.time.get_ticks() - self.last_spawn_time
        time_has_passed = time_since_last_spawn >= self.spawn_frequency
        room_left = len(self.population) < self.max_population

        if time_has_passed and room_left:
            max_spawneable = self.max_population - len(self.population)
            to_spawn = randint(1, max_spawneable)
            for _ in range(to_spawn):
                Bee(
                    self.game,
                    Vector2(self.position.x, self.position.y) +
                    Vector2(uniform(-TILESIZE, TILESIZE),
                            uniform(-TILESIZE, TILESIZE)),
                    self.data.bee_img,
                    'BEE',
                    (self.population,)
                )
            self.last_spawn_time = pygame.time.get_ticks()

class Tower(Mob):
    def __init__(self, game, position, image, name):
        super().__init__(game, (game.all_sprites, game.mobs),
                         position, image, name)

        self.weapon_name = MOBS[name]['WEAPON_NAME']
        self.vision_radius = MOBS[name]['VISION_RADIUS']
        self.mob_score = 100

    def update(self):
        towards_player = self.game.player.position - self.position
        target = self.game.player.position

        if 0 < towards_player.magnitude() < self.vision_radius:
            self.shoot_at(target.x, target.y, self.game.players)

class Spider(Mob):
    def __init__(self, game, position, image, name, groups=()):

        super().__init__(game, (game.all_sprites, game.mobs) + groups,
                         position, image, name)

        self.damage = MOBS[name]['HIT_DAMAGE']
        self.vision_radius = MOBS[name]['VISION_RADIUS']
        self.mob_score = 100

    def update(self):

        towards_player = self.game.player.position - self.position
        if towards_player.magnitude() <= self.vision_radius:
            self.desired_velocity = towards_player
        else:
            self.desired_velocity = Vector2(uniform(-1, 1),
                                            uniform(-1, 1))
        self.avoid_mobs()
        self.move()

        if pygame.sprite.collide_rect(self, self.game.player):
            self.game.player.receive_damage(self.damage * self.game.dt)

        # Kill the mobs outside the window
        if self.position.x > WIDTH or self.position.x < 0:
            self.kill()
        if self.position.y > HEIGHT or self.position.y < 0:
            self.kill()

class Bullet(pygame.sprite.Sprite):
    def __init__(self, game, position, velocity,
                 spread, ttl, speed, damage, color, size, target_group):

        self.groups = game.all_sprites, game.bullets
        pygame.sprite.Sprite.__init__(self, self.groups)
        self.game = game
        self.image = pygame.Surface((size, size))
        self.image.fill(color)
        self.rect = self.image.get_rect()

        self.position = position
        self.rect.center = self.position

        self.ttl = ttl
        self.spawn_time = pygame.time.get_ticks()
        self.speed = uniform(speed * 0.9, speed * 1.1)
        self.damage = damage
        self.velocity = velocity + Vector2(
            uniform(-spread, spread), uniform(-spread, spread))
        self.velocity = self.velocity.normalize()
        self.target_group = target_group

    def update(self):
        self.position += self.velocity * self.speed * self.game.dt
        self.rect.center = self.position

        life_time = pygame.time.get_ticks() - self.spawn_time

        if life_time > self.ttl:
            self.kill()

        if pygame.sprite.spritecollide(self, self.game.walls, False):
            self.kill()

        hits = pygame.sprite.spritecollide(self, self.target_group, False)
        if len(hits) > 0:
            hits[0].receive_damage(self.damage)
            self.kill()

class Item(pygame.sprite.Sprite):
    def __init__(self, game, position, kind):
        self.groups = game.all_sprites, game.items
        pygame.sprite.Sprite.__init__(self, self.groups)
        self.data = Data()
        self.game = game
        self.image = self.data.healthpack_img
        self.rect = self.image.get_rect()
        self.position = position
        self.rect.topleft = position
        self.kind = kind

    def update(self):
        self.rect.top = self.position.y + math.sin(pygame.time.get_ticks() *
                                                   ITEM_HOVER_SPEED) * TILESIZE // 2
        if pygame.sprite.collide_rect(self, self.game.player):
            self.picked_by(self.game.player)

    def picked_by(self, picker):
        pass

class HealthPack(Item):
    def __init__(self, game, position):
        super().__init__(
            game,
            position,
            'HEALTHPACK'
        )
        self.image = self.data.healthpack_img

    def picked_by(self, picker):
        heal = ITEMS[self.kind]['HEAL']
        if picker.health < picker.max_health:
            picker.health = min(picker.health + heal, picker.max_health)
            self.data.heal_fx.play()
            self.kill()

class SpeedUp(Item):
    def __init__(self, game, position):
        super().__init__(
            game,
            position,
            'SPEEDUP'
        )
        self.image = self.data.speedup_img
        self.speed_buff = ITEMS[self.kind]['SPEED']
        self.picker = None
        self.picker_base_speed = 0
        self.picker_max_speed = 0

    def picked_by(self, picker):

        self.picker = picker

        self.picker.max_speed += self.speed_buff

        ttl = ITEMS[self.kind]['TTL']
        self.stop_working_at = pygame.time.get_ticks() + ttl
        self.data.powerup_fx.play()
        self.rect.x = -10000000

    def update(self):
        if self.picker == None:
            super().update()
            return

        now = pygame.time.get_ticks()
        if now > self.stop_working_at:
            self.picker.max_speed -= self.speed_buff
            self.kill()

class Weapon(pygame.sprite.Sprite):
    def __init__(self, game, position):
        self.groups = game.all_sprites, game.items
        pygame.sprite.Sprite.__init__(self, self.groups)
        self.data = Data()
        self.game = game
        self.image = self.data.gun_img
        self.rect = self.image.get_rect()
        self.position = position
        self.rect.topleft = position
        self.weapon_name = 'GUN'
        self.picker = None

    def update(self):
        self.rect.top = self.position.y + math.sin(pygame.time.get_ticks() *
                                                   ITEM_HOVER_SPEED) * TILESIZE // 2
        if pygame.sprite.collide_rect(self, self.game.player):
            self.picked_by(self.game.player)

    def picked_by(self, picker):
        self.picker = picker
        if picker.weapon_name != self.weapon_name:
            self.picker.weapon_name = self.weapon_name
            self.picker.weapon_img = self.image
            self.data.weapon_fx.play()
            self.kill()

class Machinegun(Weapon):
    def __init__(self, game, position):
        super().__init__(game, position)
        self.image = self.data.machinegun_img
        self.weapon_name = 'MACHINEGUN'

class Shotgun(Weapon):
    def __init__(self, game, position):
        super().__init__(game, position)
        self.image = self.data.shotgun_img
        self.weapon_name = 'SHOTGUN'

class Deagle(Weapon):
    def __init__(self, game, position):
        super().__init__(game, position)
        self.image = self.data.deagle_img
        self.weapon_name = 'DEAGLE'

class Assault(Weapon):
    def __init__(self, game, position):
        super().__init__(game, position)
        self.image = self.data.assault_img
        self.weapon_name = 'ASSAULT'


from nose.tools import *

from alicia.configuration import *
from alicia.node import *
from alicia.element import *
from alicia.close_field import *
from alicia.contents.string_content import *
from alicia.contents.integer_content import *
from alicia.utils import *

# Nose functions ##############################################################
def setup():
    pass

def teardown():
    pass

# Node ########################################################################
def test_Node___init__():
    element0 = Element()
    node0 = Node([element0])
    assert_equals(node0.type                , "Node")
    assert_equals(node0.static              , False)
    assert_equals(node0.weight              , 1.0)
    assert_equals(node0.defaultSubElements  , [element0])
    assert_equals(node0.currentSubElements  , [element0])
    assert_equals(node0.futureSubElements   , [element0])
    assert_equals(element0.boundElements    , [node0])

    element1 = Element()
    node1 = Node([element0, element1], name="My Node", static=True, weight=2.5)
    assert_equals(node1.type                , "Node")
    assert_equals(node1.name                , "My Node")
    assert_equals(node1.static              , True)
    assert_equals(node1.weight              , 2.5)
    assert_equals(node1.defaultSubElements  , [element0, element1])
    assert_equals(node1.currentSubElements  , [element0, element1])
    assert_equals(node1.futureSubElements   , [element0, element1])
    assert_equals(element0.boundElements    , [node0, node1])
    assert_equals(element1.boundElements    , [node1])

def test_Node_getSize():
    content0 = StringContent("ABCDE")
    content1 = IntegerContent(32)
    element0 = CloseField(content0)
    element1 = CloseField(content1)
    node0 = Node([element0])
    node1 = Node([node0, element1])
    node2 = Node([])
    node3 = Node([node1, node2])

    assert_equals(node0.getSize()           , 5)
    assert_equals(node1.getSize()           , 9)
    assert_equals(node2.getSize()           , 0)
    assert_equals(node3.getSize()           , 9)

def test_Node___str__():
    element0 = Element(name="Element 0")
    element1 = Element(name="Element 1")
    node0 = Node([element0], "Node 0")
    node1 = Node([node0, element1], "Node 1")
    node2 = Node([], "Node 2")
    node3 = Node([node1, node2], "Node 3")

    assert_equals(str(node0)            , "[Node 0]\n\t[Element 0]\n")
    assert_equals(str(node1)            , "[Node 1]\n\t[Node 0]\n\t\t[Element 0]\n\t[Element 1]\n")
    assert_equals(str(node3)            , "[Node 3]\n\t[Node 1]\n\t\t[Node 0]\n\t\t\t[Element 0]\n\t\t[Element 1]\n\t[Node 2]\n")

def test_Node_preforecast():
    configuration.fuzzingNumber = 3
    configuration.overflowNumber = 2

    content0 = StringContent("ABCDE")
    content1 = IntegerContent(32)
    element0 = CloseField(content0)
    element1 = CloseField(content1)
    node0 = Node([element0])
    node1 = Node([node0, element1])
    node2 = Node([])
    node3 = Node([node1, node2])

    assert_equals(node0.fuzzNumber      , 6)
    assert_equals(node1.fuzzNumber      , 12)
    assert_equals(node2.fuzzNumber      , 3)
    assert_equals(node3.fuzzNumber      , 18)
    assert_equals(node3.ownFuzzNumber   , 3)
    assert_equals(node3.subElementsFuzzSteps, [12, 3])

    assert_equals(node0.overflowNumber  , 4)
    assert_equals(node1.overflowNumber  , 8)
    assert_equals(node2.overflowNumber  , 2)
    assert_equals(node3.overflowNumber  , 12)
    assert_equals(node3.ownOverflowNumber, 2)
    assert_equals(node3.subElementsOverflowSteps, [8, 2])

def test_Node_getSubElementAfterFuzzSteps():
    configuration.fuzzingNumber = 3
    content0 = StringContent("ABCDE")
    content1 = IntegerContent(32)
    element0 = CloseField(content0)
    element1 = CloseField(content1)
    node0 = Node([element0])
    node1 = Node([node0, element1])
    node2 = Node([])
    node3 = Node([node1, node2])

    node3.preForecast()
    subElementIndex0, remainingSteps0 = node3.getSubElementAfterFuzzSteps(3)
    assert_equals(subElementIndex0      , 0) # node1
    assert_equals(remainingSteps0       , 0)

    subElementIndex1, remainingSteps1 = node3.getSubElementAfterFuzzSteps(7)
    assert_equals(subElementIndex1      , 0) # node0
    assert_equals(remainingSteps1       , 4)

    subElementIndex2, remainingSteps2 = node3.getSubElementAfterFuzzSteps(11)
    assert_equals(subElementIndex2      , 0) # element0
    assert_equals(remainingSteps2       , 8)

    subElementIndex3, remainingSteps3 = node3.getSubElementAfterFuzzSteps(13)
    assert_equals(subElementIndex3      , 0) # element1
    assert_equals(remainingSteps3       , 10)

    subElementIndex4, remainingSteps4 = node3.getSubElementAfterFuzzSteps(15)
    assert_equals(subElementIndex4      , 1) # node2
    assert_equals(remainingSteps4       , 0)

def test_Node_getSubElementAfterOverflowSteps():
    configuration.overflowNumber = 3
    content0 = StringContent("ABCDE")
    content1 = IntegerContent(32)
    element0 = CloseField(content0)
    element1 = CloseField(content1)
    node0 = Node([element0])
    node1 = Node([node0, element1])
    node2 = Node([])
    node3 = Node([node1, node2])

    node3.preForecast()
    subElementIndex0, remainingSteps0 = node3.getSubElementAfterOverflowSteps(3)
    assert_equals(subElementIndex0      , 0) # Node1
    assert_equals(remainingSteps0       , 0)

    subElementIndex1, remainingSteps1 = node3.getSubElementAfterOverflowSteps(7)
    assert_equals(subElementIndex1      , 0) # Node0
    assert_equals(remainingSteps1       , 4)

    subElementIndex2, remainingSteps2 = node3.getSubElementAfterOverflowSteps(11)
    assert_equals(subElementIndex2      , 0) # Element0
    assert_equals(remainingSteps2       , 8)

    subElementIndex3, remainingSteps3 = node3.getSubElementAfterOverflowSteps(13)
    assert_equals(subElementIndex3      , 0) # Element1
    assert_equals(remainingSteps3       , 10)

    subElementIndex4, remainingSteps4 = node3.getSubElementAfterOverflowSteps(15)
    assert_equals(subElementIndex4      , 1) # Node2
    assert_equals(remainingSteps4       , 0)

def test_Node_compose():
    content0 = StringContent("ABCDE")
    element0 = CloseField(content0)
    content1 = IntegerContent(32)
    element1 = CloseField(content1)
    node0 = Node([element0, element1])
    assert_equals(node0.compose()       , ["ABCDE", "\x00\x00\x00 "])

def test_Node_nodeFuzz():
    configuration.fuzzing = 100
    content0 = StringContent("ABCDE")
    element0 = CloseField(content0)
    content1 = IntegerContent(32)
    element1 = CloseField(content1)
    node0 = Node([element0, element1])

    # Mutation
    node0.nodeFuzz(0)
    assert_equals(node0.compose()       , ["\x00\x00\x00 ", "\x00\x00\x00 "])
    node0.clean()

    # Remove
    node0.nodeFuzz(1)
    assert_equals(node0.compose()       , ["\x00\x00\x00 "])
    node0.clean()

    # Add
    node0.nodeFuzz(2)
    assert_equals(node0.compose()       , ['\x00\x00\x00 ', "ABCDE", "\x00\x00\x00 "])
    node0.clean()

    # Swap
    node0.nodeFuzz(3)
    assert_equals(node0.compose()       , ["\x00\x00\x00 ", "ABCDE"])

    # Remove 1 (previously only 0 was impacted)
    node0.nodeFuzz(5)
    assert_equals(node0.compose()       , ["\x00\x00\x00 "])

def test_Node_newFuzzedSubElement():
    content0 = StringContent("ABCDE")
    element0 = CloseField(content0)
    content1 = IntegerContent(32)
    element1 = CloseField(content1)
    node0 = Node([element0, element1])

    rand = random.Random(0)
    assert_equals(node0.newFuzzedSubElement(rand).compose(), element1.compose())

    rand = random.Random(1)
    assert_equals(node0.newFuzzedSubElement(rand).compose(), element0.compose())

def test_Node_fuzz():
    configuration.fuzzingNumber = 10
    content0 = StringContent("ABCDE")
    element0 = CloseField(content0)
    content1 = IntegerContent(32)
    element1 = CloseField(content1)
    node0 = Node([element0, element1])

    # NodeFuzz : Mutation
    node0.fuzz(0)
    assert_equals(node0.compose()       , ["\x00\x00\x00 ", "\x00\x00\x00 "])
    node0.clean()

    # Field fuzz
    node0.fuzz(10)
    assert_equals(node0.compose()       , ["ABCWE", "\x00\x00\x00 "])
    node0.clean()

    # Field fuzz
    node0.fuzz(20)
    assert_equals(node0.compose()       , ["ABCDE", "\x00\x00\x00 "])
    node0.clean()

def test_Node_clean():
    content0 = StringContent("ABCDE")
    element0 = CloseField(content0)
    content1 = IntegerContent(32)
    element1 = CloseField(content1)
    node0 = Node([element0, element1])

    element0.fuzz(0)
    element1.fuzz(0)
    node0.currentSubElements = [element1, element0]
    node0.clean()

    assert_equals(node0.compose()       , ["ABCDE", "\x00\x00\x00 "])
    assert_equals(node0.currentSubElements[0].boundElements, [node0])
    assert_equals(node0.currentSubElements[1].boundElements, [node0])

def test_Node_commit():
    content0 = StringContent("ABCDE")
    element0 = CloseField(content0)
    content1 = IntegerContent(32)
    element1 = CloseField(content1)
    node0 = Node([element0, element1])

    node0.futureSubElements = [element1, element0]
    content0.future = "ABCDF"
    content1.future = "\x00\x00\x00\xff"
    node0.commit()

    assert_equals(node0.compose()       , ["\x00\x00\x00\xff", "ABCDF"])
    assert_equals(node0.currentSubElements[0].boundElements, [node0])
    assert_equals(node0.currentSubElements[1].boundElements, [node0])