diff options
| -rw-r--r-- | app.py | 12 | ||||
| -rw-r--r-- | controller.py | 7 | ||||
| -rw-r--r-- | model.py | 33 | ||||
| -rw-r--r-- | static/custom.css | 15 | ||||
| -rw-r--r-- | templates/controls.j2 | 51 | ||||
| -rw-r--r-- | templates/court.j2 | 1 | ||||
| -rw-r--r-- | templates/games.j2 | 2 | ||||
| -rw-r--r-- | templates/index.j2 | 79 | ||||
| -rw-r--r-- | templates/player.j2 | 1 | ||||
| -rw-r--r-- | templates/time.j2 | 3 |
10 files changed, 125 insertions, 79 deletions
@@ -9,7 +9,9 @@ from flask import Flask, render_template, request load_dotenv() app = Flask("Match Up! Backend") app.config.from_object(getenv("APP_SETTINGS")) -rg = RoundGenerator(courts=CourtList(12), players=PlayerList(getenv("DATABASE"))) +rg = RoundGenerator( + courts=CourtList(int(getenv("COURTS"))), players=PlayerList(getenv("DATABASE")) +) re = Environment(loader=FileSystemLoader("templates")) @@ -18,6 +20,12 @@ def home(): return render_template("index.j2") +@app.route("/time", methods=["GET"]) +def get_time(): + mins, secs = rg.timer.get() + return render_template("time.j2", mins=mins, secs=secs) + + @app.route("/guests", methods=["GET"]) def get_guests(): return render_template("guests.j2", guests=rg.players.guests) @@ -68,9 +76,7 @@ def get_list_of_players(): def toggle_court(court_number): id = int(court_number) status = rg.courts.toggle_court_status(id) - print(status) t = re.from_string('{% from "macros.j2" import court %}{{ court(id, status) }}') - print(render_template(t, id=id, status=status)) return render_template(t, id=id, status=status) diff --git a/controller.py b/controller.py index 1116443..2e09e9f 100644 --- a/controller.py +++ b/controller.py @@ -2,7 +2,7 @@ from typing import Tuple from operator import attrgetter from dataclasses import dataclass from utilities import sample_list -from model import Team, Game, PlayerList, CourtList, MAX_LEVEL, PLAYER_PER_COURT +from model import Team, Game, PlayerList, CourtList, Timer, MAX_LEVEL, PLAYER_PER_COURT def _create_placeholders(courts: dict, name: str) -> list[Game]: @@ -49,6 +49,7 @@ class RoundGenerator: proposal: tuple = tuple() def __post_init__(self) -> None: + self.timer = Timer() self.history = {key: 0 for key, _ in self.players.get_players().items()} self.games = self._generate_proposal(MAX_LEVEL)[0] @@ -110,7 +111,9 @@ class RoundGenerator: return self.games self.games = proposed_games for player_id in proposed_players: - self.history[player_id] = self.history[player_id] + 1 + if player_id < self.players.guest_id_start: + self.history[player_id] = self.history[player_id] + 1 self.proposal = tuple() self.round += 1 + self.timer.start() return self.games @@ -1,6 +1,7 @@ from math import floor from csv import reader from typing import Tuple +from time import time, strftime from dataclasses import dataclass MIN_LEVEL = 1 @@ -101,3 +102,35 @@ class PlayerList: } players.update(guests) return players + + +@dataclass +class Timer: + ref: float = None + running: bool = False + max_mins: int = 1 + default: str = ("00", "00") + + def __post_init__(self): + self.max_seconds = self.max_mins * 60 + + def start(self): + self.ref = time() + self.max_seconds + self.running = True + + def stop(self): + self.ref = None + self.running = False + + def get(self): + if not self.running: + return self.default + total_seconds = self.ref - time() + if total_seconds < 0: + self.stop() + return self.default + mins = f"{int(total_seconds // 60):02d}" + secs = f"{int(total_seconds % 60):02d}" + print(mins) + print(secs) + return mins, secs diff --git a/static/custom.css b/static/custom.css new file mode 100644 index 0000000..3e57091 --- /dev/null +++ b/static/custom.css @@ -0,0 +1,15 @@ +button, input, .select, .select select { + width: 100%; +} +table { + font-size: 30px; +} +td { + width: 20%; +} +img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%,-50%); +}
\ No newline at end of file diff --git a/templates/controls.j2 b/templates/controls.j2 new file mode 100644 index 0000000..1799e01 --- /dev/null +++ b/templates/controls.j2 @@ -0,0 +1,51 @@ +<div class="columns"> + <div class="column"> + <div class="field has-addons"> + <div class="control"> + <button class="button is-large is-responsive is-dark" + style="text-align:center" + hx-post="/decrement" + hx-swap="outerHTML" + hx-target="#guests">-</button> + </div> + <div hx-get="/guests" hx-swap="outerHTML" hx-trigger="revealed"></div> + <div class="control"> + <button class="button is-large is-responsive is-dark" + style="text-align:center" + hx-post="/increment" + hx-swap="outerHTML" + hx-target="#guests">+</button> + </div> + </div> + </div> + <div class="column"> + <div class="select is-large is-responsive"> + <select name="type"> + <option>10 Levels</option> + <option>8 Levels</option> + <option>6 Levels</option> + <option>4 Levels</option> + <option>2 Levels</option> + <option>0 Levels</option> + </select> + </div> + </div> + <div class="column"> + <button class="button is-dark is-large is-responsive" + hx-post="/propose" + hx-target="#games" + hx-include="[name='type']">New Round</button> + </div> + <div class="column"></div> + <div class="column"> + <button class="button is-dark is-large is-responsive" + hx-post="/confirm" + hx-target="#games">Start Round</button> + </div> + <div class="column"> + <button class="button is-dark is-large is-responsive" + hx-post="/clear" + hx-target="#games">Reset</button> + </div> +</div> +<div hx-post="/clear" hx-swap="outerHTML" hx-trigger="revealed"></div> diff --git a/templates/court.j2 b/templates/court.j2 deleted file mode 100644 index d7aec86..0000000 --- a/templates/court.j2 +++ /dev/null @@ -1 +0,0 @@ -{% from "macros.j2" import court %}{{ court(key, value) }}
\ No newline at end of file diff --git a/templates/games.j2 b/templates/games.j2 index 50e1087..0285de1 100644 --- a/templates/games.j2 +++ b/templates/games.j2 @@ -9,7 +9,7 @@ </thead> <tbody> {% for game in games %} - <tr> + <tr {% if game.team1.player1 == 'RESERVED' %} class="is-danger" {% endif %}> <th align="center">{{ game.court }}</th> <td>{{ game.team1.player1 }}</th> <td>{{ game.team1.player2 }}</th> diff --git a/templates/index.j2 b/templates/index.j2 index 4ccdf92..fcea4e3 100644 --- a/templates/index.j2 +++ b/templates/index.j2 @@ -6,24 +6,8 @@ <title>Match Up!</title> <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='bulma.min.css') }}"> + <link rel="stylesheet" href="{{ url_for('static', filename='custom.css') }}"> <script src="{{ url_for('static', filename='htmx.min.js') }}"></script> - <style> - button, input, .select, .select select { - width: 100%; - } - table { - font-size: 30px; - } - td { - width: 20%; - } - img { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%,-50%); - } - </style> </head> <body> <section class="section"> @@ -36,63 +20,16 @@ </div> </div> <div class="level-item"> - <p class="title">Today's Games</p> + <p class="title">Match Up!</p> + </div> + <div class="level-right"> + <div hx-get="/time" hx-swap="outerHTML" hx-trigger="revealed"></div> </div> </nav> </section> <section class="section"> - <p class="title">Games</p> - <div class="columns"> - <div class="column"> - <div class="field has-addons"> - <div class="control"> - <button class="button is-large is-responsive is-dark" - style="text-align:center" - hx-post="/decrement" - hx-swap="outerHTML" - hx-target="#guests">-</button> - </div> - <div hx-get="/guests" hx-swap="outerHTML" hx-trigger="revealed"></div> - <div class="control"> - <button class="button is-large is-responsive is-dark" - style="text-align:center" - hx-post="/increment" - hx-swap="outerHTML" - hx-target="#guests">+</button> - </div> - </div> - </div> - <div class="column"> - <div class="select is-large is-responsive"> - <select name="type"> - <option>10 Levels</option> - <option>8 Levels</option> - <option>6 Levels</option> - <option>4 Levels</option> - <option>2 Levels</option> - <option>0 Levels</option> - </select> - </div> - </div> - <div class="column"> - <button class="button is-dark is-large is-responsive" - hx-post="/propose" - hx-target="#games" - hx-include="[name='type']">New Round</button> - </div> - <div class="column"></div> - <div class="column"> - <button class="button is-dark is-large is-responsive" - hx-post="/confirm" - hx-target="#games">Start Round</button> - </div> - <div class="column"> - <button class="button is-dark is-large is-responsive" - hx-post="/clear" - hx-target="#games">Reset</button> - </div> - </div> - <div hx-post="/clear" hx-swap="outerHTML" hx-trigger="revealed"></div> + <p class="title">Games</p> + {% include 'controls.j2' %} </section> <section class="section"> <h2 class="title">Courts</h2> @@ -104,7 +41,7 @@ </section> <footer class="footer"> <div class="content has-text-centered"> - Made by <a href="https://karanjayachandra.com/">K. Jayachandra</a> using <a href="https://flask.palletsprojects.com">Flask</a>, <a href="https://htmx.org/">HTMX</a> and <a href="https://bulma.io">Bulma</a> + Made by <a href="https://karanjayachandra.com/">Karan</a> using <a href="https://flask.palletsprojects.com">Flask</a>, <a href="https://htmx.org/">HTMX</a> and <a href="https://bulma.io">Bulma</a> </div> </footer> </body> diff --git a/templates/player.j2 b/templates/player.j2 deleted file mode 100644 index 68a1ea4..0000000 --- a/templates/player.j2 +++ /dev/null @@ -1 +0,0 @@ -{% from "macros.j2" import player %}{{ player(id, status, name) }}
\ No newline at end of file diff --git a/templates/time.j2 b/templates/time.j2 new file mode 100644 index 0000000..d006fc4 --- /dev/null +++ b/templates/time.j2 @@ -0,0 +1,3 @@ +<div hx-get="/time" hx-swap="outerHTML" hx-trigger="every 1s"> + <p class="title">Timer: {{mins}}:{{secs}}</p> +</div>
\ No newline at end of file |
