push before automatize version incrementation!

This commit is contained in:
OnlyPapy98
2026-06-02 09:03:46 +00:00
parent 8aa4ad3921
commit c652dc4141
37 changed files with 1291 additions and 88 deletions

View File

@@ -0,0 +1,47 @@
package com.example.quiz.data.model;
public class GainRapportProduit {
private String libelle;
private double nombre;
private double rapportUnitaire;
private double massePayee;
public GainRapportProduit(String libelle, double nombre, double rapportUnitaire, double massePayee) {
this.libelle = libelle;
this.nombre = nombre;
this.rapportUnitaire = rapportUnitaire;
this.massePayee = massePayee;
}
public String getLibelle() {
return libelle;
}
public void setLibelle(String libelle) {
this.libelle = libelle;
}
public double getNombre() {
return nombre;
}
public void setNombre(double nombre) {
this.nombre = nombre;
}
public double getRapportUnitaire() {
return rapportUnitaire;
}
public void setRapportUnitaire(double rapportUnitaire) {
this.rapportUnitaire = rapportUnitaire;
}
public double getMassePayee() {
return massePayee;
}
public void setMassePayee(double massePayee) {
this.massePayee = massePayee;
}
}

View File

@@ -0,0 +1,93 @@
package com.example.quiz.data.model;
import com.example.quiz.data.model.enums.TypeProduits;
import java.util.List;
import java.util.Map;
public class RaceReport {
private String dateCourse;
private String hippodrome;
private String codeCourse;
private String nomCourse;
private int nbrePartants;
private String arrivee;
private String nonPartants;
private Map<TypeProduits, List<GainRapportProduit>> detailsGagnantsGroupes;
public RaceReport(String dateCourse, String hippodrome, String codeCourse, String nomCourse, int nbrePartants, String arrivee, String nonPartants, Map<TypeProduits, List<GainRapportProduit>> detailsGagnantsGroupes) {
this.dateCourse = dateCourse;
this.hippodrome = hippodrome;
this.codeCourse = codeCourse;
this.nomCourse = nomCourse;
this.nbrePartants = nbrePartants;
this.arrivee = arrivee;
this.nonPartants = nonPartants;
this.detailsGagnantsGroupes = detailsGagnantsGroupes;
}
public String getNomCourse() {
return nomCourse;
}
public void setNomCourse(String nomCourse) {
this.nomCourse = nomCourse;
}
public String getDateCourse() {
return dateCourse;
}
public void setDateCourse(String dateCourse) {
this.dateCourse = dateCourse;
}
public String getHippodrome() {
return hippodrome;
}
public void setHippodrome(String hippodrome) {
this.hippodrome = hippodrome;
}
public String getCodeCourse() {
return codeCourse;
}
public void setCodeCourse(String codeCourse) {
this.codeCourse = codeCourse;
}
public int getNbrePartants() {
return nbrePartants;
}
public void setNbrePartants(int nbrePartants) {
this.nbrePartants = nbrePartants;
}
public String getArrivee() {
return arrivee;
}
public void setArrivee(String arrivee) {
this.arrivee = arrivee;
}
public String getNonPartants() {
return nonPartants;
}
public void setNonPartants(String nonPartants) {
this.nonPartants = nonPartants;
}
public Map<TypeProduits, List<GainRapportProduit>> getDetailsGagnantsGroupes() {
return detailsGagnantsGroupes;
}
public void setDetailsGagnantsGroupes(Map<TypeProduits, List<GainRapportProduit>> detailsGagnantsGroupes) {
this.detailsGagnantsGroupes = detailsGagnantsGroupes;
}
}

View File

@@ -0,0 +1,10 @@
package com.example.quiz.data.model.enums;
public enum TypeProduits {
QUINTE,
QUARTE,
TIERCE,
COUPLE_GAGNANT,
COUPLE_PLACE
}

View File

