jQuery(document).ready(function($) {
const RESULTS_CONTAINER_SELECTOR = '.sncf-board-container';
// Rechargement toutes les 90 secondes (1 min 30 s)
const AUTO_REFRESH_SECONDS = 90;
let allJourneys = [];
// ===============================================
// FONCTIONS D'EXTRACTION DE DONNÉES
// ===============================================
/** Extrait le mode (TER/Transilien N/Train) */
function getTrainMode(journey) {
if (!journey.sections || journey.sections.length === 0) return 'Train';
const firstPublicSection = journey.sections.find(s => s.type === 'public_transport');
if (!firstPublicSection || !firstPublicSection.display_informations) return 'Train';
const di = firstPublicSection.display_informations;
const lineName = di.label ? di.label.toUpperCase() : (di.code ? di.code.toUpperCase() : '');
const network = di.network ? di.network.toLowerCase() : '';
const commercialMode = di.commercial_mode ? di.commercial_mode.toLowerCase() : '';
// VÉRIFICATION 1 : TER
if (network.includes('ter') || commercialMode.includes('ter')) {
return 'TER';
}
// VÉRIFICATION 2 : Transilien (Ligne N)
if (network.includes('transilien') || lineName === 'N' || di.code === 'N') {
return 'Transilien N';
}
// VÉRIFICATION 3 : Autres trains
if (commercialMode.includes('train')) {
return 'Train';
}
return 'Train';
}
/** Extrait l'heure réelle, le retard et le statut. */
function getTimeAndStatus(journey) {
if (!journey.departure_date_time) return { time: 'N/A', delayMin: 0, leftStatus: 'N/A' };
const dtReal = journey.departure_date_time;
const firstPublicSection = journey.sections.find(s => s.type === 'public_transport');
const firstStop = firstPublicSection?.stop_date_times?.[0];
const dtBase = firstStop?.base_departure_date_time || dtReal;
const formatTime = (dt) => Date.parse(dt.replace(/(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})/, '$1-$2-$3T$4:$5:$6'));
const realTime = formatTime(dtReal);
const baseTime = formatTime(dtBase);
const timeStr = dtReal.substring(9, 15);
const departureTime = timeStr.substring(0, 2) + ':' + timeStr.substring(2, 4);
let delayMin = 0;
if (realTime && baseTime) {
delayMin = Math.round((realTime - baseTime) / 60000);
}
let leftStatus = "à l'heure";
if (delayMin > 0) {
leftStatus = `retard ${delayMin} min`;
} else if (delayMin < 0) {
leftStatus = `avance ${Math.abs(delayMin)} min`;
}
return { time: departureTime, delayMin: delayMin, leftStatus: leftStatus };
}
/** Extrait la voie (quai) et sa source. */
function getPlatform(journey) {
if (!journey.sections || journey.sections.length === 0) return { platform: 'NC', source: 'none' };
const firstPublicSection = journey.sections.find(s => s.type === 'public_transport');
if (!firstPublicSection) return { platform: 'NC', source: 'none' };
let platform = firstPublicSection.from && firstPublicSection.from.platform ? firstPublicSection.from.platform.trim() : '';
if (!platform && firstPublicSection.stop_date_times) {
const firstStop = firstPublicSection.stop_date_times[0];
if (firstStop && firstStop.platform) {
platform = firstStop.platform.trim();
}
}
if (!platform && firstPublicSection.stop_date_times) {
const firstStop = firstPublicSection.stop_date_times[0];
const pubSection = firstStop.stop_point ? firstStop.stop_point.administrative_regions : null;
if (pubSection && pubSection.length > 0 && pubSection[0].platform) {
platform = pubSection[0].platform.trim();
}
}
if (platform && platform !== '-' && platform !== ' ') {
return { platform: platform, source: 'confirmed' };
}
return { platform: 'NC', source: 'none' };
}
/** Extrait la taille du train (Long/Court). */
function getTrainBadge(journey) {
if (!journey.sections || journey.sections.length === 0) return 'Direct';
const firstPublicSection = journey.sections.find(s => s.type === 'public_transport');
if (!firstPublicSection || !firstPublicSection.display_informations) return 'Direct';
const di = firstPublicSection.display_informations;
if (di.description) {
const desc = di.description.toLowerCase();
if (desc.includes('court') && !desc.includes('long')) return 'Court';
if (desc.includes('long') && !desc.includes('court')) return 'Long';
}
if (di.label) {
const label = di.label.toLowerCase();
if (label.includes('court')) return 'Court';
if (label.includes('long')) return 'Long';
}
return 'Direct';
}
/** Formate la durée en heures et minutes */
function formatDuration(durationSeconds) {
const h = Math.floor(durationSeconds / 3600);
const m = Math.round((durationSeconds % 3600) / 60);
if (h > 0) return `${h}h ${m}min`;
return `${m} min`;
}
/** Construit l'objet de données de la ligne à afficher */
function mapJourneyToRow(journey) {
const timeStatus = getTimeAndStatus(journey);
const platformInfo = getPlatform(journey);
if (!journey.sections || journey.sections.length === 0) {
return { time: timeStatus.time, dest: 'Destination inconnue', trainNo: '', line: '', mode: 'Train', leftStatus: timeStatus.leftStatus, delayMin: timeStatus.delayMin, platform: 'NC', platformSource: 'none', badge: 'Direct', duration: '' };
}
const firstPublicSection = journey.sections.find(s => s.type === 'public_transport');
const di = firstPublicSection ? firstPublicSection.display_informations : null;
return {
time: timeStatus.time,
dest: di && di.headsign ? di.headsign : 'Destination inconnue',
trainNo: di && di.headsign ? di.headsign : '',
line: di && di.label ? di.label : '',
mode: getTrainMode(journey),
leftStatus: timeStatus.leftStatus,
delayMin: timeStatus.delayMin,
platform: platformInfo.platform,
platformSource: platformInfo.source,
badge: getTrainBadge(journey),
duration: formatDuration(journey.duration)
};
}
// Fonction de filtrage neutre (accepte tous les trajets trouvés)
function isAllowedDestination(journey) {
return true;
}
// ===============================================
// FILTRAGE ET RENDU
// ===============================================
/** Filtre les trajets selon le bouton sélectionné */
function applyClientFilter(filterValue) {
const filtered = allJourneys.filter(row => {
if (filterValue === 'all') return true;
if (filterValue === 'transilien' && row.mode === 'Transilien N') return true;
if (filterValue === 'ter' && row.mode === 'TER') return true;
return false;
});
renderBoard(filtered);
}
/** Génère et affiche la structure du panneau HTML */
function renderBoard(rows) {
const container = $(RESULTS_CONTAINER_SELECTOR);
let html = '';
if (rows.length === 0) {
html += '
Aucun train trouvé correspondant aux critères.
';
} else {
html += '';
rows.forEach(r => {
const leftCls = r.delayMin > 0 ? 'is-late' : (r.delayMin < 0 ? 'is-early' : 'is-ontime');
const plat = r.platform || 'NC';
const platSrc = r.platformSource || 'none';
const platCls = `sncf-platform sncf-platform--${platSrc}`;
const platTitle = platSrc === 'likely' ? 'Voie indicative' : (platSrc === 'confirmed' ? 'Voie confirmée' : 'Voie non publiée');
let subParts = [];
if (r.duration) {
subParts.push(r.duration);
}
if (r.line) {
subParts.push('Ligne ' + r.line);
}
const sub = subParts.join(' | ');
const mode_class = r.mode ? r.mode.toLowerCase().replace(/\s/g, '-') : 'train';
const mode_label = r.mode === 'Transilien N' ? 'N' : r.mode;
html += `
SNCF
${r.leftStatus}
${r.time}
${r.mode ? `${mode_label} ` : ''}
${r.dest}
${r.badge ? `${r.badge} ` : ''}
${sub || ' '}
${plat}
`;
});
html += '
';
}
container.html(html);
}
// ===============================================
// GESTION DU FORMULAIRE ET APPEL AJAX
// ===============================================
/** Génère l'heure actuelle au format Navitia (AAAAMMJJTHHMMSS) */
function formatCurrentNavitiaTime() {
const d = new Date();
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const h = String(d.getHours()).padStart(2, '0');
const min = String(d.getMinutes()).padStart(2, '0');
const s = String(d.getSeconds()).padStart(2, '0');
return `${y}${m}${day}T${h}${min}${s}`;
}
function fetchAndRenderData(form) {
const container = form.find(RESULTS_CONTAINER_SELECTOR);
const submitBtn = form.find('button[type="submit"]');
const fromId = form.data('from');
const toId = form.data('to');
const datetimeValue = formatCurrentNavitiaTime();
const filterBtns = form.find('.sncf-filter-buttons');
const data = {
action: 'sncf_fetch_horaires',
security: sncf_ajax.nonce,
from_id: fromId,
to_id: toId,
datetime: datetimeValue,
count: 30
};
submitBtn.prop('disabled', true);
container.html('Recherche en cours...
');
filterBtns.find('button').prop('disabled', true);
$.post(sncf_ajax.ajax_url, data)
.done(function(response) {
if (response.success) {
allJourneys = response.data
.filter(journey => isAllowedDestination(journey))
.map(mapJourneyToRow);
filterBtns.find('button').prop('disabled', false);
const activeFilter = filterBtns.find('button.active').data('filter') || 'ter';
applyClientFilter(activeFilter);
} else {
container.html('Erreur de recherche: ' + response.data + '
');
filterBtns.find('button').prop('disabled', true);
}
})
.fail(function() {
container.html('Erreur de communication AJAX.
');
filterBtns.find('button').prop('disabled', true);
})
.always(function() {
submitBtn.prop('disabled', false);
});
}
// 1. Déclenchement au chargement initial
$('.sncf-search-form').each(function() {
fetchAndRenderData($(this));
});
// 2. Clic sur les boutons de filtrage
$('.sncf-filter-buttons button').on('click', function() {
const btn = $(this);
const filter = btn.data('filter');
btn.addClass('active').siblings().removeClass('active');
applyClientFilter(filter);
});
// 3. Auto-refresh
if (!window.__hor2_refresh_global) {
window.__hor2_refresh_global = true;
setInterval(function(){
$('.sncf-search-form').each(function() {
fetchAndRenderData($(this));
});
}, AUTO_REFRESH_SECONDS * 1000);
}
});
Les liens des « Talks »
Aller au contenu
[pixflowHeader title= »Liens » bottom_text= »Talks » title_underline= »1″]
[imagebox image_url= »5373″ url= »https://youtu.be/M924aR-Rxck » target= »_blank »]
[imagebox image_url= »5379″ url= »https://youtu.be/M924aR-Rxck » target= »_blank »]
[imagebox image_url= »5375″ url= »https://youtu.be/3tyd510gGqc » target= »_blank »]
[imagebox image_url= »5378″ url= »https://youtu.be/D_D_fuC2wFc » target= »_blank »]
[imagebox image_url= »5374″ url= »https://youtu.be/M924aR-Rxck?fbclid=IwAR2CBVIMmofFL1bJf3bUT1TX-4GFHLwL_UEMJm_EmQJgTEsYWLOvnVKbnnw » target= »_blank »]
Les Traversées Maritimes
Le replay : ici
Avant de partir :
Prendre la température de l’eau (Merci Jean-Bernard)
Site brochure SIA
Site pour documenter vos balises Cospas Sarsat (Registre Français des balises de détresse)
La carte du terrain de Saint Florent
Le Mémo du Pilote page 17 pour les règles d’emport du canot (Jean-François)
Vous prendrez bien un peu de fluorisceine pour le dessert.
A propos des gilets de sauvetage :
Mise en garde d’Arnaud sur les gilets que nous utilisons.
Il est préférable d’utiliser des gilets « Port permanent », une sangle sous-cutale, 150N minimum
J’ai trouvé 2 fabricants « haut de gamme » : EAM et SWITLIK
Pour les utilisateurs de SDVFR un modèle à 52€
Pour les proprios de VL3 un modèle top à 499€
Pour les classes moyennes c’est celui à 145€ (Plastimo décrit par Arnaud, bien lire le descriptif, vraiment intéressant)
Georges avait aussi évoqué celui là à 215€ (Plastimo avec boucle)
Je vous parlais d’un radeau monoplace, Lionel a fait une traversée de la Réunion à Madagascar en FK9 avec celui là (Switlik)
Pour la fête des pères, demandez une sangle sous-cutale à 5€99
Voici en exclusivité , un harnais qui semble sérieux pour l’hélitreuillage.
Amerrissages forcés :
Panne à Piana, la vidéo et le livre , du même auteur 6mn23 (à lire)
Le rapport du BEA
Panne de notre ami Jean-Claude sur notre site
[imagebox image_url= »5321″ image_hover= »enable » target= »_blank »]
[imagebox image_url= »5334″ image_hover= »enable » image_hover_style= »classic »]
[imagebox image_url= »5322″][imagebox image_url= »5339″][imagebox image_url= »5338″][imagebox image_url= »5322″]
Le Vol Montagne
Le replay : ici
Merci à nos amis de Cipières qui ont bossé, pour préparer le sujet. La présentation powerpoint est à disposition ici .
Le site du PNVM
Le site de l’AFPM
La liste des Instructeurs montagne
L’altitude densité pour les nuls + une autre explication très intéressante, avec un super exemple sur le blog de JohanAero (pilote 737)
La vidéo de speddjojo à la Salette (qui, vous aviez raison, ne se pose pas main droite)
Trouvé sur le site de la RTS un très chouette documentaire sur Hermann Geiger
Pour suivre la formation avec l’équipe de Cipières : Danièle
Les Cartes Aéronautiques
Le replay : ici
Au delà des cartes, nous avons évoqué plusieurs sujets très interessants. En voici les resumés et surtout les liens pour retrouver les articles ou documents :
Interventions :
Pascal Faure à propos des règles VFR
La règle des 40km en Baptêmes
Les baptêmes rémunérés, conditions et responsabilité …
Ce que je retiens sur les baptêmes, n’oubliez pas si vous êtes assurés via la FFPLUM de remplir l’attestation qui les informes que vous faites du baptême rémunéré.
On attend de ce côté là le retour de la FFPLUM pour en savoir plus (limite de temps ou pas, 3 vols dans les 3 mois etc …)
Voici la page de la FFPLUM sur la réglementation
Une lettre d’info de la FFA sur les Baptêmes
Un article virulent mais bien écrit (2015) sur la situation à la Réunion
Un article tiré d’Ulm info 52 (2005) (intéressant)
Les 315 pages du SERA
SERA RCA3 RCA4 sur le site de la FFPLUM
[imagebox image_url= »5342″]
[imagebox image_url= »5323″][imagebox image_url= »5257″]
Skydemon Mode d’Emploi
Replay : Partie 1 / Partie 2
Nous avons vu les points suivants :
Afficher la météo pendant le vol
Exporter une route
Utilisation des NOTAM
Etude de l’onglet Aérodromes
Onglet avertissements
Modifier une route en vol
Utilisation du menu direct to (menu/direct)
Menu retour pour inverser une route (menu/route/retour)
Pour activer le relief (réactiver une fois en vol) il faut aller dans le menu cartographie en bas à droite puis terrain/colorer le terrain.
Georges nous a parlé d’une multiprise idéale pour les iPad/iPhone ici .
Voici la liste des ULM autorisés en suisse là.
Nous avons parlé de récepteurs ADS-B , j’ai rédigé une fiche ici dans la rubrique « Fiches pratiques « .
Naviguer à la carte ou au GPS ?
Le replay : ici
Pour bien naviguer il faut :
une bonne carte
un bon log de nav
un bon GPS
Beaucoup de bon sensJacques (notre barde) a dit: « Préparer, prévaut sur l’action ! » De nombreux intervenants ont mis l’accent sur ce point, préparer sa navigation c’est essentiel !
Ajoutons que pour faire usage d’une tablette GPS il faut parfaitement connaître son outil sous peine de se prendre un mur
Quelques liens et infos :
SPEEDJOJO dont parlait Danièle, son blog et sa chaîne youtube
01 56 30 13 01 pour clôturer les plans de vol.
Stationweather pro pour lire les METAR.
Myradar pour le radar météo
Windy , sympa la vue en coupe trouvée par Bruno (seulement sur ordi).
Webcam , projet Cam-Aéro des webcam sur de nombreux terrains (j’avais prévu d’en parler mais j’ai oublié).
Si vous nous faites parvenir des log de nav, nous les mettrons à dispo ici
[imagebox image_url= »5324″]
[imagebox image_url= »5325″]
La Radio (Phraséo et Nav)
Le replay : ici
La présentation (google slide) : là
Voici quelques liens et infos en rapport avec ce que nous avons évoqué :
Annoncer son autonomie au premier contact, peut être une bonne pratique.
Pour quitter un espace par téléphone : 01 56 30 13 01 (également clôture des plans de vol au Bourget).
le numéro d’urgence aéronautique.191
On ne doit pas dire : « nous décollons » mais « autorisé décollage »
Réglementation phraséo site DGAC
Le guide de la phraséo en PDF (semble être le même contenu que le site DGAC) merci Bernard
Prochaine réunion mardi prochain 15h00 sur le thème que nous n’avons pas encore défini ni préparé …
A propos du FCL055
Nous avons aussi parlé du FCL055,
Eric nous a trouvé des enregistrements audio téléchargeables ici
Un guide de phraséo ici
Le guide des modifications 2017 DGAC : là
Des fichiers et des liens en vrac (exercices, liens et autres) ici
Si cela vous amuse, vous pouvez regarder :
la vidéo de ma traversée de la manche ici
La chaîne youtube de Vincent Bazillio pour les vols aux USA : ici
La chaîne dont parlait Jean Marc : The flying reporter
Bonjour, hier nous avons fait un débat sur la panne au décollage, nous y avons aussi évoqué l’utilité ou non de la pompe électrique au décollage ainsi que de la conservation de l’essence.
Pas de replay pour ce talk !
Ici le document sur la conservation de l’essence vue par AGPS le constructeur de citernes (page 9).
Nous avons aussi fait un petit cours sur les espaces aériens juste pour nos élèves :
Replay ici. Accès à la présentation là Nous vous tiendrons au courant des prochains « Talk » via email ou sur le groupe facebook ULM3x
[imagebox image_url= »5346″]