Een magische machine bestaat uit glazen bellen die bonen kunnen bevatten. De bellen zijn verbonden door grote drukknoppen.

Voorbeeld van een magische machine met drie bellen en drie drukknoppen.

Als er op een knop gedrukt wordt, dan voert de machine achtereenvolgens de volgende twee acties uit:

Als je bij de machine uit bovenstaande figuur bijvoorbeeld op knop B zou drukken, dan zal er uit de bovenste bel één boon verdwijnen, en komt er in de onderste bel één boon bij.

Opgave

Schrijf een klasse Machine waarvan de objecten magische machines voorstellen die zich gedragen zoals beschreven in de inleiding. Initieel hebben de machines nog geen bellen of knoppen, maar tijdens hun levensduur kunnen er nieuwe bellen en/of knoppen aan toegevoegd worden. Om te kunnen verwijzen naar de bellen en knoppen van een machine krijgen deze elk een eigen label, dat wordt voorgesteld als een string. Voorts moeten objecten van de klasse Machine minimaal de volgende methoden ondersteunen:

In bovenstaande omschrijvingen werd niet expliciet aangegeven dat de methoden nieuweBel, nieuweKnop en druk een waarde moeten teruggeven. Zorg ervoor dat deze methoden een waarde teruggeven zodat de methoden kunnen aaneengeschakeld worden zoals aangegeven in onderstaand voorbeeld.

Gebruik een objectgerichte aanpak om de afzonderlijke componenten van magische machines (bellen en knoppen) te modelleren.

Voorbeeld

De magische machine die in onderstaande interactieve sessie wordt opgebouwd, komt overeen met de afbeelding uit de inleiding van deze opgave.

> const machine = new Machine()
..     .nieuweBel("1", 0)
..     .nieuweBel("2", 3)
..     .nieuweBel("3", 0)
..     .nieuweKnop("A", ["1", "3"], ["1", "2"])
..     .nieuweKnop("B", ["2"], ["3"])
..     .nieuweKnop("C", ["3"], ["1"]);
> machine.toString();
"1: 0\n2: 3\n3: 0"
> machine.druk("B").toString();
"1: 0\n2: 2\n3: 1"
> machine.druk("B").toString();
"1: 0\n2: 1\n3: 2"
> machine.druk("C").toString();
"1: 1\n2: 1\n3: 1"
> machine.druk(["A", "B", "A"]).toString();
"1: 1\n2: 2\n3: 0"

> machine.nieuweBel("1", 3);
AssertionError: bel bestaat reeds
> machine.nieuweKnop("A", ["2", "3"], ["1", "3"]);
AssertionError: knop bestaat reeds
> machine.nieuweKnop("X", ["1", "2"], ["3", "4"]);
AssertionError: onbekende bel
> machine.druk("Z").toString();
AssertionError: onbekende knop