Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23b67e3f60 | ||
|
|
25e29539ee | ||
|
|
dc213505e7 | ||
|
|
9a8678cdda | ||
|
|
2a93d5d9c8 | ||
|
|
9c4da2db4a | ||
|
|
b2ff61070b | ||
|
|
33e91d77cd | ||
|
|
2f788482f6 | ||
|
|
9415cffb0a | ||
|
|
2269d6a13a | ||
|
|
5d4d5d1526 | ||
|
|
1e44e0f344 | ||
|
|
c0b274698d | ||
|
|
5ee71e2189 | ||
|
|
a14a63dca3 | ||
|
|
07cef1f5ac | ||
|
|
4f037e2459 | ||
|
|
9d383fb005 | ||
|
|
197f0e01a1 | ||
|
|
43cbfb78e5 | ||
|
|
c0288e3488 | ||
|
|
d4267196a4 | ||
|
|
5654431e70 | ||
|
|
28d3ee65ad | ||
|
|
8e008d5304 | ||
|
|
8289259265 | ||
|
|
18a0ff5717 | ||
|
|
14b76e1faf | ||
|
|
7e96c15f69 | ||
|
|
58a306da64 | ||
|
|
3da120fd28 | ||
|
|
3d44015183 | ||
|
|
71286bf151 | ||
|
|
5415839361 | ||
|
|
9a793ef77b | ||
|
|
0ec9ac0388 | ||
|
|
6bcd1dfca6 | ||
|
|
efe4f989a3 | ||
|
|
3af901eede | ||
|
|
d3d2538783 | ||
|
|
51f402b149 | ||
|
|
09aee14ce1 | ||
|
|
b8638ea0be | ||
|
|
9e8007da96 | ||
|
|
ef68b32367 | ||
|
|
4c1b363e52 | ||
|
|
7b3a33a8d8 | ||
|
|
75bf82b0db | ||
|
|
b80382ca4c | ||
|
|
4b7daaeef3 | ||
|
|
69d6213b0a | ||
|
|
32ac7db0b1 | ||
|
|
3c3a858e2b | ||
|
|
69866aa30b | ||
|
|
149003f869 | ||
|
|
2f5748a5a9 | ||
|
|
74135a2f6f | ||
|
|
75c765eb09 | ||
|
|
852fd90849 | ||
|
|
71ea61b987 | ||
|
|
4aef25f973 | ||
|
|
7a4a8b7193 | ||
|
|
5e3b262382 | ||
|
|
d0aed8fcfb | ||
|
|
f89276f39f | ||
|
|
d15022ec4e | ||
|
|
41b191ff94 | ||
|
|
d8e85f81cf | ||
|
|
db86142e81 | ||
|
|
515e055375 | ||
|
|
803edd6f86 | ||
|
|
3da48acf33 | ||
|
|
0e3f7f5dd4 | ||
|
|
367b42ba6b | ||
|
|
d13b30ee50 | ||
|
|
0758ca47c7 | ||
|
|
4552a8a540 | ||
|
|
5003acdb3d | ||
|
|
9ba9e665de | ||
|
|
a313da141a | ||
|
|
901c9caf50 | ||
|
|
968480e71b | ||
|
|
6fac0ba2b5 | ||
|
|
50cfe0552a | ||
|
|
feca2ffc74 | ||
|
|
39b347cdf9 | ||
|
|
4c5381065b | ||
|
|
f4fed79b61 | ||
|
|
b329abe78e | ||
|
|
1f9f295c48 | ||
|
|
b9d83cac68 | ||
|
|
f486acc176 | ||
|
|
ab94a75adf | ||
|
|
2c9ed3bdfe | ||
|
|
d3628a4ab6 | ||
|
|
a836d9806f | ||
|
|
659a119421 | ||
|
|
41e657b6aa | ||
|
|
ed677a320b | ||
|
|
620456dca0 | ||
|
|
f85a845685 | ||
|
|
4e7cb1c345 | ||
|
|
9640688cc7 | ||
|
|
f1348d1987 | ||
|
|
4e43c5e060 | ||
|
|
b07115022a | ||
|
|
9c8aa1c2c9 | ||
|
|
a6b9b0eb91 | ||
|
|
b061613cd1 |
4 changed files with 161 additions and 9 deletions
15
README.md
15
README.md
|
|
@ -1,10 +1,23 @@
|
|||
# Navigation computer of the SS Probably Fine
|
||||
|
||||
Computes flight plans for the *SS Probably Fine*: route, distance,
|
||||
travel time, and the amout of fuel required.
|
||||
travel time, and the amount of fuel required.
|
||||
|
||||
```console
|
||||
$ python3 nav.py mars
|
||||
```
|
||||
|
||||
Requires Python 3.9 or newer; no further dependencies.
|
||||
|
||||
All routes start at Earth. Getting back is your own problem.
|
||||
|
||||
## Contributing
|
||||
|
||||
Use Conventional Commits. Do not push broken code.
|
||||
(Yes, Dr. Honk, this means you.)
|
||||
|
||||
## Maintenance
|
||||
|
||||
All maintenance is recorded in `maintenance.md`.
|
||||
|
||||
To list all known destinations, run `python3 nav.py --list`.
|
||||
|
|
|
|||
7
crew.md
7
crew.md
|
|
@ -3,5 +3,10 @@
|
|||
| Name | Role |
|
||||
|------|------|
|
||||
| Captain Vega | Captain |
|
||||
| Dr. Honk | Ship's doctor |
|
||||
| Dr. Honk | Chief medical officer |
|
||||
| Lt. Byte | Chief engineer |
|
||||
| Cmdr. Nova | Pilot |
|
||||
| Ensign Pixel | Navigator |
|
||||
| Quackers, the debugging duck | Morale officer |
|
||||
| `coffeed` | Beverage officer |
|
||||
| Mission control | Remote support (does not accept pushes) |
|
||||
|
|
|
|||
|
|
@ -1,3 +1,64 @@
|
|||
# Maintenance log
|
||||
|
||||
Newest entries at the bottom.
|
||||
- 2026-09-01: Escape pod batteries charged.
|
||||
- 2026-09-02: Antenna realigned.
|
||||
- 2026-09-02: Fire extinguishers checked.
|
||||
- 2026-09-04: Gyroscopes recalibrated.
|
||||
- 2026-09-04: Escape pod batteries charged.
|
||||
- 2026-09-04: Oxygen scrubbers replaced.
|
||||
- 2026-09-05: Water recycling filters replaced.
|
||||
- 2026-09-05: Antenna realigned.
|
||||
- 2026-09-06: Fuel lines checked for leaks.
|
||||
- 2026-09-07: Solar panels cleaned.
|
||||
- 2026-09-07: Coffee machine descaled.
|
||||
- 2026-09-07: Hull inspection, no leaks.
|
||||
- 2026-09-09: Antenna realigned.
|
||||
- 2026-09-09: Solar panels cleaned.
|
||||
- 2026-09-10: Escape pod batteries charged.
|
||||
- 2026-09-10: Debugging duck accounted for.
|
||||
- 2026-09-11: Comms backup tested.
|
||||
- 2026-09-14: Water recycling filters replaced.
|
||||
- 2026-09-15: Airlock seals checked.
|
||||
- 2026-09-15: Water recycling filters replaced.
|
||||
- 2026-09-16: Coffee machine descaled.
|
||||
- 2026-09-16: Antenna realigned.
|
||||
- 2026-09-17: Cabin pressure sensors tested.
|
||||
- 2026-09-18: Radiation shielding inspected.
|
||||
- 2026-09-18: Debugging duck accounted for.
|
||||
- 2026-09-18: Fire extinguishers checked.
|
||||
- 2026-09-20: Fire extinguishers checked.
|
||||
- 2026-09-20: Oxygen scrubbers replaced.
|
||||
- 2026-09-21: Solar panels cleaned.
|
||||
- 2026-09-21: Gyroscopes recalibrated.
|
||||
- 2026-09-22: Fuel lines checked for leaks.
|
||||
- 2026-09-23: Escape pod batteries charged.
|
||||
- 2026-09-24: Galley fridge defrosted.
|
||||
- 2026-09-27: Escape pod batteries charged.
|
||||
- 2026-09-27: Comms backup tested.
|
||||
- 2026-09-28: Gyroscopes recalibrated.
|
||||
- 2026-09-28: Hull inspection, no leaks.
|
||||
- 2026-09-30: Navigation lights checked.
|
||||
- 2026-10-01: Cabin pressure sensors tested.
|
||||
- 2026-10-02: Escape pod batteries charged.
|
||||
- 2026-10-03: Navigation lights checked.
|
||||
- 2026-10-05: Fuel lines checked for leaks.
|
||||
- 2026-10-05: Fire extinguishers checked.
|
||||
- 2026-10-05: Hull inspection, no leaks.
|
||||
- 2026-10-06: Water recycling filters replaced.
|
||||
- 2026-10-06: Debugging duck accounted for.
|
||||
- 2026-10-07: Oxygen scrubbers replaced.
|
||||
- 2026-10-07: Coffee machine descaled.
|
||||
- 2026-10-08: Cabin pressure sensors tested.
|
||||
- 2026-10-08: Thrusters test-fired.
|
||||
- 2026-10-09: Galley fridge defrosted.
|
||||
- 2026-10-10: Airlock seals checked.
|
||||
- 2026-10-10: Galley fridge defrosted.
|
||||
- 2026-10-11: Thrusters test-fired.
|
||||
- 2026-10-11: Cabin pressure sensors tested.
|
||||
- 2026-10-11: Antenna realigned.
|
||||
- 2026-10-12: Thrusters test-fired.
|
||||
- 2026-10-13: Fuel lines checked for leaks.
|
||||
- 2026-10-14: Fuel lines checked for leaks.
|
||||
- 2026-10-14: Hull inspection, no leaks.
|
||||
- 2026-10-15: Escape pod batteries charged.
|
||||
|
|
|
|||
87
nav.py
87
nav.py
|
|
@ -2,21 +2,52 @@
|
|||
"""Navigation computer of the SS Probably Fine.
|
||||
|
||||
Usage: python3 nav.py DESTINATION
|
||||
python3 nav.py --list
|
||||
python3 nav.py --all
|
||||
"""
|
||||
|
||||
import sys
|
||||
from collections.abc import Iterator
|
||||
|
||||
# Distances between neighboring waypoints, in million km.
|
||||
DISTANCES = {
|
||||
("earth", "moon"): 0.4,
|
||||
("earth", "gateway"): 0.4,
|
||||
("gateway", "mars"): 225.0,
|
||||
("gateway", "venus"): 41.0,
|
||||
("mars", "phobos"): 0.01,
|
||||
("mars", "deimos"): 0.02,
|
||||
("venus", "mercury"): 48.0,
|
||||
("mars", "ceres"): 265.0,
|
||||
("gateway", "milliways"): 42.0,
|
||||
("ceres", "vesta"): 96.0,
|
||||
("ceres", "europa"): 399.0,
|
||||
("europa", "io"): 0.25,
|
||||
("europa", "ganymede"): 0.4,
|
||||
("ganymede", "callisto"): 0.8,
|
||||
("europa", "titan"): 655.0,
|
||||
("titan", "enceladus"): 1.0,
|
||||
("titan", "pluto"): 4387.0,
|
||||
}
|
||||
|
||||
# Every route starts at Earth.
|
||||
ROUTES = {
|
||||
"moon": ["earth", "moon"],
|
||||
"mars": ["earth", "gateway", "mars"],
|
||||
"venus": ["earth", "gateway", "venus"],
|
||||
"phobos": ["earth", "gateway", "mars", "phobos"],
|
||||
"deimos": ["earth", "gateway", "mars", "deimos"],
|
||||
"mercury": ["earth", "gateway", "venus", "mercury"],
|
||||
"ceres": ["earth", "gateway", "mars", "ceres"],
|
||||
"milliways": ["earth", "gateway", "milliways"],
|
||||
"vesta": ["earth", "gateway", "mars", "ceres", "vesta"],
|
||||
"europa": ["earth", "gateway", "mars", "ceres", "europa"],
|
||||
"io": ["earth", "gateway", "mars", "ceres", "europa", "io"],
|
||||
"ganymede": ["earth", "gateway", "mars", "ceres", "europa", "ganymede"],
|
||||
"callisto": ["earth", "gateway", "mars", "ceres", "europa", "ganymede", "callisto"],
|
||||
"titan": ["earth", "gateway", "mars", "ceres", "europa", "titan"],
|
||||
"enceladus": ["earth", "gateway", "mars", "ceres", "europa", "titan", "enceladus"],
|
||||
"pluto": ["earth", "gateway", "mars", "ceres", "europa", "titan", "pluto"],
|
||||
}
|
||||
|
||||
NAMES = {
|
||||
|
|
@ -24,6 +55,20 @@ NAMES = {
|
|||
"moon": "Moon",
|
||||
"gateway": "Lunar Gateway",
|
||||
"mars": "Mars",
|
||||
"venus": "Venus",
|
||||
"phobos": "Phobos",
|
||||
"deimos": "Deimos",
|
||||
"mercury": "Mercury",
|
||||
"ceres": "Ceres",
|
||||
"milliways": "Restaurant at the End of the Universe",
|
||||
"vesta": "Vesta",
|
||||
"europa": "Europa",
|
||||
"io": "Io",
|
||||
"ganymede": "Ganymede",
|
||||
"callisto": "Callisto",
|
||||
"titan": "Titan",
|
||||
"enceladus": "Enceladus",
|
||||
"pluto": "Pluto",
|
||||
}
|
||||
|
||||
CRUISE_SPEED = 0.87 # million km per day
|
||||
|
|
@ -31,17 +76,21 @@ FUEL_PER_MKM = 0.142 # tonnes of fuel per million km
|
|||
LAUNCH_FUEL = 380.0 # tonnes of fuel to escape Earth's gravity
|
||||
|
||||
|
||||
def distance(a, b):
|
||||
def distance(a: str, b: str) -> float:
|
||||
"""Return the distance between two neighboring waypoints."""
|
||||
if (a, b) in DISTANCES:
|
||||
return DISTANCES[(a, b)]
|
||||
return DISTANCES[(b, a)]
|
||||
|
||||
|
||||
def legs(route):
|
||||
return [(route[i], route[i + 1]) for i in range(len(route) - 1)]
|
||||
def legs(route: list[str]) -> Iterator[tuple[str, str]]:
|
||||
"""Yield the legs (pairs of consecutive waypoints) of a route."""
|
||||
for i in range(1, len(route) - 1):
|
||||
yield route[i], route[i + 1]
|
||||
|
||||
|
||||
def plan(destination):
|
||||
def plot_course(destination: str) -> tuple[list[str], float, float, float]:
|
||||
"""Return route, distance, travel time (days) and fuel (t)."""
|
||||
route = ROUTES[destination]
|
||||
total = 0.0
|
||||
fuel = 0.0
|
||||
|
|
@ -54,14 +103,38 @@ def plan(destination):
|
|||
return route, total, total / CRUISE_SPEED, fuel
|
||||
|
||||
|
||||
def main():
|
||||
destination = sys.argv[1]
|
||||
route, total, days, fuel = plan(destination)
|
||||
def asteroid_route(belt: str) -> list[str]:
|
||||
"""Return a route through the asteroid belt (currently: via Ceres)."""
|
||||
return ROUTES["ceres"] + [belt]
|
||||
|
||||
|
||||
def print_plan(destination: str) -> None:
|
||||
"""Print the flight plan for a destination."""
|
||||
route, total, days, fuel = plot_course(destination)
|
||||
print("Route: " + " -> ".join(NAMES[w] for w in route))
|
||||
print(f"Distance: {total:.1f} million km")
|
||||
print(f"Travel time: {round(days)} days")
|
||||
print(f"Fuel required: {round(fuel)} t")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit(__doc__)
|
||||
if sys.argv[1] == "--list":
|
||||
for key in sorted(ROUTES):
|
||||
print(f"{key:12} {NAMES[key]}")
|
||||
return
|
||||
if sys.argv[1] == "--all":
|
||||
for key in sorted(ROUTES):
|
||||
print_plan(key)
|
||||
print()
|
||||
return
|
||||
destination = sys.argv[1].lower()
|
||||
if destination not in ROUTES:
|
||||
known = ", ".join(sorted(ROUTES))
|
||||
sys.exit(f"Unknown destination: {destination} (known: {known})")
|
||||
print_plan(destination)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in a new issue