Compare commits

..

1 Commits
main ... ui

Author SHA1 Message Date
57e3c86b20 Start building a drag and drop ui
Apparently this is synced between all windows... I don't actually want that
2025-01-09 17:18:56 -08:00
5 changed files with 1934 additions and 27 deletions

View File

@ -0,0 +1,25 @@
from argparse import ArgumentParser, Namespace
from pathlib import Path
QUEENS_FILE = "queens.txt"
PICKS_FILE_GLOB = "picks-*.txt"
ELIMINATIONS_FILE = "eliminations.txt"
ROSTERS_FILE = "rosters.json"
def parse_args() -> Namespace:
parser = ArgumentParser()
parser.add_argument(
"season_dir",
type=Path,
default=Path("."),
help="Directory containing season data",
)
parser.add_argument(
"--eliminate", type=str, help="Eliminate a queen", metavar="QUEEN"
)
parser.add_argument("--draft", action="store_true", help="Run the initial draft")
parser.add_argument("--print", action="store_true", help="Print the current status")
return parser.parse_args()

View File

@ -1,13 +1,15 @@
import json
import random
from argparse import ArgumentParser
from pathlib import Path
from typing import DefaultDict
QUEENS_FILE = "queens.txt"
PICKS_FILE_GLOB = "picks-*.txt"
ELIMINATIONS_FILE = "eliminations.txt"
ROSTERS_FILE = "rosters.json"
from drag_draft import (
ELIMINATIONS_FILE,
PICKS_FILE_GLOB,
QUEENS_FILE,
ROSTERS_FILE,
parse_args,
)
class Draft:
@ -33,7 +35,10 @@ class Draft:
"""
def __init__(
self, queens_file: Path, picks_files: list[Path], roster_file: Path|None = None
self,
queens_file: Path,
picks_files: list[Path],
roster_file: Path | None = None,
):
self.queens = self.load_queens(queens_file)
self.players = self.load_players(picks_files)
@ -58,7 +63,9 @@ class Draft:
picks_set = set(picks)
assert len(picks_set) == len(picks), f"Player {player} has duplicate picks"
unknown_queens = picks_set - self.queens
assert len(unknown_queens) == 0, f"Player {player} has invalid picks: {unknown_queens}"
assert (
len(unknown_queens) == 0
), f"Player {player} has invalid picks: {unknown_queens}"
players[player] = picks
@ -143,7 +150,9 @@ class Draft:
return scores
def eliminate_queen(queens_file: Path, eliminations_file: Path, queen: str) -> list[str]|None:
def eliminate_queen(
queens_file: Path, eliminations_file: Path, queen: str
) -> list[str] | None:
"""Eliminate a queen from the list of queens."""
queens = set(queens_file.read_text().strip().split("\n"))
if queen not in queens:
@ -162,22 +171,9 @@ def eliminate_queen(queens_file: Path, eliminations_file: Path, queen: str) -> l
def main():
parser = ArgumentParser()
parser.add_argument(
"season_dir",
type=Path,
default=Path("."),
help="Directory containing season data",
)
parser.add_argument(
"--eliminate", type=str, help="Eliminate a queen", metavar="QUEEN"
)
parser.add_argument("--draft", action="store_true", help="Run the initial draft")
parser.add_argument("--print", action="store_true", help="Print the current status")
args = parser.parse_args()
args = parse_args()
# Create a Draft object for the given season directory
queens_file = args.season_dir / QUEENS_FILE
picks_files = list(args.season_dir.glob(PICKS_FILE_GLOB))
eliminations_file = args.season_dir / ELIMINATIONS_FILE
@ -212,4 +208,3 @@ def main():
if __name__ == "__main__":
main()

62
drag_draft/ui.py Normal file
View File

@ -0,0 +1,62 @@
from nicegui import context, ui
from drag_draft import QUEENS_FILE, parse_args
def run_draft() -> None:
args = parse_args()
queens_file = args.season_dir / QUEENS_FILE
queens = queens_file.read_text().strip().split("\n")
ui.label("Make your picks")
player_name = ui.input("Player name", placeholder="Enter your name")
with ui.row():
with ui.column().classes("sortable"):
for queen in queens:
with ui.card().classes("cursor-grab"):
ui.label(queen)
def drop_queen(e) -> None:
# Move in UI
print(e)
context.client.elements[e.args["id"]].move(target_index=e.args["new_index"])
queens.insert(e.args["new_index"], queens.pop(e.args["old_index"]))
print(
f'Moved queen {queens[e.args["new_index"]]} to index {e.args["new_index"]}'
)
ui.on(
"item-drop",
drop_queen,
)
def save_picks() -> None:
print(f"Player {player_name.value} picked:")
print(context.client.elements)
(args.season_dir / f"picks-{player_name.value}.txt").write_text(
"\n".join(queen for queen in queens)
)
print("Picks saved!")
ui.button("Save").on_click(save_picks)
ui.add_body_html(
r"""
<script type="module">
import 'https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.6/Sortable.min.js';
document.addEventListener('DOMContentLoaded', () => {
Sortable.create(document.querySelector('.sortable'), {
animation: 150,
ghostClass: 'opacity-50',
onEnd: (evt) => emitEvent("item-drop", {id: parseInt(evt.item.id.slice(1)), new_index: evt.newIndex, old_index: evt.oldIndex}),
});
});
</script>
"""
)
run_draft()
ui.run()

1830
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,9 @@ authors = [
]
license = {text = "MIT"}
readme = "README.md"
requires-python = ">=3.12"
requires-python = ">=3.12,<4.0.0"
dependencies = [
"nicegui (>=2.9.1,<3.0.0)"
]