watt-the-hack 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- watt_the_hack-0.2.0/LICENSE +21 -0
- watt_the_hack-0.2.0/PKG-INFO +145 -0
- watt_the_hack-0.2.0/README.md +125 -0
- watt_the_hack-0.2.0/pyproject.toml +42 -0
- watt_the_hack-0.2.0/setup.cfg +4 -0
- watt_the_hack-0.2.0/tests/test_engine.py +1591 -0
- watt_the_hack-0.2.0/tests/test_forecast.py +251 -0
- watt_the_hack-0.2.0/tests/test_metrics.py +190 -0
- watt_the_hack-0.2.0/tests/test_metrics_contract.py +175 -0
- watt_the_hack-0.2.0/tests/test_runner.py +67 -0
- watt_the_hack-0.2.0/watt_the_hack/__init__.py +1 -0
- watt_the_hack-0.2.0/watt_the_hack/api/__init__.py +1 -0
- watt_the_hack-0.2.0/watt_the_hack/api/sandbox.py +147 -0
- watt_the_hack-0.2.0/watt_the_hack/api/server.py +482 -0
- watt_the_hack-0.2.0/watt_the_hack/constants.py +11 -0
- watt_the_hack-0.2.0/watt_the_hack/controllers/__init__.py +11 -0
- watt_the_hack-0.2.0/watt_the_hack/controllers/parametric.py +40 -0
- watt_the_hack-0.2.0/watt_the_hack/controllers/rule_based.py +82 -0
- watt_the_hack-0.2.0/watt_the_hack/data_loaders/__init__.py +0 -0
- watt_the_hack-0.2.0/watt_the_hack/data_loaders/aemo.py +44 -0
- watt_the_hack-0.2.0/watt_the_hack/data_loaders/scenarios.py +472 -0
- watt_the_hack-0.2.0/watt_the_hack/engine/__init__.py +8 -0
- watt_the_hack-0.2.0/watt_the_hack/engine/base_engine.py +18 -0
- watt_the_hack-0.2.0/watt_the_hack/engine/engine.py +1584 -0
- watt_the_hack-0.2.0/watt_the_hack/engine/legacy engines/simple_engine.py +117 -0
- watt_the_hack-0.2.0/watt_the_hack/metrics/__init__.py +3 -0
- watt_the_hack-0.2.0/watt_the_hack/metrics/metrics.py +122 -0
- watt_the_hack-0.2.0/watt_the_hack/playtest.py +1099 -0
- watt_the_hack-0.2.0/watt_the_hack/scenarios/synthetic/agentic_demo.json +381 -0
- watt_the_hack-0.2.0/watt_the_hack/scenarios/synthetic/duck_curve.json +1023 -0
- watt_the_hack-0.2.0/watt_the_hack/simulation/__init__.py +1 -0
- watt_the_hack-0.2.0/watt_the_hack/simulation/boot.py +96 -0
- watt_the_hack-0.2.0/watt_the_hack/simulation/runner.py +265 -0
- watt_the_hack-0.2.0/watt_the_hack/simulation/strategy.py +190 -0
- watt_the_hack-0.2.0/watt_the_hack.egg-info/PKG-INFO +145 -0
- watt_the_hack-0.2.0/watt_the_hack.egg-info/SOURCES.txt +37 -0
- watt_the_hack-0.2.0/watt_the_hack.egg-info/dependency_links.txt +1 -0
- watt_the_hack-0.2.0/watt_the_hack.egg-info/requires.txt +14 -0
- watt_the_hack-0.2.0/watt_the_hack.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepNeuron / Watt The Hack contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: watt-the-hack
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Watt The Hack 24-hour energy grid simulation hackathon engine
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: pydantic>=2.0
|
|
9
|
+
Provides-Extra: api
|
|
10
|
+
Requires-Dist: fastapi; extra == "api"
|
|
11
|
+
Requires-Dist: uvicorn; extra == "api"
|
|
12
|
+
Requires-Dist: python-dotenv; extra == "api"
|
|
13
|
+
Provides-Extra: playtest
|
|
14
|
+
Requires-Dist: matplotlib>=3.5; extra == "playtest"
|
|
15
|
+
Requires-Dist: openai>=1.0; extra == "playtest"
|
|
16
|
+
Provides-Extra: test
|
|
17
|
+
Requires-Dist: pytest; extra == "test"
|
|
18
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# Watt The Hack Engine
|
|
22
|
+
|
|
23
|
+
The simulation engine for the **Watt The Hack** energy grid hackathon (DeepNeuron).
|
|
24
|
+
|
|
25
|
+
This is the public engine package — controllers, scenarios authoring, and the judging server live in private repos. Participants use this package to develop and test their controllers locally before submitting to the hackathon evaluation server.
|
|
26
|
+
|
|
27
|
+
## How it works
|
|
28
|
+
|
|
29
|
+
You write a **controller**. The engine runs a grid as a simulation in 15-minute steps (`duck_curve` = 96 steps over 24 h). At each step it hands your controller a snapshot of the grid and asks for an action:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
every 15 minutes:
|
|
33
|
+
|
|
34
|
+
state ──► your controller ──► action ──► engine simulates ──► cost
|
|
35
|
+
(demand, solar, step(state) (battery, physics + market
|
|
36
|
+
price, soc, …) diesel, …)
|
|
37
|
+
|
|
38
|
+
score = sum of cost over all 96 steps (lower wins)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
You see only the **current** step (plus a forecast in later scenarios) and return how much to charge/discharge the battery, run diesel, or curtail solar. The engine simulates that 15 minutes — clipping to physical limits, then applying the market — and charges you a cost. Your score is the total over every step.
|
|
42
|
+
|
|
43
|
+
**One worked step — the duck curve at noon.** Solar is 80 MW, demand 30 MW: a 50 MW surplus. Do nothing and that surplus floods the grid past its 50 MW export cap → an **overvoltage penalty**. Instead, charge the battery (`battery_flow_mw = -20`): you bank cheap midday energy and release it into the 6 pm peak, when grid power is dear. *Store the midday glut, spend it at the evening peak* — that trade-off is the duck curve, and it's exactly what the starter below does. Every run also prints how your cost compares to a do-nothing and a best-known baseline, so you always know whether a change helped.
|
|
44
|
+
|
|
45
|
+
## Quick start
|
|
46
|
+
|
|
47
|
+
Three steps: install, write `strategy.py`, run `python strategy.py`.
|
|
48
|
+
|
|
49
|
+
> **⚠️ Make a virtual environment first.** Installing into your system Python (or conda base) can clash with other tools; a venv isolates it and you can delete it with `rm -rf .venv` if anything goes wrong. **Colab users:** skip the venv — run the `pip install` line in a cell, or just [open the starter notebook](https://colab.research.google.com/github/AaronEliasZachariah/Watt-The-Hack-Engine-Public/blob/main/notebooks/training_starter.ipynb).
|
|
50
|
+
|
|
51
|
+
**1. Create a venv and install the engine.** The `[playtest]` extra adds plots and the agentic-track OpenAI client.
|
|
52
|
+
|
|
53
|
+
macOS / Linux:
|
|
54
|
+
```bash
|
|
55
|
+
python3 -m venv .venv
|
|
56
|
+
source .venv/bin/activate
|
|
57
|
+
python3 -m pip install "watt_the_hack[playtest] @ git+https://github.com/AaronEliasZachariah/Watt-The-Hack-Engine-Public.git@main"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Windows (PowerShell):
|
|
61
|
+
```powershell
|
|
62
|
+
python -m venv .venv
|
|
63
|
+
.venv\Scripts\Activate.ps1
|
|
64
|
+
python -m pip install "watt_the_hack[playtest] @ git+https://github.com/AaronEliasZachariah/Watt-The-Hack-Engine-Public.git@main"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Your prompt should now start with `(.venv)`. (`python -m pip` — not bare `pip` — guarantees you install into the active venv on every OS.)
|
|
68
|
+
|
|
69
|
+
**2. Create `strategy.py`.** Your controller *and* its local test live in one file:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# strategy.py — edit the controller, then run: python strategy.py
|
|
73
|
+
def controller(state):
|
|
74
|
+
# Duck curve 101: bank the midday solar surplus, spend it at the evening peak.
|
|
75
|
+
demand, solar, soc = state["demand"], state["solar"], state["soc"]
|
|
76
|
+
surplus = solar - demand # +ve = excess solar right now
|
|
77
|
+
flow = 0.0
|
|
78
|
+
if surplus > 5 and soc < 0.9: # midday: store the excess
|
|
79
|
+
flow = -min(20.0, surplus) # negative = charge
|
|
80
|
+
elif surplus < 0 and soc > 0.2: # evening: cover the shortfall
|
|
81
|
+
flow = min(20.0, -surplus) # positive = discharge
|
|
82
|
+
net = demand - solar - flow # what's left for the grid
|
|
83
|
+
curtail = max(0.0, -net - 50.0) # dump unstorable export
|
|
84
|
+
return {"battery_flow_mw": flow, "curtail_solar": curtail}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# --- Local playtest. Runs on `python strategy.py`; the judge ignores this block. ---
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
from watt_the_hack.playtest import run_playtest
|
|
90
|
+
result = run_playtest(__file__, "duck_curve", plots=True, open_report=True)
|
|
91
|
+
print(f"\nRaw cost (lower wins): ${result['metrics']['final_score']:,.2f}")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**3. Run it:**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
python strategy.py
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
It prints your cost breakdown and opens an HTML report (plots, worst timesteps, diagnostics). In an IDE (VS Code, PyCharm) this is just the ▶ Run button — no command line at all. Edit the controller, re-run, repeat.
|
|
101
|
+
|
|
102
|
+
`result["metrics"]["final_score"]` is your **raw cost in dollars — lower wins.** The 0–150 leaderboard points are computed server-side on the hidden judging variants; locally you minimise the raw cost.
|
|
103
|
+
|
|
104
|
+
### Scenarios you can run offline
|
|
105
|
+
|
|
106
|
+
The wheel bundles two: `duck_curve` (rule-based track) and `agentic_demo` (LLM / `plan`-`replan` track). List them any time:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
python -m watt_the_hack.playtest --list-scenarios
|
|
110
|
+
```
|
|
111
|
+
```text
|
|
112
|
+
duck_curve synthetic The Duck Curve
|
|
113
|
+
agentic_demo synthetic Agentic Demo — Your First LLM Controller
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Switch scenario by changing the id in `run_playtest(__file__, "duck_curve", ...)`. The scored judging variants stay on the server — a green local run translates directly to a submission.
|
|
117
|
+
|
|
118
|
+
### Updating as new scenarios drop
|
|
119
|
+
|
|
120
|
+
Scenarios are released incrementally. Update inside the same venv:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python -m pip install --upgrade --force-reinstall "watt_the_hack[playtest] @ git+https://github.com/AaronEliasZachariah/Watt-The-Hack-Engine-Public.git@main"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Power user: the CLI
|
|
127
|
+
|
|
128
|
+
`run_playtest` is the easy path. The CLI runs the same harness without editing the file, and adds a **sweep** — compare several controllers on one scenario, ranked side by side:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
python -m watt_the_hack.playtest strategy.py --scenario duck_curve --open-report
|
|
132
|
+
python -m watt_the_hack.playtest a.py b.py c.py --scenario duck_curve
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## What's in here
|
|
136
|
+
|
|
137
|
+
- `watt_the_hack/engine/` — physics + market step
|
|
138
|
+
- `watt_the_hack/metrics/` — scoring metrics
|
|
139
|
+
- `watt_the_hack/simulation/` — runner glue
|
|
140
|
+
- `watt_the_hack/controllers/` — reference controllers (rule-based, parametric)
|
|
141
|
+
- `watt_the_hack/data_loaders/` — scenario loading utilities
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Watt The Hack Engine
|
|
2
|
+
|
|
3
|
+
The simulation engine for the **Watt The Hack** energy grid hackathon (DeepNeuron).
|
|
4
|
+
|
|
5
|
+
This is the public engine package — controllers, scenarios authoring, and the judging server live in private repos. Participants use this package to develop and test their controllers locally before submitting to the hackathon evaluation server.
|
|
6
|
+
|
|
7
|
+
## How it works
|
|
8
|
+
|
|
9
|
+
You write a **controller**. The engine runs a grid as a simulation in 15-minute steps (`duck_curve` = 96 steps over 24 h). At each step it hands your controller a snapshot of the grid and asks for an action:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
every 15 minutes:
|
|
13
|
+
|
|
14
|
+
state ──► your controller ──► action ──► engine simulates ──► cost
|
|
15
|
+
(demand, solar, step(state) (battery, physics + market
|
|
16
|
+
price, soc, …) diesel, …)
|
|
17
|
+
|
|
18
|
+
score = sum of cost over all 96 steps (lower wins)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
You see only the **current** step (plus a forecast in later scenarios) and return how much to charge/discharge the battery, run diesel, or curtail solar. The engine simulates that 15 minutes — clipping to physical limits, then applying the market — and charges you a cost. Your score is the total over every step.
|
|
22
|
+
|
|
23
|
+
**One worked step — the duck curve at noon.** Solar is 80 MW, demand 30 MW: a 50 MW surplus. Do nothing and that surplus floods the grid past its 50 MW export cap → an **overvoltage penalty**. Instead, charge the battery (`battery_flow_mw = -20`): you bank cheap midday energy and release it into the 6 pm peak, when grid power is dear. *Store the midday glut, spend it at the evening peak* — that trade-off is the duck curve, and it's exactly what the starter below does. Every run also prints how your cost compares to a do-nothing and a best-known baseline, so you always know whether a change helped.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
Three steps: install, write `strategy.py`, run `python strategy.py`.
|
|
28
|
+
|
|
29
|
+
> **⚠️ Make a virtual environment first.** Installing into your system Python (or conda base) can clash with other tools; a venv isolates it and you can delete it with `rm -rf .venv` if anything goes wrong. **Colab users:** skip the venv — run the `pip install` line in a cell, or just [open the starter notebook](https://colab.research.google.com/github/AaronEliasZachariah/Watt-The-Hack-Engine-Public/blob/main/notebooks/training_starter.ipynb).
|
|
30
|
+
|
|
31
|
+
**1. Create a venv and install the engine.** The `[playtest]` extra adds plots and the agentic-track OpenAI client.
|
|
32
|
+
|
|
33
|
+
macOS / Linux:
|
|
34
|
+
```bash
|
|
35
|
+
python3 -m venv .venv
|
|
36
|
+
source .venv/bin/activate
|
|
37
|
+
python3 -m pip install "watt_the_hack[playtest] @ git+https://github.com/AaronEliasZachariah/Watt-The-Hack-Engine-Public.git@main"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Windows (PowerShell):
|
|
41
|
+
```powershell
|
|
42
|
+
python -m venv .venv
|
|
43
|
+
.venv\Scripts\Activate.ps1
|
|
44
|
+
python -m pip install "watt_the_hack[playtest] @ git+https://github.com/AaronEliasZachariah/Watt-The-Hack-Engine-Public.git@main"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Your prompt should now start with `(.venv)`. (`python -m pip` — not bare `pip` — guarantees you install into the active venv on every OS.)
|
|
48
|
+
|
|
49
|
+
**2. Create `strategy.py`.** Your controller *and* its local test live in one file:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
# strategy.py — edit the controller, then run: python strategy.py
|
|
53
|
+
def controller(state):
|
|
54
|
+
# Duck curve 101: bank the midday solar surplus, spend it at the evening peak.
|
|
55
|
+
demand, solar, soc = state["demand"], state["solar"], state["soc"]
|
|
56
|
+
surplus = solar - demand # +ve = excess solar right now
|
|
57
|
+
flow = 0.0
|
|
58
|
+
if surplus > 5 and soc < 0.9: # midday: store the excess
|
|
59
|
+
flow = -min(20.0, surplus) # negative = charge
|
|
60
|
+
elif surplus < 0 and soc > 0.2: # evening: cover the shortfall
|
|
61
|
+
flow = min(20.0, -surplus) # positive = discharge
|
|
62
|
+
net = demand - solar - flow # what's left for the grid
|
|
63
|
+
curtail = max(0.0, -net - 50.0) # dump unstorable export
|
|
64
|
+
return {"battery_flow_mw": flow, "curtail_solar": curtail}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# --- Local playtest. Runs on `python strategy.py`; the judge ignores this block. ---
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
from watt_the_hack.playtest import run_playtest
|
|
70
|
+
result = run_playtest(__file__, "duck_curve", plots=True, open_report=True)
|
|
71
|
+
print(f"\nRaw cost (lower wins): ${result['metrics']['final_score']:,.2f}")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**3. Run it:**
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
python strategy.py
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
It prints your cost breakdown and opens an HTML report (plots, worst timesteps, diagnostics). In an IDE (VS Code, PyCharm) this is just the ▶ Run button — no command line at all. Edit the controller, re-run, repeat.
|
|
81
|
+
|
|
82
|
+
`result["metrics"]["final_score"]` is your **raw cost in dollars — lower wins.** The 0–150 leaderboard points are computed server-side on the hidden judging variants; locally you minimise the raw cost.
|
|
83
|
+
|
|
84
|
+
### Scenarios you can run offline
|
|
85
|
+
|
|
86
|
+
The wheel bundles two: `duck_curve` (rule-based track) and `agentic_demo` (LLM / `plan`-`replan` track). List them any time:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
python -m watt_the_hack.playtest --list-scenarios
|
|
90
|
+
```
|
|
91
|
+
```text
|
|
92
|
+
duck_curve synthetic The Duck Curve
|
|
93
|
+
agentic_demo synthetic Agentic Demo — Your First LLM Controller
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Switch scenario by changing the id in `run_playtest(__file__, "duck_curve", ...)`. The scored judging variants stay on the server — a green local run translates directly to a submission.
|
|
97
|
+
|
|
98
|
+
### Updating as new scenarios drop
|
|
99
|
+
|
|
100
|
+
Scenarios are released incrementally. Update inside the same venv:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
python -m pip install --upgrade --force-reinstall "watt_the_hack[playtest] @ git+https://github.com/AaronEliasZachariah/Watt-The-Hack-Engine-Public.git@main"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Power user: the CLI
|
|
107
|
+
|
|
108
|
+
`run_playtest` is the easy path. The CLI runs the same harness without editing the file, and adds a **sweep** — compare several controllers on one scenario, ranked side by side:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
python -m watt_the_hack.playtest strategy.py --scenario duck_curve --open-report
|
|
112
|
+
python -m watt_the_hack.playtest a.py b.py c.py --scenario duck_curve
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## What's in here
|
|
116
|
+
|
|
117
|
+
- `watt_the_hack/engine/` — physics + market step
|
|
118
|
+
- `watt_the_hack/metrics/` — scoring metrics
|
|
119
|
+
- `watt_the_hack/simulation/` — runner glue
|
|
120
|
+
- `watt_the_hack/controllers/` — reference controllers (rule-based, parametric)
|
|
121
|
+
- `watt_the_hack/data_loaders/` — scenario loading utilities
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "watt-the-hack"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Watt The Hack 24-hour energy grid simulation hackathon engine"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"pydantic>=2.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
api = [
|
|
17
|
+
"fastapi",
|
|
18
|
+
"uvicorn",
|
|
19
|
+
"python-dotenv",
|
|
20
|
+
]
|
|
21
|
+
playtest = [
|
|
22
|
+
"matplotlib>=3.5",
|
|
23
|
+
"openai>=1.0",
|
|
24
|
+
]
|
|
25
|
+
test = [
|
|
26
|
+
"pytest",
|
|
27
|
+
"pytest-cov",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[tool.setuptools.packages.find]
|
|
31
|
+
include = ["watt_the_hack*"]
|
|
32
|
+
|
|
33
|
+
# Ship scenario JSONs that live in-package. The public mirror keeps released
|
|
34
|
+
# scenarios under watt_the_hack/scenarios/ for pip distribution. In this source
|
|
35
|
+
# repo scenarios live top-level, so this glob matches nothing here — harmless.
|
|
36
|
+
[tool.setuptools.package-data]
|
|
37
|
+
watt_the_hack = ["scenarios/*/*.json"]
|
|
38
|
+
|
|
39
|
+
[tool.pytest.ini_options]
|
|
40
|
+
# Only collect the real test suite. Keeps bare `pytest` from scanning stray
|
|
41
|
+
# scratch dirs (e.g. codex-pytest-tmp) that can trip collection on Windows.
|
|
42
|
+
testpaths = ["tests"]
|