@@ -1,9 +1,12 @@
package com.example.quiz.data.remote;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.example.quiz.utils.SharedPrefsHelper;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
@@ -11,6 +14,7 @@ import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import dagger.hilt.InstallIn;
import dagger.hilt.android.qualifiers.ApplicationContext;
import dagger.hilt.components.SingletonComponent;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
@@ -20,8 +24,12 @@ import retrofit2.converter.gson.GsonConverterFactory;
@Module
@InstallIn(SingletonComponent.class)
public class ApiClient {
private static final String BASE_URL = "https://alr.pmu.ml/api/";
private static final String DEFAULT_BASE_URL = "https://api-alr.pmu.ml/api/";
private static final String DEFAULT_REPORT_BASE_URL = "https://dep-alr.pmu.ml/api/v1/";
private static final String BASE_URL_KEY = "MAIN_API_URL";
private static final String REPORT_BASE_URL_KEY = "REPORT_API_URL";
@Provides
@Singleton
@@ -55,7 +63,9 @@ public class ApiClient {
@Provides
@Singleton
public Retrofit provideRetrofit(OkHttpClient okHttpClient){
public Retrofit provideRetrofit(OkHttpClient okHttpClient, @ApplicationContext Context context){
SharedPrefsHelper prefsHelper = SharedPrefsHelper.getInstance(context);
String BASE_URL = prefsHelper.getString(BASE_URL_KEY, DEFAULT_BASE_URL);
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
@@ -68,4 +78,23 @@ public class ApiClient {
public ApiService provideApiService(Retrofit retrofit){
return retrofit.create(ApiService.class);
}
@Provides
@Singleton
@ReportApiClient
public Retrofit provideReportRetrofit(OkHttpClient okHttpClient, @ApplicationContext Context context){
SharedPrefsHelper prefsHelper = SharedPrefsHelper.getInstance(context);
String REPORT_BASE_URL = prefsHelper.getString(REPORT_BASE_URL_KEY, DEFAULT_REPORT_BASE_URL);
return new Retrofit.Builder()
.baseUrl(REPORT_BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
@Provides
@Singleton
public ReportApiService provideReportApiService(@ReportApiClient Retrofit retrofit){
return retrofit.create(ReportApiService.class);
}
}

View File

@@ -43,7 +43,7 @@ public interface ApiService {
Call<List<ParisResponse>> derniersParis(@Path("agentId") String agentId);
@PATCH("paris/numero/{numeroTicket}/cancel")
Call<ParisResponse> annulerPari(@Path("numeroTicket") String numeroTicket);
Call<ParisResponse> annulerPari(@Path("numeroTicket") String numeroTicket, @Query("agentId") String agentId);
@PATCH("paris/numero/{numeroTicket}/rembourser")
Call<ParisResponse> rembourserPari(@Path("numeroTicket") String numeroTicket);

View File

@@ -0,0 +1,9 @@
package com.example.quiz.data.remote;
import java.lang.annotation.RetentionPolicy;
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@javax.inject.Qualifier
public @interface ReportApiClient{
}

View File

@@ -0,0 +1,12 @@
package com.example.quiz.data.remote;
import com.example.quiz.data.model.RaceReport;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface ReportApiService {
@GET("rapports/course/{courseId}/fiche-calcul")
Call<RaceReport> getRaceReport(@Path("courseId") String courseId);
}

View File

@@ -1,9 +1,11 @@
package com.example.quiz.data.remote;
import android.content.Context;
import android.util.Log;
import com.example.quiz.data.model.Course;
import com.example.quiz.data.model.dtos.NotifPayload;
import com.example.quiz.utils.SharedPrefsHelper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
@@ -17,6 +19,7 @@ import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.hilt.android.qualifiers.ApplicationContext;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
@@ -34,6 +37,10 @@ public class StompManager {
private StompClient stompClient;
private boolean isConnected = false;
private String url = "wss://api-alr.pmu.ml/ws";
SharedPrefsHelper prefsHelper;
// Map topic -> liste de listeners
private final Map<String, List<Consumer<String>>> topicListeners = new HashMap<>();
@@ -42,10 +49,40 @@ public class StompManager {
// Map pour stocker les subscriptions par topic
private final Map<String, Disposable> topicSubscriptions = new HashMap<>();
private String genererUrlWebSocket(String httpUrl) {
if (httpUrl == null || httpUrl.isEmpty()) {
return "wss://api-alr.pmu.ml/ws"; // Sécurité au cas où
}
String wsUrl = httpUrl;
// 1. On remplace le protocole au début
if (wsUrl.startsWith("https://")) {
wsUrl = wsUrl.replace("https://", "wss://");
} else if (wsUrl.startsWith("http://")) {
wsUrl = wsUrl.replace("http://", "ws://");
}
// 2. On remplace la route finale "/api/" ou "/api" par "/ws"
if (wsUrl.endsWith("/api/")) {
// Enlève "/api/" (5 caractères) à la fin et ajoute "/ws"
wsUrl = wsUrl.substring(0, wsUrl.length() - 5) + "/ws";
} else if (wsUrl.endsWith("/api")) {
// Enlève "/api" (4 caractères) à la fin et ajoute "/ws"
wsUrl = wsUrl.substring(0, wsUrl.length() - 4) + "/ws";
}
return wsUrl;
}
@Inject
public StompManager(TokenManager tokenManager,
NotificationHelper notificationHelper) {
NotificationHelper notificationHelper, Context context) {
prefsHelper = SharedPrefsHelper.getInstance(context);
String apiUrl = prefsHelper.get("MAIN_API_URL");
if(apiUrl != null){
url = genererUrlWebSocket(apiUrl);
}
this.tokenManager = tokenManager;
this.notificationHelper = notificationHelper;
}
@@ -61,7 +98,7 @@ public class StompManager {
}
// URL de connexion WebSocket
String url = "wss://alr.pmu.ml/ws";
try {
// Créer le client STOMP
@@ -162,12 +199,12 @@ public class StompManager {
NotifPayload<Course> notifCourse = new Gson().fromJson(payload, type);
Course updatedCourse = notifCourse.getPayload();
switch (notifCourse.getType()){
case COURSE_CREATED:
notif = "Nouvelle course "+updatedCourse.getNom()+" créée";
break;
case COURSE_UPDATED:
notif = "Course "+updatedCourse.getNom()+" modifiée";
break;
case COURSE_UPDATED:{
if(updatedCourse.getStatut() == Course.Statut.OUVERT){
notif = "Course "+updatedCourse.getNom()+" a été créée avec succès";
break;
}
}
case COURSE_CANCELLED:
notif = "Course "+updatedCourse.getNom()+" annulée";
break;
@@ -181,7 +218,7 @@ public class StompManager {
notif = "Non partants déclarés pour la course "+updatedCourse.getNom();
break;
}
// Notification
if(notif.isEmpty()) return;
notificationHelper.showNotification(topic, notif);
},
throwable -> {

View File

@@ -45,6 +45,10 @@ public class LoginRepository {
}else{
try {
String error = response.errorBody().string();
if(!error.startsWith("{")){
liveLogin.postValue(Result.error(error));
return;
}
Gson gson = new Gson();
ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
liveLogin.postValue(Result.error(errorResponse.getMessage()));

View File

@@ -148,10 +148,10 @@ public class PariRepository {
return pariResponse;
}
public LiveData<Result<ParisResponse>> annulerPari(String numeroTicket){
public LiveData<Result<ParisResponse>> annulerPari(String numeroTicket, String agentId){
MutableLiveData<Result<ParisResponse>> pariResponse = new MutableLiveData<>();
pariResponse.setValue(Result.loading());
apiService.annulerPari(numeroTicket).enqueue(new Callback<ParisResponse>(){
apiService.annulerPari(numeroTicket, agentId).enqueue(new Callback<ParisResponse>(){
@Override
public void onResponse(Call<ParisResponse> call, Response<ParisResponse> response) {
if(response.isSuccessful()){

View File

@@ -0,0 +1,57 @@
package com.example.quiz.data.repository;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.example.quiz.data.model.RaceReport;
import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.remote.ReportApiService;
import com.example.quiz.utils.Result;
import com.google.gson.Gson;
import javax.inject.Inject;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class RapportCourseRepository {
private final ReportApiService reportApiService;
@Inject
public RapportCourseRepository(ReportApiService reportApiService) {
this.reportApiService = reportApiService;
}
public LiveData<Result<RaceReport>> getRaceReport(String courseId) {
MutableLiveData<Result<RaceReport>> raceReport = new MutableLiveData<>();
raceReport.setValue(Result.loading());
reportApiService.getRaceReport(courseId).enqueue(new Callback<RaceReport>() {
@Override
public void onResponse(Call<RaceReport> call, Response<RaceReport> response) {
if(response.isSuccessful() && response.body() != null){
raceReport.postValue(Result.success(response.body()));
}else{
if(response.code() == 404){
raceReport.postValue(Result.error("Aucun rapport disponible pour cette course"));
}else{
try {
String error = response.errorBody().string();
Gson gson = new Gson();
ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
raceReport.postValue(Result.error(errorResponse.getMessage()));
} catch (Exception e) {
raceReport.postValue(Result.error("Erreur serveur"));
}
}
}
}
@Override
public void onFailure(Call<RaceReport> call, Throwable throwable) {
raceReport.postValue(Result.error(throwable.getMessage()));
}
});
return raceReport;
}
}