summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaran Jayachandra <mail@karanjayachandra.com>2024-11-09 18:19:48 +0000
committerKaran Jayachandra <mail@karanjayachandra.com>2024-11-09 18:19:48 +0000
commit1a7ae4bc2b759de7a03e6ad83632e6ad678754c8 (patch)
tree5b771e755f3a55c6794c649431de35798242a2e0
parent2b18e0929a0b3e083cbe9e5e8ffd421ed8d17e52 (diff)
parent75a3ef7d14fcaedab29da46ba3dc5cf9c1bab699 (diff)
Merge branch 'feature/package' into 'develop'
Implemented packaging and command line arguments See merge request KaranJayachandra/match_up!10
-rw-r--r--config.py16
-rw-r--r--gen_test_data.py32
-rw-r--r--pyproject.toml34
-rw-r--r--src/match_up/__init__.py31
-rw-r--r--src/match_up/controller.py (renamed from controller.py)17
-rw-r--r--src/match_up/model.py (renamed from model.py)41
-rw-r--r--src/match_up/routes.py (renamed from app.py)20
-rw-r--r--src/match_up/static/bulma.min.css (renamed from static/bulma.min.css)0
-rw-r--r--src/match_up/static/custom.css (renamed from static/custom.css)0
-rw-r--r--src/match_up/static/favicon.ico (renamed from static/favicon.ico)bin15406 -> 15406 bytes
-rw-r--r--src/match_up/static/htmx.min.js (renamed from static/htmx.min.js)0
-rw-r--r--src/match_up/static/logo.png (renamed from static/logo.png)0
-rw-r--r--src/match_up/templates/controls.j2 (renamed from templates/controls.j2)0
-rw-r--r--src/match_up/templates/games.j2 (renamed from templates/games.j2)0
-rw-r--r--src/match_up/templates/index.j2 (renamed from templates/index.j2)4
-rw-r--r--src/match_up/templates/macros.j2 (renamed from templates/macros.j2)4
-rw-r--r--src/match_up/templates/players.j2 (renamed from templates/players.j2)4
-rw-r--r--src/match_up/utilities.py (renamed from utilities.py)5
18 files changed, 124 insertions, 84 deletions
diff --git a/config.py b/config.py
deleted file mode 100644
index 7d01933..0000000
--- a/config.py
+++ /dev/null
@@ -1,16 +0,0 @@
-class Config:
- DEBUG = False
- DEVELOPMENT = False
- CSRF_ENABLED = True
- ASSETS_DEBUG = False
-
-
-class ProductionConfig(Config):
- pass
-
-
-class DevelopmentConfig(Config):
- DEBUG = True
- DEVELOPMENT = True
- TEMPLATES_AUTO_RELOAD = True
- ASSETS_DEBUG = True
diff --git a/gen_test_data.py b/gen_test_data.py
deleted file mode 100644
index a49594f..0000000
--- a/gen_test_data.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from csv import writer
-from random import randint
-from names import get_full_name
-from model import Player, MIN_LEVEL, MAX_LEVEL
-
-PLAYER_COUNT = 80
-
-
-def _generate_players(player_count: int) -> list[Player]:
- players = []
- for _ in range(player_count):
- random_name = get_full_name()
- random_skill = randint(MIN_LEVEL, MAX_LEVEL)
- players.append(Player(name=random_name, skill=random_skill))
- return players
-
-
-def _write_players_to_csv(player_list: list[Player]) -> None:
- with open("database_test.csv", "w", newline="") as file:
- data_writer = writer(file)
- data_writer.writerow(["name", "skill"])
- for player in player_list:
- data_writer.writerow([player.name, player.skill])
-
-
-def main(player_count: int):
- players = _generate_players(player_count)
- _write_players_to_csv(players)
-
-
-if __name__ == "__main__":
- main(PLAYER_COUNT)
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..de1a93f
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,34 @@
+[build-system]
+requires = ["setuptools>=64", "setuptools_scm>=8"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "match_up"
+dynamic = ["version"]
+dependencies = ["flask", "names"]
+authors = [
+ { name="Karan Jayachandra", email="mail@karanjayachandra.com" },
+]
+description = "A small web application for matchmaking"
+readme = "README.md"
+requires-python = ">=3.10"
+classifiers = [
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+]
+
+[project.urls]
+Homepage = "https://gitlab.com/KaranJayachandra/match_up"
+Issues = "https://gitlab.com/KaranJayachandra/match_up/-/issues"
+
+
+[tool.setuptools.packages.find]
+where = ["src"]
+
+[tool.setuptools.package-data]
+"templates" = ["*.j2"]
+"static" = ["*.css", "*.js", "*.png", "*.ico"]
+
+[project.scripts]
+match_up = "match_up:main" \ No newline at end of file
diff --git a/src/match_up/__init__.py b/src/match_up/__init__.py
new file mode 100644
index 0000000..3aa3b98
--- /dev/null
+++ b/src/match_up/__init__.py
@@ -0,0 +1,31 @@
+from flask import Flask
+from argparse import ArgumentParser
+from importlib.resources import path
+from match_up.utilities import Timer
+from match_up.controller import RoundGenerator
+from match_up.model import CourtList, PlayerList
+
+with path("match_up", "static") as p:
+ static_folder = p
+with path("match_up", "templates") as p:
+ template_folder = p
+app = Flask(
+ "Match Up! Backend", static_folder=static_folder, template_folder=template_folder
+)
+rg = RoundGenerator()
+
+
+from match_up import routes
+
+
+def main():
+ parser = ArgumentParser()
+ parser.add_argument("-t", "--timer", help="Min per round", type=float, default=12)
+ parser.add_argument("-c", "--courts", help="Total courts", type=int, default=12)
+ parser.add_argument("-d", "--database", help="CSV database", default=None)
+ args = parser.parse_args()
+ global rg
+ rg.courts = CourtList(total=args.courts)
+ rg.timer = Timer(max_mins=args.timer)
+ rg.players = PlayerList(location=args.database)
+ app.run()
diff --git a/controller.py b/src/match_up/controller.py
index e6dc827..a21fced 100644
--- a/controller.py
+++ b/src/match_up/controller.py
@@ -1,8 +1,15 @@
from typing import Tuple
from operator import attrgetter
-from dataclasses import dataclass
-from utilities import sample_list, Timer
-from model import Team, Game, PlayerList, CourtList, MAX_LEVEL, PLAYER_PER_COURT
+from dataclasses import dataclass, field
+from match_up.utilities import sample_list, Timer
+from match_up.model import (
+ Team,
+ Game,
+ PlayerList,
+ CourtList,
+ MAX_LEVEL,
+ PLAYER_PER_COURT,
+)
def _create_placeholders(courts: dict, name: str) -> list[Game]:
@@ -43,8 +50,8 @@ def _create_games(courts: dict, players: list[dict], levels: int):
@dataclass
class RoundGenerator:
- courts: CourtList
- players: PlayerList
+ courts: CourtList = field(default_factory=lambda: CourtList())
+ players: PlayerList = field(default_factory=lambda: PlayerList())
round: int = 0
proposal: tuple = tuple()
diff --git a/model.py b/src/match_up/model.py
index c652ce8..5d6c0f5 100644
--- a/model.py
+++ b/src/match_up/model.py
@@ -1,11 +1,13 @@
-from os import getenv
from math import floor
from csv import reader
from typing import Tuple
+from names import get_full_name
from dataclasses import dataclass
+from random import randint, getrandbits
MIN_LEVEL = 1
MAX_LEVEL = 10
+DEFAULT_COURTS = 12
PLAYER_PER_COURT = 4
@@ -31,7 +33,7 @@ class Game:
@dataclass
class CourtList:
- total: int = int(getenv("COURTS"))
+ total: int = DEFAULT_COURTS
def __post_init__(self) -> None:
self.courts = {i + 1: True for i in range(self.total)}
@@ -53,20 +55,37 @@ class CourtList:
return active_courts, inactive_courts
+def _load_csv_players(file_name: str) -> dict:
+ with open(file_name, newline="") as file:
+ pointer = reader(file)
+ next(pointer, None)
+ players = {id: Player(row[0], int(row[1])) for id, row in enumerate(pointer)}
+ return players
+
+
+def _generate_random_players(player_count: int = 80) -> list[Player]:
+ players = {
+ i: Player(
+ name=get_full_name(),
+ skill=randint(MIN_LEVEL, MAX_LEVEL),
+ status=bool(getrandbits(1)),
+ )
+ for i in range(player_count)
+ }
+ return players
+
+
@dataclass
class PlayerList:
- location: str = getenv("DATABASE")
+ location: str = None
guests: int = 0
def __post_init__(self) -> None:
- with open("data/" + self.location, newline="") as file:
- pointer = reader(file)
- next(pointer, None)
- players = {
- id: Player(row[0], int(row[1])) for id, row in enumerate(pointer)
- }
- self.guest_id_start = len(players) + 1
- self.players = players
+ if self.location is not None:
+ self.players = _load_csv_players(self.location)
+ else:
+ self.players = _generate_random_players()
+ self.guest_id_start = len(self.players) + 1
def increment_guests(self):
self.guests = self.guests + 1
diff --git a/app.py b/src/match_up/routes.py
index cb790f3..319b111 100644
--- a/app.py
+++ b/src/match_up/routes.py
@@ -1,19 +1,13 @@
-from dotenv import load_dotenv
-from controller import RoundGenerator
-from model import CourtList, PlayerList
-from jinja2 import FileSystemLoader, Environment
-from flask import Flask, render_template, request
+from match_up import app, rg
+from jinja2 import Environment, PackageLoader
+from flask import render_template, request, url_for
-
-load_dotenv()
-app = Flask("Match Up! Backend")
-rg = RoundGenerator(courts=CourtList(), players=PlayerList())
-re = Environment(loader=FileSystemLoader("templates"))
+re = Environment(loader=PackageLoader("match_up"))
@app.route("/", methods=["GET"])
def home():
- return render_template("index.j2")
+ return re.get_template("index.j2").render(url_for=url_for)
@app.route("/time", methods=["GET"])
@@ -74,7 +68,9 @@ def toggle_player(player_request):
@app.route("/players", methods=["GET"])
def get_list_of_players():
- return render_template("players.j2", players=rg.players.get_players())
+ return re.get_template("players.j2").render(
+ players=rg.players.get_players(), url_for=url_for
+ )
@app.route("/court-toggle/<court_number>", methods=["POST"])
diff --git a/static/bulma.min.css b/src/match_up/static/bulma.min.css
index eaa3fb5..eaa3fb5 100644
--- a/static/bulma.min.css
+++ b/src/match_up/static/bulma.min.css
diff --git a/static/custom.css b/src/match_up/static/custom.css
index 11d583f..11d583f 100644
--- a/static/custom.css
+++ b/src/match_up/static/custom.css
diff --git a/static/favicon.ico b/src/match_up/static/favicon.ico
index 64eab0a..64eab0a 100644
--- a/static/favicon.ico
+++ b/src/match_up/static/favicon.ico
Binary files differ
diff --git a/static/htmx.min.js b/src/match_up/static/htmx.min.js
index de5f0f1..de5f0f1 100644
--- a/static/htmx.min.js
+++ b/src/match_up/static/htmx.min.js
diff --git a/static/logo.png b/src/match_up/static/logo.png
index 7d2d8c7..7d2d8c7 100644
--- a/static/logo.png
+++ b/src/match_up/static/logo.png
diff --git a/templates/controls.j2 b/src/match_up/templates/controls.j2
index 6ba724a..6ba724a 100644
--- a/templates/controls.j2
+++ b/src/match_up/templates/controls.j2
diff --git a/templates/games.j2 b/src/match_up/templates/games.j2
index d5afef1..d5afef1 100644
--- a/templates/games.j2
+++ b/src/match_up/templates/games.j2
diff --git a/templates/index.j2 b/src/match_up/templates/index.j2
index 832dbfb..ce0d531 100644
--- a/templates/index.j2
+++ b/src/match_up/templates/index.j2
@@ -1,10 +1,10 @@
{% from "macros.j2" import header, footer, navbar %}
<!doctype html>
<html lang="en">
- {{ header() }}
+ {{ header(url_for) }}
<body>
<section class="section">
- {{ navbar() }}
+ {{ navbar(url_for) }}
<div hx-post="/clear" hx-swap="outerHTML" hx-trigger="load"></div>
<div hx-get="/control" hx-swap="outerHTML" hx-trigger="load"></div>
{{ footer() }}
diff --git a/templates/macros.j2 b/src/match_up/templates/macros.j2
index 8d05bb0..dedbf48 100644
--- a/templates/macros.j2
+++ b/src/match_up/templates/macros.j2
@@ -22,7 +22,7 @@
</div>
{%- endmacro %}
-{% macro header() -%}
+{% macro header(url_for) -%}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -38,7 +38,7 @@
<div class="content has-text-centered">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>
{%- endmacro %}
-{% macro navbar() -%}
+{% macro navbar(url_for) -%}
<nav class="level">
<div class="level-left">
<div class="level-item">
diff --git a/templates/players.j2 b/src/match_up/templates/players.j2
index ae6afe0..0d1f96c 100644
--- a/templates/players.j2
+++ b/src/match_up/templates/players.j2
@@ -1,10 +1,10 @@
{% from "macros.j2" import header, navbar, footer, player %}
<!doctype html>
<html lang="en">
- {{ header() }}
+ {{ header(url_for) }}
<body>
<section class="section">
- {{ navbar() }}
+ {{ navbar(url_for) }}
<div class="fixed-grid has-4-cols">
<div class="grid">
{% for id, value in players.items() %}
diff --git a/utilities.py b/src/match_up/utilities.py
index 7a9d55d..8a905ba 100644
--- a/utilities.py
+++ b/src/match_up/utilities.py
@@ -1,10 +1,11 @@
-from os import getenv
from time import time
from typing import Tuple
from random import shuffle
from dataclasses import dataclass
+
SECS_IN_MIN = 60
+DEFAULT_TIMER = 12.0
def _shuffle_two_lists(a: list, b: list) -> Tuple[list, list]:
@@ -30,9 +31,9 @@ def sample_list(indices: list, cost: list[int], count: int = None) -> list:
@dataclass
class Timer:
+ max_mins: float = DEFAULT_TIMER
ref: float = None
running: bool = False
- max_mins: float = float(getenv("TIMER"))
default: str = ("00", "00")
def __post_init__(self):