Fin intégration jumele place
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package com.pmumali.ch3_jumeleplace.controller;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Cheval;
|
||||
import com.pmumali.ch3_jumeleplace.service.ChevalService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/chevaux")
|
||||
public class ChevalController {
|
||||
|
||||
@Autowired
|
||||
private ChevalService chevalService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Cheval> ajouterCheval(@RequestBody Cheval cheval) {
|
||||
return ResponseEntity.ok(chevalService.ajouterCheval(cheval));
|
||||
}
|
||||
|
||||
@GetMapping("/course/{courseId}")
|
||||
public ResponseEntity<List<Cheval>> obtenirChevauxParCourse(@PathVariable Long courseId) {
|
||||
return ResponseEntity.ok(chevalService.obtenirChevauxParCourse(courseId));
|
||||
}
|
||||
|
||||
@GetMapping("/non-partants")
|
||||
public ResponseEntity<List<Cheval>> obtenirChevauxNonPartants() {
|
||||
return ResponseEntity.ok(chevalService.obtenirChevauxNonPartants());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.pmumali.ch3_jumeleplace.controller;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Course;
|
||||
import com.pmumali.ch3_jumeleplace.service.CourseService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/courses")
|
||||
public class CourseController {
|
||||
|
||||
@Autowired
|
||||
private CourseService courseService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Course> creerCourse(@RequestBody Course course) {
|
||||
return ResponseEntity.ok(courseService.creerCourse(course));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<List<Course>> obtenirToutesCourses() {
|
||||
return ResponseEntity.ok(courseService.obtenirToutesCourses());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<Course> obtenirCourseParId(@PathVariable Long id) {
|
||||
Course course = courseService.obtenirCourseParId(id);
|
||||
return course != null ? ResponseEntity.ok(course) : ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
@GetMapping("/terminees")
|
||||
public ResponseEntity<List<Course>> obtenirCoursesTerminees() {
|
||||
return ResponseEntity.ok(courseService.obtenirCoursesTerminees());
|
||||
}
|
||||
|
||||
@GetMapping("/avenir")
|
||||
public ResponseEntity<List<Course>> obtenirCoursesAVenir() {
|
||||
return ResponseEntity.ok(courseService.obtenirCoursesAVenir());
|
||||
}
|
||||
|
||||
@GetMapping("/annulees")
|
||||
public ResponseEntity<List<Course>> obtenirCoursesAnnulees() {
|
||||
return ResponseEntity.ok(courseService.obtenirCoursesAnnulees());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.pmumali.ch3_jumeleplace.controller;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Gains;
|
||||
import com.pmumali.ch3_jumeleplace.model.ResultatCourse;
|
||||
import com.pmumali.ch3_jumeleplace.service.GainsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/gains")
|
||||
public class GainsController {
|
||||
|
||||
@Autowired
|
||||
private GainsService gainsService;
|
||||
|
||||
@PostMapping("/calculer/{courseId}")
|
||||
public ResponseEntity<Gains> calculerGains(@PathVariable Long courseId, @RequestBody ResultatCourse resultat) {
|
||||
return ResponseEntity.ok(gainsService.calculerGains(courseId, resultat));
|
||||
}
|
||||
|
||||
@GetMapping("/course/{courseId}")
|
||||
public ResponseEntity<Gains> obtenirGainsParCourse(@PathVariable Long courseId) {
|
||||
Gains gains = gainsService.obtenirGainsParCourse(courseId);
|
||||
return gains != null ? ResponseEntity.ok(gains) : ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.pmumali.ch3_jumeleplace.controller;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.PariJumelePlace;
|
||||
import com.pmumali.ch3_jumeleplace.service.PariJumelePlaceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/paris-jumele-place")
|
||||
public class PariJumelePlaceController {
|
||||
|
||||
@Autowired
|
||||
private PariJumelePlaceService pariService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<PariJumelePlace> placerPari(@RequestBody PariJumelePlace pari) {
|
||||
return ResponseEntity.ok(pariService.placerPari(pari));
|
||||
}
|
||||
|
||||
@GetMapping("/course/{courseId}")
|
||||
public ResponseEntity<List<PariJumelePlace>> obtenirParisParCourse(@PathVariable Long courseId) {
|
||||
return ResponseEntity.ok(pariService.obtenirParisParCourse(courseId));
|
||||
}
|
||||
|
||||
@GetMapping("/cheval/{chevalId}")
|
||||
public ResponseEntity<List<PariJumelePlace>> obtenirParisParCheval(@PathVariable Long chevalId) {
|
||||
return ResponseEntity.ok(pariService.obtenirParisParCheval(chevalId));
|
||||
}
|
||||
|
||||
@GetMapping("/calculer-formule-combinee/{nombreChevaux}")
|
||||
public ResponseEntity<Double> calculerCoutFormuleCombinee(@PathVariable int nombreChevaux) {
|
||||
return ResponseEntity.ok(pariService.calculerCoutFormuleCombinee(nombreChevaux));
|
||||
}
|
||||
|
||||
@GetMapping("/calculer-formule-champ")
|
||||
public ResponseEntity<Double> calculerCoutFormuleChamp(
|
||||
@RequestParam int nombreChevauxPartants,
|
||||
@RequestParam int nombreChevauxSelectionnes,
|
||||
@RequestParam boolean estChampTotal) {
|
||||
return ResponseEntity.ok(pariService.calculerCoutFormuleChamp(
|
||||
nombreChevauxPartants, nombreChevauxSelectionnes, estChampTotal));
|
||||
}
|
||||
}
|
||||
|
||||
12
src/main/java/com/pmumali/ch3_jumeleplace/dto/ChevalDto.java
Normal file
12
src/main/java/com/pmumali/ch3_jumeleplace/dto/ChevalDto.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.pmumali.ch3_jumeleplace.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ChevalDto {
|
||||
private Long id;
|
||||
private String nom;
|
||||
private int numero;
|
||||
private boolean estNonPartant;
|
||||
private Long courseId;
|
||||
}
|
||||
17
src/main/java/com/pmumali/ch3_jumeleplace/dto/CourseDto.java
Normal file
17
src/main/java/com/pmumali/ch3_jumeleplace/dto/CourseDto.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.pmumali.ch3_jumeleplace.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class CourseDto {
|
||||
private Long id;
|
||||
private String nom;
|
||||
private LocalDateTime date;
|
||||
private String lieu;
|
||||
private int nombreChevauxInscrits;
|
||||
private boolean estTerminee;
|
||||
private boolean estAnnulee;
|
||||
private List<Long> chevauxIds;
|
||||
}
|
||||
16
src/main/java/com/pmumali/ch3_jumeleplace/dto/GainsDto.java
Normal file
16
src/main/java/com/pmumali/ch3_jumeleplace/dto/GainsDto.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.pmumali.ch3_jumeleplace.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class GainsDto {
|
||||
private Long id;
|
||||
private Long courseId;
|
||||
private double masseAPartager;
|
||||
private double montantCagnotte;
|
||||
private List<Double> rapports;
|
||||
private LocalDateTime dateCalcul;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.pmumali.ch3_jumeleplace.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class PariJumelePlaceDto {
|
||||
private Long id;
|
||||
private String typePari;
|
||||
private double mise;
|
||||
private LocalDateTime datePari;
|
||||
private Long cheval1Id;
|
||||
private Long cheval2Id;
|
||||
private Long courseId;
|
||||
private boolean estPaye;
|
||||
private boolean estRembourse;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.pmumali.ch3_jumeleplace.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ResultatCourseDto {
|
||||
private Long id;
|
||||
private Long courseId;
|
||||
private List<Long> chevauxPremiers;
|
||||
private List<Long> chevauxDeuxiemes;
|
||||
private List<Long> chevauxTroisiemes;
|
||||
private boolean aDeadHeat;
|
||||
}
|
||||
23
src/main/java/com/pmumali/ch3_jumeleplace/model/Cheval.java
Normal file
23
src/main/java/com/pmumali/ch3_jumeleplace/model/Cheval.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.pmumali.ch3_jumeleplace.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "cheval")
|
||||
public class Cheval {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String nom;
|
||||
private int numero;
|
||||
private boolean estNonPartant;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "course_id")
|
||||
private Course course;
|
||||
}
|
||||
33
src/main/java/com/pmumali/ch3_jumeleplace/model/Course.java
Normal file
33
src/main/java/com/pmumali/ch3_jumeleplace/model/Course.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.pmumali.ch3_jumeleplace.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "course")
|
||||
public class Course {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String nom;
|
||||
private LocalDateTime date;
|
||||
private String lieu;
|
||||
private int nombreChevauxInscrits;
|
||||
private boolean estTerminee;
|
||||
private boolean estAnnulee;
|
||||
|
||||
@OneToMany(mappedBy = "course", cascade = CascadeType.ALL)
|
||||
private List<Cheval> chevaux;
|
||||
|
||||
@OneToOne(mappedBy = "course", cascade = CascadeType.ALL)
|
||||
private ResultatCourse resultat;
|
||||
}
|
||||
30
src/main/java/com/pmumali/ch3_jumeleplace/model/Gains.java
Normal file
30
src/main/java/com/pmumali/ch3_jumeleplace/model/Gains.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.pmumali.ch3_jumeleplace.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "gains")
|
||||
public class Gains {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "course_id")
|
||||
private Course course;
|
||||
|
||||
private double masseAPartager;
|
||||
private double montantCagnotte;
|
||||
|
||||
@ElementCollection
|
||||
private List<Double> rapports;
|
||||
|
||||
private LocalDateTime dateCalcul;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.pmumali.ch3_jumeleplace.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "pari_jumele_place")
|
||||
public class PariJumelePlace {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String typePari; // UNITAIRE, COMBINE, CHAMP_TOTAL, CHAMP_PARTIEL
|
||||
private double mise = 500.0;
|
||||
private LocalDateTime datePari;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cheval1_id")
|
||||
private Cheval cheval1;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cheval2_id")
|
||||
private Cheval cheval2;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "course_id")
|
||||
private Course course;
|
||||
|
||||
private boolean estPaye;
|
||||
private boolean estRembourse;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.pmumali.ch3_jumeleplace.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "resultat_course")
|
||||
public class ResultatCourse {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "course_id")
|
||||
private Course course;
|
||||
|
||||
@ElementCollection
|
||||
private List<Long> chevauxPremiers;
|
||||
|
||||
@ElementCollection
|
||||
private List<Long> chevauxDeuxiemes;
|
||||
|
||||
@ElementCollection
|
||||
private List<Long> chevauxTroisiemes;
|
||||
|
||||
private boolean aDeadHeat;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.pmumali.ch3_jumeleplace.repository;
|
||||
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Cheval;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ChevalRepository extends JpaRepository<Cheval, Long> {
|
||||
List<Cheval> findByCourseId(Long courseId);
|
||||
List<Cheval> findByEstNonPartant(boolean estNonPartant);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.pmumali.ch3_jumeleplace.repository;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Course;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface CourseRepository extends JpaRepository<Course, Long> {
|
||||
List<Course> findByEstTerminee(boolean estTerminee);
|
||||
List<Course> findByEstAnnulee(boolean estAnnulee);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.pmumali.ch3_jumeleplace.repository;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Gains;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface GainsRepository extends JpaRepository<Gains, Long> {
|
||||
Gains findByCourseId(Long courseId);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.pmumali.ch3_jumeleplace.repository;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.PariJumelePlace;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface PariJumelePlaceRepository extends JpaRepository<PariJumelePlace, Long> {
|
||||
List<PariJumelePlace> findByCourseId(Long courseId);
|
||||
List<PariJumelePlace> findByCheval1IdOrCheval2Id(Long cheval1Id, Long cheval2Id);
|
||||
List<PariJumelePlace> findByEstRembourse(boolean estRembourse);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.pmumali.ch3_jumeleplace.repository;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.ResultatCourse;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ResultatCourseRepository extends JpaRepository<ResultatCourse, Long> {
|
||||
ResultatCourse findByCourseId(Long courseId);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.pmumali.ch3_jumeleplace.service;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Cheval;
|
||||
import com.pmumali.ch3_jumeleplace.repository.ChevalRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class ChevalService {
|
||||
|
||||
@Autowired
|
||||
private ChevalRepository chevalRepository;
|
||||
|
||||
public Cheval ajouterCheval(Cheval cheval) {
|
||||
return chevalRepository.save(cheval);
|
||||
}
|
||||
|
||||
public List<Cheval> obtenirChevauxParCourse(Long courseId) {
|
||||
return chevalRepository.findByCourseId(courseId);
|
||||
}
|
||||
|
||||
public List<Cheval> obtenirChevauxNonPartants() {
|
||||
return chevalRepository.findByEstNonPartant(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.pmumali.ch3_jumeleplace.service;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Course;
|
||||
import com.pmumali.ch3_jumeleplace.repository.CourseRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Service
|
||||
public class CourseService {
|
||||
|
||||
@Autowired
|
||||
private CourseRepository courseRepository;
|
||||
|
||||
public Course creerCourse(Course course) {
|
||||
return courseRepository.save(course);
|
||||
}
|
||||
|
||||
public List<Course> obtenirToutesCourses() {
|
||||
return courseRepository.findAll();
|
||||
}
|
||||
|
||||
public Course obtenirCourseParId(Long id) {
|
||||
return courseRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
public List<Course> obtenirCoursesTerminees() {
|
||||
return courseRepository.findByEstTerminee(true);
|
||||
}
|
||||
|
||||
public List<Course> obtenirCoursesAVenir() {
|
||||
return courseRepository.findByEstTerminee(false);
|
||||
}
|
||||
|
||||
public List<Course> obtenirCoursesAnnulees() {
|
||||
return courseRepository.findByEstAnnulee(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
package com.pmumali.ch3_jumeleplace.service;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.Course;
|
||||
import com.pmumali.ch3_jumeleplace.model.Gains;
|
||||
import com.pmumali.ch3_jumeleplace.model.PariJumelePlace;
|
||||
import com.pmumali.ch3_jumeleplace.model.ResultatCourse;
|
||||
import com.pmumali.ch3_jumeleplace.repository.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class GainsService {
|
||||
|
||||
@Autowired
|
||||
private PariJumelePlaceRepository pariRepository;
|
||||
|
||||
@Autowired
|
||||
private GainsRepository gainsRepository;
|
||||
|
||||
@Autowired
|
||||
private CourseRepository courseRepository;
|
||||
|
||||
@Autowired
|
||||
private ChevalRepository chevalRepository;
|
||||
|
||||
@Autowired
|
||||
private ResultatCourseRepository resultatRepository;
|
||||
|
||||
private static final double RAPPORT_MINIMUM = 1.1;
|
||||
private static final double PRELEVEMENTS = 0.15; // 15% de prélèvements
|
||||
|
||||
public Gains calculerGains(Long courseId, ResultatCourse resultat) {
|
||||
Course course = courseRepository.findById(courseId)
|
||||
.orElseThrow(() -> new RuntimeException("Course non trouvée"));
|
||||
|
||||
List<PariJumelePlace> tousParis = pariRepository.findByCourseId(courseId);
|
||||
|
||||
// Calcul de la recette nette (Article 5)
|
||||
double totalMises = tousParis.stream().mapToDouble(PariJumelePlace::getMise).sum();
|
||||
double recetteNette = totalMises;
|
||||
|
||||
// Calcul des remboursements (Article 4)
|
||||
double montantRemboursements = calculerRemboursements(tousParis);
|
||||
|
||||
// Masse à partager (Article 5)
|
||||
double masseAPartager = recetteNette - montantRemboursements - (recetteNette * PRELEVEMENTS);
|
||||
|
||||
// Déterminer les combinaisons payables
|
||||
List<CombinaisonPayable> combinaisonsPayables = determinerCombinaisonsPayables(resultat);
|
||||
|
||||
// Calcul des rapports
|
||||
Gains gains = new Gains();
|
||||
gains.setCourse(course);
|
||||
gains.setMasseAPartager(masseAPartager);
|
||||
gains.setDateCalcul(LocalDateTime.now());
|
||||
|
||||
// Calcul détaillé des gains selon les règles
|
||||
if (resultat.isADeadHeat()) {
|
||||
calculerRapportsDeadHeat(gains, combinaisonsPayables, tousParis);
|
||||
} else {
|
||||
calculerRapportsNormaux(gains, combinaisonsPayables, tousParis);
|
||||
}
|
||||
|
||||
// Gérer la cagnotte si nécessaire (Article 8 et 9)
|
||||
gererCagnotte(gains, combinaisonsPayables);
|
||||
|
||||
return gainsRepository.save(gains);
|
||||
}
|
||||
|
||||
private double calculerRemboursements(List<PariJumelePlace> paris) {
|
||||
double remboursements = 0.0;
|
||||
|
||||
for (PariJumelePlace pari : paris) {
|
||||
// Article 4: Remboursement si un ou deux chevaux non partants
|
||||
if (pari.getCheval1().isEstNonPartant() || pari.getCheval2().isEstNonPartant()) {
|
||||
remboursements += pari.getMise();
|
||||
pari.setEstRembourse(true);
|
||||
pariRepository.save(pari);
|
||||
}
|
||||
}
|
||||
|
||||
return remboursements;
|
||||
}
|
||||
|
||||
private List<CombinaisonPayable> determinerCombinaisonsPayables(ResultatCourse resultat) {
|
||||
List<CombinaisonPayable> combinaisons = new ArrayList<>();
|
||||
|
||||
// Article 1: Le pari est payable si les deux chevaux occupent deux des trois premières places
|
||||
// Article 3: Gestion des dead-heats
|
||||
|
||||
if (resultat.isADeadHeat()) {
|
||||
// Cas de dead-heat
|
||||
if (resultat.getChevauxPremiers().size() >= 3) {
|
||||
// Article 3a: Dead-heat de trois chevaux ou plus à la première place
|
||||
// Toutes les combinaisons deux à deux des chevaux classés premiers
|
||||
for (int i = 0; i < resultat.getChevauxPremiers().size(); i++) {
|
||||
for (int j = i + 1; j < resultat.getChevauxPremiers().size(); j++) {
|
||||
combinaisons.add(new CombinaisonPayable(
|
||||
resultat.getChevauxPremiers().get(i),
|
||||
resultat.getChevauxPremiers().get(j)
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if (resultat.getChevauxPremiers().size() == 2 &&
|
||||
!resultat.getChevauxTroisiemes().isEmpty()) {
|
||||
// Article 3b: Dead-heat de deux chevaux à la première place et un ou plusieurs à la troisième
|
||||
// Combinaison des deux premiers + combinaisons de chaque premier avec chaque troisième
|
||||
combinaisons.add(new CombinaisonPayable(
|
||||
resultat.getChevauxPremiers().get(0),
|
||||
resultat.getChevauxPremiers().get(1)
|
||||
));
|
||||
|
||||
for (Long chevalPremier : resultat.getChevauxPremiers()) {
|
||||
for (Long chevalTroisieme : resultat.getChevauxTroisiemes()) {
|
||||
combinaisons.add(new CombinaisonPayable(chevalPremier, chevalTroisieme));
|
||||
}
|
||||
}
|
||||
} else if (resultat.getChevauxTroisiemes().size() >= 2) {
|
||||
// Article 3c: Dead-heat de deux chevaux ou plus à la troisième place
|
||||
// Combinaison premier + deuxième + combinaisons premier avec chaque troisième + deuxième avec chaque troisième
|
||||
if (!resultat.getChevauxPremiers().isEmpty() && !resultat.getChevauxDeuxiemes().isEmpty()) {
|
||||
combinaisons.add(new CombinaisonPayable(
|
||||
resultat.getChevauxPremiers().get(0),
|
||||
resultat.getChevauxDeuxiemes().get(0)
|
||||
));
|
||||
|
||||
for (Long chevalTroisieme : resultat.getChevauxTroisiemes()) {
|
||||
combinaisons.add(new CombinaisonPayable(
|
||||
resultat.getChevauxPremiers().get(0),
|
||||
chevalTroisieme
|
||||
));
|
||||
|
||||
combinaisons.add(new CombinaisonPayable(
|
||||
resultat.getChevauxDeuxiemes().get(0),
|
||||
chevalTroisieme
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Cas normal - Article 1: Les deux chevaux doivent occuper deux des trois premières places
|
||||
List<Long> chevauxPayables = new ArrayList<>();
|
||||
chevauxPayables.addAll(resultat.getChevauxPremiers());
|
||||
chevauxPayables.addAll(resultat.getChevauxDeuxiemes());
|
||||
chevauxPayables.addAll(resultat.getChevauxTroisiemes());
|
||||
|
||||
// Générer toutes les combinaisons deux à deux
|
||||
for (int i = 0; i < chevauxPayables.size(); i++) {
|
||||
for (int j = i + 1; j < chevauxPayables.size(); j++) {
|
||||
combinaisons.add(new CombinaisonPayable(
|
||||
chevauxPayables.get(i),
|
||||
chevauxPayables.get(j)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return combinaisons;
|
||||
}
|
||||
|
||||
private void calculerRapportsNormaux(Gains gains, List<CombinaisonPayable> combinaisonsPayables,
|
||||
List<PariJumelePlace> tousParis) {
|
||||
// Article 5a: Cas d'arrivée normale
|
||||
if (combinaisonsPayables.isEmpty()) {
|
||||
gains.setMontantCagnotte(gains.getMasseAPartager());
|
||||
gains.setMasseAPartager(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Article 5a: Le bénéfice à répartir est divisé en trois parties égales
|
||||
double beneficeARepartir = gains.getMasseAPartager();
|
||||
double part = beneficeARepartir / 3;
|
||||
|
||||
List<Double> rapports = new ArrayList<>();
|
||||
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
double totalMises = calculerMisesSurCombinaison(combinaison, tousParis);
|
||||
|
||||
if (totalMises > 0) {
|
||||
double rapport = (part / totalMises) + 1;
|
||||
rapports.add(Math.max(rapport, RAPPORT_MINIMUM));
|
||||
} else {
|
||||
rapports.add(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
gains.setRapports(rapports);
|
||||
}
|
||||
|
||||
private void calculerRapportsDeadHeat(Gains gains, List<CombinaisonPayable> combinaisonsPayables,
|
||||
List<PariJumelePlace> tousParis) {
|
||||
// Article 5b: Cas d'arrivée "dead heat"
|
||||
if (combinaisonsPayables.isEmpty()) {
|
||||
gains.setMontantCagnotte(gains.getMasseAPartager());
|
||||
gains.setMasseAPartager(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
double beneficeARepartir = gains.getMasseAPartager();
|
||||
List<Double> rapports = new ArrayList<>();
|
||||
|
||||
// Déterminer le type de dead-heat pour appliquer les règles spécifiques
|
||||
ResultatCourse resultat = gains.getCourse().getResultat();
|
||||
|
||||
if (resultat.getChevauxPremiers().size() >= 3) {
|
||||
// Article 5b1: Dead-heat de trois chevaux ou plus à la première place
|
||||
double partParCombinaison = beneficeARepartir / combinaisonsPayables.size();
|
||||
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
double totalMises = calculerMisesSurCombinaison(combinaison, tousParis);
|
||||
|
||||
if (totalMises > 0) {
|
||||
double rapport = (partParCombinaison / totalMises) + 1;
|
||||
rapports.add(Math.max(rapport, RAPPORT_MINIMUM));
|
||||
} else {
|
||||
rapports.add(0.0);
|
||||
}
|
||||
}
|
||||
} else if (resultat.getChevauxPremiers().size() == 2 &&
|
||||
!resultat.getChevauxTroisiemes().isEmpty()) {
|
||||
// Article 5b2: Dead-heat de deux chevaux à la première place et un ou plusieurs à la troisième
|
||||
double part = beneficeARepartir / 3;
|
||||
|
||||
// Trouver la combinaison des deux premiers
|
||||
CombinaisonPayable combinaisonPremiers = null;
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
if (resultat.getChevauxPremiers().contains(combinaison.getCheval1Id()) &&
|
||||
resultat.getChevauxPremiers().contains(combinaison.getCheval2Id())) {
|
||||
combinaisonPremiers = combinaison;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculer les rapports
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
double totalMises = calculerMisesSurCombinaison(combinaison, tousParis);
|
||||
|
||||
if (totalMises > 0) {
|
||||
double rapportPart = part;
|
||||
if (combinaison.equals(combinaisonPremiers)) {
|
||||
// Combinaison des deux premiers - 1/3 du bénéfice
|
||||
rapportPart = part;
|
||||
} else {
|
||||
// Combinaisons premier-troisième - 1/3 du bénéfice divisé par le nombre de ces combinaisons
|
||||
int nbCombinaisonsPremierTroisieme = combinaisonsPayables.size() - 1;
|
||||
rapportPart = part / nbCombinaisonsPremierTroisieme;
|
||||
}
|
||||
|
||||
double rapport = (rapportPart / totalMises) + 1;
|
||||
rapports.add(Math.max(rapport, RAPPORT_MINIMUM));
|
||||
} else {
|
||||
rapports.add(0.0);
|
||||
}
|
||||
}
|
||||
} else if (resultat.getChevauxDeuxiemes().size() >= 2) {
|
||||
// Article 5b3: Dead-heat de deux chevaux ou plus à la deuxième place
|
||||
double deuxTiers = beneficeARepartir * 2 / 3;
|
||||
double unTiers = beneficeARepartir / 3;
|
||||
|
||||
// Compter les types de combinaisons
|
||||
int nbCombinaisonsPremierDeuxieme = 0;
|
||||
int nbCombinaisonsDeuxiemeDeuxieme = 0;
|
||||
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
if (resultat.getChevauxPremiers().contains(combinaison.getCheval1Id()) ||
|
||||
resultat.getChevauxPremiers().contains(combinaison.getCheval2Id())) {
|
||||
nbCombinaisonsPremierDeuxieme++;
|
||||
} else {
|
||||
nbCombinaisonsDeuxiemeDeuxieme++;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculer les rapports
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
double totalMises = calculerMisesSurCombinaison(combinaison, tousParis);
|
||||
|
||||
if (totalMises > 0) {
|
||||
double rapportPart;
|
||||
if (resultat.getChevauxPremiers().contains(combinaison.getCheval1Id()) ||
|
||||
resultat.getChevauxPremiers().contains(combinaison.getCheval2Id())) {
|
||||
// Combinaisons premier-deuxième - 2/3 du bénéfice divisé par le nombre de ces combinaisons
|
||||
rapportPart = deuxTiers / nbCombinaisonsPremierDeuxieme;
|
||||
} else {
|
||||
// Combinaisons deuxième-deuxième - 1/3 du bénéfice divisé par le nombre de ces combinaisons
|
||||
rapportPart = unTiers / nbCombinaisonsDeuxiemeDeuxieme;
|
||||
}
|
||||
|
||||
double rapport = (rapportPart / totalMises) + 1;
|
||||
rapports.add(Math.max(rapport, RAPPORT_MINIMUM));
|
||||
} else {
|
||||
rapports.add(0.0);
|
||||
}
|
||||
}
|
||||
} else if (resultat.getChevauxTroisiemes().size() >= 2) {
|
||||
// Article 5b4: Dead-heat de deux chevaux ou plus à la troisième place
|
||||
double part = beneficeARepartir / 3;
|
||||
|
||||
// Compter les types de combinaisons
|
||||
int nbCombinaisonsPremierTroisieme = 0;
|
||||
int nbCombinaisonsDeuxiemeTroisieme = 0;
|
||||
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
if (resultat.getChevauxPremiers().contains(combinaison.getCheval1Id()) ||
|
||||
resultat.getChevauxPremiers().contains(combinaison.getCheval2Id())) {
|
||||
nbCombinaisonsPremierTroisieme++;
|
||||
} else if (resultat.getChevauxDeuxiemes().contains(combinaison.getCheval1Id()) ||
|
||||
resultat.getChevauxDeuxiemes().contains(combinaison.getCheval2Id())) {
|
||||
nbCombinaisonsDeuxiemeTroisieme++;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculer les rapports
|
||||
for (CombinaisonPayable combinaison : combinaisonsPayables) {
|
||||
double totalMises = calculerMisesSurCombinaison(combinaison, tousParis);
|
||||
|
||||
if (totalMises > 0) {
|
||||
double rapportPart;
|
||||
if (resultat.getChevauxPremiers().contains(combinaison.getCheval1Id()) &&
|
||||
resultat.getChevauxDeuxiemes().contains(combinaison.getCheval2Id()) ||
|
||||
resultat.getChevauxPremiers().contains(combinaison.getCheval2Id()) &&
|
||||
resultat.getChevauxDeuxiemes().contains(combinaison.getCheval1Id())) {
|
||||
// Combinaison premier-deuxième - 1/3 du bénéfice
|
||||
rapportPart = part;
|
||||
} else if (resultat.getChevauxPremiers().contains(combinaison.getCheval1Id()) ||
|
||||
resultat.getChevauxPremiers().contains(combinaison.getCheval2Id())) {
|
||||
// Combinaisons premier-troisième - 1/3 du bénéfice divisé par le nombre de ces combinaisons
|
||||
rapportPart = part / nbCombinaisonsPremierTroisieme;
|
||||
} else {
|
||||
// Combinaisons deuxième-troisième - 1/3 du bénéfice divisé par le nombre de ces combinaisons
|
||||
rapportPart = part / nbCombinaisonsDeuxiemeTroisieme;
|
||||
}
|
||||
|
||||
double rapport = (rapportPart / totalMises) + 1;
|
||||
rapports.add(Math.max(rapport, RAPPORT_MINIMUM));
|
||||
} else {
|
||||
rapports.add(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gains.setRapports(rapports);
|
||||
}
|
||||
|
||||
private double calculerMisesSurCombinaison(CombinaisonPayable combinaison, List<PariJumelePlace> tousParis) {
|
||||
double totalMises = 0.0;
|
||||
|
||||
for (PariJumelePlace pari : tousParis) {
|
||||
if ((pari.getCheval1().getId().equals(combinaison.getCheval1Id()) &&
|
||||
pari.getCheval2().getId().equals(combinaison.getCheval2Id())) ||
|
||||
(pari.getCheval1().getId().equals(combinaison.getCheval2Id()) &&
|
||||
pari.getCheval2().getId().equals(combinaison.getCheval1Id()))) {
|
||||
totalMises += pari.getMise();
|
||||
}
|
||||
}
|
||||
|
||||
return totalMises;
|
||||
}
|
||||
|
||||
private void gererCagnotte(Gains gains, List<CombinaisonPayable> combinaisonsPayables) {
|
||||
// Article 8 et 9: Gestion de la cagnotte
|
||||
if (combinaisonsPayables.isEmpty()) {
|
||||
gains.setMontantCagnotte(gains.getMasseAPartager());
|
||||
gains.setMasseAPartager(0.0);
|
||||
}
|
||||
|
||||
// Article 8d: Course annulée ou reportée
|
||||
if (gains.getCourse().isEstAnnulee()) {
|
||||
gains.setMontantCagnotte(gains.getMasseAPartager());
|
||||
gains.setMasseAPartager(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Classe interne pour représenter une combinaison payable
|
||||
private static class CombinaisonPayable {
|
||||
private Long cheval1Id;
|
||||
private Long cheval2Id;
|
||||
|
||||
public CombinaisonPayable(Long cheval1Id, Long cheval2Id) {
|
||||
this.cheval1Id = cheval1Id;
|
||||
this.cheval2Id = cheval2Id;
|
||||
}
|
||||
|
||||
public Long getCheval1Id() { return cheval1Id; }
|
||||
public Long getCheval2Id() { return cheval2Id; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CombinaisonPayable that = (CombinaisonPayable) o;
|
||||
return (Objects.equals(cheval1Id, that.cheval1Id) &&
|
||||
Objects.equals(cheval2Id, that.cheval2Id)) ||
|
||||
(Objects.equals(cheval1Id, that.cheval2Id) &&
|
||||
Objects.equals(cheval2Id, that.cheval1Id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
long id1 = Math.min(cheval1Id, cheval2Id);
|
||||
long id2 = Math.max(cheval1Id, cheval2Id);
|
||||
return Objects.hash(id1, id2);
|
||||
}
|
||||
}
|
||||
|
||||
public Gains obtenirGainsParCourse(Long courseId) {
|
||||
return gainsRepository.findByCourseId(courseId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.pmumali.ch3_jumeleplace.service;
|
||||
|
||||
import com.pmumali.ch3_jumeleplace.model.PariJumelePlace;
|
||||
import com.pmumali.ch3_jumeleplace.repository.ChevalRepository;
|
||||
import com.pmumali.ch3_jumeleplace.repository.CourseRepository;
|
||||
import com.pmumali.ch3_jumeleplace.repository.PariJumelePlaceRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PariJumelePlaceService {
|
||||
|
||||
@Autowired
|
||||
private PariJumelePlaceRepository pariRepository;
|
||||
|
||||
@Autowired
|
||||
private CourseRepository courseRepository;
|
||||
|
||||
@Autowired
|
||||
private ChevalRepository chevalRepository;
|
||||
|
||||
private static final double MISE_DE_BASE = 500.0;
|
||||
private static final double MISE_MAXIMALE = 20 * MISE_DE_BASE;
|
||||
|
||||
public PariJumelePlace placerPari(PariJumelePlace pari) {
|
||||
// Vérification de la limite d'enjeu (Article 2)
|
||||
if (pari.getMise() > MISE_MAXIMALE) {
|
||||
pari.setMise(MISE_MAXIMALE);
|
||||
// TODO: Implémenter le remboursement de la différence
|
||||
}
|
||||
|
||||
return pariRepository.save(pari);
|
||||
}
|
||||
|
||||
public List<PariJumelePlace> obtenirParisParCourse(Long courseId) {
|
||||
return pariRepository.findByCourseId(courseId);
|
||||
}
|
||||
|
||||
public List<PariJumelePlace> obtenirParisParCheval(Long chevalId) {
|
||||
return pariRepository.findByCheval1IdOrCheval2Id(chevalId, chevalId);
|
||||
}
|
||||
|
||||
// Méthode pour calculer le coût d'une formule combinée (Article 6a)
|
||||
public double calculerCoutFormuleCombinee(int nombreChevauxSelectionnes) {
|
||||
if (nombreChevauxSelectionnes < 2) {
|
||||
return 0;
|
||||
}
|
||||
int nombreCombinaisons = (nombreChevauxSelectionnes * (nombreChevauxSelectionnes - 1)) / 2;
|
||||
return nombreCombinaisons * MISE_DE_BASE;
|
||||
}
|
||||
|
||||
// Méthode pour calculer le coût d'une formule champ (Article 6b)
|
||||
public double calculerCoutFormuleChamp(int nombreChevauxPartants, int nombreChevauxSelectionnes, boolean estChampTotal) {
|
||||
if (estChampTotal) {
|
||||
return (nombreChevauxPartants - 1) * MISE_DE_BASE;
|
||||
} else {
|
||||
return nombreChevauxSelectionnes * MISE_DE_BASE;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user