RELEASE V5.0.0 : Voici les modifications apportées :

-> IMPLÉMENTATION DONNÉES GTFS / GTFS-RT / SIRI LTE SNCF
-> RESTRUCTURATION DE L'APP.

FONCTIONNALITÉS EN COURS DE DÉVELOPPEMENT :

-> REFONTE DU DESIGN DES AFFICHEURS CLASSIQUES
-> AMÉLIORATION DES
This commit is contained in:
mathis committed 2026-08-30 02:26:08 +02:00
1 parent 78e0a0ef7b
commit 1729ab4831
1 file changed
+59 -18
+59 -18
View File
@@ -20,6 +20,20 @@ let siriLiteCache = {
updates: new Map()
};
// Helper fetch avec timeout pour ne jamais bloquer l'affichage en cas de réseau lent ou de blocage
async function fetchWithTimeout(url, options = {}, timeoutMs = 7000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeoutMs);
try {
const res = await fetch(url, { ...options, signal: controller.signal });
clearTimeout(id);
return res;
} catch (err) {
clearTimeout(id);
throw err;
}
}
function cleanNum(n) {
if (!n) return '';
const m = String(n).match(/\d+/);
@@ -39,8 +53,8 @@ async function fetchSiriLiteData() {
const updatesMap = new Map();
try {
const res = await fetch(SNCF_SIRI_LITE_TIMETABLE);
if (res.ok) {
const res = await fetchWithTimeout(SNCF_SIRI_LITE_TIMETABLE, {}, 8000);
if (res && res.ok) {
const xml = await res.text();
const journeys = xml.split('<EstimatedVehicleJourney>');
@@ -123,7 +137,7 @@ async function fetchSiriLiteData() {
updates: updatesMap
};
} catch (err) {
console.warn('[sncfApi] Notice: SIRI-Lite refresh error:', err);
console.warn('[sncfApi] Notice: SIRI-Lite refresh error/timeout:', err);
}
return siriLiteCache;
@@ -143,12 +157,12 @@ async function fetchGtfsRealtimeData() {
try {
const [rtRes, alertsRes] = await Promise.allSettled([
fetch(SNCF_GTFS_RT_TRIP_UPDATES),
fetch(SNCF_GTFS_RT_SERVICE_ALERTS)
fetchWithTimeout(SNCF_GTFS_RT_TRIP_UPDATES, {}, 6000),
fetchWithTimeout(SNCF_GTFS_RT_SERVICE_ALERTS, {}, 6000)
]);
// 1. Décodage Trip Updates (Retards, Suppressions)
if (rtRes.status === 'fulfilled' && rtRes.value.ok) {
if (rtRes.status === 'fulfilled' && rtRes.value && rtRes.value.ok) {
const buffer = await rtRes.value.arrayBuffer();
const feed = transit_realtime.FeedMessage.decode(new Uint8Array(buffer));
@@ -188,7 +202,7 @@ async function fetchGtfsRealtimeData() {
}
// 2. Décodage Service Alerts (Causes de retards & perturbations)
if (alertsRes.status === 'fulfilled' && alertsRes.value.ok) {
if (alertsRes.status === 'fulfilled' && alertsRes.value && alertsRes.value.ok) {
const buffer = await alertsRes.value.arrayBuffer();
const alertFeed = transit_realtime.FeedMessage.decode(new Uint8Array(buffer));
@@ -294,13 +308,29 @@ async function fetchGtfsStationTimetable(uic, mode = 'departs') {
if (!uic) return null;
try {
const publicUrl = (typeof process !== 'undefined' && process.env && process.env.PUBLIC_URL) ? process.env.PUBLIC_URL : '';
const stationUrl = `${publicUrl}/data/stations/${uic}.json`;
// Chargement parallèle tolérant aux pannes réseau / CORS
const [jsonRes, rtData, siriData] = await Promise.all([
fetch(`/data/stations/${uic}.json`),
fetchGtfsRealtimeData(),
fetchSiriLiteData()
fetch(stationUrl).catch(err => {
console.warn(`[sncfApi] Notice: fetch station ${uic} error:`, err);
return null;
}),
fetchGtfsRealtimeData().catch(err => {
console.warn('[sncfApi] Notice: GTFS-RT error:', err);
return { updates: new Map(), alerts: [] };
}),
fetchSiriLiteData().catch(err => {
console.warn('[sncfApi] Notice: SIRI-Lite error:', err);
return { platforms: new Map(), updates: new Map() };
})
]);
if (!jsonRes.ok) return null;
if (!jsonRes || !jsonRes.ok) {
console.warn(`[sncfApi] Fichier de gare introuvable : ${stationUrl} (statut : ${jsonRes ? jsonRes.status : 'réseau bloqué'})`);
return null;
}
const data = await jsonRes.json();
const rawList = mode === 'arrivees' ? data.arrivees : data.departs;
@@ -311,19 +341,19 @@ async function fetchGtfsStationTimetable(uic, mode = 'departs') {
const currentDay = now.getDay(); // 0 = Dimanche, 1 = Lundi, ..., 6 = Samedi
const currentYYYYMMDD = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`;
// Filtrage complet de circulation GTFS
const circulatingList = rawList.filter(t => {
// 1. Si la date courante figure dans les dates explicites
// 1. Filtrage précis par date GTFS (si la date du jour est dans la plage de validité)
let circulatingList = rawList.filter(t => {
// Si la date courante figure dans les dates explicites
if (Array.isArray(t.dates) && t.dates.length > 0 && t.dates.includes(currentYYYYMMDD)) {
return true;
}
// 2. Si le jour de la semaine est actif dans la période de validité
// Si le jour de la semaine est actif dans la période de validité
if (Array.isArray(t.days) && t.days.length > 0 && t.days.includes(currentDay)) {
if ((!t.start || currentYYYYMMDD >= t.start) && (!t.end || currentYYYYMMDD <= t.end)) {
return true;
}
}
// 3. Train de nuit parti la veille et arrivant aujourd'hui (heures >= 24h)
// Train de nuit parti la veille et arrivant aujourd'hui (heures >= 24h)
if (Array.isArray(t.days) && t.days.length > 0) {
const prevDay = (currentDay + 6) % 7;
const rawTime = mode === 'arrivees' ? (t.arr || t.dep) : (t.dep || t.arr);
@@ -333,13 +363,24 @@ async function fetchGtfsStationTimetable(uic, mode = 'departs') {
return true;
}
}
// 4. Si aucune règle n'est renseignée
// Si aucune règle n'est renseignée
if (!t.dates?.length && !t.days?.length) return true;
return false;
});
// 2. Fallback robuste : si la date actuelle est hors calendrier GTFS, filtrer par jour de la semaine
if (circulatingList.length === 0) {
return [];
circulatingList = rawList.filter(t => {
if (Array.isArray(t.days) && t.days.length > 0) {
return t.days.includes(currentDay);
}
return true;
});
}
// 3. Fallback complet : si toujours vide, renvoyer la grille quotidienne complète
if (circulatingList.length === 0) {
circulatingList = rawList;
}
// Helper de résolution ultra-robuste de quai par couple (train, gare)