umalite 0.1.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.
Files changed (89) hide show
  1. umalite-0.1.0/LICENSE +21 -0
  2. umalite-0.1.0/PKG-INFO +374 -0
  3. umalite-0.1.0/README.md +347 -0
  4. umalite-0.1.0/pyproject.toml +114 -0
  5. umalite-0.1.0/setup.cfg +4 -0
  6. umalite-0.1.0/tests/test_contracts.py +330 -0
  7. umalite-0.1.0/tests/test_planning_api.py +276 -0
  8. umalite-0.1.0/tests/test_trackblazer_basic.py +771 -0
  9. umalite-0.1.0/tests/test_unity_basic.py +154 -0
  10. umalite-0.1.0/tests/test_ura_basic.py +229 -0
  11. umalite-0.1.0/umalite/__init__.py +62 -0
  12. umalite-0.1.0/umalite/actions.py +137 -0
  13. umalite-0.1.0/umalite/api/__init__.py +46 -0
  14. umalite-0.1.0/umalite/client.py +23 -0
  15. umalite-0.1.0/umalite/config/__init__.py +20 -0
  16. umalite-0.1.0/umalite/config/career_profile.py +83 -0
  17. umalite-0.1.0/umalite/config/evaluation_config.py +38 -0
  18. umalite-0.1.0/umalite/config/missing_data_mode.py +6 -0
  19. umalite-0.1.0/umalite/config/utility_config.py +85 -0
  20. umalite-0.1.0/umalite/contracts/__init__.py +3 -0
  21. umalite-0.1.0/umalite/contracts/planner.py +23 -0
  22. umalite-0.1.0/umalite/contracts/scenario.py +33 -0
  23. umalite-0.1.0/umalite/engine/__init__.py +3 -0
  24. umalite-0.1.0/umalite/engine/evaluation_engine.py +77 -0
  25. umalite-0.1.0/umalite/engine/intent_resolution.py +50 -0
  26. umalite-0.1.0/umalite/engine/planning_engine.py +72 -0
  27. umalite-0.1.0/umalite/evaluation_core.py +244 -0
  28. umalite-0.1.0/umalite/evaluator.py +58 -0
  29. umalite-0.1.0/umalite/math/__init__.py +21 -0
  30. umalite-0.1.0/umalite/math/core.py +137 -0
  31. umalite-0.1.0/umalite/models/__init__.py +50 -0
  32. umalite-0.1.0/umalite/models/action_bid.py +32 -0
  33. umalite-0.1.0/umalite/models/action_option.py +18 -0
  34. umalite-0.1.0/umalite/models/action_payloads.py +166 -0
  35. umalite-0.1.0/umalite/models/checkpoint.py +27 -0
  36. umalite-0.1.0/umalite/models/enums.py +119 -0
  37. umalite-0.1.0/umalite/models/evaluation_result.py +26 -0
  38. umalite-0.1.0/umalite/models/preparation_step.py +15 -0
  39. umalite-0.1.0/umalite/models/reward_bundle.py +28 -0
  40. umalite-0.1.0/umalite/models/run_context.py +78 -0
  41. umalite-0.1.0/umalite/models/scenario_terms.py +21 -0
  42. umalite-0.1.0/umalite/models/turn_plan.py +35 -0
  43. umalite-0.1.0/umalite/models/turn_snapshot.py +163 -0
  44. umalite-0.1.0/umalite/projection_defaults.py +216 -0
  45. umalite-0.1.0/umalite/registry.py +29 -0
  46. umalite-0.1.0/umalite/scenarios/__init__.py +1 -0
  47. umalite-0.1.0/umalite/scenarios/trackblazer/__init__.py +44 -0
  48. umalite-0.1.0/umalite/scenarios/trackblazer/actions.py +144 -0
  49. umalite-0.1.0/umalite/scenarios/trackblazer/client.py +272 -0
  50. umalite-0.1.0/umalite/scenarios/trackblazer/config.py +210 -0
  51. umalite-0.1.0/umalite/scenarios/trackblazer/enums.py +89 -0
  52. umalite-0.1.0/umalite/scenarios/trackblazer/planning/__init__.py +17 -0
  53. umalite-0.1.0/umalite/scenarios/trackblazer/planning/candidates.py +833 -0
  54. umalite-0.1.0/umalite/scenarios/trackblazer/plans.py +138 -0
  55. umalite-0.1.0/umalite/scenarios/trackblazer/plugin.py +303 -0
  56. umalite-0.1.0/umalite/scenarios/trackblazer/projection/__init__.py +13 -0
  57. umalite-0.1.0/umalite/scenarios/trackblazer/projection/prepared_state.py +124 -0
  58. umalite-0.1.0/umalite/scenarios/trackblazer/projection/race.py +345 -0
  59. umalite-0.1.0/umalite/scenarios/trackblazer/projection/recovery.py +151 -0
  60. umalite-0.1.0/umalite/scenarios/trackblazer/projection/training.py +105 -0
  61. umalite-0.1.0/umalite/scenarios/trackblazer/scoring/__init__.py +13 -0
  62. umalite-0.1.0/umalite/scenarios/trackblazer/scoring/common.py +42 -0
  63. umalite-0.1.0/umalite/scenarios/trackblazer/scoring/fatigue.py +110 -0
  64. umalite-0.1.0/umalite/scenarios/trackblazer/scoring/race.py +383 -0
  65. umalite-0.1.0/umalite/scenarios/trackblazer/scoring/runtime.py +193 -0
  66. umalite-0.1.0/umalite/scenarios/trackblazer/scoring/training.py +143 -0
  67. umalite-0.1.0/umalite/scenarios/trackblazer/state.py +365 -0
  68. umalite-0.1.0/umalite/scenarios/trackblazer/support/__init__.py +1 -0
  69. umalite-0.1.0/umalite/scenarios/trackblazer/support/item_catalog.py +380 -0
  70. umalite-0.1.0/umalite/scenarios/trackblazer/support/pressures.py +270 -0
  71. umalite-0.1.0/umalite/scenarios/trackblazer/support/trace.py +28 -0
  72. umalite-0.1.0/umalite/scenarios/unity/__init__.py +10 -0
  73. umalite-0.1.0/umalite/scenarios/unity/client.py +301 -0
  74. umalite-0.1.0/umalite/scenarios/unity/config.py +44 -0
  75. umalite-0.1.0/umalite/scenarios/unity/evaluation.py +178 -0
  76. umalite-0.1.0/umalite/scenarios/unity/models.py +27 -0
  77. umalite-0.1.0/umalite/scenarios/unity/plugin.py +128 -0
  78. umalite-0.1.0/umalite/scenarios/unity/reward_projection.py +118 -0
  79. umalite-0.1.0/umalite/scenarios/ura/__init__.py +4 -0
  80. umalite-0.1.0/umalite/scenarios/ura/client.py +249 -0
  81. umalite-0.1.0/umalite/scenarios/ura/config.py +18 -0
  82. umalite-0.1.0/umalite/scenarios/ura/evaluation.py +47 -0
  83. umalite-0.1.0/umalite/scenarios/ura/plugin.py +129 -0
  84. umalite-0.1.0/umalite/scenarios/ura/reward_projection.py +96 -0
  85. umalite-0.1.0/umalite.egg-info/PKG-INFO +374 -0
  86. umalite-0.1.0/umalite.egg-info/SOURCES.txt +87 -0
  87. umalite-0.1.0/umalite.egg-info/dependency_links.txt +1 -0
  88. umalite-0.1.0/umalite.egg-info/requires.txt +6 -0
  89. umalite-0.1.0/umalite.egg-info/top_level.txt +1 -0
