179 lines
5.3 KiB
Python
179 lines
5.3 KiB
Python
import json
|
|
import time
|
|
import typing
|
|
import uuid
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from PyQt6.QtCore import pyqtSignal
|
|
from PyQt6.QtWidgets import QVBoxLayout, QProgressBar, QWidget, QMessageBox
|
|
|
|
from source import translate, ui, save
|
|
from source.survey.base import BaseSurvey
|
|
from source.survey import Empty, survey_get
|
|
from source.utils import compress
|
|
|
|
|
|
class SurveyEngine(QWidget):
|
|
signal_abandon = pyqtSignal()
|
|
signal_skip = pyqtSignal()
|
|
signal_success = pyqtSignal()
|
|
|
|
signal_warning = pyqtSignal(str)
|
|
|
|
def __init__(self, surveys_data: dict, discord_webhook_result_url: Optional[str] = None):
|
|
super().__init__()
|
|
|
|
self.surveys_data = surveys_data
|
|
self.discord_webhook_result_url = discord_webhook_result_url
|
|
self._current_survey_index = 0
|
|
|
|
self.collected_datas: dict[str, dict] = {
|
|
"time": time.time(), # get the time of the start of the survey
|
|
"language": translate.get_language(), # get the user language
|
|
"surveys": {} # prepare the individual surveys data
|
|
}
|
|
|
|
# signals
|
|
self.signal_abandon.connect(self._on_signal_abandon) # NOQA: connect exist
|
|
self.signal_skip.connect(self._on_signal_skip) # NOQA: connect exist
|
|
self.signal_success.connect(self._on_signal_success) # NOQA: connect exist
|
|
|
|
self.signal_warning.connect(self._on_signal_warning) # NOQA: connect exist
|
|
|
|
# set the layout
|
|
self._layout = QVBoxLayout()
|
|
self.setLayout(self._layout)
|
|
|
|
# prepare the frame for the survey elements
|
|
self.survey: BaseSurvey = Empty()
|
|
self._layout.addWidget(self.survey)
|
|
|
|
# progress bar
|
|
self.progress = QProgressBar()
|
|
self._layout.addWidget(self.progress)
|
|
self.progress.setStyleSheet("QProgressBar::chunk { background-color: #03A9FC; }")
|
|
self.progress.setTextVisible(False)
|
|
self.progress.setFixedHeight(8)
|
|
self.progress.setMaximum(len(surveys_data))
|
|
|
|
# finalize the initialisation
|
|
self.update_survey()
|
|
|
|
@classmethod
|
|
def from_dict(cls, data: dict) -> "SurveyEngine":
|
|
return cls(
|
|
surveys_data=data["surveys"],
|
|
discord_webhook_result_url=data.get("discord_webhook_result_url"),
|
|
)
|
|
|
|
@classmethod
|
|
def from_file(cls, path: Path | str) -> "SurveyEngine":
|
|
with open(path, encoding="utf-8") as file:
|
|
data = json.load(file)
|
|
|
|
return cls.from_dict(data)
|
|
|
|
# property
|
|
|
|
@property
|
|
def current_survey_index(self):
|
|
return self._current_survey_index
|
|
|
|
@current_survey_index.setter
|
|
def current_survey_index(self, value: int):
|
|
self._current_survey_index = value
|
|
self.progress.setValue(self.current_survey_index)
|
|
|
|
@property
|
|
def current_survey_id(self) -> str:
|
|
return list(self.surveys_data.keys())[self.current_survey_index]
|
|
|
|
# events
|
|
|
|
def _on_signal_abandon(self):
|
|
# on abandon, quit the survey
|
|
window = typing.cast(ui.SurveyWindow, self.window())
|
|
window.quit()
|
|
|
|
def _on_signal_skip(self):
|
|
# on skip, skip to the next survey
|
|
self.next_survey()
|
|
|
|
def _on_signal_success(self):
|
|
# on success, go to the next survey
|
|
self.next_survey()
|
|
|
|
def next_survey(self):
|
|
# get the collected data from the survey
|
|
collected_data = self.survey.get_collected_data()
|
|
if collected_data is not None:
|
|
# save the response in the data
|
|
self.collected_datas["surveys"][self.current_survey_id] = collected_data
|
|
|
|
# go to the next survey
|
|
self.current_survey_index += 1
|
|
|
|
if self.current_survey_index < len(self.surveys_data):
|
|
# if there are still survey to do, show it
|
|
self.update_survey()
|
|
else:
|
|
# otherwise end the survey
|
|
self.finish_survey()
|
|
|
|
def update_survey(self):
|
|
|
|
# mark the actual survey as the old one
|
|
old_survey = self.survey
|
|
|
|
# finalize the old_survey
|
|
old_survey.on_finalize()
|
|
|
|
# get the currently selected survey
|
|
new_survey = survey_get(
|
|
self.surveys_data[self.current_survey_id],
|
|
signals={
|
|
"abandon": self.signal_abandon,
|
|
"skip": self.signal_skip,
|
|
"success": self.signal_success,
|
|
}
|
|
)
|
|
|
|
# update it to the new one
|
|
self.survey = new_survey
|
|
# change the widget on the layout
|
|
self._layout.replaceWidget(old_survey, self.survey)
|
|
|
|
# delete the old frame
|
|
old_survey.deleteLater()
|
|
|
|
# mark the new survey as ready
|
|
self.survey.on_ready()
|
|
|
|
def finish_survey(self):
|
|
# get the filename for the save
|
|
filename: str = f"{uuid.uuid4()}.rsl"
|
|
|
|
# compress the data
|
|
compressed_datas = compress.compress_data(self.collected_datas)
|
|
|
|
# save them
|
|
save.save_all(
|
|
compressed_datas,
|
|
filename,
|
|
self.discord_webhook_result_url,
|
|
signal_warning=self.signal_warning
|
|
)
|
|
|
|
# finally, close the window
|
|
window = typing.cast(ui.SurveyWindow, self.window())
|
|
window.quit()
|
|
|
|
# signals
|
|
|
|
def _on_signal_warning(self, message: str):
|
|
QMessageBox.warning(
|
|
self,
|
|
self.tr("WARNING"),
|
|
self.tr(message),
|
|
)
|