Skip to content

Refactorisationducode BUG: Booking places in past competitions #5 #271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ bin
include
lib
.Python
tests/

.envrc
__pycache__
4 changes: 4 additions & 0 deletions CACHEDIR.TAG
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Python virtualenv.
# For information about cache directory tags, see:
# https://bford.info/cachedir/
Empty file added app/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions app/booking_manager/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# app/booking_manager/__init__.py

from .booking_service import BookingService
from .club_manager import ClubManager
from .competition_manager import CompetitionManager
from .data_loader import JSONDataLoader
36 changes: 36 additions & 0 deletions app/booking_manager/booking_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# app/booking_manager/booking_service.py

from app.booking_manager.club_manager import ClubManager
from app.booking_manager.competition_manager import CompetitionManager


class BookingService:
"""
Ordonne le processus de réservation en utilisant les gestionnaires de clubs et de compétitions.
"""

def __init__(self, clubs_file: str, competitions_file: str):
self.club_manager = ClubManager(clubs_file)
self.competition_manager = CompetitionManager(competitions_file)

def purchase_places(self, club_name: str, competition_name: str, places_requested: int) -> bool:
club = self.club_manager.find_by_name(club_name)
competition = self.competition_manager.find_by_name(competition_name)

if not club or not competition:
return False
if places_requested > 12:
return False
if places_requested > club.points:
return False
if places_requested > competition.number_of_places:
return False

competition.number_of_places -= places_requested
club.points -= places_requested

# Sauvegarde des modifications dans les fichiers JSON
self.club_manager.save_clubs()
self.competition_manager.save_competitions()

return True
55 changes: 55 additions & 0 deletions app/booking_manager/club_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# app/booking_manager/club_manager.py

import json
from typing import List, Optional
from app.models import Club
from .data_loader import JSONDataLoader


class ClubManager:
"""
Gère le chargement, la recherche et la sauvegarde des clubs.
"""

def __init__(self, clubs_file: str):
self.clubs_file = clubs_file # Pour la sauvegarde
loader = JSONDataLoader(clubs_file)
data = loader.load_data()
self.clubs: List[Club] = self._parse_clubs(data)

def _parse_clubs(self, data: dict) -> List[Club]:
clubs = []
for c in data.get("clubs", []):
clubs.append(
Club(
name=c["name"],
email=c["email"],
points=int(c["points"]),
id=c.get("id")
)
)
return clubs

def find_by_email(self, email: str) -> Optional[Club]:
return next((club for club in self.clubs if club.email == email), None)

def find_by_name(self, name: str) -> Optional[Club]:
return next((club for club in self.clubs if club.name == name), None)

def save_clubs(self, filepath: Optional[str] = None) -> None:
"""
Sauvegarde l'état actuel des clubs dans un fichier JSON.
"""
if filepath is None:
filepath = self.clubs_file
clubs_data = {"clubs": []}
for club in self.clubs:
club_dict = {
"id": club.id,
"name": club.name,
"email": club.email,
"points": str(club.points)
}
clubs_data["clubs"].append(club_dict)
with open(filepath, "w") as f:
json.dump(clubs_data, f, indent=4)
50 changes: 50 additions & 0 deletions app/booking_manager/competition_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# app/booking_manager/competition_manager.py

import json
from typing import List, Optional
from app.models import Competition
from .data_loader import JSONDataLoader


class CompetitionManager:
"""
Gère le chargement, la recherche et la sauvegarde des compétitions.
"""

def __init__(self, competitions_file: str):
self.competitions_file = competitions_file # Pour la sauvegarde
loader = JSONDataLoader(competitions_file)
data = loader.load_data()
self.competitions: List[Competition] = self._parse_competitions(data)

def _parse_competitions(self, data: dict) -> List[Competition]:
competitions = []
for c in data.get("competitions", []):
competitions.append(
Competition(
name=c["name"],
date=c["date"],
number_of_places=int(c["numberOfPlaces"])
)
)
return competitions

def find_by_name(self, name: str) -> Optional[Competition]:
return next((comp for comp in self.competitions if comp.name == name), None)

def save_competitions(self, filepath: Optional[str] = None) -> None:
"""
Sauvegarde l'état actuel des compétitions dans un fichier JSON.
"""
if filepath is None:
filepath = self.competitions_file
competitions_data = {"competitions": []}
for comp in self.competitions:
comp_dict = {
"name": comp.name,
"date": comp.date,
"numberOfPlaces": str(comp.number_of_places)
}
competitions_data["competitions"].append(comp_dict)
with open(filepath, "w") as f:
json.dump(competitions_data, f, indent=4)
21 changes: 21 additions & 0 deletions app/booking_manager/data_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# app/booking_manager/data_loader.py

import json
import os
from typing import Any


class JSONDataLoader:
"""
Classe générique pour charger des données depuis un fichier JSON.
"""

def __init__(self, filepath: str):
self.filepath = filepath

def load_data(self) -> Any:
if not os.path.exists(self.filepath):
raise FileNotFoundError(f"Fichier introuvable : {self.filepath}")
with open(self.filepath, "r") as f:
data = json.load(f)
return data
15 changes: 15 additions & 0 deletions app/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# app/models.py

