Undo and history
The cargo console works: operators add and remove crates and check the hold. What it can't do is answer "what happened?" or take back a slip of the finger, and last week a crate was removed by mistake and had to be typed back in from memory.
Extend the console with a history of changes, then an undo that uses it.
Finish stage 1 to unlock this stage.
The console works as it is. Add a list, history, and record every change that actually happens as (action, item, mass): ("add", "CG-0042", 18.5) or ("remove", "CG-0042", 18.5). Refused commands change nothing, so they aren't recorded. Add a history command that lists them, numbered:
Added CG-0042 Added CG-0043 Removed CG-0042 Not in the hold: CG-0099 Added CG-0044 1. add CG-0042 18.5 2. add CG-0043 2.36 3. remove CG-0042 18.5 4. add CG-0044 31.0 Hold: CG-0043, CG-0044 (33.36 kg)
For a removal you need the mass of the crate that is going: hold.pop(item) removes it and returns its mass.
Finish stage 1 to unlock this stage.
Add undo: take the last change off history with pop() and do the opposite, removing an added crate or putting a removed one back with its mass. With nothing left to undo, say so:
Added CG-0042 Added CG-0043 Removed CG-0042 Undid remove CG-0042 Added CG-0044 Hold: CG-0042, CG-0043, CG-0044 (51.86 kg) Undid add CG-0044 Undid add CG-0043 Undid add CG-0042 Nothing to undo Hold: empty (0.00 kg)
The new command list undoes everything, then a bit more.
Hints
List Methods - append, insert, pop
# List methods that change the list in place
# Observatories lined up to follow up an alert
followup = ["ZTF", "Gemini South", "ALMA"]
print("Queue:", followup)
# append() adds one item to the end
followup.append("Keck")
print("After append:", followup)
# insert() takes the position first, then the value
followup.insert(0, "Swift")
print("After insert:", followup)
# pop() removes the last item and hands it back
dropped = followup.pop()
print("Clouded out:", dropped)
# pop(0) takes from the front - this is how you work a queue
observing_now = followup.pop(0)
print("Observing now:", observing_now)
print("Still waiting:", followup)
# These methods return None, not a new list
print("What append gives back:", followup.append("VLT"))
# clear() empties the list, the list itself survives
followup.clear()
print("Alert closed:", followup, "left in queue:", len(followup))
Separate arguments with commas. They're passed on every Run as sys.argv[1:].