sequenceDiagram
participant Vue
participant Service
participant Dao
participant BDD
Note over Vue: MenuJoueurVue
Vue->>Vue: Choice "S'inscrire à un tournoi"
Note over Vue: InscriptionTournoiVue
Vue->>Service: TournoiService.lister_tous()
Note over Service: TournoiService
Service->>Dao: TournoiDao.lister_tous()
Dao->>BDD: SELECT * FROM tournoi
BDD-->>Dao: tournois JSON
Dao-->>Service: list[Tournoi]
Service-->>Vue: list[Tournoi]
Vue->>Vue: Affiche la liste, option Retour<br> Attend une sélection
Vue->>Service: JoueurService.s_inscrire_tournoi(tournoi)
Note over Service: JoueurService
Service->>Dao: InscriptionDao.est_inscrit(joueur,tournoi)
Dao->>BDD: SELECT COUNT(*)<br> FROM inscription<br> WHERE id_joueur=? <br>AND id_tournoi=?
BDD-->>Dao: true/false
Dao-->>Service: true/false
Service-->>Vue: if true, back to MenuJoueurVue
Service->>Dao: TournoiDao.est_complet(tournoi)
Dao->>BDD: SELECT FROM tournoi, inscription
BDD-->>Dao: true/false
Dao-->>Service: true/false
Service-->>Vue: if false, back to MenuJoueurVue
Service-->>Dao: InscriptionDao.creer(tournoi, joueur)
Dao->>BDD: INSERT INTO inscription
BDD-->>Dao: true/false
Dao-->>Service: true/false
Service-->>Vue: back to MenuJoueurVue
Bonus: revise layer programming
Objectives
For the moment, this application simply contains a list of players.
The aim will be to create a feature that will allow players to register for tournaments.
We will proceed step by step.
Before you start
You will work on a fork or a copy of the repo ENSAI-2A-projet-info-template.
1 Initialisation of views
If this item is selected, you must now access the list of tournaments in a new view.
It will display the list of tournaments and allow the user to choose which one they want to register for.
- You will need a service method that returns the list of all tournaments
- TournoiService.lister_tous() -> list[Tournoi]
- The list of tournaments will be available in the database
- a service method should not communicate directly with a database; that is the role of a DAO
- The dao method TournoiDao.lister_tous() -> list[Tournoi] will communicate with the database to transfer the list of tournaments to the service method
- To transfer tournament lists, you must also create Tournoi business object
Now we are beginning to get an idea of the methods and objects to create.
2 Create the business object
Let us begin by creating the Tournoi business object.
Business objects mainly contain attributes and few methods. They are primarily used to transfer information between layers.
-
- attributes: id_tournoi, nom, ville, capacite_max
- add a constructor with all attributes
3 Map it with a database table
Usually, the business object class and its attributes correspond to the table and columns in the database.
Assuming that a player can participate in several tournaments and that a tournament can have several players, it is therefore necessary to create a table to keep track of which player is participating in which tournament.
CREATE TABLE tournoi (
id_tournoi SERIAL PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
ville VARCHAR(100) NOT NULL,
capacite_max INT CHECK (capacite_max > 0)
);
CREATE TABLE inscription (
id_inscription SERIAL PRIMARY KEY,
id_tournoi INT NOT NULL REFERENCES tournoi(id_tournoi),
id_joueur INT NOT NULL REFERENCES joueur(id_joueur),
UNIQUE(id_tournoi, id_joueur) -- un joueur ne peut pas s inscrire deux fois au meme tournoi
);4 DAO
We now need the DAO method, which allows us to retrieve the list of tournaments from the database.
5 Service
The view does not communicate directly with the DAO. It must request the service class.
Even though in this case, the service method simply flat passes: it receives a tournament list and returns that same list.
6 Back to the view
Great, we now have a service method that allows us to obtain a list of all tournaments. We will display it so that players can choose.
In view InscriptionTournoiVue:
If they change their mind, players can also return to the previous menu without registering for any tournament.
You will need to manage the registration:
- JoueurService.s_inscrire_tournoi(tournoi) -> bool
- This service must verify that the registration is valid
- If so, a row will be created in the inscription table
- Therefore, the service will need to use the dao method InscriptionDao.creer(joueur, tournoi) -> bool
7 Methods needed
In this method we will call InscriptionDao.creer(joueur, tournoi) -> bool.
This method requires two parameters:
- tournoi: easy to get it, it is a parameter of calling method s_inscrire_tournoi(tournoi)
- joueur: how to get it?
joueur_service.py
class JoueurService:
...
def s_inscrire_tournoi(self, tournoi) -> bool:
...
succes = InscriptionDao.creer(joueur, tournoi)This is where the Session class comes into play.
7.1 Session
When a player is logged in, we must have access to their information at all times.
This is the role of the Session class.
So we can get the player using Session().joueur
7.2 Back to service method s_inscrire_tournoi()
joueur_service.py
from view.session import Session
class JoueurService:
...
def s_inscrire_tournoi(self, tournoi) -> bool:
...
joueur = Session().joueur
succes = InscriptionDao.creer(joueur, tournoi)Great, we have everything we need to call the dao method to create an Inscription, but aren’t there a few things we should check first?
What if the player is already registered?
Now let’s check that the tournament is not already full:
8 Let’s finish the view
To summarise the flows
The principle would be broadly the same. You will need the same services, but instead of going through views:
- create a endpoint
GET /tournamentto display the list - create a endpoint
POST /registration body: {player_id: ?, tournament_id: ?}