class Competition:
def __init__(self, name, date, number_of_places):
self.name = name
self.date = date
self.number_of_places = number_of_places


class Club:
def __init__(self, name, email, points, id=None):
self.name = name
self.email = email
self.points = points
self.id = id
71 changes: 71 additions & 0 deletions app/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# app/server.py

from flask import Flask, render_template, request, redirect, flash, url_for
from app.booking_manager import BookingService

app = Flask(__name__, static_folder="../static")
app.secret_key = "secret_key_xyz"

# Instanciation du service de réservation
booking_service = BookingService(
clubs_file="data/clubs.json",
competitions_file="data/competitions.json"
)


@app.route("/")
def index():
return render_template("index.html")


@app.route("/showSummary", methods=["POST"])
def show_summary():
email = request.form.get("email", "")
club = booking_service.club_manager.find_by_email(email)
if not club:
flash("Email inconnu ou invalide.")
return redirect(url_for("index"))
return render_template("welcome.html", club=club, competitions=booking_service.competition_manager.competitions)


@app.route("/book/<competition>/<club>")
def book(competition, club):
found_competition = booking_service.competition_manager.find_by_name(
competition)
found_club = booking_service.club_manager.find_by_name(club)
if not found_competition or not found_club:
flash("Something went wrong - please try again")
return redirect(url_for("index"))
return render_template("booking.html", club=found_club, competition=found_competition)


@app.route("/purchasePlaces", methods=["POST"])
def purchase_places():
competition_name = request.form.get("competition")
club_name = request.form.get("club")
places_str = request.form.get("places")
try:
places_requested = int(places_str)
except ValueError:
flash("Le nombre de places est invalide.")
return redirect(url_for("index"))

success = booking_service.purchase_places(
club_name, competition_name, places_requested)
if success:
flash("Great-booking complete!")
else:
flash("Impossible de réserver ces places (Règle non respectée).")

club = booking_service.club_manager.find_by_name(club_name)
return render_template("welcome.html", club=club, competitions=booking_service.competition_manager.competitions)


@app.route("/clubsPoints")
def clubs_points():
return render_template("clubs_points.html", clubs=booking_service.club_manager.clubs)


@app.route("/logout")
def logout():
return redirect(url_for("index"))
31 changes: 31 additions & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!-- app/templates/base.html -->
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}GUDLFT{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<nav>
<ul>
<li><a href="{{ url_for('index') }}">Accueil</a></li>
<li><a href="{{ url_for('clubs_points') }}">Points Clubs</a></li>
<li><a href="{{ url_for('logout') }}">Déconnexion</a></li>
</ul>
</nav>
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class="flashes">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
</body>
</html>
16 changes: 16 additions & 0 deletions app/templates/booking.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!-- app/templates/booking.html -->
{% extends "base.html" %}

{% block title %}Réservation | {{ competition['name'] }}{% endblock %}

{% block content %}
<h2>{{ competition['name'] }}</h2>
<p>Places disponibles: {{ competition['number_of_places'] }}</p>
<form action="/purchasePlaces" method="post">
<input type="hidden" name="club" value="{{ club['name'] }}">
<input type="hidden" name="competition" value="{{ competition['name'] }}">
<label for="places">Combien de places ?</label>
<input type="number" name="places" id="places" min="1" required>
<button type="submit">Réserver</button>
</form>
{% endblock %}
24 changes: 24 additions & 0 deletions app/templates/clubs_points.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!-- app/templates/clubs_points.html -->
{% extends "base.html" %}

{% block title %}Points des Clubs{% endblock %}

{% block content %}
<h2>Points des Clubs</h2>
<table border="1">
<thead>
<tr>
<th>Club</th>
<th>Points</th>
</tr>
</thead>
<tbody>
{% for club in clubs %}
<tr>
<td>{{ club['name'] }}</td>
<td>{{ club['points'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
13 changes: 13 additions & 0 deletions app/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- app/templates/index.html -->
{% extends "base.html" %}

{% block title %}Accueil | GUDLFT{% endblock %}

{% block content %}
<h1>Bienvenue sur GUDLFT</h1>
<form action="/showSummary" method="post">
<label for="email">Email :</label>
<input type="email" name="email" id="email" required>
<button type="submit">Se connecter</button>
</form>
{% endblock %}
21 changes: 21 additions & 0 deletions app/templates/welcome.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- app/templates/welcome.html -->
{% extends "base.html" %}

{% block title %}Résumé | GUDLFT Registration{% endblock %}

{% block content %}
<h2>Welcome, {{ club['email'] }}</h2>
<p>Points disponibles: {{ club['points'] }}</p>
<h3>Compétitions :</h3>
<ul>
{% for comp in competitions %}
<li>
{{ comp['name'] }}<br />
Date: {{ comp['date'] }}<br />
Places disponibles: {{ comp['number_of_places'] }}<br />
<a href="{{ url_for('book', competition=comp['name'], club=club['name']) }}">Réserver</a>
</li>
<hr />
{% endfor %}
</ul>
{% endblock %}
Loading