umalite-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 UmaLite 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.
umalite-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,374 @@
1
+ Metadata-Version: 2.4
2
+ Name: umalite
3
+ Version: 0.1.0
4
+ Summary: A minimal Python library for Uma Musume turn evaluation
5
+ Author: UmaLite Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ReaVNaiL/UmaLite
8
+ Project-URL: Repository, https://github.com/ReaVNaiL/UmaLite
9
+ Project-URL: Issues, https://github.com/ReaVNaiL/UmaLite/issues
10
+ Keywords: umamusume,uma-musume,simulation,evaluation,python
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7.0; extra == "dev"
23
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
24
+ Requires-Dist: mypy>=1.0; extra == "dev"
25
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # UmaLite
29
+
30
+ <img width="1701" height="124" alt="image" src="https://github.com/user-attachments/assets/9089e8f3-e6dc-45f2-840b-672ad043c0ba" />
31
+
32
+ UmaLite is a small Python library for scoring **Uma Musume turn actions**.
33
+
34
+ You give it a snapshot of the current state, a run context, and a list of candidate actions.
35
+ It returns ranked results with a score breakdown for each action.
36
+
37
+ The library does not read the game or run automation.
38
+ It scores actions from what the caller knows right now.
39
+
40
+ The goal is to keep evaluation logic isolated and reusable so other tools can use the same scoring engine.
41
+
42
+ UmaLite is **snapshot-first**.
43
+ The more visible state the caller supplies, the more accurate scenario-specific scoring becomes.
44
+ Missing optional data should reduce precision, not be silently invented.
45
+
46
+ ---
47
+
48
+ ## Quick start
49
+
50
+ Most callers now use a scenario client.
51
+
52
+ The preferred entrypoint is:
53
+
54
+ ```python
55
+ from umalite import UmaLiteClient
56
+
57
+ umalite = UmaLiteClient()
58
+ ura_client = umalite.ura
59
+ unity_client = umalite.unity
60
+ trackblazer_client = umalite.trackblazer
61
+ ```
62
+
63
+ Each scenario client exposes:
64
+
65
+ - `.snapshots`
66
+ - `.contexts`
67
+ - `.profiles`
68
+ - `.actions`
69
+
70
+ For URA and Unity, the normal path is `evaluate_turn(...)`.
71
+ For Trackblazer, the normal path is `plan_turn(...)`.
72
+
73
+ ```python
74
+ from umalite import CheckpointContext, CheckpointKind, MoodLevel, RaceGrade, StatType, UmaLiteClient
75
+
76
+ ura_client = UmaLiteClient().ura
77
+
78
+ snapshot = ura_client.snapshots.minimal(
79
+ stats={
80
+ StatType.SPEED: 420,
81
+ StatType.STAMINA: 360,
82
+ StatType.POWER: 340,
83
+ StatType.GUTS: 250,
84
+ StatType.WIT: 390,
85
+ },
86
+ energy=58,
87
+ mood=MoodLevel.NORMAL,
88
+ fans=42000,
89
+ )
90
+
91
+ context = ura_client.contexts.basic(
92
+ checkpoint=CheckpointContext(
93
+ kind=CheckpointKind.GOAL_RACE,
94
+ turns_remaining=8,
95
+ ),
96
+ )
97
+
98
+ career_profile = ura_client.profiles.basic(
99
+ target_stats={
100
+ StatType.SPEED: 1200,
101
+ StatType.STAMINA: 800,
102
+ StatType.POWER: 1000,
103
+ StatType.GUTS: 400,
104
+ StatType.WIT: 1100,
105
+ },
106
+ minimum_training_mood=MoodLevel.GOOD,
107
+ )
108
+
109
+ actions = [
110
+ ura_client.actions.train(
111
+ "speed_training",
112
+ training_type=StatType.SPEED,
113
+ stat_gains={StatType.SPEED: 18, StatType.POWER: 9},
114
+ sp_gain=5,
115
+ fail_rate=0.15,
116
+ ),
117
+ ura_client.actions.race(
118
+ "g3_race",
119
+ race_grade=RaceGrade.G3,
120
+ fan_gain=5000,
121
+ ),
122
+ ura_client.actions.rest("rest", mood_change=1),
123
+ ]
124
+
125
+ result = ura_client.evaluate_turn(
126
+ snapshot=snapshot,
127
+ context=context,
128
+ actions=actions,
129
+ career_profile=career_profile,
130
+ )
131
+
132
+ print(result.best_action_id)
133
+
134
+ for bid in result.bids:
135
+ print(bid.action.action_id, bid.score)
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Reusing an evaluator
141
+
142
+ If you're evaluating many turns, construct an evaluator once.
143
+
144
+ ```python
145
+ from umalite import Evaluator, ScenarioName
146
+
147
+ engine = Evaluator(scenario=ScenarioName.URA)
148
+
149
+ result = engine.evaluate(snapshot, context, actions, career_profile=career_profile)
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Scenario support
155
+
156
+ | Scenario | Public entrypoint | Status | Notes |
157
+ | -------------- | ------------------------ | -------------- | ---------------------------------------------------- |
158
+ | **URA Finale** | `UmaLiteClient().ura` | Implemented | Evaluator-first baseline model |
159
+ | **Unity** | `UmaLiteClient().unity` | Implemented | Evaluator-first with optional Unity-specific terms |
160
+ | **Trackblazer** | `UmaLiteClient().trackblazer` | Experimental | Planner-first with preparation steps |
161
+
162
+ Scenarios are implemented as plugins so each mode can adjust reward projection and evaluation logic without modifying the core engine.
163
+ Scenario clients provide the recommended public surface.
164
+
165
+ ---
166
+
167
+ ## Core models
168
+
169
+ Evaluation uses three primary inputs.
170
+
171
+ - `TurnSnapshot` - current visible state of the run
172
+ - `RunContext` - checkpoint horizon, local urgency, risk settings
173
+ - `ActionOption` - candidate action and its payload
174
+
175
+ `CareerProfile` is the run-intent object.
176
+
177
+ It is used by both `evaluate_turn(...)` and `plan_turn(...)`.
178
+ It currently carries:
179
+
180
+ - final target stats
181
+ - milestone target stats
182
+ - minimum training mood
183
+ - year-specific training mood floors
184
+ - maximum training fail rate
185
+
186
+ If both `CareerProfile` and `RunContext.target_stats` are provided, the explicit context targets win.
187
+
188
+ The output is a ranked list of `ActionBid` results.
189
+
190
+ ---
191
+
192
+ ## Action contract
193
+
194
+ Action inputs follow the same rule across scenarios:
195
+
196
+ - the caller supplies visible facts
197
+ - UmaLite projects hidden outcomes when needed
198
+
199
+ Training is mostly observable.
200
+ Callers usually provide visible stat gains, visible SP gain, fail rate, and `training_type`.
201
+ `energy_delta` is optional.
202
+ If omitted, UmaLite falls back to a bootstrap default.
203
+ Wit is the only training lane whose shared fallback `energy_delta` is non-negative.
204
+ The default Wit fallback is `+5` energy.
205
+
206
+ Race is partly projected.
207
+ Callers usually provide `race_grade` and visible `fan_gain`.
208
+ If explicit race rewards are omitted, UmaLite projects a baseline reward bundle from the grade.
209
+
210
+ Rest is projected by default.
211
+ Callers do not need to hardcode a fixed recovery amount unless they want an explicit override.
212
+
213
+ Recreation remains an explicit reward action.
214
+
215
+ The raw action builders remain available:
216
+
217
+ - `train_action(...)`
218
+ - `race_action(...)`
219
+ - `rest_action(...)`
220
+ - `recreation_action(...)`
221
+
222
+ Scenario clients wrap the same builders behind `.actions`.
223
+
224
+ ---
225
+
226
+ ## Minimal snapshot
227
+
228
+ The smallest useful snapshot:
229
+
230
+ ```python
231
+ from umalite import MoodLevel, ScenarioName
232
+ from umalite.models import TurnSnapshot
233
+
234
+ snapshot = TurnSnapshot.minimal(
235
+ scenario=ScenarioName.URA,
236
+ stats={
237
+ StatType.SPEED: 420,
238
+ StatType.STAMINA: 360,
239
+ StatType.POWER: 340,
240
+ StatType.GUTS: 250,
241
+ StatType.WIT: 390,
242
+ },
243
+ energy=58,
244
+ mood=MoodLevel.NORMAL,
245
+ fans=42000,
246
+ )
247
+ ```
248
+
249
+ Additional fields such as bonds, facilities, turn metadata, conditions, and scenario state are optional enrichment.
250
+
251
+ String values are also accepted for convenience, but enums are the preferred public API.
252
+
253
+ ---
254
+
255
+ ## Raw API
256
+
257
+ The raw API is still available:
258
+
259
+ ```python
260
+ result = evaluate_turn(
261
+ snapshot,
262
+ context,
263
+ actions,
264
+ config=None,
265
+ career_profile=None,
266
+ milestone=None,
267
+ )
268
+ ```
269
+
270
+ ```python
271
+ plan = plan_turn(
272
+ snapshot,
273
+ context,
274
+ actions,
275
+ config=None,
276
+ career_profile=None,
277
+ milestone=None,
278
+ )
279
+ ```
280
+
281
+ Use the raw API when you want direct control over snapshots, contexts, and action payloads.
282
+
283
+ ---
284
+
285
+ ## Precision model
286
+
287
+ UmaLite does not require perfect state.
288
+
289
+ Required core state should always be present.
290
+ Optional enrichment improves scoring quality.
291
+ If optional scenario data is missing, the evaluator should fall back to a reduced path instead of inventing hidden game state.
292
+
293
+ In practice this means:
294
+
295
+ - minimal snapshots are valid
296
+ - enriched snapshots score better
297
+ - scenario-specific terms activate only when the needed state exists
298
+
299
+ Projection defaults are bootstrap library approximations, not final scenario truth.
300
+
301
+ ---
302
+
303
+ ## Configuration
304
+
305
+ Most usage can rely on defaults.
306
+
307
+ If needed you can supply your own config:
308
+
309
+ ```python
310
+ from umalite.config import EvaluationConfig, UtilityConfig
311
+
312
+ config = EvaluationConfig(
313
+ utility=UtilityConfig(...),
314
+ )
315
+ ```
316
+
317
+ Or attach the config to an evaluator instance.
318
+
319
+ Configuration is intended for **policy**, such as weights, urgency shaping, and risk tolerance.
320
+ Core game semantics should remain owned by the library.
321
+
322
+ ---
323
+
324
+ ## Examples
325
+
326
+ See the `examples/` directory for:
327
+
328
+ - minimal URA usage
329
+ - enriched URA usage
330
+ - reusable evaluator pattern
331
+ - minimal Unity usage
332
+ - enriched Unity usage
333
+ - minimal Trackblazer usage
334
+ - enriched Trackblazer usage
335
+
336
+ The scenario client examples are the recommended starting point.
337
+
338
+ ---
339
+
340
+ ## Developing locally
341
+
342
+ Clone the repo and install dependencies.
343
+
344
+ ```bash
345
+ git clone https://github.com/yourusername/umalite.git
346
+ cd umalite
347
+ python -m venv .venv
348
+ source .venv/bin/activate # or .venv\Scripts\activate on Windows
349
+ pip install -e ".[dev]"
350
+ ```
351
+
352
+ Run tests.
353
+
354
+ ```bash
355
+ pytest
356
+ ```
357
+
358
+ Run linters and type checks.
359
+
360
+ ```bash
361
+ ruff check .
362
+ ruff format --check .
363
+ mypy .
364
+ ```
365
+
366
+ Install pre-commit hooks for automatic checks on commit.
367
+
368
+ ```bash
369
+ pre-commit install
370
+ ```
371
+
372
+ The project uses ruff for formatting and linting, mypy for type checking, and pytest for tests.
373
+
374
+