Download mathly2/comets.py from wzender/mathly: direct link, hf CLI and curl.
- Browser
- Download file 4.6 kB
-
https://huggingface.co/spaces/wzender/mathly/resolve/main/mathly2/comets.py
- Command line
-
hf download hf://spaces/wzender/mathly/mathly2/comets.py
-
curl -L -o comets.py https://huggingface.co/spaces/wzender/mathly/resolve/main/mathly2/comets.py
4.6 kB
| """The twelve comets (PRD CMT-3) and the rule for when one crosses (CMT-1). The server decides both: the browser only draws.""" | |
| import random | |
| from datetime import date | |
| COMETS = [ | |
| {"id": "pi", "sym": "ฯ", "name": "ืคืื", "fact": "ืืืืก ืืื ืืืืงืฃ ืฉื ืืขืื ืืงืืืจ ืฉืื. ืืกืคืจืืช ืฉืื ืืืจื ืื ืงืืื ืื ื ืืืจืืช ืืื ืืืืจืืช ืขื ืขืฆืื."}, | |
| {"id": "fib", "sym": "1,1,2,3,5", "name": "ืคืืืื ืืฆืณื", "fact": "ืื ืืกืคืจ ืืกืืจื ืืื ืกืืื ืฉื ื ืืงืืืืื. ืืกืืจื ืืืคืืขื ืืกืคืืจืืืช ืฉื ืืจืขืื ื ืืื ืืื ืืืืฆืืจืืืืื."}, | |
| {"id": "phi", "sym": "ฯ", "name": "ืืืก ืืืื", "fact": "ืืขืจื 1.618. ืืืืงืื ืงืืข ืื ืฉืืืืก ืืื ืืฉืื ืืืืง ืืืืื ืฉืืื ืืืืก ืืื ืืืืื ืืงืื. ืืืคืืข ืืคืจืืื, ืืฆืืคืื ืืืืื ืืช."}, | |
| {"id": "inf", "sym": "โ", "name": "ืืื ืกืืฃ", "fact": "ืืฉ ืืื ืกืืฃ ืืกืคืจืื ืฉืืืื, ืืืฉ ืื ืืื ืกืืฃ ืืกืคืจืื ืืื 0 ืึพ1. ืืชืืจืจ ืฉืืืื ืกืืฃ ืืฉื ื ืืืื ืืืชืจ."}, | |
| {"id": "e", "sym": "e", "name": "ืืืกืคืจ e", "fact": "ืืขืจื 2.718. ืืืคืืข ืืื ืืงืื ืฉืื ืืฉืื ืืื ืืงืฆื ืฉืชืืื ืืืืื ืฉืื: ืจืืืืช, ืืืืืืกืืืช, ืืืืืงืื."}, | |
| {"id": "r2", "sym": "โ2", "name": "ืฉืืจืฉ 2", "fact": "ืืืืจื ืฉื ืืืืกืื ืืจืืืืข ืฉืฆืืขื 1. ืืืจ ืืืืื ืื ืืงืืืื ืื ืืืืืื ืฉืื ืืคืฉืจ ืืืชืื ืืืชื ืืฉืืจ."}, | |
| {"id": "zero", "sym": "0", "name": "ืืคืก", "fact": "ืืืฉื ืืืคื ืฉื ืื ืื ืืื ืกืืื ืืืคืก. ืืื ืืืืข ืืืืื, ืืืืืืชื ืืคืฉืจ ืืืชืื ืื ืืกืคืจ ืืขืฉืจ ืกืคืจืืช ืืืื."}, | |
| {"id": "pyth", "sym": "aยฒ+bยฒ=cยฒ", "name": "ืคืืชืืืจืก", "fact": "ืืืฉืืืฉ ืืฉืจ ืืืืืช, ืกืืื ืจืืืืขื ืื ืืฆืืื ืฉืืื ืืจืืืืข ืืืชืจ. ืืืืข ืืืืชืจ ืึพ370 ืืืืืืช ืฉืื ืืช."}, | |
| {"id": "prime", "sym": "2,3,5,7", "name": "ืืกืคืจืื ืจืืฉืื ืืื", "fact": "ืืกืคืจืื ืฉืืชืืืงืื ืจืง ืึพ1 ืืืขืฆืื. ืืฉ ืืื ืกืืฃ ืืืื, ืืขืืืื ืื ืืื ืืืฆืคื ื ืฉื ืืืื ืืจื ื."}, | |
| {"id": "pascal", "sym": "1 2 1", "name": "ืืฉืืืฉ ืคืกืงื", "fact": "ืื ืืกืคืจ ืืื ืกืืื ืฉื ื ืืืกืคืจืื ืฉืืขืืื. ืืฉืืจืืช ืฉืื ื ืืชื ืืช ืืช ืืืงืืืื ืฉื (a + b) ืืื ืืืงื."}, | |
| {"id": "euler", "sym": "VโE+F=2", "name": "ื ืืกืืช ืืืืืจ", "fact": "ืืื ืืืฃ ืืฉืืืื, ืงืืืงืืืื ืคืืืช ืืงืฆืืขืืช ืืขืื ืคืืืช ืฉืืื ืชืืื 2. ื ืกื ืขื ืงืืืืื: 8 โ 12 + 6."}, | |
| {"id": "mobius", "sym": "โ", "name": "ืืืขืช ืืืืืก", "fact": "ืจืฆืืขืช ื ืืืจ ืขื ืืฆื ืกืืืื: ืืฉ ืื ืจืง ืฆื ืืื ืืฉืคื ืืืช. ื ืืื ืฉืืืืืช ืขืืื ืชืขืืืจ ืืฉื ื ืืดืฆืืืืืด."}, | |
| ] | |
| IDS = [c["id"] for c in COMETS] | |
| CHANCE = 0.12 # a right answer's chance of a comet, once the student has been offered their first | |
| def get(comet_id: str) -> dict | None: | |
| return next((c for c in COMETS if c["id"] == comet_id), None) | |
| def due(state: dict | None, caught: set[str], today: date, goal_just_reached: bool, roll: float | None = None) -> bool: | |
| """Is a comet due after this right answer? At most one a day; none once all are caught; the first one only on the answer that | |
| reaches the daily goal; after any comet was offered, a small chance on each right answer. `roll` (0..1) is injectable for tests.""" | |
| if len(caught) >= len(COMETS): | |
| return False | |
| last = (state or {}).get("last_comet_day") | |
| if last == today: | |
| return False | |
| if last is None: | |
| return goal_just_reached | |
| return (random.random() if roll is None else roll) < CHANCE | |
| def surely_not(state: dict | None, today: date, goal_just_reached: bool, roll: float | None) -> bool: | |
| """True when no comet can be due whatever the student has caught, so the caught list need not be read (the usual case).""" | |
| last = (state or {}).get("last_comet_day") | |
| if last == today: | |
| return True | |
| if last is None: | |
| return not goal_just_reached | |
| return (random.random() if roll is None else roll) >= CHANCE | |
| def pick(caught: set[str], roll: float | None = None) -> dict | None: | |
| """A comet the student does not have yet, at random.""" | |
| left = [c for c in COMETS if c["id"] not in caught] | |
| if not left: | |
| return None | |
| return left[int((random.random() if roll is None else roll) * len(left)) % len(left)] | |