arch & placeholders

This commit is contained in:
Maxime Réaux 2025-12-19 09:56:45 +01:00
parent a3b16ae58a
commit 57543e139a
10 changed files with 233 additions and 2 deletions

60
.gitignore vendored Normal file
View file

@ -0,0 +1,60 @@
# =========================
# Python bytecode & cache
# =========================
__pycache__/
*.py[cod]
*$py.class
# =========================
# Virtual environments
# =========================
.env
.venv
env/
venv/
ENV/
# =========================
# Packaging / build
# =========================
build/
dist/
*.egg-info/
.eggs/
# =========================
# Test & coverage
# =========================
.pytest_cache/
.coverage
htmlcov/
.tox/
.nox/
# =========================
# IDE / editors
# =========================
.vscode/
.idea/
*.swp
*.swo
# =========================
# OS generated files
# =========================
.DS_Store
Thumbs.db
# =========================
# Logs
# =========================
*.log
# =========================
# Application data
# =========================
data/*.json
data/*.bak
# But keep example files
!data/example.json

View file

@ -1,3 +1,16 @@
# Wargame_campain_app # Wargame_campaign_app
A simplie CLI app to manage players and their scores throughout several organised games of a tabletop wargame. A simple CLI app to manage players and their scores throughout several organised games of a tabletop wargame.
## Main logic
Manage a list of players to sign them up to be selectable for war(s) and campaign(s).
A year "war" contains several "campaign" events which contain several "battle" games organised in successive rounds.
Battle results determine campaign score which determines the war score. Wars are independent.
## Design notes
Players are global identities
Influence tokens are scoped to a war
Campaign order enables historical tie-breakers
Effects are generic → future-proof

9
cli/menu.py Normal file
View file

@ -0,0 +1,9 @@
def main_menu():
print("\n=== Wargame Campaign App ===")
print("1. List wars")
print("2. Start new campaign")
print("3. Start new round")
print("4. Enter battle results")
print("5. Save & exit")
return input("> ")

78
data/example.json Normal file
View file

@ -0,0 +1,78 @@
{
"version": 1,
"players": {
"P1": {
"name": "Alice"
},
"P2": {
"name": "Bob"
},
"P3": {
"name": "Charlie"
}
},
"wars": [
{
"id": "WAR2025",
"name": "Llael War 2025",
"year": 2025,
"registered_players": {
"P1": {
"war_points": 0,
"influence_tokens": 1
},
"P2": {
"war_points": 0,
"influence_tokens": 0
}
},
"campaigns": [
{
"id": "CAMP01",
"name": "Widower's Wood",
"order": 1,
"participants": {
"P1": { "campaign_points": 0 },
"P2": { "campaign_points": 0 }
},
"rounds": [
{
"number": 1,
"sectors": ["North", "South"],
"choices": {
"P1": { "primary": "North", "secondary": "South" },
"P2": { "primary": "North", "secondary": "South" }
},
"battles": [
{
"sector": "North",
"players": ["P1", "P2"],
"winner": "P1",
"effects": {
"campaign_points": 1,
"grants_influence_token": false
}
}
],
"completed": true
}
],
"completed": false
}
],
"completed": false
}
]
}

21
main.py Normal file
View file

@ -0,0 +1,21 @@
from storage.repository import load_data, save_data
from cli.menu import main_menu
def main():
data = load_data()
while True:
choice = main_menu()
if choice == "1":
print("Wars:")
for war in data["wars"]:
print(f"- {war['name']}")
elif choice == "5":
save_data(data)
print("Goodbye.")
break
if __name__ == "__main__":
main()

4
models/player.py Normal file
View file

@ -0,0 +1,4 @@
def create_player(player_id, name):
return {
"name": name
}

View file

@ -0,0 +1,7 @@
def resolve_round(round_data, campaign, war):
"""
Placeholder:
- resolve sector assignments
- create battle entries
"""
pass

View file

@ -0,0 +1,10 @@
def apply_battle_effects(battle, campaign, war):
"""
Placeholder scoring logic.
"""
winner = battle["winner"]
effects = battle.get("effects", {})
campaign_points = effects.get("campaign_points", 0)
if winner in campaign["participants"]:
campaign["participants"][winner]["campaign_points"] += campaign_points

View file

@ -0,0 +1,7 @@
def break_tie(players, current_campaign, war):
"""
Placeholder:
- future implementation will check
previous campaigns and influence tokens
"""
return players

22
storage/repository.py Normal file
View file

@ -0,0 +1,22 @@
import json
import shutil
from pathlib import Path
DATA_FILE = Path("data/warmachron.json")
def load_data():
if not DATA_FILE.exists() or DATA_FILE.stat().st_size == 0:
return {"version": 1, "players": {}, "wars": []}
try:
with open(DATA_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except json.JSONDecodeError:
raise RuntimeError("Data file is corrupted")
def save_data(data):
if DATA_FILE.exists():
shutil.copy(DATA_FILE, DATA_FILE.with_suffix(".json.bak"))
with open(DATA_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)