Compare commits
No commits in common. "back-sp-security" and "master" have entirely different histories.
back-sp-se
...
master
35 changed files with 1 additions and 2080 deletions
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
|
|
@ -1,9 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
|
||||||
<file type="web" url="file://$PROJECT_DIR$/FencerJudgeBack" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager">
|
<component name="ProjectRootManager">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
|
|
@ -2,6 +2,7 @@
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/FencerJudgeBack/FencerJudgeBack.iml" filepath="$PROJECT_DIR$/FencerJudgeBack/FencerJudgeBack.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/jpe-controle.iml" filepath="$PROJECT_DIR$/jpe-controle.iml" />
|
<module fileurl="file://$PROJECT_DIR$/jpe-controle.iml" filepath="$PROJECT_DIR$/jpe-controle.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
# Entités
|
|
||||||
## MATCHES (MatchBean)
|
|
||||||
- id -> Long
|
|
||||||
- country -> String
|
|
||||||
- city -> String
|
|
||||||
- weapon -> String
|
|
||||||
- player1ID -> Long
|
|
||||||
- player2ID -> Long
|
|
||||||
- refereeID (arbitre) -> Long
|
|
||||||
- score1 (score du joueur 1) -> Integer
|
|
||||||
- score2 (score du joueur 2) -> Integer
|
|
||||||
- date -> Date
|
|
||||||
- state (état du match : en cours, terminé, pas commencé) -> Integer (ENUM)
|
|
||||||
|
|
||||||
## ETATS D'UN MATCH (MatchesStates)
|
|
||||||
- ONGOING -> Integer (1)
|
|
||||||
- OVER -> Integer (2)
|
|
||||||
- NOT STARTED -> Integer (3)
|
|
||||||
|
|
||||||
## ARBITRES (RefereeBean)
|
|
||||||
- id -> Long
|
|
||||||
- name (nom de famille) -> String
|
|
||||||
- firstName (prénom) -> String
|
|
||||||
- qualification -> String
|
|
||||||
|
|
||||||
## JOUEURS (PlayerBean)
|
|
||||||
- id -> Long
|
|
||||||
- name (nom de famille) -> String
|
|
||||||
- firstName (prénom) -> String
|
|
||||||
- club -> String
|
|
||||||
|
|
||||||
# Actions REST sur les entités
|
|
||||||
## matches (MatchRestController, "/matches")
|
|
||||||
- Lister tous les matches -> **GET "/matches/"** -> List<MatchBean>
|
|
||||||
- Lister tous les matches à partir d'une certaine date -> **GET "/matches/date=&date"** -> List<MatchBean>
|
|
||||||
- Lister les matches en cours (état : en cours) -> **GET "/matches/active"** -> List<MatchBean>
|
|
||||||
- Lister les matches terminés (état : terminé) -> **GET "/matches/over"** -> List<MatchBean>
|
|
||||||
- Lister les matches non commencés (état : non commencé) -> **GET "/matches/not-started"** -> List<MatchBean>
|
|
||||||
- Afficher un match par id -> **GET "/matches/id=&id"** -> MatchBean
|
|
||||||
- Mettre à jour les score d'un match récupéré par id -> **POST "/matches/update-match"**
|
|
||||||
{
|
|
||||||
id=$id,
|
|
||||||
score1=$score1,
|
|
||||||
score2=$score2
|
|
||||||
}
|
|
||||||
-> MatchBean
|
|
||||||
- Ajouter un match -> **POST "/matches/add-match"**
|
|
||||||
{
|
|
||||||
date=$date,
|
|
||||||
country=$country
|
|
||||||
city=$city,
|
|
||||||
weapon=$weapon,
|
|
||||||
refereeID=$refereeID,
|
|
||||||
player1ID=$player1ID,
|
|
||||||
player2ID=$player2ID,
|
|
||||||
|
|
||||||
}
|
|
||||||
-> MatchBean
|
|
||||||
- Supprimer un match (supprimer élément de MatchRepository en récupérant l'id) -> **POST "/matches/delete-match"**
|
|
||||||
{
|
|
||||||
id=$id
|
|
||||||
}
|
|
||||||
|
|
||||||
## ARBITRES (RefereeRestController, "/referees") :
|
|
||||||
- Lister tous les arbitres -> **GET "/referees/"** -> List<RefereeBean>
|
|
||||||
- Afficher un arbitre par id -> **GET "/referees/id=$id"** -> RefereeBean
|
|
||||||
- Afficher un arbitre par nom ->**GET "/referees/name=$name"** -> RefereeBean
|
|
||||||
- Ajouter un arbitre ->**POST "/referees/add-referee"**
|
|
||||||
{
|
|
||||||
name=$name,
|
|
||||||
firstName=$firstName,
|
|
||||||
qualification=$qualification
|
|
||||||
}
|
|
||||||
-> RefereeBean
|
|
||||||
- Supprimer un arbitre ->**POST "/referees/delete-referee/"**
|
|
||||||
{
|
|
||||||
id=$id
|
|
||||||
}
|
|
||||||
|
|
||||||
## JOUEURS (PlayerRestController, "/players") :
|
|
||||||
- Lister tous les joueurs ->**GET "/players/"** -> List<PlayerBean>
|
|
||||||
- Afficher un joueur par id ->**GET "/players/id=$id"** -> PlayerBean
|
|
||||||
- Afficher un joueur par nom ->**GET "/players/name=$name"** -> PlayerBean
|
|
||||||
- Ajouter un joueur ->**POST "/players/add-player"**
|
|
||||||
{
|
|
||||||
name=$name,
|
|
||||||
firstName=$firstName,
|
|
||||||
club=$club
|
|
||||||
}
|
|
||||||
-> PlayerBean
|
|
||||||
- Supprimer un joueur ->**POST "/players/delete-player"**
|
|
||||||
{
|
|
||||||
id=$id
|
|
||||||
}
|
|
||||||
|
|
||||||
# Websocket (http://localhost:8080/ws)
|
|
||||||
- Vider le channel
|
|
||||||
- Insérer une donnée dans le channel
|
|
||||||
- Modifier une donnée dans le channel
|
|
||||||
- Supprimer une donnée du channel
|
|
||||||
|
|
||||||
## MATCHES
|
|
||||||
## matches (MatchRestController, "/matches")
|
|
||||||
- Lister tous les matches -> dans le channel Websocket
|
|
||||||
- Lister tous les matches à partir d'une certaine date -> dans le channel Websocket
|
|
||||||
- Lister les matches en cours (état : en cours) -> **GET "/matches/active"** -> List<MatchBean>
|
|
||||||
- Lister les matches terminés (état : terminé) -> **GET "/matches/over"** -> List<MatchBean>
|
|
||||||
- Lister les matches non commencés (état : non commencé) -> **GET "/matches/not-started"** -> List<MatchBean>
|
|
||||||
- Afficher un match par id -> **GET "/matches/id=&id"** -> MatchBean
|
|
||||||
- Mettre à jour les score d'un match récupéré par id -> **POST "/matches/update-match"**
|
|
||||||
{
|
|
||||||
id=$id,
|
|
||||||
score1=$score1,
|
|
||||||
score2=$score2
|
|
||||||
}
|
|
||||||
-> MatchBean
|
|
||||||
- Ajouter un match -> **POST "/matches/add-match"**
|
|
||||||
{
|
|
||||||
date=$date,
|
|
||||||
country=$country
|
|
||||||
city=$city,
|
|
||||||
weapon=$weapon,
|
|
||||||
refereeID=$refereeID,
|
|
||||||
player1ID=$player1ID,
|
|
||||||
player2ID=$player2ID,
|
|
||||||
|
|
||||||
}
|
|
||||||
-> MatchBean
|
|
||||||
- Supprimer un match (supprimer élément de MatchRepository en récupérant l'id) -> **POST "/matches/delete-match"**
|
|
||||||
{
|
|
||||||
id=$id
|
|
||||||
}
|
|
||||||
|
|
||||||
## REFEREES
|
|
||||||
|
|
||||||
|
|
||||||
## PLAYERS
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
corriger les services - V
|
|
||||||
tester les restcontrollers via des requêtes http - V
|
|
||||||
créer la bdd avec toutes les tables (repositories) - V
|
|
||||||
tester le websocket -
|
|
||||||
prévoir l'utilisation en admin uniquement (spring security)
|
|
||||||
faire le jackarta de l'api
|
|
||||||
|
|
@ -22,21 +22,10 @@ dependencies {
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
|
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
implementation("org.springframework.boot:spring-boot-starter-validation")
|
|
||||||
|
|
||||||
// WEBSOCKET
|
|
||||||
implementation("org.springframework.boot:spring-boot-starter-websocket")
|
|
||||||
|
|
||||||
// SECURITY
|
|
||||||
implementation("org.springframework.boot:spring-boot-starter-security")
|
|
||||||
|
|
||||||
// H2 Database
|
|
||||||
runtimeOnly("com.h2database:h2")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|
|
||||||
|
|
@ -1,269 +0,0 @@
|
||||||
## Websocket
|
|
||||||
// Ouvrir channel websocket sur port 8500 --> DONE
|
|
||||||
function startWebsocket(var integer port) -> Websocket:
|
|
||||||
var Websocket websocket = start Websocket at port [port]
|
|
||||||
return websocket
|
|
||||||
|
|
||||||
## Entités
|
|
||||||
MATCHS -> MatchBean, MatchRepository
|
|
||||||
MatchBean:
|
|
||||||
- id:Long
|
|
||||||
- player1:PlayerBean
|
|
||||||
- player2:PlayerBean
|
|
||||||
- referee:RefereeBean
|
|
||||||
- score1:Int (score du player1)
|
|
||||||
- score2:Int (score du player2)
|
|
||||||
- date:String (date du match)
|
|
||||||
- state:String (état du match : terminé, en cours, pas commencé)
|
|
||||||
|
|
||||||
REFEREES (arbitres) -> RefereeBean, RefereeRepository
|
|
||||||
RefereeBean:
|
|
||||||
- id:Long
|
|
||||||
- name:Long (nom)
|
|
||||||
- firstName:String (prénom)
|
|
||||||
|
|
||||||
PLAYERS -> PlayerBean, PlayerRepository
|
|
||||||
PlayerBean:
|
|
||||||
- id:Long
|
|
||||||
- name:String (nom)
|
|
||||||
- firstName:String (prénom)
|
|
||||||
|
|
||||||
## Services
|
|
||||||
MatchService --> DONE:
|
|
||||||
// Obtenir tous les matchs (public) --> DONE
|
|
||||||
function getAll() -> array<MatchBean> :
|
|
||||||
return MatchRepository.getAll()
|
|
||||||
|
|
||||||
// Obtenir un match par id (public) --> DONE
|
|
||||||
function getById(var long id) -> MatchBean :
|
|
||||||
return MatchRepository.findById(id)
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs match(s) par joueurs (id) (public) --> DONE
|
|
||||||
function getByPlayers(var long player1ID, var long player2ID) -> array<MatchBean> {
|
|
||||||
return MatchRepository.getAll().filterBy(player1ID or player2ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter un match (admin) --> DONE
|
|
||||||
function createMatch(var MatchBean newMatch) -> MatchBean :
|
|
||||||
MatchRepository.add(newMatch)
|
|
||||||
return newMatch
|
|
||||||
|
|
||||||
// Modifier un match (admin) --> DONE
|
|
||||||
function updateMatch(var long id, var Date date, var long refereeID, var long player1ID, var long player2ID, var integer scorePlayer1, var integer scorePlayer2, var Date date, var string matchState) -> integr (success or not):
|
|
||||||
// Vérifier si le match existe à l'id renseigné
|
|
||||||
if MatchRepository.getById(id) doesn't exist {
|
|
||||||
return FAILED
|
|
||||||
}
|
|
||||||
|
|
||||||
// Créer nouveau MatchBean à l'id renseigné
|
|
||||||
var MatchBean newMatch = new MatchBean(id, player1ID, player2ID, refereeID, score1, score2, date, state)
|
|
||||||
|
|
||||||
// Supprimer le MatchBean à l'id en paramètre
|
|
||||||
MatchRepository.deleteById(id)
|
|
||||||
|
|
||||||
// Insérer le nouveau MatchBean à l'id en paramètre
|
|
||||||
MatchRepository.add(newMatch)
|
|
||||||
|
|
||||||
return SUCCESS
|
|
||||||
|
|
||||||
|
|
||||||
// Supprimer un match (admin) --> DONE
|
|
||||||
function deleteMatch(var long id) -> integer (success or failure) :
|
|
||||||
try:
|
|
||||||
MatchRepository.deleteById(id)
|
|
||||||
catch error:
|
|
||||||
return FAILED
|
|
||||||
|
|
||||||
return SUCCESS
|
|
||||||
|
|
||||||
RefereeService --> DONE:
|
|
||||||
// Obtenir tous les arbitres (public) --> DONE
|
|
||||||
function getAll() -> array<RefereeBean> :
|
|
||||||
return RefereeRepository.getAll()
|
|
||||||
|
|
||||||
// Obtenir un arbitre par id (public) --> DONE
|
|
||||||
function getById(var long id) -> RefereeBean :
|
|
||||||
return RefereeRepository.findById(id)
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs arbitre(s) par nom (public) --> DONE
|
|
||||||
function getByName(var string name) -> array<RefereeBean> :
|
|
||||||
return RefereeRepository.getAll().filterBy(name)
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs arbitre(s) par prénom (public)
|
|
||||||
function getByFirstName(var string firstName) -> array<RefereeBean> :
|
|
||||||
return RefereeRepository.getAll().filterBy(firstName)
|
|
||||||
|
|
||||||
// Ajouter un arbitre (admin) --> DONE
|
|
||||||
function createReferee(var RefereeBean newReferee) -> RefereeBean:
|
|
||||||
RefereeRepository.add(newReferee)
|
|
||||||
return newReferee
|
|
||||||
|
|
||||||
// Modifier un arbitre (admin) --> DONE
|
|
||||||
function updateReferee(var long id, var string name, var string firstName) -> integer (success or not):
|
|
||||||
|
|
||||||
// Vérifier si l'arbitre existe à l'id renseigné
|
|
||||||
if RefereeRepository.getById(id) doesn't exist {
|
|
||||||
return FAILED
|
|
||||||
}
|
|
||||||
|
|
||||||
// Créer nouveau RefereeBean à l'id renseigné
|
|
||||||
var RefereeBean newReferee = new RefereeBean(id, name, firstName)
|
|
||||||
|
|
||||||
// Supprimer le RefereeBean à l'id en paramètre
|
|
||||||
RefereeRepository.deleteById(id)
|
|
||||||
|
|
||||||
// Insérer le nouveau RefereeBean à l'id en paramètre
|
|
||||||
RefereeRepository.add(newReferee)
|
|
||||||
|
|
||||||
return SUCCESS
|
|
||||||
|
|
||||||
|
|
||||||
// Supprimer un arbitre (admin) --> DONE
|
|
||||||
function delete(var long id) -> integer (success or failure) :
|
|
||||||
try:
|
|
||||||
RefereeRepository.deleteById(id)
|
|
||||||
catch error:
|
|
||||||
return FAILED
|
|
||||||
|
|
||||||
return SUCCESS
|
|
||||||
|
|
||||||
PlayerService --> DONE:
|
|
||||||
// Obtenir tous les joueurs (public) --> DONE
|
|
||||||
function getAll() -> array<PlayerBean> :
|
|
||||||
return PlayerRepository.getAll()
|
|
||||||
|
|
||||||
// Obtenir un joueur par id (public) --> DONE
|
|
||||||
function getById(var long id) -> PlayerBean :
|
|
||||||
return PlayerRepository.findById(id)
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs joueur(s) par nom (public) --> DONE
|
|
||||||
function getByName(var string name) -> array<PlayerBean> :
|
|
||||||
return PlayerRepository.getAll().filterBy(name)
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs joueur(s) par prénom (public) --> DONE
|
|
||||||
function getByFirstName(var string firstName) -> array<PlayerBean> :
|
|
||||||
return PlayerRepository.getAll().filterBy(firstName)
|
|
||||||
|
|
||||||
// Ajouter un joueur (admin) --> DONE
|
|
||||||
function add(var PlayerBean newPlayer) -> PlayerBean:
|
|
||||||
PlayerRepository.add(newPlayer)
|
|
||||||
return newPlayer
|
|
||||||
|
|
||||||
// Modifier un joueur (admin) --> DONE
|
|
||||||
function update(var long id, var string name, var string firstName) -> PlayerBean :
|
|
||||||
// Créer nouveau PlayerBean
|
|
||||||
var PlayerBean newPlayer = new PlayerBean(id, name, firstName)
|
|
||||||
|
|
||||||
// Supprimer le PlayerBean à l'id en paramètre
|
|
||||||
deleteById(id)
|
|
||||||
|
|
||||||
// Insérer le nouveau PlayerBean à l'id en paramètre
|
|
||||||
PlayerRepository.add(newPlayer)
|
|
||||||
|
|
||||||
return newPlayer
|
|
||||||
|
|
||||||
// Supprimer un joueur (admin) --> DONE
|
|
||||||
function delete(var long id) -> integer (success or failure) :
|
|
||||||
try:
|
|
||||||
PlayerRepository.deleteById(id)
|
|
||||||
catch error:
|
|
||||||
return FAILED
|
|
||||||
|
|
||||||
return SUCCESS
|
|
||||||
|
|
||||||
## RestControllers
|
|
||||||
MatchRestController --> TODO:
|
|
||||||
// Lister tous les matchs --> DONE
|
|
||||||
function getAll() -> array<MatchBean> :
|
|
||||||
return MatchService.getAll()
|
|
||||||
|
|
||||||
// Lister tous les matchs à partir d'une certaine date
|
|
||||||
function getAllFromDate(var Date dateToFilter) -> array<MatchBean> :
|
|
||||||
return MatchService.getAll().filter(date == dateToFilter)
|
|
||||||
|
|
||||||
// Lister les matchs en cours (état : en cours)
|
|
||||||
function getAllActive() -> array<MatchBean> :
|
|
||||||
return MatchService.getAll().filter(state == "ONGOING")
|
|
||||||
|
|
||||||
// Lister les matchs terminés (état : terminé)
|
|
||||||
function getAllOver() -> array<MatchBean> :
|
|
||||||
return MatchService.getAll().filter(state == "FINISHED")
|
|
||||||
|
|
||||||
// Lister les matchs non commencés (état : non commencé)
|
|
||||||
function getAllNotStarted() -> array<MatchBean> :
|
|
||||||
// MatchService :
|
|
||||||
return MatchService.getAll().filter(state == "NOT STARTED")
|
|
||||||
|
|
||||||
// Afficher un match par id
|
|
||||||
function get(var long id) -> MatchBean :
|
|
||||||
return MatchService.get(id)
|
|
||||||
|
|
||||||
// Mettre à jour le score1 d'un match récupéré par id --> TODO
|
|
||||||
function updateScore1Of(var long id, var integer newScore) -> integer (success or failure) :
|
|
||||||
return MatchService.update(
|
|
||||||
|
|
||||||
// Mettre à jour le score2 d'un match récupéré par id --> TODO
|
|
||||||
function updateScore2Of(var long id, var integer newScore) -> integer (success or failure) :
|
|
||||||
return MatchService.update(
|
|
||||||
|
|
||||||
// Ajouter un match (créer nouveau MatchBean dans MatchRepository)
|
|
||||||
function add(var MatchBean newMatch) -> integer (success or failure):
|
|
||||||
return MatchService.add(newMatch)
|
|
||||||
|
|
||||||
// Supprimer un match (supprimer élément de MatchRepository en récupérant l'id)
|
|
||||||
function deleteById(var long id) -> integer (success or failure) :
|
|
||||||
return MatchService.deleteById(id)
|
|
||||||
|
|
||||||
RefereeRestController --> DONE:
|
|
||||||
// Lister tous les arbitres
|
|
||||||
function getAll() -> array<RefereeBean> :
|
|
||||||
return RefereeService.getAll()
|
|
||||||
|
|
||||||
// Afficher un arbitre par id
|
|
||||||
function get(var long id) -> RefereeBean :
|
|
||||||
return RefereeService.get(id)
|
|
||||||
|
|
||||||
// Afficher un arbitre par nom
|
|
||||||
function get(var string name) -> RefereeBean:
|
|
||||||
return RefereeService.get(name)
|
|
||||||
|
|
||||||
// Ajouter un arbitre (créer nouveau RefereeBean dans RefereeRepository)
|
|
||||||
function add(var RefereeBean newReferee) -> integer (success or failure) :
|
|
||||||
return RefereeService.add(newReferee)
|
|
||||||
|
|
||||||
// Supprimer un arbitre (supprimer élément de RefereeRepository en récupérant l'id)
|
|
||||||
function deleteById(var long id) -> integer (success or failure) :
|
|
||||||
return RefereeService.deleteById(id)
|
|
||||||
|
|
||||||
PlayerRestController --> DONE:
|
|
||||||
// Lister tous les joueurs
|
|
||||||
function getAll() -> array<PlayerBean> :
|
|
||||||
return PlayerService.getAll()
|
|
||||||
|
|
||||||
// Afficher un joueur par id
|
|
||||||
function get(var long id) -> PlayerBean :
|
|
||||||
return PlayerService.get(id)
|
|
||||||
|
|
||||||
// Afficher un joueur par nom
|
|
||||||
function get(var string name) -> PlayerBean :
|
|
||||||
return PlayerService.get(name)
|
|
||||||
|
|
||||||
// Ajouter un joueur (créer nouveau PlayerBean dans PlayerRepository)
|
|
||||||
function add(var PlayerBean newPlayer) -> integer (success or failure) :
|
|
||||||
return PlayerService.add(newPlayer)
|
|
||||||
|
|
||||||
// Supprimer un joueur (supprimer élément de PlayerRepository en récupérant l'id)
|
|
||||||
function deleteById(var long id) -> integer (success or failure) :
|
|
||||||
return PlayerService.deleteById(id)
|
|
||||||
|
|
||||||
## Pages
|
|
||||||
Page des matchs (publique) :
|
|
||||||
à définir (partie front sur Angular ?)
|
|
||||||
|
|
||||||
Page de connexion à l'administration (publique) :
|
|
||||||
formulaire :
|
|
||||||
- nom d'utilisateur
|
|
||||||
- mot de passe
|
|
||||||
|
|
||||||
Page d'administration (privée) :
|
|
||||||
à définir (partie front sur Angular ?)
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.config
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.context.annotation.Bean
|
|
||||||
import org.springframework.context.annotation.Configuration
|
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
|
||||||
import org.springframework.security.core.userdetails.User
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService
|
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager
|
|
||||||
import org.springframework.security.web.SecurityFilterChain
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
class SecurityConfig {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
open fun configureGlobal(auth: AuthenticationManagerBuilder) {
|
|
||||||
val encoder = BCryptPasswordEncoder()
|
|
||||||
|
|
||||||
//Créer des utilisateurs fixes
|
|
||||||
auth.inMemoryAuthentication()
|
|
||||||
.passwordEncoder(encoder)
|
|
||||||
.withUser("aaa")
|
|
||||||
.password(encoder.encode("bbb"))
|
|
||||||
.roles("USER")
|
|
||||||
.and()
|
|
||||||
.withUser("Admin")
|
|
||||||
.password(encoder.encode("Admin"))
|
|
||||||
.roles("ADMIN")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
|
||||||
http.authorizeHttpRequests { authorize ->
|
|
||||||
authorize.requestMatchers("/ws/*").authenticated()
|
|
||||||
.anyRequest().permitAll()
|
|
||||||
}
|
|
||||||
.httpBasic { }
|
|
||||||
.formLogin { }
|
|
||||||
.csrf { it.disable() }
|
|
||||||
return http.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun userDetailsService(): UserDetailsService {
|
|
||||||
val user = User.withUsername("user")
|
|
||||||
.password("{noop}password") // {noop} = pas de hash pour dev
|
|
||||||
.roles("USER")
|
|
||||||
.build()
|
|
||||||
|
|
||||||
return InMemoryUserDetailsManager(user)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.config
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration
|
|
||||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry
|
|
||||||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
|
|
||||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry
|
|
||||||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
|
|
||||||
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor
|
|
||||||
|
|
||||||
const val CHANNEL_MATCH_NAME: String = "/ws/topic/match"
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSocketMessageBroker
|
|
||||||
open class MatchWebSocketConfig : WebSocketMessageBrokerConfigurer {
|
|
||||||
|
|
||||||
override fun configureMessageBroker(registry: MessageBrokerRegistry) {
|
|
||||||
// Enable a simple memory-based message broker to send messages to clients
|
|
||||||
// Prefix for messages FROM server TO client
|
|
||||||
registry.enableSimpleBroker(CHANNEL_MATCH_NAME)
|
|
||||||
|
|
||||||
// Prefix for messages FROM client TO server
|
|
||||||
registry.setApplicationDestinationPrefixes("/ws")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
|
|
||||||
// Register the "/ws" endpoint, enabling SockJS fallback options
|
|
||||||
registry.addEndpoint("/ws/matches-app")
|
|
||||||
.addInterceptors(HttpSessionHandshakeInterceptor())
|
|
||||||
.setAllowedOriginPatterns("*") // Allow connections from any origin (adjust for production)
|
|
||||||
.withSockJS()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.entities
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity
|
|
||||||
import jakarta.persistence.GeneratedValue
|
|
||||||
import jakarta.persistence.GenerationType
|
|
||||||
import jakarta.persistence.Id
|
|
||||||
import jakarta.persistence.SequenceGenerator
|
|
||||||
import jakarta.persistence.Table
|
|
||||||
import jakarta.validation.constraints.*
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name="matches")
|
|
||||||
data class MatchBean(
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "match_sequence")
|
|
||||||
@SequenceGenerator(name = "match_sequence", sequenceName = "match_seq", allocationSize = 1)
|
|
||||||
var id:Long?=null,
|
|
||||||
val weapon:String?=null,
|
|
||||||
val country:String?=null,
|
|
||||||
val city:String?=null,
|
|
||||||
@field:NotNull(message = "Player 1 ID must not be null")
|
|
||||||
val player1ID:Long?=null,
|
|
||||||
@field:NotNull(message = "Player 2 ID must not be null")
|
|
||||||
val player2ID:Long?=null,
|
|
||||||
val refereeID: Long?=null,
|
|
||||||
@field:Min(value = 0, message = "Score must be at least 0")
|
|
||||||
var score1:Int=0,
|
|
||||||
@field:Min(value = 0, message = "Score must be at least 0")
|
|
||||||
var score2:Int=0,
|
|
||||||
val date: String?=null,
|
|
||||||
val state:String?=null
|
|
||||||
)
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.entities
|
|
||||||
|
|
||||||
data class MatchUpdateBean(val match: MatchBean?=null, val playerId:Long?=null)
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.entities
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity
|
|
||||||
import jakarta.persistence.GeneratedValue
|
|
||||||
import jakarta.persistence.GenerationType
|
|
||||||
import jakarta.persistence.Id
|
|
||||||
import jakarta.persistence.SequenceGenerator
|
|
||||||
import jakarta.persistence.Table
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name="players")
|
|
||||||
data class PlayerBean(
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "player_sequence")
|
|
||||||
@SequenceGenerator(name = "player_sequence", sequenceName = "player_seq", allocationSize = 1)
|
|
||||||
val id:Long?=null,
|
|
||||||
val name:String?="",
|
|
||||||
val firstName:String?="",
|
|
||||||
val club:String?=""
|
|
||||||
)
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.entities
|
|
||||||
|
|
||||||
import jakarta.persistence.Entity
|
|
||||||
import jakarta.persistence.GeneratedValue
|
|
||||||
import jakarta.persistence.GenerationType
|
|
||||||
import jakarta.persistence.Id
|
|
||||||
import jakarta.persistence.SequenceGenerator
|
|
||||||
import jakarta.persistence.Table
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name="referees")
|
|
||||||
data class RefereeBean(
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "referee_sequence")
|
|
||||||
@SequenceGenerator(name = "referee_sequence", sequenceName = "referee_seq", allocationSize = 1)
|
|
||||||
val id:Long?=null,
|
|
||||||
val name:String?=null,
|
|
||||||
val firstName:String?=null,
|
|
||||||
val qualification:String?=null
|
|
||||||
)
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.repositories
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.MatchBean
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
interface MatchRepository: JpaRepository<MatchBean, Long> {
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.repositories
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.PlayerBean
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
interface PlayerRepository: JpaRepository<PlayerBean, Long> {
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.repositories
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.RefereeBean
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
interface RefereeRepository : JpaRepository<RefereeBean, Long> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.restControllers
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
class MainController {
|
|
||||||
@GetMapping("/")
|
|
||||||
fun main() {
|
|
||||||
return print("Hello")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.restControllers
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.MatchBean
|
|
||||||
import fr.teamflash.fencerjudgeback.services.MatchService
|
|
||||||
import org.springframework.http.ResponseEntity
|
|
||||||
import org.springframework.web.bind.annotation.*
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/matches")
|
|
||||||
class MatchRestController(private val matchService: MatchService) {
|
|
||||||
|
|
||||||
// Lister tous les matchs
|
|
||||||
@GetMapping("/")
|
|
||||||
fun getAll(): ResponseEntity<List<MatchBean>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getAll())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lister tous les matchs à partir d'une certaine date
|
|
||||||
@GetMapping("/date/{date}")
|
|
||||||
fun getAllFromDate(@PathVariable date:String): ResponseEntity<List<MatchBean?>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getAll().filter { it.date == date })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lister tous les matchs par pays
|
|
||||||
@GetMapping("/country/{country}")
|
|
||||||
fun getAllFromCountry(@PathVariable country:String): ResponseEntity<List<MatchBean>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getAll().filter { it.country == country })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lister tous les matchs par ville
|
|
||||||
@GetMapping("/city/{city}")
|
|
||||||
fun getAllFromCity(@PathVariable city:String): ResponseEntity<List<MatchBean>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getAll().filter { it.city == city })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lister tous les matchs par joueurs
|
|
||||||
@GetMapping("/players/{player1ID}/{player2ID}")
|
|
||||||
fun getAllWithPlayers(@PathVariable player1ID: Long?, @PathVariable player2ID: Long?): ResponseEntity<List<MatchBean>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getByPlayers(player1ID, player2ID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lister les matchs en cours
|
|
||||||
@GetMapping("/active")
|
|
||||||
fun getAllActive(): ResponseEntity<List<MatchBean>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getAll().filter { it.state == "ACTIVE" })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lister les matchs terminés
|
|
||||||
@GetMapping("/over")
|
|
||||||
fun getAllFinished(): ResponseEntity<List<MatchBean>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getAll().filter { it.state == "FINISHED" })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lister les matchs non commencés
|
|
||||||
@GetMapping("/not-started")
|
|
||||||
fun getAllNotStarted(): ResponseEntity<List<MatchBean>?> {
|
|
||||||
return ResponseEntity.ok(matchService.getAll().filter { it.state == "NOT STARTED" })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un match par id
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
fun getById(@PathVariable id: Long): ResponseEntity<MatchBean?> {
|
|
||||||
return ResponseEntity.ok(matchService.getById(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter un match
|
|
||||||
@PostMapping("/create-match")
|
|
||||||
fun createMatch(@RequestBody match: MatchBean): ResponseEntity<MatchBean> {
|
|
||||||
// return ResponseEntity.status(HttpStatus.CREATED).body(matchService.createMatch(match))
|
|
||||||
return ResponseEntity.ok(matchService.createMatch(match))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mettre à jour un match
|
|
||||||
@PutMapping("/update-match/{id}")
|
|
||||||
fun updateMatch(@PathVariable id: Long, @RequestBody match: MatchBean): ResponseEntity<Int> {
|
|
||||||
return ResponseEntity.ok(matchService.updateMatch(id, match))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer un match
|
|
||||||
@DeleteMapping("/delete-match/{id}")
|
|
||||||
fun deleteMatch(@PathVariable id: Long): ResponseEntity<Int> {
|
|
||||||
return ResponseEntity.ok(matchService.deleteMatchById(id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.restControllers
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.PlayerBean
|
|
||||||
import fr.teamflash.fencerjudgeback.services.PlayerService
|
|
||||||
import org.springframework.http.ResponseEntity
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/players")
|
|
||||||
class PlayerRestController(private val playerService: PlayerService) {
|
|
||||||
|
|
||||||
// Lister tous les joueurs
|
|
||||||
@GetMapping("/")
|
|
||||||
fun getAll(): ResponseEntity<List<PlayerBean>> {
|
|
||||||
return ResponseEntity.ok(playerService.getAll())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un joueur par id
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
fun getById(@PathVariable id: Long): ResponseEntity<PlayerBean?> {
|
|
||||||
return ResponseEntity.ok(playerService.getById(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un ou plusieurs joueur(s) par nom
|
|
||||||
@GetMapping("/name/{name}")
|
|
||||||
fun getByName(@PathVariable name: String): ResponseEntity<List<PlayerBean?>?> {
|
|
||||||
return ResponseEntity.ok(playerService.getByName(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un ou plusieurs joueur(s) par prénom
|
|
||||||
@GetMapping("/firstName/{firstName}")
|
|
||||||
fun getByFirstName(@PathVariable firstName: String): ResponseEntity<List<PlayerBean?>?> {
|
|
||||||
return ResponseEntity.ok(playerService.getByFirstName(firstName))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un ou plusieurs joueur(s) par club
|
|
||||||
@GetMapping("/club/{club}")
|
|
||||||
fun getByClub(@PathVariable club: String): ResponseEntity<List<PlayerBean?>?> {
|
|
||||||
return ResponseEntity.ok(playerService.getByClub(club))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter un joueur
|
|
||||||
@PostMapping("/create-player")
|
|
||||||
fun createPlayer(@RequestBody player: PlayerBean): ResponseEntity<PlayerBean> {
|
|
||||||
return ResponseEntity.ok(playerService.createPlayer(player))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifier un joueur
|
|
||||||
@PutMapping("/update-player/{id}")
|
|
||||||
fun updatePlayer(@PathVariable id: Long, @RequestBody player: PlayerBean): ResponseEntity<Int> {
|
|
||||||
return ResponseEntity.ok(playerService.updatePlayer(id, player))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer un joueur
|
|
||||||
@DeleteMapping("/delete-player/{id}")
|
|
||||||
fun deletePlayer(@PathVariable id: Long): ResponseEntity<Int> {
|
|
||||||
return ResponseEntity.ok(playerService.deletePlayerById(id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.restControllers
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.RefereeBean
|
|
||||||
import fr.teamflash.fencerjudgeback.services.RefereeService
|
|
||||||
import org.springframework.http.ResponseEntity
|
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/referees")
|
|
||||||
class RefereeRestController(private val refereeService: RefereeService) {
|
|
||||||
|
|
||||||
// Lister tous les arbitres
|
|
||||||
@GetMapping("/")
|
|
||||||
fun getAll() : ResponseEntity<List<RefereeBean>> {
|
|
||||||
return ResponseEntity.ok(refereeService.getAll())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un arbitre par id
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
fun getById(@PathVariable id: Long): ResponseEntity<RefereeBean?> {
|
|
||||||
return ResponseEntity.ok(refereeService.getById(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un ou plusieurs arbitre(s) par nom
|
|
||||||
@GetMapping("/name/{name}")
|
|
||||||
fun getByName(@PathVariable name:String): ResponseEntity<List<RefereeBean?>?> {
|
|
||||||
return ResponseEntity.ok(refereeService.getByName(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un ou plusieurs arbitre(s) par prénom
|
|
||||||
@GetMapping("/firstname/{firstName}")
|
|
||||||
fun getByFirstName(@PathVariable firstName:String): ResponseEntity<List<RefereeBean?>?> {
|
|
||||||
return ResponseEntity.ok(refereeService.getByFirstName(firstName))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Afficher un ou plusieurs arbitre(s) par qualification
|
|
||||||
@GetMapping("/qualification/{qualification}")
|
|
||||||
fun getByQualification(@PathVariable qualification:String): ResponseEntity<List<RefereeBean?>?> {
|
|
||||||
return ResponseEntity.ok(refereeService.getByQualification(qualification))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter un arbitre
|
|
||||||
@PostMapping("/create-referee")
|
|
||||||
fun createReferee(@RequestBody referee: RefereeBean): ResponseEntity<RefereeBean> {
|
|
||||||
return ResponseEntity.ok(refereeService.createReferee(referee))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifier un arbitre
|
|
||||||
@PutMapping("/update-referee/{id}")
|
|
||||||
fun updateReferee(@PathVariable id: Long, @RequestBody referee: RefereeBean) : ResponseEntity<Int> {
|
|
||||||
return ResponseEntity.ok(refereeService.updateReferee(id, referee))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer un arbitre
|
|
||||||
@DeleteMapping("/delete-referee/{id}")
|
|
||||||
fun deleteReferee(@PathVariable id:Long): ResponseEntity<Int> {
|
|
||||||
return ResponseEntity.ok(refereeService.deleteRefereeById(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.services
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.MatchBean
|
|
||||||
import fr.teamflash.fencerjudgeback.repositories.MatchRepository
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.controllers.MatchWebSocketController
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.context.annotation.Lazy
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class MatchService(
|
|
||||||
@Autowired private val matchRepository: MatchRepository,
|
|
||||||
@Lazy private val matchWebSocketController: MatchWebSocketController? = null
|
|
||||||
) {
|
|
||||||
// Obtenir tous les matchs (public)
|
|
||||||
fun getAll() : List<MatchBean> {
|
|
||||||
println("MatchService.getMatchs")
|
|
||||||
return matchRepository.findAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un match par id (public)
|
|
||||||
fun getById(id: Long?): MatchBean? {
|
|
||||||
println("MatchService.getMatchById : $id")
|
|
||||||
|
|
||||||
if (id == null) {
|
|
||||||
println("MatchService.getMatchById : Match not found")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchRepository.findById(id).get()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs match(s) par joueurs (id) (public)
|
|
||||||
fun getByPlayers(player1ID: Long?, player2ID: Long?): List<MatchBean> {
|
|
||||||
println("MatchService.getMatchByPlayers : $player1ID - $player2ID")
|
|
||||||
return matchRepository.findAll().filter { it.player1ID == player1ID && it.player2ID == player2ID }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter un match (admin)
|
|
||||||
fun createMatch(newMatch: MatchBean): MatchBean {
|
|
||||||
println("MatchService.createMatch : $newMatch")
|
|
||||||
val savedMatch = matchRepository.save(newMatch)
|
|
||||||
// Broadcast the new match via WebSocket
|
|
||||||
matchWebSocketController?.broadcastMatchUpdate(savedMatch, fr.teamflash.fencerjudgeback.websocket.models.MatchUpdateMessage.UpdateType.MATCH_START)
|
|
||||||
|
|
||||||
return savedMatch
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifier un match (admin)
|
|
||||||
fun updateMatch(id: Long?, newMatch: MatchBean): Int {
|
|
||||||
println("MatchService.updateMatch : $newMatch")
|
|
||||||
|
|
||||||
if (getById(id) == null) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
val updatedMatch = newMatch.copy(id = id)
|
|
||||||
val savedMatch = matchRepository.save(updatedMatch)
|
|
||||||
// Broadcast the updated match via WebSocket
|
|
||||||
matchWebSocketController?.broadcastMatchUpdate(savedMatch, fr.teamflash.fencerjudgeback.websocket.models.MatchUpdateMessage.UpdateType.SCORE_UPDATE)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer un match (admin)
|
|
||||||
fun deleteMatchById(id: Long?) : Int? {
|
|
||||||
println("MatchService.deleteMatchById : $id")
|
|
||||||
|
|
||||||
val match = getById(id)
|
|
||||||
if (match == null) {
|
|
||||||
println("MatchService.deleteMatchById : Match not found")
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Broadcast the match deletion via WebSocket before deleting
|
|
||||||
matchWebSocketController?.broadcastMatchUpdate(match, fr.teamflash.fencerjudgeback.websocket.models.MatchUpdateMessage.UpdateType.MATCH_CANCEL)
|
|
||||||
|
|
||||||
matchRepository.deleteById(id!!)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMatchesByCity(city: String): List<MatchBean>? {
|
|
||||||
println("MatchService.getMatchesByCity : $city")
|
|
||||||
|
|
||||||
return matchRepository.findAll()
|
|
||||||
.filter { it.city == city }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMatchesByCountry(country: String): List<MatchBean>? {
|
|
||||||
println("MatchService.getMatchesByCountry : $country")
|
|
||||||
|
|
||||||
return matchRepository.findAll()
|
|
||||||
.filter { it.country == country }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addMatch(match:MatchBean) {
|
|
||||||
matchRepository.save(match)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.services
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.PlayerBean
|
|
||||||
import fr.teamflash.fencerjudgeback.repositories.PlayerRepository
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.controllers.PlayerWebSocketController
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.models.PlayerUpdateMessage
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.context.annotation.Lazy
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class PlayerService(
|
|
||||||
@Autowired private val playerRepository: PlayerRepository,
|
|
||||||
@Lazy private val playerWebSocketController: PlayerWebSocketController? = null
|
|
||||||
) {
|
|
||||||
// Obtenir tous les joueurs (public)
|
|
||||||
fun getAll(): List<PlayerBean> {
|
|
||||||
println("PlayerService.getAll")
|
|
||||||
return playerRepository.findAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un joueur par id (public)
|
|
||||||
fun getById(id:Long?) : PlayerBean? {
|
|
||||||
println("PlayerService.getById : $id")
|
|
||||||
|
|
||||||
if (id == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return playerRepository.findById(id).get()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs joueur(s) par nom (public)
|
|
||||||
fun getByName(name:String): List<PlayerBean?>? {
|
|
||||||
println("PlayerService.getByName : $name")
|
|
||||||
return playerRepository.findAll().filter{ it.name == name }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs joueur(s) par prénom
|
|
||||||
fun getByFirstName(firstName:String): List<PlayerBean?>? {
|
|
||||||
println("PlayerService.getByFirstName : $firstName")
|
|
||||||
return playerRepository.findAll().filter{ it.firstName == firstName }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs joueur(s) par club
|
|
||||||
fun getByClub(club:String): List<PlayerBean?>? {
|
|
||||||
println("PlayerService.getByClub : $club")
|
|
||||||
return playerRepository.findAll().filter{ it.club == club }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter un joueur (admin)
|
|
||||||
fun createPlayer(player: PlayerBean) : PlayerBean {
|
|
||||||
println("PlayerService.createPlayer : $player")
|
|
||||||
val savedPlayer = playerRepository.save(player)
|
|
||||||
// Broadcast the new player via WebSocket
|
|
||||||
playerWebSocketController?.broadcastPlayerUpdate(savedPlayer, PlayerUpdateMessage.UpdateType.PLAYER_CREATE)
|
|
||||||
return savedPlayer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifier un joueur (admin)
|
|
||||||
fun updatePlayer(id:Long, newPlayer: PlayerBean) : Int {
|
|
||||||
// Vérifier si le joueur existe à l'id renseigné
|
|
||||||
if (getById(id) == null) {
|
|
||||||
println("PlayerService.updatePlayer : Player not found")
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
val updatedPlayer = newPlayer.copy(id = id)
|
|
||||||
val savedPlayer = playerRepository.save(updatedPlayer)
|
|
||||||
// Broadcast the updated player via WebSocket
|
|
||||||
playerWebSocketController?.broadcastPlayerUpdate(savedPlayer, PlayerUpdateMessage.UpdateType.PLAYER_UPDATE)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer un joueur (admin)
|
|
||||||
fun deletePlayerById(id:Long?): Int {
|
|
||||||
println("PlayerService.deletePlayer : $id")
|
|
||||||
|
|
||||||
val player = getById(id)
|
|
||||||
if (player == null) {
|
|
||||||
println("PlayerService.deletePlayer : Player not found")
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Broadcast the player deletion via WebSocket before deleting
|
|
||||||
playerWebSocketController?.broadcastPlayerUpdate(player, PlayerUpdateMessage.UpdateType.PLAYER_DELETE)
|
|
||||||
|
|
||||||
playerRepository.deleteById(id!!)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addPlayer(player:PlayerBean) {
|
|
||||||
playerRepository.save(player)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.services
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.RefereeBean
|
|
||||||
import fr.teamflash.fencerjudgeback.repositories.RefereeRepository
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.controllers.RefereeWebSocketController
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.models.RefereeUpdateMessage
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.context.annotation.Lazy
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class RefereeService(
|
|
||||||
@Autowired private val refereeRepository: RefereeRepository,
|
|
||||||
@Lazy private val refereeWebSocketController: RefereeWebSocketController? = null
|
|
||||||
) {
|
|
||||||
// Obtenir tous les arbitres (public)
|
|
||||||
fun getAll(): List<RefereeBean> {
|
|
||||||
println("RefereeService.getReferees")
|
|
||||||
return refereeRepository.findAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un arbitre par id (public)
|
|
||||||
fun getById(id:Long?) : RefereeBean? {
|
|
||||||
println("RefereeService.getRefereeById : $id")
|
|
||||||
|
|
||||||
if (id == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return refereeRepository.findById(id).get()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs arbitre(s) par nom (public)
|
|
||||||
fun getByName(name:String): List<RefereeBean?>? {
|
|
||||||
println("RefereeService.getRefereeByName : $name")
|
|
||||||
return refereeRepository.findAll().filter{ it.name == name }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs arbitre(s) par prénom
|
|
||||||
fun getByFirstName(firstName:String): List<RefereeBean?>? {
|
|
||||||
println("RefereeService.getRefereeByFirstName : $firstName")
|
|
||||||
return refereeRepository.findAll().filter{ it.firstName == firstName }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtenir un ou plusieurs arbitre(s) par qualification
|
|
||||||
fun getByQualification(qualification:String): List<RefereeBean?>? {
|
|
||||||
println("RefereeService.getRefereeByQualification : $qualification")
|
|
||||||
return refereeRepository.findAll().filter{ it.qualification == qualification }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajouter un arbitre (admin)
|
|
||||||
fun createReferee(referee: RefereeBean) : RefereeBean {
|
|
||||||
println("RefereeService.createReferee : $referee")
|
|
||||||
val savedReferee = refereeRepository.save(referee)
|
|
||||||
// Broadcast the new referee via WebSocket
|
|
||||||
refereeWebSocketController?.broadcastRefereeUpdate(savedReferee, RefereeUpdateMessage.UpdateType.REFEREE_CREATE)
|
|
||||||
return savedReferee
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifier un arbitre (admin)
|
|
||||||
fun updateReferee(id:Long, newReferee: RefereeBean) : Int? {
|
|
||||||
// Vérifier si l'arbitre existe à l'id renseigné
|
|
||||||
if (getById(id) == null) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
val updatedReferee = newReferee.copy(id = id)
|
|
||||||
val savedReferee = refereeRepository.save(updatedReferee)
|
|
||||||
// Broadcast the updated referee via WebSocket
|
|
||||||
refereeWebSocketController?.broadcastRefereeUpdate(savedReferee, RefereeUpdateMessage.UpdateType.REFEREE_UPDATE)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer un arbitre (admin)
|
|
||||||
fun deleteRefereeById(id:Long): Int {
|
|
||||||
println("RefereeService.deleteReferee : $id")
|
|
||||||
|
|
||||||
val referee = getById(id)
|
|
||||||
if (referee == null) {
|
|
||||||
println("RefereeService.deleteReferee : Referee not found")
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Broadcast the referee deletion via WebSocket before deleting
|
|
||||||
refereeWebSocketController?.broadcastRefereeUpdate(referee, RefereeUpdateMessage.UpdateType.REFEREE_DELETE)
|
|
||||||
|
|
||||||
refereeRepository.deleteById(id)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
# WebSocket Implementation for FencerJudge
|
|
||||||
|
|
||||||
This document explains how to use the WebSocket functionality in the FencerJudge application for real-time match updates.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The WebSocket implementation allows for real-time updates of match information, including:
|
|
||||||
- Match creation
|
|
||||||
- Score updates
|
|
||||||
- Match completion
|
|
||||||
- Match cancellation
|
|
||||||
|
|
||||||
## WebSocket Endpoints
|
|
||||||
|
|
||||||
### Connection Endpoint
|
|
||||||
```
|
|
||||||
ws://localhost:8080/ws
|
|
||||||
```
|
|
||||||
|
|
||||||
The WebSocket endpoint supports SockJS for fallback in browsers that don't support WebSockets natively.
|
|
||||||
|
|
||||||
## Message Topics
|
|
||||||
|
|
||||||
### Subscribe to Match Updates
|
|
||||||
To receive real-time match updates, subscribe to:
|
|
||||||
```
|
|
||||||
/topic/match.updates
|
|
||||||
```
|
|
||||||
|
|
||||||
### Send Match Updates
|
|
||||||
To send match updates from the client to the server:
|
|
||||||
```
|
|
||||||
/app/match.update
|
|
||||||
```
|
|
||||||
|
|
||||||
## Message Format
|
|
||||||
|
|
||||||
Match update messages use the following JSON format:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"matchId": 1,
|
|
||||||
"player1Id": 101,
|
|
||||||
"player2Id": 102,
|
|
||||||
"refereeId": 201,
|
|
||||||
"score1": 5,
|
|
||||||
"score2": 3,
|
|
||||||
"date": "2023-06-01",
|
|
||||||
"type": "SCORE_UPDATE"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `type` field can have the following values:
|
|
||||||
- `SCORE_UPDATE`: When a match score is updated
|
|
||||||
- `MATCH_START`: When a new match is created
|
|
||||||
- `MATCH_END`: When a match is completed
|
|
||||||
- `MATCH_CANCEL`: When a match is cancelled
|
|
||||||
|
|
||||||
## Integration with REST API
|
|
||||||
|
|
||||||
The WebSocket functionality is integrated with the REST API. Any changes made through the REST endpoints will automatically trigger WebSocket messages to all connected clients.
|
|
||||||
|
|
||||||
REST endpoints:
|
|
||||||
- `GET /api/matches`: Get all matches
|
|
||||||
- `GET /api/matches/{id}`: Get a match by ID
|
|
||||||
- `POST /api/matches`: Create a new match (triggers MATCH_START WebSocket message)
|
|
||||||
- `PUT /api/matches/{id}`: Update a match (triggers SCORE_UPDATE WebSocket message)
|
|
||||||
- `PATCH /api/matches/{id}/score`: Update just the score (triggers SCORE_UPDATE WebSocket message)
|
|
||||||
- `DELETE /api/matches/{id}`: Delete a match (triggers MATCH_CANCEL WebSocket message)
|
|
||||||
|
|
||||||
## Client-Side Example (JavaScript)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// Using SockJS and STOMP client
|
|
||||||
import SockJS from 'sockjs-client';
|
|
||||||
import { Client } from '@stomp/stompjs';
|
|
||||||
|
|
||||||
// Create a new STOMP client
|
|
||||||
const socket = new SockJS('http://localhost:8080/ws');
|
|
||||||
const stompClient = new Client({
|
|
||||||
webSocketFactory: () => socket,
|
|
||||||
debug: (str) => console.log(str)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Connect to the WebSocket server
|
|
||||||
stompClient.activate();
|
|
||||||
|
|
||||||
// Subscribe to match updates
|
|
||||||
stompClient.onConnect = (frame) => {
|
|
||||||
console.log('Connected to WebSocket');
|
|
||||||
|
|
||||||
// Subscribe to match updates
|
|
||||||
stompClient.subscribe('/topic/match.updates', (message) => {
|
|
||||||
const matchUpdate = JSON.parse(message.body);
|
|
||||||
console.log('Received match update:', matchUpdate);
|
|
||||||
|
|
||||||
// Handle the update in your application
|
|
||||||
// e.g., update UI, play sound, etc.
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send a match update (e.g., when a referee updates a score)
|
|
||||||
function sendMatchUpdate(matchId, score1, score2) {
|
|
||||||
if (stompClient.connected) {
|
|
||||||
stompClient.publish({
|
|
||||||
destination: '/app/match.update',
|
|
||||||
body: JSON.stringify({
|
|
||||||
matchId: matchId,
|
|
||||||
score1: score1,
|
|
||||||
score2: score2,
|
|
||||||
type: 'SCORE_UPDATE'
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Security Considerations
|
|
||||||
|
|
||||||
The WebSocket endpoint is currently configured to allow connections from any origin (`*`). For production environments, this should be restricted to specific allowed origins.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.websocket
|
|
||||||
|
|
||||||
import org.springframework.messaging.handler.annotation.MessageMapping
|
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate
|
|
||||||
import org.springframework.stereotype.Controller
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
|
|
||||||
data class Data(val id: String, val value: Any)
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/ws")
|
|
||||||
class WebSocketController(private val messagingTemplate: SimpMessagingTemplate) {
|
|
||||||
|
|
||||||
// Insérer une donnée dans le channel
|
|
||||||
@MessageMapping("/insert")
|
|
||||||
fun insertData(data: Data) {
|
|
||||||
// Logique d'insertion
|
|
||||||
messagingTemplate.convertAndSend("/topic/data", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifier une donnée existente dans le channel
|
|
||||||
@MessageMapping("/modify")
|
|
||||||
fun modifyData(data: Data) {
|
|
||||||
// Logique de modification
|
|
||||||
messagingTemplate.convertAndSend("/topic/data", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer une donnée existante dans le channel
|
|
||||||
@MessageMapping("/delete")
|
|
||||||
fun deleteData(id: String) {
|
|
||||||
// Logique de suppression
|
|
||||||
messagingTemplate.convertAndSend("/topic/data/delete", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vider le channel
|
|
||||||
@MessageMapping("/clear")
|
|
||||||
fun clearChannel() {
|
|
||||||
// Logique pour vider le channel
|
|
||||||
messagingTemplate.convertAndSend("/topic/data/clear", null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.websocket.controllers
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.config.CHANNEL_MATCH_NAME
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.MatchBean
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.MatchUpdateBean
|
|
||||||
import fr.teamflash.fencerjudgeback.services.MatchService
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.models.MatchUpdateMessage
|
|
||||||
import org.springframework.context.event.EventListener
|
|
||||||
import org.springframework.messaging.handler.annotation.MessageMapping
|
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate
|
|
||||||
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
|
|
||||||
import org.springframework.stereotype.Controller
|
|
||||||
import org.springframework.web.socket.messaging.SessionSubscribeEvent
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
class MatchWebSocketController(
|
|
||||||
private val matchService: MatchService,
|
|
||||||
private val messagingTemplate: SimpMessagingTemplate
|
|
||||||
) {
|
|
||||||
|
|
||||||
private var mainId:Long? = 1
|
|
||||||
private val messageHistory = ArrayList<MatchBean>()
|
|
||||||
|
|
||||||
@MessageMapping("/all")
|
|
||||||
fun receiveMessage(message: MatchBean) {
|
|
||||||
println("/ws/matches $message")
|
|
||||||
messageHistory.add(message)
|
|
||||||
|
|
||||||
// Envoyer la liste des messages sur le channel
|
|
||||||
//Si la variable est dans le même package il faut enlever WebSocketConfig.
|
|
||||||
messagingTemplate.convertAndSend(CHANNEL_MATCH_NAME, messageHistory)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle match update requests from clients
|
|
||||||
* Client sends to: /app/match.update
|
|
||||||
* Server broadcasts to: /topic/match.updates
|
|
||||||
*/
|
|
||||||
@MessageMapping("/update")
|
|
||||||
fun handleMatchUpdate(matchUpdateMessage: MatchUpdateMessage): MatchUpdateMessage {
|
|
||||||
// Create a MatchBean from the update message
|
|
||||||
val matchBean = MatchBean(
|
|
||||||
id = matchUpdateMessage.matchId,
|
|
||||||
player1ID = matchUpdateMessage.player1Id,
|
|
||||||
player2ID = matchUpdateMessage.player2Id,
|
|
||||||
refereeID = matchUpdateMessage.refereeId,
|
|
||||||
score1 = matchUpdateMessage.score1,
|
|
||||||
score2 = matchUpdateMessage.score2,
|
|
||||||
date = matchUpdateMessage.date
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update the match in the database
|
|
||||||
matchService.updateMatch(matchBean.id, matchBean)
|
|
||||||
|
|
||||||
// Return the update message to be broadcast to all subscribers
|
|
||||||
return matchUpdateMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Broadcast a match update to all connected clients
|
|
||||||
* This method can be called from other services
|
|
||||||
*/
|
|
||||||
fun broadcastMatchUpdate(matchBean: MatchBean, type: MatchUpdateMessage.UpdateType = MatchUpdateMessage.UpdateType.SCORE_UPDATE) {
|
|
||||||
val updateMessage = MatchUpdateMessage.fromMatchBean(matchBean, type)
|
|
||||||
messagingTemplate.convertAndSend("/topic/match.updates", updateMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
//A mettre dans le controller
|
|
||||||
@EventListener
|
|
||||||
fun handleWebSocketSubscribeListener(event: SessionSubscribeEvent) {
|
|
||||||
val headerAccessor = StompHeaderAccessor.wrap(event.message)
|
|
||||||
if (CHANNEL_MATCH_NAME == headerAccessor.destination) {
|
|
||||||
messagingTemplate.convertAndSend(CHANNEL_MATCH_NAME, messageHistory)
|
|
||||||
println("Lancement du WebSocket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MessageMapping("/plusPoint")
|
|
||||||
fun addPoint(matchUpdateBean: MatchUpdateBean) {
|
|
||||||
val playerId = matchUpdateBean.playerId
|
|
||||||
val match = matchUpdateBean.match
|
|
||||||
print("plus")
|
|
||||||
if (match != null) {
|
|
||||||
print("minus")
|
|
||||||
when (playerId) {
|
|
||||||
match.player1ID -> if (match.score1 > 0) match.score1 -= 1
|
|
||||||
match.player2ID -> if (match.score2 > 0) match.score2 -= 1
|
|
||||||
}
|
|
||||||
matchService.updateMatch(match.id, match)
|
|
||||||
broadcastMatchUpdate(match)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MessageMapping("/minusPoint")
|
|
||||||
fun minusPoint(matchUpdateBean: MatchUpdateBean) {
|
|
||||||
val playerId = matchUpdateBean.playerId
|
|
||||||
val match = matchUpdateBean.match
|
|
||||||
print("minus")
|
|
||||||
if (match != null) {
|
|
||||||
when (playerId) {
|
|
||||||
match.player1ID -> if (match.score1 > 0) match.score1 -= 1
|
|
||||||
match.player2ID -> if (match.score2 > 0) match.score2 -= 1
|
|
||||||
}
|
|
||||||
matchService.updateMatch(match.id, match)
|
|
||||||
broadcastMatchUpdate(match)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MessageMapping("/add")
|
|
||||||
fun addMatchtoMainList(match:MatchBean) {
|
|
||||||
match.id = mainId;
|
|
||||||
matchService.addMatch(match)
|
|
||||||
messageHistory.add(match)
|
|
||||||
broadcastMatchUpdate(match, MatchUpdateMessage.UpdateType.NEW_MATCH)
|
|
||||||
mainId = mainId?.plus(1)
|
|
||||||
println("Ajout du match $match.id en bdd")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.websocket.controllers
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.PlayerBean
|
|
||||||
import fr.teamflash.fencerjudgeback.services.PlayerService
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.models.PlayerUpdateMessage
|
|
||||||
import org.springframework.context.event.EventListener
|
|
||||||
import org.springframework.messaging.handler.annotation.MessageMapping
|
|
||||||
import org.springframework.messaging.handler.annotation.SendTo
|
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate
|
|
||||||
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
|
|
||||||
import org.springframework.stereotype.Controller
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
import org.springframework.web.socket.messaging.SessionSubscribeEvent
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/ws")
|
|
||||||
class PlayerWebSocketController(
|
|
||||||
private val playerService: PlayerService,
|
|
||||||
private val messagingTemplate: SimpMessagingTemplate
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val messageHistory = ArrayList<PlayerBean>()
|
|
||||||
|
|
||||||
@MessageMapping("/player.update")
|
|
||||||
@SendTo("/topic/player.updates")
|
|
||||||
fun handlePlayerUpdate(playerUpdateMessage: PlayerUpdateMessage): PlayerUpdateMessage {
|
|
||||||
// Create a PlayerBean from the update message
|
|
||||||
val playerBean = PlayerBean(
|
|
||||||
id = playerUpdateMessage.playerId,
|
|
||||||
name = playerUpdateMessage.name,
|
|
||||||
firstName = playerUpdateMessage.firstName,
|
|
||||||
club = playerUpdateMessage.club
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update the player in the database
|
|
||||||
playerService.updatePlayer(playerBean.id ?: 0, playerBean)
|
|
||||||
|
|
||||||
// Return the update message to be broadcast to all subscribers
|
|
||||||
return playerUpdateMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Broadcast a player update to all connected clients
|
|
||||||
* This method can be called from other services
|
|
||||||
*/
|
|
||||||
fun broadcastPlayerUpdate(playerBean: PlayerBean, type: PlayerUpdateMessage.UpdateType = PlayerUpdateMessage.UpdateType.PLAYER_UPDATE) {
|
|
||||||
val updateMessage = PlayerUpdateMessage.fromPlayerBean(playerBean, type)
|
|
||||||
messagingTemplate.convertAndSend("/topic/player.updates", updateMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
fun handleWebSocketSubscribeListener(event: SessionSubscribeEvent) {
|
|
||||||
val headerAccessor = StompHeaderAccessor.wrap(event.message)
|
|
||||||
if ("/topic/player.updates" == headerAccessor.destination) {
|
|
||||||
// When a client subscribes, send them the current players
|
|
||||||
val players = playerService.getAll()
|
|
||||||
players.forEach { player ->
|
|
||||||
messagingTemplate.convertAndSend(
|
|
||||||
"/topic/player.updates",
|
|
||||||
PlayerUpdateMessage.fromPlayerBean(player, PlayerUpdateMessage.UpdateType.PLAYER_UPDATE)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MessageMapping
|
|
||||||
fun addPlayerToMainList(playerBean: PlayerBean) {
|
|
||||||
playerService.addPlayer(playerBean)
|
|
||||||
broadcastPlayerUpdate(playerBean, PlayerUpdateMessage.UpdateType.PLAYER_CREATE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.websocket.controllers
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.config.CHANNEL_MATCH_NAME
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.RefereeBean
|
|
||||||
import fr.teamflash.fencerjudgeback.services.RefereeService
|
|
||||||
import fr.teamflash.fencerjudgeback.websocket.models.RefereeUpdateMessage
|
|
||||||
import org.springframework.context.event.EventListener
|
|
||||||
import org.springframework.messaging.handler.annotation.MessageMapping
|
|
||||||
import org.springframework.messaging.handler.annotation.SendTo
|
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate
|
|
||||||
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
|
|
||||||
import org.springframework.stereotype.Controller
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
import org.springframework.web.socket.messaging.SessionSubscribeEvent
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/ws")
|
|
||||||
class RefereeWebSocketController(
|
|
||||||
private val refereeService: RefereeService,
|
|
||||||
private val messagingTemplate: SimpMessagingTemplate
|
|
||||||
) {
|
|
||||||
|
|
||||||
private val messageHistory = ArrayList<RefereeBean>()
|
|
||||||
|
|
||||||
@MessageMapping("/referee.update")
|
|
||||||
@SendTo("/topic/referee.updates")
|
|
||||||
fun handleRefereeUpdate(refereeUpdateMessage: RefereeUpdateMessage): RefereeUpdateMessage {
|
|
||||||
// Create a RefereeBean from the update message
|
|
||||||
val refereeBean = RefereeBean(
|
|
||||||
id = refereeUpdateMessage.refereeId,
|
|
||||||
name = refereeUpdateMessage.name,
|
|
||||||
firstName = refereeUpdateMessage.firstName,
|
|
||||||
qualification = refereeUpdateMessage.qualification
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update the referee in the database
|
|
||||||
refereeService.updateReferee(refereeBean.id ?: 0, refereeBean)
|
|
||||||
|
|
||||||
// Return the update message to be broadcast to all subscribers
|
|
||||||
return refereeUpdateMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Broadcast a referee update to all connected clients
|
|
||||||
* This method can be called from other services
|
|
||||||
*/
|
|
||||||
fun broadcastRefereeUpdate(refereeBean: RefereeBean, type: RefereeUpdateMessage.UpdateType = RefereeUpdateMessage.UpdateType.REFEREE_UPDATE) {
|
|
||||||
val updateMessage = RefereeUpdateMessage.fromRefereeBean(refereeBean, type)
|
|
||||||
messagingTemplate.convertAndSend("/topic/referee.updates", updateMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventListener
|
|
||||||
fun handleWebSocketSubscribeListener(event: SessionSubscribeEvent) {
|
|
||||||
val headerAccessor = StompHeaderAccessor.wrap(event.message)
|
|
||||||
if ("/topic/referee.updates" == headerAccessor.destination) {
|
|
||||||
// When a client subscribes, send them the current referees
|
|
||||||
val referees = refereeService.getAll()
|
|
||||||
referees.forEach { referee ->
|
|
||||||
messagingTemplate.convertAndSend(
|
|
||||||
"/topic/referee.updates",
|
|
||||||
RefereeUpdateMessage.fromRefereeBean(referee, RefereeUpdateMessage.UpdateType.REFEREE_UPDATE)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.websocket.models
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.MatchBean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message model for match updates sent through WebSocket
|
|
||||||
*/
|
|
||||||
data class MatchUpdateMessage(
|
|
||||||
val matchId: Long,
|
|
||||||
val player1Id: Long?,
|
|
||||||
val player2Id: Long?,
|
|
||||||
val refereeId: Long?,
|
|
||||||
val score1: Int,
|
|
||||||
val score2: Int,
|
|
||||||
val date: String?,
|
|
||||||
val type: UpdateType = UpdateType.SCORE_UPDATE
|
|
||||||
) {
|
|
||||||
enum class UpdateType {
|
|
||||||
SCORE_UPDATE,
|
|
||||||
MATCH_START,
|
|
||||||
MATCH_END,
|
|
||||||
MATCH_CANCEL,
|
|
||||||
NEW_MATCH,
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a MatchUpdateMessage from a MatchBean
|
|
||||||
*/
|
|
||||||
fun fromMatchBean(matchBean: MatchBean, type: UpdateType = UpdateType.SCORE_UPDATE): MatchUpdateMessage {
|
|
||||||
return MatchUpdateMessage(
|
|
||||||
matchId = matchBean.id ?: 0,
|
|
||||||
player1Id = matchBean.player1ID,
|
|
||||||
player2Id = matchBean.player2ID,
|
|
||||||
refereeId = matchBean.refereeID,
|
|
||||||
score1 = matchBean.score1,
|
|
||||||
score2 = matchBean.score2,
|
|
||||||
date = matchBean.date,
|
|
||||||
type = type
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.websocket.models
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.PlayerBean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message model for player updates sent through WebSocket
|
|
||||||
*/
|
|
||||||
data class PlayerUpdateMessage(
|
|
||||||
val playerId: Long,
|
|
||||||
val name: String?,
|
|
||||||
val firstName: String?,
|
|
||||||
val club: String?,
|
|
||||||
val type: UpdateType = UpdateType.PLAYER_UPDATE
|
|
||||||
) {
|
|
||||||
enum class UpdateType {
|
|
||||||
PLAYER_UPDATE,
|
|
||||||
PLAYER_CREATE,
|
|
||||||
PLAYER_DELETE
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a PlayerUpdateMessage from a PlayerBean
|
|
||||||
*/
|
|
||||||
fun fromPlayerBean(playerBean: PlayerBean, type: UpdateType = UpdateType.PLAYER_UPDATE): PlayerUpdateMessage {
|
|
||||||
return PlayerUpdateMessage(
|
|
||||||
playerId = playerBean.id ?: 0,
|
|
||||||
name = playerBean.name,
|
|
||||||
firstName = playerBean.firstName,
|
|
||||||
club = playerBean.club,
|
|
||||||
type = type
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package fr.teamflash.fencerjudgeback.websocket.models
|
|
||||||
|
|
||||||
import fr.teamflash.fencerjudgeback.entities.RefereeBean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message model for referee updates sent through WebSocket
|
|
||||||
*/
|
|
||||||
data class RefereeUpdateMessage(
|
|
||||||
val refereeId: Long,
|
|
||||||
val name: String?,
|
|
||||||
val firstName: String?,
|
|
||||||
val qualification: String?,
|
|
||||||
val type: UpdateType = UpdateType.REFEREE_UPDATE
|
|
||||||
) {
|
|
||||||
enum class UpdateType {
|
|
||||||
REFEREE_UPDATE,
|
|
||||||
REFEREE_CREATE,
|
|
||||||
REFEREE_DELETE
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
/**
|
|
||||||
* Create a RefereeUpdateMessage from a RefereeBean
|
|
||||||
*/
|
|
||||||
fun fromRefereeBean(refereeBean: RefereeBean, type: UpdateType = UpdateType.REFEREE_UPDATE): RefereeUpdateMessage {
|
|
||||||
return RefereeUpdateMessage(
|
|
||||||
refereeId = refereeBean.id ?: 0,
|
|
||||||
name = refereeBean.name,
|
|
||||||
firstName = refereeBean.firstName,
|
|
||||||
qualification = refereeBean.qualification,
|
|
||||||
type = type
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +1 @@
|
||||||
spring.application.name=FencerJudgeBack
|
spring.application.name=FencerJudgeBack
|
||||||
|
|
||||||
# H2 Database Configuration
|
|
||||||
spring.datasource.url=jdbc:h2:file:./db;AUTO_SERVER=true
|
|
||||||
spring.datasource.driverClassName=org.h2.Driver
|
|
||||||
spring.datasource.username=sa
|
|
||||||
spring.datasource.password=password
|
|
||||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
|
||||||
|
|
||||||
# Enable H2 Console
|
|
||||||
spring.h2.console.enabled=true
|
|
||||||
spring.h2.console.path=/h2-console
|
|
||||||
|
|
||||||
# Hibernate Configuration
|
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
|
||||||
spring.jpa.show-sql=true
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Test WebSocket Match</title>
|
|
||||||
<style>
|
|
||||||
#messageArea {
|
|
||||||
width: 100%;
|
|
||||||
height: 300px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
input, button {
|
|
||||||
padding: 8px;
|
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
.input-group {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h2>Test WebSocket Match</h2>
|
|
||||||
|
|
||||||
<div id="messageArea">Connexion...</div>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="number" id="player1Id" placeholder="Joueur 1 ID" value="2">
|
|
||||||
<input type="number" id="player2Id" placeholder="Joueur 2 ID" value="2">
|
|
||||||
<input type="number" id="refereeId" placeholder="Arbitre ID" value="2">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="number" id="score1" placeholder="Score Joueur 1" value="2">
|
|
||||||
<input type="number" id="score2" placeholder="Score Joueur 2" value="14">
|
|
||||||
<input type="datetime-local" id="matchDate">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button onclick="sendMatch()">Envoyer Match</button>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const stompClient = Stomp.over(new SockJS('/ws/matches-app'));
|
|
||||||
const channel = "/ws/topic/match";
|
|
||||||
|
|
||||||
stompClient.connect({}, function () {
|
|
||||||
stompClient.subscribe(channel, function (message) {
|
|
||||||
const msg = JSON.parse(message.body);
|
|
||||||
console.log("Match reçu :", msg);
|
|
||||||
displayMessage(msg);
|
|
||||||
});
|
|
||||||
document.getElementById('messageArea').textContent = 'Connecté au WebSocket';
|
|
||||||
}, function (error) {
|
|
||||||
document.getElementById('messageArea').textContent = 'Erreur WebSocket : ' + error;
|
|
||||||
});
|
|
||||||
|
|
||||||
function sendMatch() {
|
|
||||||
const match = {
|
|
||||||
id: 1,
|
|
||||||
player1Id: parseInt(document.getElementById("player1Id").value),
|
|
||||||
player2Id: parseInt(document.getElementById("player2Id").value),
|
|
||||||
refereeId: parseInt(document.getElementById("refereeId").value),
|
|
||||||
score1: parseInt(document.getElementById("score1").value),
|
|
||||||
score2: parseInt(document.getElementById("score2").value),
|
|
||||||
date: document.getElementById("matchDate").value
|
|
||||||
};
|
|
||||||
|
|
||||||
stompClient.send("/ws/add", {}, JSON.stringify(match));
|
|
||||||
|
|
||||||
displayMessage(match)
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayMessage(match) {
|
|
||||||
const area = document.getElementById("messageArea");
|
|
||||||
const div = document.createElement("div");
|
|
||||||
div.textContent = `Match ${match.id}: ${match.player1Id} (${match.score1}) vs ${match.player2Id} (${match.score2})`;
|
|
||||||
area.appendChild(div);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Test WebSocket Match</title>
|
|
||||||
<style>
|
|
||||||
#messageArea {
|
|
||||||
width: 100%;
|
|
||||||
height: 300px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
input, button {
|
|
||||||
padding: 8px;
|
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
.input-group {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h2>Test WebSocket Match</h2>
|
|
||||||
|
|
||||||
<div id="messageArea">Connexion...</div>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="number" id="matchId" placeholder="Match ID">
|
|
||||||
<input type="number" id="player1Id" placeholder="Joueur 1 ID">
|
|
||||||
<input type="number" id="player2Id" placeholder="Joueur 2 ID">
|
|
||||||
<input type="number" id="refereeId" placeholder="Arbitre ID">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="number" id="score1" placeholder="Score Joueur 1">
|
|
||||||
<input type="number" id="score2" placeholder="Score Joueur 2">
|
|
||||||
<input type="datetime-local" id="matchDate">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button onclick="sendMatch()">Envoyer Match</button>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const stompClient = Stomp.over(new SockJS('/ws/players-app'));
|
|
||||||
const channel = "/ws/topic/player";
|
|
||||||
|
|
||||||
stompClient.connect({}, function () {
|
|
||||||
stompClient.subscribe(channel, function (message) {
|
|
||||||
const msg = JSON.parse(message.body);
|
|
||||||
console.log("Match reçu :", msg);
|
|
||||||
displayMessage(msg);
|
|
||||||
});
|
|
||||||
document.getElementById('messageArea').textContent = 'Connecté au WebSocket';
|
|
||||||
}, function (error) {
|
|
||||||
document.getElementById('messageArea').textContent = 'Erreur WebSocket : ' + error;
|
|
||||||
});
|
|
||||||
|
|
||||||
function sendMatch() {
|
|
||||||
const match = {
|
|
||||||
matchId: parseInt(document.getElementById("matchId").value),
|
|
||||||
player1Id: parseInt(document.getElementById("player1Id").value),
|
|
||||||
player2Id: parseInt(document.getElementById("player2Id").value),
|
|
||||||
refereeId: parseInt(document.getElementById("refereeId").value),
|
|
||||||
score1: parseInt(document.getElementById("score1").value),
|
|
||||||
score2: parseInt(document.getElementById("score2").value),
|
|
||||||
date: document.getElementById("matchDate").value
|
|
||||||
};
|
|
||||||
|
|
||||||
stompClient.send("/ws/matches/add", {}, JSON.stringify(match));
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayMessage(match) {
|
|
||||||
const area = document.getElementById("messageArea");
|
|
||||||
const div = document.createElement("div");
|
|
||||||
div.textContent = `Match ${match.matchId}: ${match.player1Id} (${match.score1}) vs ${match.player2Id} (${match.score2})`;
|
|
||||||
area.appendChild(div);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Test WebSocket Match</title>
|
|
||||||
<style>
|
|
||||||
#messageArea {
|
|
||||||
width: 100%;
|
|
||||||
height: 300px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
input, button {
|
|
||||||
padding: 8px;
|
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
.input-group {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h2>Test WebSocket Match</h2>
|
|
||||||
|
|
||||||
<div id="messageArea">Connexion...</div>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="number" id="player1Id" placeholder="Joueur 1 ID" value="2">
|
|
||||||
<input type="number" id="player2Id" placeholder="Joueur 2 ID" value="2">
|
|
||||||
<input type="number" id="refereeId" placeholder="Arbitre ID" value="2">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="number" id="score1" placeholder="Score Joueur 1" value="2">
|
|
||||||
<input type="number" id="score2" placeholder="Score Joueur 2" value="14">
|
|
||||||
<input type="datetime-local" id="matchDate">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button onclick="sendMatch()">Envoyer Match</button>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const stompClient = Stomp.over(new SockJS('/ws/matches-app'));
|
|
||||||
const channel = "/ws/topic/match";
|
|
||||||
|
|
||||||
stompClient.connect({}, function () {
|
|
||||||
stompClient.subscribe(channel, function (message) {
|
|
||||||
const msg = JSON.parse(message.body);
|
|
||||||
console.log("Match reçu :", msg);
|
|
||||||
displayMessage(msg);
|
|
||||||
});
|
|
||||||
document.getElementById('messageArea').textContent = 'Connecté au WebSocket';
|
|
||||||
}, function (error) {
|
|
||||||
document.getElementById('messageArea').textContent = 'Erreur WebSocket : ' + error;
|
|
||||||
});
|
|
||||||
|
|
||||||
function sendMatch() {
|
|
||||||
const match = {
|
|
||||||
id: 1,
|
|
||||||
player1ID: parseInt(document.getElementById("player1Id").value),
|
|
||||||
player2ID: parseInt(document.getElementById("player2Id").value),
|
|
||||||
refereeID: parseInt(document.getElementById("refereeId").value),
|
|
||||||
score1: parseInt(document.getElementById("score1").value),
|
|
||||||
score2: parseInt(document.getElementById("score2").value),
|
|
||||||
date: document.getElementById("matchDate").value
|
|
||||||
};
|
|
||||||
|
|
||||||
stompClient.send("/ws/plusPoint", {}, JSON.stringify({
|
|
||||||
match: match,
|
|
||||||
playerId: match.player1Id
|
|
||||||
}));
|
|
||||||
|
|
||||||
displayMessage(match)
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayMessage(match) {
|
|
||||||
const area = document.getElementById("messageArea");
|
|
||||||
const div = document.createElement("div");
|
|
||||||
div.textContent = `Match ${match.id}: ${match.player1Id} (${match.score1}) vs ${match.player2Id} (${match.score2})`;
|
|
||||||
area.appendChild(div);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
### Get all matches
|
|
||||||
GET http://localhost:8080/matches/
|
|
||||||
|
|
||||||
### Get matches by players --> TODO
|
|
||||||
GET http://localhost:8080/matches/players/1/2
|
|
||||||
|
|
||||||
### Get matches by date
|
|
||||||
GET http://localhost:8080/matches/date/2025-06-02
|
|
||||||
|
|
||||||
### Get matches by country
|
|
||||||
GET http://localhost:8080/matches/country/France
|
|
||||||
|
|
||||||
### Get matches by city
|
|
||||||
GET http://localhost:8080/matches/city/Paris
|
|
||||||
|
|
||||||
### Get active matches
|
|
||||||
GET http://localhost:8080/matches/active
|
|
||||||
|
|
||||||
### Get finished matches
|
|
||||||
GET http://localhost:8080/matches/over
|
|
||||||
|
|
||||||
### Get not started matches
|
|
||||||
GET http://localhost:8080/matches/not-started
|
|
||||||
|
|
||||||
### Get match by ID
|
|
||||||
GET http://localhost:8080/matches/2
|
|
||||||
|
|
||||||
### Create new match
|
|
||||||
POST http://localhost:8080/matches/create-match
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"weapon": "Épée",
|
|
||||||
"country": "France",
|
|
||||||
"city": "Paris",
|
|
||||||
"player1ID": 1,
|
|
||||||
"player2ID": 2,
|
|
||||||
"refereeID": 1,
|
|
||||||
"score1": 0,
|
|
||||||
"score2": 0,
|
|
||||||
"date": "2025-06-02",
|
|
||||||
"state": "NOT STARTED"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Update match
|
|
||||||
PUT http://localhost:8080/matches/update-match/4
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
"weapon": "Épée",
|
|
||||||
"country": "France",
|
|
||||||
"city": "Paris",
|
|
||||||
"player1ID": 1,
|
|
||||||
"player2ID": 2,
|
|
||||||
"refereeID": 1,
|
|
||||||
"score1": 5,
|
|
||||||
"score2": 3,
|
|
||||||
"date": "2025-06-02",
|
|
||||||
"state": "OVER"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Delete match
|
|
||||||
DELETE http://localhost:8080/matches/delete-match/3
|
|
||||||
|
|
||||||
### Get all referees
|
|
||||||
GET http://localhost:8080/referees/
|
|
||||||
|
|
||||||
### Get referee by ID
|
|
||||||
GET http://localhost:8080/referees/1
|
|
||||||
|
|
||||||
### Get referees by name
|
|
||||||
GET http://localhost:8080/referees/name/Smith
|
|
||||||
|
|
||||||
### Get referees by firstname
|
|
||||||
GET http://localhost:8080/referees/firstname/John
|
|
||||||
|
|
||||||
### Get referees by qualification
|
|
||||||
GET http://localhost:8080/referees/qualification/NATIONAL
|
|
||||||
|
|
||||||
### Create new referee
|
|
||||||
POST http://localhost:8080/referees/create-referee
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Smith",
|
|
||||||
"firstName": "John",
|
|
||||||
"qualification": "NATIONAL"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Update referee
|
|
||||||
PUT http://localhost:8080/referees/update-referee/6
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Smith",
|
|
||||||
"firstName": "John",
|
|
||||||
"qualification": "INTERNATIONAL"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Delete referee
|
|
||||||
DELETE http://localhost:8080/referees/delete-referee/5
|
|
||||||
|
|
||||||
### Get all players
|
|
||||||
GET http://localhost:8080/players/
|
|
||||||
|
|
||||||
### Get player by ID
|
|
||||||
GET http://localhost:8080/players/10
|
|
||||||
|
|
||||||
### Get players by name
|
|
||||||
GET http://localhost:8080/players/name/Doe
|
|
||||||
|
|
||||||
### Get players by firstname
|
|
||||||
GET http://localhost:8080/players/firstname/Jane
|
|
||||||
|
|
||||||
### Create new player
|
|
||||||
POST http://localhost:8080/players/create-player
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Doe",
|
|
||||||
"firstName": "Jane",
|
|
||||||
"club": "Paris Escrime Club"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Update player
|
|
||||||
PUT http://localhost:8080/players/update-player/10
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Doe",
|
|
||||||
"firstName": "Jane",
|
|
||||||
"club": "Un autre club"
|
|
||||||
}
|
|
||||||
|
|
||||||
### Delete player
|
|
||||||
DELETE http://localhost:8080/players/delete-player/10
|
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue