From e27e2b5bc069ce7400845405bef3488457ce6f22 Mon Sep 17 00:00:00 2001 From: stephan Date: Wed, 22 Jul 2026 18:02:20 -0400 Subject: [PATCH] =?UTF-8?q?MSIN-4461=20=E2=80=94=20Implement=20new=20funct?= =?UTF-8?q?ions=20for=20handling=20entry=20notes=20in=20ChronoTrack,=20inc?= =?UTF-8?q?luding=20indexing=20questions=20and=20mapping=20responses=20for?= =?UTF-8?q?=20participants.=20Update=20SQL=20queries=20to=20enhance=20data?= =?UTF-8?q?=20retrieval=20for=20active=20questions.=20Ensure=20synchroniza?= =?UTF-8?q?tion=20logic=20accommodates=20custom=20notes=20effectively.=20I?= =?UTF-8?q?ncrement=20version=20code.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- php/chronotrack_api/fx_chronotrack_sync.php | 125 +++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/php/chronotrack_api/fx_chronotrack_sync.php b/php/chronotrack_api/fx_chronotrack_sync.php index 9942b35..8a7c90a 100644 --- a/php/chronotrack_api/fx_chronotrack_sync.php +++ b/php/chronotrack_api/fx_chronotrack_sync.php @@ -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 d’un é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> + * 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 l’instant ; filtrer plus tard si trop lourd (voir LoadMs1QuestionsIndex). + foreach (fxChronotrackApiSyncEntryNotesForParticipant($arrRow) as $strNoteKey => $strNoteValue) { + $arrEntry[$strNoteKey] = $strNoteValue; + } + return $arrEntry; }