895 lines
37 KiB
Java
895 lines
37 KiB
Java
package com.example.quiz;
|
||
|
||
|
||
import android.annotation.SuppressLint;
|
||
import android.app.Dialog;
|
||
import android.content.Intent;
|
||
|
||
import android.graphics.Bitmap;
|
||
import android.graphics.BitmapFactory;
|
||
import android.graphics.Canvas;
|
||
import android.graphics.Color;
|
||
import android.graphics.ColorMatrix;
|
||
import android.graphics.ColorMatrixColorFilter;
|
||
import android.graphics.Paint;
|
||
import android.graphics.drawable.ColorDrawable;
|
||
import android.os.Build;
|
||
import android.os.Bundle;
|
||
|
||
import androidx.activity.result.ActivityResultLauncher;
|
||
import androidx.annotation.NonNull;
|
||
import androidx.annotation.Nullable;
|
||
import androidx.appcompat.app.AlertDialog;
|
||
import androidx.appcompat.app.AppCompatActivity;
|
||
import androidx.fragment.app.Fragment;
|
||
import androidx.lifecycle.MutableLiveData;
|
||
import androidx.lifecycle.Observer;
|
||
import androidx.lifecycle.ViewModelProvider;
|
||
|
||
import android.text.Editable;
|
||
import android.text.TextWatcher;
|
||
import android.util.Log;
|
||
import android.view.Gravity;
|
||
import android.view.LayoutInflater;
|
||
import android.view.View;
|
||
import android.view.ViewGroup;
|
||
import android.widget.AdapterView;
|
||
import android.widget.GridLayout;
|
||
import android.widget.TextView;
|
||
import android.widget.Toast;
|
||
|
||
import com.anggastudio.printama.Printama;
|
||
import com.example.quiz.data.model.Course;
|
||
import com.example.quiz.data.model.MiseInitiale;
|
||
import com.example.quiz.data.model.Pari;
|
||
import com.example.quiz.data.model.PariMise;
|
||
import com.example.quiz.data.model.ParisResponse;
|
||
|
||
import com.example.quiz.data.model.TypeOfBet;
|
||
import com.example.quiz.data.model.dtos.NotifPayload;
|
||
import com.example.quiz.data.remote.StompManager;
|
||
import com.example.quiz.databinding.FragmentBetValidationBinding;
|
||
import com.example.quiz.utils.BluetoothUtils;
|
||
import com.example.quiz.utils.LoaderDialog;
|
||
import com.example.quiz.utils.MessageDialog;
|
||
import com.example.quiz.utils.Result;
|
||
import com.example.quiz.utils.SharedPrefsHelper;
|
||
import com.example.quiz.utils.SunmiPrinterManager;
|
||
import com.example.quiz.viewModel.LogsViewModel;
|
||
import com.example.quiz.viewModel.PariMiseViewModel;
|
||
import com.example.quiz.viewModel.PariViewModel;
|
||
import com.example.quiz.viewModel.SharedViewModel;
|
||
import com.google.android.material.appbar.MaterialToolbar;
|
||
import com.google.gson.Gson;
|
||
import com.google.gson.reflect.TypeToken;
|
||
import com.google.zxing.BarcodeFormat;
|
||
import com.google.zxing.MultiFormatWriter;
|
||
import com.google.zxing.WriterException;
|
||
import com.google.zxing.common.BitMatrix;
|
||
|
||
import java.lang.reflect.Type;
|
||
|
||
import java.time.LocalDateTime;
|
||
import java.time.OffsetDateTime;
|
||
import java.time.ZoneOffset;
|
||
import java.time.format.DateTimeFormatter;
|
||
import java.util.ArrayList;
|
||
import java.util.Arrays;
|
||
import java.util.List;
|
||
|
||
import java.util.Objects;
|
||
import java.util.Observable;
|
||
import java.util.stream.Collectors;
|
||
|
||
import javax.inject.Inject;
|
||
|
||
import dagger.hilt.android.AndroidEntryPoint;
|
||
|
||
/**
|
||
* A simple {@link Fragment} subclass.
|
||
* Use the {@link BetValidation#newInstance} factory method to
|
||
* create an instance of this fragment.
|
||
*/
|
||
|
||
@AndroidEntryPoint
|
||
public class BetValidation extends Fragment {
|
||
|
||
FragmentBetValidationBinding binding;
|
||
|
||
|
||
SharedViewModel shared;
|
||
|
||
|
||
PariMiseViewModel pariMiseViewModel;
|
||
|
||
List<MiseInitiale> misesInitiales;
|
||
|
||
private AlertDialog dialog;
|
||
|
||
@Inject
|
||
StompManager stompManager;
|
||
|
||
SunmiPrinterManager sunmiPrinterManager;
|
||
|
||
private int nombreX;
|
||
|
||
LogsViewModel logsViewModel;
|
||
|
||
|
||
private boolean order;
|
||
|
||
private long mise;
|
||
|
||
String mobileName;
|
||
|
||
|
||
private TypeOfBet typeOfBet;
|
||
|
||
MutableLiveData<Boolean> isPrinterReady = new MutableLiveData<>(false);
|
||
|
||
SharedPrefsHelper prefsHelper;
|
||
|
||
|
||
private Course course;
|
||
|
||
|
||
LoaderDialog loader;
|
||
|
||
|
||
private int coeff;
|
||
|
||
private ActivityResultLauncher<Intent> enableBluetoothLauncher;
|
||
|
||
|
||
private final MutableLiveData<List<String>> selectedHorses = new MutableLiveData<>(List.of());
|
||
|
||
PariViewModel pariViewModel;
|
||
|
||
|
||
public BetValidation() {
|
||
// Required empty public constructor
|
||
}
|
||
|
||
public static BetValidation newInstance() {
|
||
BetValidation fragment = new BetValidation();
|
||
Bundle args = new Bundle();
|
||
fragment.setArguments(args);
|
||
return fragment;
|
||
}
|
||
|
||
@Override
|
||
public void onCreate(Bundle savedInstanceState) {
|
||
super.onCreate(savedInstanceState);
|
||
prefsHelper = SharedPrefsHelper.getInstance(getContext());
|
||
mobileName = Build.MANUFACTURER;
|
||
sunmiPrinterManager = SunmiPrinterManager.getInstance(requireContext());
|
||
if(mobileName.toLowerCase().contains("sunmi")){
|
||
sunmiPrinterManager.connectPrinter(status ->{
|
||
isPrinterReady.setValue(status);
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
@Override
|
||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||
Bundle savedInstanceState) {
|
||
binding = FragmentBetValidationBinding.inflate(inflater, container, false);
|
||
loader = new LoaderDialog(getContext());
|
||
logsViewModel = new ViewModelProvider(this).get(LogsViewModel.class);
|
||
binding.coeff.setText(String.valueOf(1));
|
||
coeff = Integer.parseInt(binding.coeff.getText().toString());
|
||
binding.coeff.addTextChangedListener(new TextWatcher() {
|
||
@Override
|
||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||
|
||
}
|
||
|
||
@Override
|
||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||
if (charSequence.toString().isEmpty()) {
|
||
binding.coeff.setError("Le coefficient est obligatoire");
|
||
return;
|
||
}
|
||
if (Integer.parseInt(charSequence.toString()) < 1) {
|
||
binding.coeff.setError("Le coefficient doit être supérieur ou égal à 1 ");
|
||
return;
|
||
}
|
||
coeff = Integer.parseInt(charSequence.toString());
|
||
calculateMise(selectedHorses.getValue());
|
||
|
||
}
|
||
|
||
@Override
|
||
public void afterTextChanged(Editable editable) {
|
||
|
||
}
|
||
});
|
||
return binding.getRoot();
|
||
}
|
||
|
||
private void setupNumberGrid(GridLayout grid) {
|
||
binding.gridNumbers.removeAllViews();
|
||
int columns = 8;
|
||
grid.setColumnCount(columns);
|
||
if (shared.selectedCourse.getValue() != null) {
|
||
for (int i = 1; i <= shared.selectedCourse.getValue().getNombrePartants(); i++) {
|
||
createNumberItem(String.valueOf(i));
|
||
grid.addView(createNumberItem(String.valueOf(i)));
|
||
}
|
||
}
|
||
createNumberItem("X");
|
||
grid.addView(createNumberItem("X"));
|
||
}
|
||
private TextView createNumberItem(String horse) {
|
||
TextView textView = new TextView(requireContext());
|
||
textView.setText(horse);
|
||
textView.setTextColor(getResources().getColor(R.color.white));
|
||
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
|
||
params.setMargins(1, 1, 1, 1);
|
||
textView.setLayoutParams(params);
|
||
textView.setTextSize(10);
|
||
textView.setWidth(80);
|
||
textView.setHeight(100);
|
||
textView.setGravity(Gravity.CENTER);
|
||
textView.setBackgroundResource(Objects.equals(horse, "X") ? R.drawable.x_background : R.drawable.number_background);
|
||
if (!Objects.equals(horse, "X") && shared.selectedCourse.getValue().getNonPartants() != null && shared.selectedCourse.getValue().getNonPartants().contains(Integer.valueOf(horse))) {
|
||
textView.setTextColor(getResources().getColor(R.color.white));
|
||
textView.setBackgroundResource(R.drawable.number_background_grey);
|
||
}
|
||
textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||
textView.setOnClickListener(v -> {
|
||
if (!Objects.equals(horse, "X") && shared.selectedCourse.getValue().getNonPartants() != null && shared.selectedCourse.getValue().getNonPartants().contains(Integer.valueOf(horse))) {
|
||
Toast.makeText(getContext(), "Ce cheval n'est pas partant", Toast.LENGTH_SHORT).show();
|
||
return;
|
||
}
|
||
final List<String> horses = new ArrayList<>(selectedHorses.getValue());
|
||
if (horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse() && horse.equals("X")) {
|
||
Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show();
|
||
return;
|
||
}
|
||
if (_notClickable(horses) && horse.equals("X")) {
|
||
Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show();
|
||
return;
|
||
}
|
||
if (horses.contains(horse) && !horse.equals("X")) {
|
||
horses.remove(horse);
|
||
selectedHorses.setValue(horses);
|
||
v.setSelected(false);
|
||
v.setBackgroundResource(R.drawable.number_background);
|
||
} else {
|
||
horses.add(horse);
|
||
selectedHorses.setValue(horses);
|
||
v.setSelected(true);
|
||
v.setBackgroundResource(R.drawable.number_selected_background);
|
||
}
|
||
String combinationText = selectedHorses.getValue().stream()
|
||
.map(h -> h)
|
||
.collect(Collectors.joining("-"));
|
||
binding.combination.setText(combinationText);
|
||
});
|
||
return textView;
|
||
}
|
||
|
||
|
||
boolean _notClickable(List<String> selectedHorses) {
|
||
int numberOfElement = 0;
|
||
if (shared.typeOfBet.getValue().getNumberOfHorse() < 2) {
|
||
return true;
|
||
}
|
||
for (String horse : selectedHorses) {
|
||
numberOfElement = horse.equals("X") ? numberOfElement + 1 : numberOfElement;
|
||
}
|
||
nombreX = numberOfElement;
|
||
return numberOfElement == shared.typeOfBet.getValue().getNumberOfHorse() - 1;
|
||
}
|
||
|
||
@Override
|
||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||
super.onViewCreated(view, savedInstanceState);
|
||
shared = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
|
||
pariMiseViewModel = new ViewModelProvider(this).get(PariMiseViewModel.class);
|
||
pariMiseViewModel.getBetInitMise().observe(
|
||
getViewLifecycleOwner(),
|
||
result -> {
|
||
switch (result.status) {
|
||
case LOADING: {
|
||
loader.show("Chargement des mise");
|
||
break;
|
||
}
|
||
case SUCCESS: {
|
||
misesInitiales = result.data;
|
||
loader.dismiss();
|
||
break;
|
||
}
|
||
case ERROR: {
|
||
loader.dismiss();
|
||
MessageDialog.showError(getContext(), result.message);
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
);
|
||
if (shared.selectedCourse.getValue() != null) {
|
||
stompManager.subscribe("courses/" + shared.selectedCourse.getValue().getId(), json -> {
|
||
Type type = new TypeToken<NotifPayload<Course>>() {
|
||
}.getType();
|
||
NotifPayload<Course> notif = new Gson().fromJson(json, type);
|
||
Course updatedCourse = notif.getPayload();
|
||
if (shared.selectedCourse.getValue().getId() == updatedCourse.getId()) {
|
||
shared.setSelectedCourse(updatedCourse);
|
||
setupNumberGrid(binding.gridNumbers);
|
||
}
|
||
});
|
||
}
|
||
setSelectedTypeOfBetImage();
|
||
pariViewModel = new ViewModelProvider(this).get(PariViewModel.class);
|
||
typeOfBet = shared.typeOfBet.getValue();
|
||
course = shared.selectedCourse.getValue();
|
||
AppCompatActivity activity = (AppCompatActivity) getActivity();
|
||
if (activity != null) {
|
||
MaterialToolbar toolbar = activity.findViewById(R.id.toolbar);
|
||
toolbar.setBackgroundColor(getResources().getColor(R.color.primary_green));
|
||
activity.setSupportActionBar(toolbar);
|
||
if (activity.getSupportActionBar() != null) {
|
||
activity.getSupportActionBar().setTitle("Pari " + shared.selectedCourse.getValue().getNom());
|
||
}
|
||
}
|
||
setupNumberGrid(binding.gridNumbers);
|
||
binding.paymentType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||
@Override
|
||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||
String selected = binding.paymentType.getSelectedItem().toString();
|
||
|
||
if (selected.equals("Orange Money")) {
|
||
binding.phoneNumber.setVisibility(View.VISIBLE);
|
||
} else {
|
||
binding.phoneNumber.setVisibility(View.GONE); // ou GONE
|
||
binding.phoneNumber.setText(""); // vider le champ si non utilisé
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onNothingSelected(AdapterView<?> parent) {
|
||
binding.phoneNumber.setVisibility(View.INVISIBLE);
|
||
}
|
||
});
|
||
|
||
selectedHorses.observe(getViewLifecycleOwner(), new Observer<List<String>>() {
|
||
@Override
|
||
public void onChanged(List<String> horses) {
|
||
calculateMise(horses);
|
||
if (shared.typeOfBet.getValue().getNumberOfHorse() > 2 && horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse()) {
|
||
binding.order.setVisibility(View.VISIBLE);
|
||
} else {
|
||
binding.order.setVisibility(View.GONE);
|
||
}
|
||
if (horses.contains("X")) {
|
||
if (selectedHorses.getValue().size() == shared.typeOfBet.getValue().getNumberOfHorse()) {
|
||
binding.elargie.setVisibility(View.VISIBLE);
|
||
binding.elargie.setText("Champ total");
|
||
return;
|
||
} else {
|
||
if (selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse()) {
|
||
binding.elargie.setVisibility(View.VISIBLE);
|
||
binding.elargie.setText("Champ partiel");
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
if (horses.size() > shared.typeOfBet.getValue().getNumberOfHorse()) {
|
||
binding.elargie.setVisibility(View.VISIBLE);
|
||
binding.elargie.setText("Elargi");
|
||
} else {
|
||
binding.elargie.setVisibility(View.GONE);
|
||
}
|
||
}
|
||
});
|
||
binding.order.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||
order = isChecked;
|
||
calculateMise(selectedHorses.getValue());
|
||
});
|
||
|
||
binding.betValidateBtn.setOnClickListener(v -> {
|
||
if (binding.paymentType.getSelectedItem().toString().equals("Orange Money") && binding.phoneNumber.getText().toString().isEmpty()) {
|
||
MessageDialog.showError(getContext(), "Veuillez saisir le numéro de téléphone");
|
||
return;
|
||
}
|
||
|
||
if (shared.typeOfBet == null || shared.selectedCourse == null) {
|
||
return;
|
||
}
|
||
|
||
|
||
int required = typeOfBet.getNumberOfHorse();
|
||
if (Objects.requireNonNull(selectedHorses.getValue()).size() < required) {
|
||
Toast.makeText(getContext(), "Veuillez sélectionner au moins" + required + " chevaux", Toast.LENGTH_SHORT).show();
|
||
return;
|
||
}
|
||
|
||
if (this.mise == 0) {
|
||
Toast.makeText(getContext(), "Pari non valide", Toast.LENGTH_SHORT).show();
|
||
return;
|
||
}
|
||
|
||
Pari pari = new Pari(
|
||
OffsetDateTime.now(ZoneOffset.UTC).toString(),
|
||
Long.valueOf(course.getId()),
|
||
Long.valueOf(prefsHelper.get("id")),
|
||
Long.valueOf(prefsHelper.get("terminalId")),
|
||
Long.valueOf(prefsHelper.get("pointDeVenteId")),
|
||
List.of(new PariMise(String.valueOf(shared.typeOfBet.getValue().getName()), mise)),
|
||
_getFormule(),
|
||
_getCombinaison(),
|
||
coeff,
|
||
"XOF",
|
||
"Pari"
|
||
);
|
||
if (dialog != null && dialog.isShowing()) {
|
||
return;
|
||
}
|
||
_showPariDialog(pari);
|
||
});
|
||
|
||
binding.backBtn.setOnClickListener(v -> {
|
||
getActivity().onBackPressed();
|
||
});
|
||
|
||
binding.deleteBtn.setOnClickListener(v -> {
|
||
_initializeToZero();
|
||
});
|
||
}
|
||
|
||
|
||
String _getCombinaison() {
|
||
if (selectedHorses.getValue().contains("X") && shared.typeOfBet.getValue().getNumberOfHorse() < selectedHorses.getValue().size()) {
|
||
String first = selectedHorses.getValue().subList(0, shared.typeOfBet.getValue().getNumberOfHorse()).stream()
|
||
.map(String::valueOf)
|
||
.collect(Collectors.joining(","));
|
||
String last = selectedHorses.getValue().subList(shared.typeOfBet.getValue().getNumberOfHorse(), selectedHorses.getValue().size()).stream()
|
||
.map(String::valueOf)
|
||
.collect(Collectors.joining(","));
|
||
return first + ",R," + last;
|
||
} else {
|
||
return selectedHorses.getValue().stream().map(String::valueOf).collect(Collectors.joining(","));
|
||
}
|
||
}
|
||
|
||
List<String> _getFormule() {
|
||
List<String> combinaison = selectedHorses.getValue();
|
||
if (!combinaison.contains("X")) {
|
||
if (!order) {
|
||
return List.of("UNITAIRE");
|
||
} else {
|
||
return List.of("FORMULE_COMPLETE");
|
||
}
|
||
} else {
|
||
if (shared.typeOfBet.getValue().getNumberOfHorse() < selectedHorses.getValue().size()) {
|
||
if (order) {
|
||
return List.of("CHAMP_X", "FORMULE_COMPLETE");
|
||
} else {
|
||
return List.of("CHAMP_X");
|
||
}
|
||
} else {
|
||
if (order) {
|
||
return List.of("CHAMP_TOTAL", "FORMULE_COMPLETE");
|
||
} else {
|
||
return List.of("CHAMP_TOTAL");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void setSelectedTypeOfBetImage() {
|
||
switch (shared.typeOfBet.getValue().getName()) {
|
||
case COUPLE_PLACE:
|
||
binding.icTypeOfBet.setImageResource(R.drawable.ic_couple_place);
|
||
break;
|
||
case COUPLE_GAGNANT:
|
||
binding.icTypeOfBet.setImageResource(R.drawable.ic_couple_gagnant);
|
||
break;
|
||
case TIERCE:
|
||
binding.icTypeOfBet.setImageResource(R.drawable.ic_tierce);
|
||
break;
|
||
case QUARTE:
|
||
binding.icTypeOfBet.setImageResource(R.drawable.ic_quarte);
|
||
break;
|
||
case QUINTE:
|
||
binding.icTypeOfBet.setImageResource(R.drawable.ic_quinte_plus);
|
||
break;
|
||
}
|
||
}
|
||
|
||
public void printPari(ParisResponse pari) throws WriterException {
|
||
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo);
|
||
Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100);
|
||
StringBuilder tspl = new StringBuilder();
|
||
tspl.append("Bamako").append("\n");
|
||
tspl.append(shared.selectedCourse.getValue().getNom()).append("\n");
|
||
OffsetDateTime dateTime = OffsetDateTime.parse(shared.selectedCourse.getValue().getHeureDepartPrevue());
|
||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
|
||
String formattedDate = dateTime.format(formatter);
|
||
tspl.append(formattedDate).append("\n");
|
||
tspl.append("Course ").append(String.valueOf(shared.selectedCourse.getValue().getId())).append("\n");
|
||
tspl.append(sunmiPrinterManager.separationText()+ "\n");
|
||
boolean isElargie = selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse();
|
||
String typePari = pari.getTypesParisMises().get(0).getTypePari();
|
||
tspl.append(isElargie ? typePari + "/Elargie" : typePari).append("\n");
|
||
tspl.append(order ? "COMBINAISON COMPLETE" + "\n" : "");
|
||
String combinationText = formatLineWithNumbers(selectedHorses.getValue().stream().map(String::valueOf).toArray(String[]::new), "-") ;
|
||
tspl.append(combinationText).append("\n");
|
||
tspl.append("COEF: ").append(String.valueOf(coeff)).append(".0");
|
||
tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n");
|
||
tspl.append("MONTANT: ").append(pari.getTypesParisMises().get(0).getMiseTotale()).append(" XOF");
|
||
tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n");
|
||
tspl.append("AGENT: ").append(prefsHelper.get("code")).append("\n");
|
||
tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(LocalDateTime.now())).append("\n");
|
||
if(mobileName.toLowerCase().contains("sunmi")){
|
||
String pariText = tspl.toString();
|
||
if(!sunmiPrinterManager.printPari(resizeToPrinterWidth(bitmap, 384), barcode, pari.getNumeroTicket(), pariText)){
|
||
MessageDialog.showError(getContext(), "Erreur d'impression");
|
||
prefsHelper.save("noPrintId", String.valueOf(pari.getId()));
|
||
return;
|
||
};
|
||
_initializeToZero();
|
||
return;
|
||
}
|
||
|
||
try {
|
||
if (BluetoothUtils.needsBluetoothPermissions()) {
|
||
if (!BluetoothUtils.hasBluetoothPermission(requireContext())) {
|
||
// Demande la permission si non accordée
|
||
BluetoothUtils.requestBluetoothPermission(requireActivity());
|
||
return; // arrête ici, la popup va apparaître
|
||
}
|
||
}
|
||
|
||
// 2️⃣ Permission OK, on peut afficher la liste
|
||
|
||
Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode, new Printama.PrintCallback() {
|
||
@Override
|
||
public void onResult(boolean success, String errorMessage) {
|
||
if (!success) {
|
||
new android.app.AlertDialog.Builder(getContext())
|
||
.setTitle("Impréssion pari")
|
||
.setMessage("Voulez-vous rééimprimer ce ticket?")
|
||
.setPositiveButton("Oui", (dialog, which) -> {
|
||
try {
|
||
printPari(pari);
|
||
} catch (WriterException e) {
|
||
throw new RuntimeException(e);
|
||
}
|
||
})
|
||
.setNegativeButton("Non", (dialog, which) -> {
|
||
dialog.dismiss();
|
||
});
|
||
} else {
|
||
_initializeToZero();
|
||
}
|
||
}
|
||
});
|
||
} catch (SecurityException e) {
|
||
Toast.makeText(requireContext(),
|
||
"Permission Bluetooth non accordée", Toast.LENGTH_SHORT).show();
|
||
}
|
||
}
|
||
|
||
|
||
public String formatLineWithNumbers(String[] numbers, String separator) {
|
||
StringBuilder currentLine = new StringBuilder();
|
||
StringBuilder finalOutput = new StringBuilder();
|
||
List<String> formatted = new ArrayList<>();
|
||
int requiredHorse = shared.typeOfBet.getValue().getNumberOfHorse();
|
||
if(Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList()).contains("X")){
|
||
if(numbers.length <= requiredHorse){
|
||
return Arrays.stream(numbers).map(String::valueOf).collect(Collectors.joining("-")).toString();
|
||
}
|
||
List<String> firstPart = Arrays.stream(numbers).limit(requiredHorse).map(String::valueOf).collect(Collectors.toList());
|
||
List<String> secondPart = Arrays.stream(numbers).skip(requiredHorse).map(String::valueOf).collect(Collectors.toList());
|
||
formatted.addAll(firstPart);
|
||
formatted.add("R");
|
||
formatted.addAll(secondPart);
|
||
}else{
|
||
formatted = Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList());
|
||
}
|
||
|
||
for (String number : formatted) {
|
||
String element = (currentLine.length() == 0 ? "":separator) + number;
|
||
|
||
// Si l'ajout dépasse la largeur max, on termine la ligne et on recommence
|
||
if (currentLine.length() + element.length() > sunmiPrinterManager.getMaxChar()) {
|
||
finalOutput.append(currentLine.toString()).append("\n");
|
||
currentLine = new StringBuilder(number);
|
||
} else {
|
||
currentLine.append(element);
|
||
}
|
||
}
|
||
|
||
if (currentLine.length() > 0) {
|
||
finalOutput.append(currentLine.toString());
|
||
}
|
||
|
||
return finalOutput.toString();
|
||
}
|
||
|
||
|
||
@SuppressLint({"MissingInflatedId", "SetTextI18n"})
|
||
void _showPariDialog(Pari pari) {
|
||
LayoutInflater inflater = getLayoutInflater();
|
||
View view = inflater.inflate(R.layout.pari_confirmation, null);
|
||
TextView numero_course = (TextView) view.findViewById(R.id.alert_course_numero);
|
||
numero_course.setText("Numero Course: " + String.valueOf(shared.selectedCourse.getValue().getId()));
|
||
TextView alert_pari_type = (TextView) view.findViewById(R.id.alert_pari_type);
|
||
alert_pari_type.setText(String.valueOf(shared.typeOfBet.getValue().getName()));
|
||
TextView is_elargie = (TextView) view.findViewById(R.id.alert_is_elargie);
|
||
is_elargie.setText(selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse() ? "CE" : "SI");
|
||
TextView alert_combinaison = (TextView) view.findViewById(R.id.alert_combinaison);
|
||
alert_combinaison.setText(selectedHorses.getValue().stream()
|
||
.map(String::valueOf)
|
||
.collect(Collectors.joining("-")));
|
||
TextView aler_coeff = (TextView) view.findViewById(R.id.alert_coeff);
|
||
aler_coeff.setText("Coef:" + String.valueOf(coeff));
|
||
TextView alert_montant = (TextView) view.findViewById(R.id.alert_montant);
|
||
alert_montant.setText("Montant: " + String.valueOf(pari.getTypesParisMises().get(0).getMiseTotale()) + " CFA");
|
||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||
builder.setView(view);
|
||
builder.setCancelable(false);
|
||
dialog = builder.create();
|
||
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||
|
||
view.findViewById(R.id.alert_validate).setOnClickListener(v -> {
|
||
if(mobileName.toLowerCase().contains("sunmi")){
|
||
if(isPrinterReady.getValue() != null && !isPrinterReady.getValue()){
|
||
sunmiPrinterManager.connectPrinter(status ->{
|
||
isPrinterReady.setValue(status);
|
||
});
|
||
}
|
||
switch (sunmiPrinterManager.printerStatus()){
|
||
case 2:{
|
||
MessageDialog.showError(getContext(), "L'imprimante n'est pas connectée!");
|
||
return;
|
||
}
|
||
case 3:{
|
||
MessageDialog.showError(getContext(), "L'imprimante n'est pas disponible!");
|
||
return;
|
||
}
|
||
case 4:{
|
||
MessageDialog.showError(getContext(), "Veuillez insérer du papier dans l'imprimante, SVP!");
|
||
return;
|
||
}
|
||
case 5: {
|
||
MessageDialog.showError(getContext(), "Suchauffe iminante de l'imprimante, Veuillez laisser reposer!");
|
||
return;
|
||
}
|
||
case 6: {
|
||
MessageDialog.showError(getContext(), "Le capot est ouvert, veuillez fermer SVP!");
|
||
return;
|
||
}
|
||
|
||
}
|
||
}
|
||
pariViewModel.createPari(pari).observe(getViewLifecycleOwner(), new Observer<Result<ParisResponse>>() {
|
||
@Override
|
||
public void onChanged(Result<ParisResponse> pariResult) {
|
||
switch (pariResult.status) {
|
||
case ERROR:
|
||
loader.dismiss();
|
||
dialog.dismiss();
|
||
MessageDialog.showError(getContext(), pariResult.message);
|
||
break;
|
||
case LOADING:
|
||
loader.show("Prise de pari");
|
||
break;
|
||
case SUCCESS:
|
||
try {
|
||
loader.dismiss();
|
||
logsViewModel.insertLog(prefsHelper.get("id"), "BET", "Création du pari " + pariResult.data.getNumeroTicket() + ", type de paris: " + pariResult.data.getTypesParisMises().get(0).getTypePari() + ", combinaison:" + selectedHorses.getValue().stream().map(String::valueOf).collect(Collectors.joining("-")), System.currentTimeMillis());
|
||
printPari(pariResult.data);
|
||
dialog.dismiss();
|
||
MessageDialog.showSuccess(getContext(), "Pari créé avec succès");
|
||
} catch (WriterException e) {
|
||
loader.dismiss();
|
||
MessageDialog.showError(getContext(), e.getMessage());
|
||
throw new RuntimeException(e);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
});
|
||
view.findViewById(R.id.alert_cancel).setOnClickListener(v -> {
|
||
dialog.dismiss();
|
||
});
|
||
dialog.show();
|
||
}
|
||
|
||
void _initializeToZero() {
|
||
selectedHorses.setValue(List.of());
|
||
binding.combination.setText("");
|
||
binding.order.setChecked(false);
|
||
order = false;
|
||
binding.order.setVisibility(View.GONE);
|
||
binding.coeff.setText("1");
|
||
coeff = Integer.parseInt(binding.coeff.getText().toString());
|
||
setupNumberGrid(binding.gridNumbers);
|
||
}
|
||
|
||
public void calculateMise(List<String> selectedHorses) {
|
||
_notClickable(selectedHorses);
|
||
int nombreChevauxSelectionnes = selectedHorses.size();
|
||
long mise = 0;
|
||
int nonPartants = 0;
|
||
if (shared.typeOfBet.getValue() == null || shared.selectedCourse.getValue() == null) {
|
||
return;
|
||
}
|
||
if (shared.selectedCourse.getValue().getNonPartants() != null) {
|
||
nonPartants = shared.selectedCourse.getValue().getNonPartants().size();
|
||
}
|
||
int typeOfBetHorses = shared.typeOfBet.getValue().getNumberOfHorse();
|
||
int partants = shared.selectedCourse.getValue().getNombrePartants();
|
||
Course.TypeParis courseName = shared.typeOfBet.getValue().getName();
|
||
if (shared.typeOfBet.getValue().getNumberOfHorse() > nombreChevauxSelectionnes) {
|
||
binding.mise.setText(mise + " CFA");
|
||
return;
|
||
}
|
||
MiseInitiale miseModel = misesInitiales.stream()
|
||
.filter(miseInitiale -> miseInitiale.getTypePari().equals(courseName))
|
||
.findFirst()
|
||
.orElse(null);
|
||
if (miseModel == null) {
|
||
MessageDialog.showError(getContext(), "Erreur lors de l'initialisation de la mise");
|
||
_initializeToZero();
|
||
return;
|
||
}
|
||
mise = miseModel.getMiseInitialeMin();
|
||
|
||
Course.TypeParis typePari = shared.typeOfBet.getValue().getName();
|
||
boolean estCoupleGagnantOuPlace = typePari.equals(Course.TypeParis.COUPLE_GAGNANT) || typePari.equals(Course.TypeParis.COUPLE_PLACE);
|
||
Log.d("TYPE_PARI", typePari.toString());
|
||
|
||
if (estCoupleGagnantOuPlace) {
|
||
// Pour COUPLE_GAGNANT ou COUPLE_PLACE: coefficient < 200
|
||
if (coeff > 200) {
|
||
// Erreur: coefficient trop élevé
|
||
MessageDialog.showError(getContext(), "Le coefficient doit être au plus 200 pour " + typePari.toString());
|
||
_initializeToZero();
|
||
return;
|
||
}
|
||
} else {
|
||
// Pour les autres types: coefficient <= 20
|
||
if (coeff > 20) {
|
||
// Erreur: coefficient trop élevé
|
||
MessageDialog.showError(getContext(), "Le coefficient doit être inférieur ou égal à 20 pour " + typePari.toString());
|
||
_initializeToZero();
|
||
return;
|
||
}
|
||
}
|
||
|
||
mise = mise * coeff;
|
||
if (nombreX > 0) {
|
||
if (nombreChevauxSelectionnes == typeOfBetHorses) {
|
||
mise = mise * _calculateArrangement((partants - (typeOfBetHorses - nombreX) - nonPartants), nombreX);
|
||
} else {
|
||
if (nombreChevauxSelectionnes - typeOfBetHorses < nombreX || nombreChevauxSelectionnes - typeOfBetHorses == 1) {
|
||
mise = 0;
|
||
this.mise = mise;
|
||
binding.mise.setText(mise + " CFA");
|
||
return;
|
||
}
|
||
mise = mise * _calculateArrangement(nombreChevauxSelectionnes - typeOfBetHorses, nombreX);
|
||
}
|
||
if (order) {
|
||
mise = mise * _calculateArrangement(typeOfBetHorses, (typeOfBetHorses - nombreX));
|
||
}
|
||
this.mise = mise;
|
||
binding.mise.setText(mise + " CFA");
|
||
return;
|
||
}
|
||
if (!order) {
|
||
mise = mise * _calculateCombinaison(nombreChevauxSelectionnes, typeOfBetHorses);
|
||
} else {
|
||
mise = mise * _calculateArrangement(nombreChevauxSelectionnes, typeOfBetHorses);
|
||
}
|
||
this.mise = mise;
|
||
binding.mise.setText(mise + " CFA");
|
||
}
|
||
|
||
Long _calculateArrangement(int n, int k) {
|
||
return _calculateFactorial(n) / _calculateFactorial(n - k);
|
||
}
|
||
|
||
Long _calculateCombinaison(int n, int k) {
|
||
return _calculateFactorial(n) / (_calculateFactorial(k) * _calculateFactorial(n - k));
|
||
}
|
||
|
||
Long _calculateFactorial(int n) {
|
||
long f = 1;
|
||
if (n == 0) {
|
||
return f;
|
||
}
|
||
for (int i = 1; i <= n; i++) {
|
||
f *= i;
|
||
}
|
||
return f;
|
||
}
|
||
|
||
|
||
private Bitmap resizeToPrinterWidth(Bitmap originalBitmap, int printerWidthPx) {
|
||
int originalWidth = originalBitmap.getWidth();
|
||
int originalHeight = originalBitmap.getHeight();
|
||
int newHeight = (originalHeight * printerWidthPx) / originalWidth;
|
||
|
||
// 1. Redimensionner sans filtre (conserve les contours nets)
|
||
Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap,
|
||
printerWidthPx,
|
||
newHeight,
|
||
false);
|
||
|
||
// 2. Créer un bitmap ARGB_8888 (meilleure qualité que RGB_565)
|
||
Bitmap result = Bitmap.createBitmap(printerWidthPx, newHeight, Bitmap.Config.ARGB_8888);
|
||
Canvas canvas = new Canvas(result);
|
||
canvas.drawColor(Color.WHITE);
|
||
|
||
// 3. Dessiner avec un Paint qui préserve les couleurs
|
||
Paint paint = new Paint();
|
||
paint.setAntiAlias(false); // Pas d'anti-aliasing (évite le flou)
|
||
canvas.drawBitmap(scaledBitmap, 0, 0, paint);
|
||
|
||
// 4. Seuillage intelligent pour garder les détails
|
||
for (int x = 0; x < result.getWidth(); x++) {
|
||
for (int y = 0; y < result.getHeight(); y++) {
|
||
int pixel = result.getPixel(x, y);
|
||
int r = Color.red(pixel);
|
||
int g = Color.green(pixel);
|
||
int b = Color.blue(pixel);
|
||
|
||
// Calculer la luminosité
|
||
int gray = (r + g + b) / 3;
|
||
|
||
// Seuil adaptatif : si c'est sombre, deviens noir
|
||
if (gray < 130) { // Seuil à 200 pour garder les gris clairs
|
||
result.setPixel(x, y, Color.BLACK);
|
||
} else {
|
||
result.setPixel(x, y, Color.WHITE);
|
||
}
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
public Bitmap generateBarcodeBitmap(String contents, int width, int height) throws WriterException {
|
||
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, width, height);
|
||
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||
for (int x = 0; x < width; x++) {
|
||
for (int y = 0; y < height; y++) {
|
||
bmp.setPixel(x, y, bitMatrix.get(x, y) ? android.graphics.Color.BLACK : android.graphics.Color.WHITE);
|
||
}
|
||
}
|
||
return bmp;
|
||
}
|
||
|
||
public static String generate12Digits() {
|
||
StringBuilder sb = new StringBuilder();
|
||
for (int i = 0; i < 8; i++) {
|
||
int digit = (int) (Math.random() * 10); // 0 à 9
|
||
sb.append(digit);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
|
||
@Override
|
||
public void onDestroyView() {
|
||
super.onDestroyView();
|
||
binding = null;
|
||
}
|
||
|
||
@Override
|
||
public void onDestroy() {
|
||
super.onDestroy();
|
||
stompManager.disconnect();
|
||
}
|
||
} |