diff --git a/src/fivemserver/queuemanager.py b/src/fivemserver/queuemanager.py index c50f5cd..06b7b9a 100644 --- a/src/fivemserver/queuemanager.py +++ b/src/fivemserver/queuemanager.py @@ -1,128 +1,57 @@ +# queue_manager.py — Aucune dépendance Qt import requests -from PySide6.QtCore import QThread, Signal +import time +from typing import Callable from config.constants import Urls, ApiEndPoints - -class JoinQueueThread(QThread): - result = Signal(dict) - error = Signal(str) - - def __init__(self, user_id: str): - super().__init__() +class QueueManager: + def __init__(self, user_id: str, on_update: Callable[[str], None]): self.user_id = user_id - self.api_url = Urls.API_URL.value - - def run(self): - try: - res = requests.post( - f"{self.api_url}{ApiEndPoints.QUEUE_JOIN.value}", - headers={"Content-Type": "application/json"}, - json={"uuid": self.user_id} - ) - self.result.emit(res.json()) - except Exception as e: - self.error.emit(str(e)) - - -class CheckStatusThread(QThread): - result = Signal(dict) - error = Signal(str) - - def __init__(self, user_id: str): - super().__init__() - self.user_id = user_id - self.api_url = Urls.API_URL.value - - def run(self): - try: - res = requests.get(f"{self.api_url}{ApiEndPoints.QUEUE_STATUS.value}{self.user_id}") - self.result.emit(res.json()) - except Exception as e: - self.error.emit(str(e)) - - -class LeaveQueueThread(QThread): - done = Signal() - error = Signal(str) - - def __init__(self, user_id: str): - super().__init__() - self.user_id = user_id - self.api_url = Urls.API_URL.value - - def run(self): - try: - requests.post( - f"{self.api_url}{ApiEndPoints.QUEUE_LEAVE.value}", - headers={"Content-Type": "application/json"}, - json={"uuid": self.user_id} - ) - self.done.emit() - except Exception as e: - self.error.emit(str(e)) - - -class QueueManager(QThread): - """ - Équivalent de startQueue() — gère tout le cycle : - join → poll toutes les 5s → lance FiveM quand c'est le tour - """ - update_ui = Signal(str) # → updateQueueUI() - launch_game = Signal() # → launchFiveM() - error = Signal(str) - - def __init__(self, user_id: str, parent=None): - super().__init__(parent) - self.user_id = user_id - self.api_url = Urls.API_URL.value + self.on_update = on_update # Callback pour envoyer les mises à jour self._running = True def stop(self): self._running = False - def run(self): - # 1. Join queue - try: - res = requests.post( - f"{self.api_url}/queue/join", - headers={"Content-Type": "application/json"}, - json={"uuid": self.user_id} - ) - join = res.json() - except Exception as e: - self.error.emit(str(e)) - return + def join_queue(self) -> dict: + res = requests.post( + f"{Urls.API_URL.value}{ApiEndPoints.QUEUE_JOIN.value}", + json={"uuid": self.user_id}, + verify=False + ) + return res.json() - # 2. Slot dispo directement - if join.get("status") == "ok": - self.update_ui.emit("Slot dispo, lancement du jeu...") - self.launch_game.emit() - return + def check_status(self) -> dict: + res = requests.get(f"{Urls.API_URL.value}{ApiEndPoints.QUEUE_STATUS.value}/{self.user_id}") + return res.json() - # 3. En file d'attente → poll toutes les 5s - self.update_ui.emit( - f"⏳ Vous êtes en file d'attente : position {join.get('position')} / {join.get('queueSize')}" + def leave_queue(self): + requests.post( + f"{Urls.API_URL.value}{ApiEndPoints.QUEUE_LEAVE.value}", + json={"uuid": self.user_id}, + verify=False ) - while self._running: - self.sleep(5) # Équivalent setInterval 5000ms + def start(self): + join = self.join_queue() + # print(f"[QueueManager] join response: {join}") # ← Debug + if join.get("position") == 0: # Position 0 = slot libre + self.on_update("ok") + return + + self.on_update(f"position:{join.get('position')}:{join.get('queueSize')}") + + while self._running: + time.sleep(5) if not self._running: break - try: - res = requests.get(f"{self.api_url}/queue/status/{self.user_id}") - status = res.json() - except Exception as e: - self.error.emit(str(e)) - return + status = self.check_status() - if status.get("status") == "queued": - self.update_ui.emit( - f"⏳ Votre position : {status.get('position')} / {status.get('queueSize')}" - ) - else: - self.update_ui.emit("🚀 C'est votre tour !") - self.launch_game.emit() + if status.get("position") == 0: # Position 0 = c'est le tour + self.on_update("ready") return + else: + self.on_update(f"position:{status.get('position')}:{status.get('queueSize')}") diff --git a/src/ui/main_window.py b/src/ui/main_window.py index b77d7cb..4627d5d 100644 --- a/src/ui/main_window.py +++ b/src/ui/main_window.py @@ -6,6 +6,7 @@ from PySide6 import QtGui from PySide6.QtCore import Qt from PySide6.QtUiTools import QUiLoader from PySide6.QtWidgets import QMainWindow, QSizePolicy +from PySide6.QtCore import QThread, Signal from config.config_manager import ConfigManager from config.constants import PlayerServerInfo, Urls @@ -25,14 +26,13 @@ if platform.startswith('linux'): environ["QT_QPA_PLATFORM"] = "xcb" class MainWindow(QMainWindow): + #update = Signal(str) # Reçoit les callbacks de QueueManager + def __init__(self, bundle_dir: str, config_manager: ConfigManager): super().__init__() self.config = config_manager - - WhiteList.checkwhitelist(Urls.API_URL.value, self.config.get_discord_user()) - if PlayerServerInfo.is_whitelist: - QueueManager(self.config.get_discord_user()) + self.queue_thread = None # UI self.ui = QUiLoader().load(f"{bundle_dir}/ui/mainwindow_vertical_pager.ui", self) @@ -49,6 +49,10 @@ class MainWindow(QMainWindow): self.ui.queue_position.hide() self.ui.stackedWidget.setCurrentIndex(1) + WhiteList.checkwhitelist(Urls.API_URL.value, self.config.get_discord_user()) + if PlayerServerInfo.is_whitelist: + self.start_queue() + # Test bouton en contruction en_chantier = False # on set la css du bouton en fonction de la valeur de la variable en_chantier @@ -99,10 +103,8 @@ class MainWindow(QMainWindow): # si le jouer n'est pas whitelisté, on affiche la page pour se faire whitelister if not PlayerServerInfo.is_whitelist: self.ui.stackedWidget.setCurrentIndex(2) - - # pour le moment on cache les controle queue - self.ui.queue_lbl.setVisible(False) - self.ui.queue_position.setVisible(False) + else: + self.start_queue() # ← Tout à la fin, UI complètement prête self.show() @@ -171,6 +173,9 @@ class MainWindow(QMainWindow): # ------------------------------------------------------------------ def closeEvent(self, event) -> None: + if self.queue_thread and self.queue_thread.isRunning(): + self.queue_thread.stop() + self.queue_thread.wait() # Attend que le thread se termine proprement self.config.save() super().closeEvent(event) @@ -182,3 +187,56 @@ class MainWindow(QMainWindow): self.ui.connexion_btn.setProperty("en_chantier", valeur) # propriété Qt self.ui.connexion_btn.style().unpolish(self.ui.connexion_btn) self.ui.connexion_btn.style().polish(self.ui.connexion_btn) + + # ------------------------------------------------------------------ + # Queue managment + # ------------------------------------------------------------------ + def start_queue(self): + user_id = self.config.get_discord_user() + self.queue_thread = QueueThread(user_id) + self.queue_thread.update.connect(self.handle_update) + self.queue_thread.start() + + # 🧪 TEMP - Simule une position en queue pour tester l'UI + self.handle_update("position:3:10") + + def handle_update(self, message: str): + # print(f"[handle_update] reçu: {message}") # ← Debug + if message == "ok": + self.ui.queue_lbl.setVisible(False) + self.ui.queue_position.setVisible(False) + #self.ui.connexion_btn.setEnabled(True) + #self.ui.connexion_btn.setText("Lancer FiveM") + #self.launch_fivem() + + elif message == "ready": + self.ui.queue_lbl.setVisible(True) + self.ui.queue_position.setVisible(False) + self.ui.queue_lbl.setText("🚀 C'est votre tour !") + self.launch_fivem() + + elif message.startswith("position:"): + _, pos, total = message.split(":") + self.ui.queue_lbl.setVisible(True) + self.ui.queue_position.setVisible(True) + #self.ui.queue_position.setText(f"{pos} / {total}") <- si on veux le total de slots + self.ui.queue_position.setText(f"{pos}") + + def launch_fivem(self): + pass + +class QueueThread(QThread): + update = Signal(str) # Reçoit les callbacks de QueueManager + + def __init__(self, user_id: str): + super().__init__() + self.manager = QueueManager( + user_id=user_id, + on_update=self.update.emit # Le callback envoie un Signal Qt + ) + + def run(self): + self.manager.start() + + def stop(self): + self.manager.stop()