MSIN-4461 — Implement new functions for handling entry notes in ChronoTrack, including indexing questions and mapping responses for participants. Update SQL queries to enhance data retrieval for active questions. Ensure synchronization logic accommodates custom notes effectively. Increment version code.

This commit is contained in:
2026-07-22 18:02:20 -04:00
parent b18407f64b
commit e27e2b5bc0

View File

@ -765,7 +765,7 @@ function fxChronotrackApiSyncLoadMs1Participants($intEveId) {
. " (SELECT pay_iso FROM inscriptions_pays WHERE pay_id = p.pay_id) AS country_iso2";
}
$sql = "SELECT p.par_id, p.par_id_original, p.epr_id, p.pec_id, p.rol_id, p.par_equipe, p.par_nom_equipe,"
$sql = "SELECT p.par_id, p.par_id_original, p.eve_id, p.epr_id, p.pec_id, p.rol_id, p.par_equipe, p.par_nom_equipe,"
. " p.par_prenom, p.par_nom, p.par_sexe,"
. " p.par_naissance, p.no_bib, p.no_bib_remis, p.no_bib_remis_date, p.par_date_bib, p.par_statut_course,"
. " p.par_ville, p.par_adresse, p.par_codepostal,"
@ -793,6 +793,123 @@ function fxChronotrackApiSyncLoadMs1Participants($intEveId) {
return $tabOut;
}
/**
* MSIN-4461 — clé CT entry_note_{label} (support ChronoTrack).
*/
function fxChronotrackApiSyncEntryNoteKey($strLabel, $intQueId) {
$strLabel = trim((string)$strLabel);
$strLabel = preg_replace('/\s+/u', '_', $strLabel);
$strLabel = preg_replace('/["\\\\\x00-\x1F]+/u', '', $strLabel);
$strLabel = trim($strLabel, '_');
if ($strLabel === '') {
$strLabel = 'q' . intval($intQueId);
}
return 'entry_note_' . $strLabel;
}
/**
* MSIN-4461 — index des réponses questions dun événement (1 requête / eve_id).
*
* Périmètre actuel : TOUTES les questions actives de lévénement (pas seulement que_rapport).
* Si le payload devient trop lourd (beaucoup de questions / événements volumineux),
* restreindre ici (ex. que_rapport = 1, liste blanche, ou exclusion des validations techniques).
*
* @return array<int, array<int, array{par_id:int,que_id:int,label:string,value:string}>>
* indexé par pec_id
*/
function fxChronotrackApiSyncLoadMs1QuestionsIndex($intEveId) {
global $objDatabase;
static $tabCache = array();
$intEveId = intval($intEveId);
if ($intEveId <= 0) {
return array();
}
if (isset($tabCache[$intEveId])) {
return $tabCache[$intEveId];
}
$sql = "SELECT rq.pec_id, rq.par_id, rq.que_id,"
. " TRIM(COALESCE("
. " NULLIF(iq.que_rapport_label_fr, ''),"
. " NULLIF(rq.que_question_fr, ''),"
. " NULLIF(iq.que_question_fr, ''),"
. " '')) AS note_label,"
. " TRIM(COALESCE("
. " NULLIF(rq.que_choix_fr, ''),"
. " NULLIF(rq.pqu_note, ''),"
. " NULLIF(rq.que_choix_en, ''),"
. " '')) AS note_value"
. " FROM resultats_questions rq"
. " INNER JOIN inscriptions_questions iq ON iq.que_id = rq.que_id AND iq.eve_id = " . $intEveId
. " WHERE rq.que_actif = 1"
. " ORDER BY rq.pec_id, rq.que_id";
$tabRows = $objDatabase->fxGetResults($sql);
$tabIndex = array();
if (is_array($tabRows)) {
for ($i = 1; $i <= count($tabRows); $i++) {
$arrQ = $tabRows[$i];
$intPecId = intval($arrQ['pec_id'] ?? 0);
$strValue = trim((string)($arrQ['note_value'] ?? ''));
if ($intPecId <= 0 || $strValue === '') {
continue;
}
if (!isset($tabIndex[$intPecId])) {
$tabIndex[$intPecId] = array();
}
$tabIndex[$intPecId][] = array(
'par_id' => intval($arrQ['par_id'] ?? 0),
'que_id' => intval($arrQ['que_id'] ?? 0),
'label' => trim((string)($arrQ['note_label'] ?? '')),
'value' => $strValue,
);
}
}
$tabCache[$intEveId] = $tabIndex;
return $tabIndex;
}
/**
* MSIN-4461 — map entry_note_* pour un participant (réponses épreuve + participant).
* resultats_questions.par_id = par_id_original (legacy) ; par_id 0 = question niveau épreuve.
*/
function fxChronotrackApiSyncEntryNotesForParticipant(array $arrRow) {
$intEveId = intval($arrRow['eve_id'] ?? 0);
$intPecId = intval($arrRow['pec_id'] ?? 0);
if ($intEveId <= 0 || $intPecId <= 0) {
return array();
}
$tabIndex = fxChronotrackApiSyncLoadMs1QuestionsIndex($intEveId);
if (!isset($tabIndex[$intPecId]) || !is_array($tabIndex[$intPecId])) {
return array();
}
$intParOrig = intval($arrRow['par_id_original'] ?? 0);
$intParId = intval($arrRow['par_id'] ?? 0);
$tabNotes = array();
$tabUsedKeys = array();
foreach ($tabIndex[$intPecId] as $arrQ) {
$intQPar = intval($arrQ['par_id'] ?? 0);
// Question dépreuve (par_id vide) ou réponse de ce participant
if ($intQPar > 0 && $intQPar !== $intParOrig && $intQPar !== $intParId) {
continue;
}
$intQueId = intval($arrQ['que_id'] ?? 0);
$strKey = fxChronotrackApiSyncEntryNoteKey($arrQ['label'] ?? '', $intQueId);
if (isset($tabUsedKeys[$strKey])) {
$strKey = 'entry_note_q' . $intQueId;
}
$tabUsedKeys[$strKey] = true;
$tabNotes[$strKey] = (string)$arrQ['value'];
}
return $tabNotes;
}
function fxChronotrackApiSyncResolveRegChoiceIdForRace($intCtEventId, $intCtRaceId) {
static $tabCache = array();
$strKey = intval($intCtEventId) . ':' . intval($intCtRaceId);
@ -927,6 +1044,12 @@ function fxChronotrackApiSyncBuildEntryPayload(array $arrRow, array $arrRaceMap,
// MSIN-4328 — Dossard récupéré (MS1) → Check In Status CT (entry_check_in = "1" / null)
$arrEntry['entry_check_in'] = (intval($arrRow['no_bib_remis'] ?? 0) === 1) ? '1' : null;
// MSIN-4461 — questions MS1 → notes CT (entry_note_{label}).
// Toutes les réponses actives pour linstant ; filtrer plus tard si trop lourd (voir LoadMs1QuestionsIndex).
foreach (fxChronotrackApiSyncEntryNotesForParticipant($arrRow) as $strNoteKey => $strNoteValue) {
$arrEntry[$strNoteKey] = $strNoteValue;
}
return $arrEntry;
}