ABONAMENTE VIDEO REDACȚIA
RO
EN
Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 104
Abonament PDF

Aeronautical Bug Story

Cătălin Roman
Lead Software Architect @Frequentis



PROGRAMARE


Atunci când pe un aeroport se construiește o pistă nouă sau într-o regiune se definește un spațiu aerian ori o rută de zbor noi, acestea intră în utilizare, nu arbitrar, ci urmând un calendar aeronautic. Calendar numit Aeronautical Information Regulation And Control, pe scurt AIRAC. De exemplu, în acest moment al scrierii acestui articol, adică 16 ianuarie 2021, următoarea dată AIRAC este 28 ianuarie 2021, apoi următoarea este 25 februarie 2021, adică e un ciclu de 28 de zile. Asta înseamnă că într-un an calendaristic au loc 13 cicluri AIRAC.

Motivul pentru care s-a introdus acest calendar este necesitatea unei sincronizări la nivel internațional între toate părțile implicate. Dacă ROMATSA aplică restricții pe o rută, e posibil ca o companie aeriană tocmai din Australia să fie interesată de acea schimbare pentru că respectiva companie survolează zilnic România. Mai mult, în trecut distribuția acestor informații se făcea pe suport de hârtie, prin urmare era nevoie de timp pentru prelucrare datelor. Cu toate că acum aceasta se face electronic, încă e nevoie de timp ca acei consumatori de date de acest tip să poată reacționa.

Toate aceste date despre unde se află un anumit aeroport și cum se numește sau care sunt caracteristicele pistei de rulare se numesc informații aeronautice. De asemenea, există un domeniu pe cât de complex, pe atât de fascinant numit Managementul Informațiilor Aeronautice (Aeronautical Information Management), care- în mod evident- are nevoie de software. În rândurile următoare voi încerca să detaliez problematica implicată de acest tip de software.

Existe câteva standarde folosite pentru encodarea acestor date, cele mai faimoase sunt ARINC-424, AIXM 4.5 și AIXM 5.1. Ultimele două folosesc XML, deci au în spate niște XSD-uri care deși sunt destul de stufoase, e relativ ușor pentru programatori să lucreze cu ele. Poate voi povesti despre ele într-un articol viitor. În schimb, ARINC-424 e un standard arhaic, conceput înainte de invenția XML-ului. Cu toate că e un format text, a fost optimizat pentru procesare de către hardware, nu e foarte human readable. O entitate e descrisă prin minim un record, adică o linie de text, iar altele prin mai multe recorduri, mai ales spațiile aeriene. Important de ținut minte că toate aceste standarde versionează entitățile după timp.

Mai jos e un fragment:

SEEUD     CHU   LR010920 DH 
CHU N46105900E024491400     025002  376WGEDEALUL CIUHII              413001305
SEEUD     CKG   ZU011610VDLW N29444800E106391200    N29444800E106391200W0020013711  514WGEJIANGBEI (CHONGQING)       413021311
SEEUD     CLJ   LR011120VDHW N46480040E023471410    N46480040E023471410E0050016002  416WGECLUJ NAPOCA                413031311
SEEUD     CMP   EP011450VDH  N52080000E016430900    N52080000E016430900E0050002952  527WGECZEMPIN                    413041509
SEEUD     CND   LR011270VDHW N44174010E028284630    N44174010E028284630E0050003002  486WGECONSTANTA                  413051002
SEEUD     CNI   LR011560 DH                     CNI N45425800E020542700     003002  297WGECENEI                      413061205
SEEUD  CRV   LR011020VDHW N44190700E023552190    N44190700E023552190E0040006002  368WGECRAIOVA                    413081003

ARINC-424 a fost conceput pentru a încărca cu date FMS-urile, adică niște calculatoare (Flight Management Systems) ce se găsesc în cockpiturile aeronavelor moderne.

Flight Management System - sursa foto: Wikipedia

Dar în același timp e folosit de companiile aeriene să-și alimenteze cu date bazele de date online sau diversele sisteme pentru calculul rutei optime de zbor între două aeroporturi.

Ultimele 4 caractere dintr-un record ARINC-424 reprezintă un câmp numit AIRAC Cycle ID. Acesta e numeric, de exemplu ID-ul 2101 înseamnă primul ciclu din anul 2021, iar ID-ul 2102 reprezintă al doilea ciclu din anul 2021. Concret, cycle id 2101 corespunde datei calendaristice 28 ianuarie 2021.

Cei care sunteți programatori cred că vă imaginați deja cum ar arăta implementarea unui parser pentru formatul ARINC-424. Nu e tocmai simplu și, bineînțeles, acest parser are nevoie de o formulă ce convertește cycle id-ul într-o dată calendaristică. Pe baza unei date de start considerată referință și ținând cont că e vorba de un ciclu format din 28 de zile se poate implementa un algoritm de calcul al datei calendaristice.

Cred că am făcut o introducere suficient de lungă, și acum să trecem la acțiune și revenim în prezent sau în context.

Recent, un client, o companie aeriană, îmi cere ajutorul în investigarea unei anomalii. Procesul lor, de sincronizare a datelor aeronautice a eșuat. Situația e tratată cu calm, pentru că s-au obișnuit să exerseze sincronizarea într-un environment de pre-producție și mai e suficient timp până la începutul următorului ciclu AIRAC.

Încep să studiez logurile și datele, și observ anomalia. 50 de entități de tip DesignatedPoint și 2 entități de tip RouteSegment, deși erau prezente în fișierul AIRAC-424 lipsesc la output. Se pierd undeva prin pipeline și mai sunt și efecte colaterale.

Mă apuc să citesc codul sursă și nimic nu se leagă, totul pare ilogic.

Într-un final, observ că AIRAC Cycle ID 2101 e convertit ca fiind 31 ianuarie 2020, dar acesta e data ciclului anterior, cu id-ul 2014! Adică atât 2014 cât și 2101 se converteau la aceeași dată calendaristică. Găsesc rapid metoda de conversie. Faceți cunoștință cu ea:

public String 
  transformAIRACDateToISO(String airacCycle) {
if (airacCycle != null && airacCycle.length() >= 4) {
  int yearRef = 10;
  int cycleRef = 1;
  int year = Integer.parseInt(
    airacCycle.substring(0, 2));
  int cycle = Integer.parseInt(
    airacCycle.substring(2, 4));

  int cycles = (year - yearRef) * 13 
    + cycle - cycleRef;

  if (cycles < 0) {
    cycles--;
  }

  return ISODateTimeFormat.dateTime()
    .print(new DateTime(2010, 1, 14, 0, 0,
     DateTimeZone.UTC)
    .plusDays(cycles * 28));

 }
return "2012-06-28T00:00:00.000Z";
}

Nu mă leg de valoarea implicită returnată, aceea e o altă poveste.

Codul acesta face parte dintr-o soluție software de anvergură ce e în producție de doi ani și jumătate, iar înainte a rulat în diverse teste de integrare cam încă doi ani jumate cât a durat dezvoltarea proiectului. Cum e posibil să dea rateuri tocmai acum?

Ziceam că un ciclu AIRAC are 28 de zile și că într-un an pot exista 13 cicluri AIRAC. Da, doar că odată la 23 de ani, ținând cont de anii bisecți, este un an în care sunt 14 cicluri AIRAC. Programatorului care a scris aceste linii de cod i-a scăpat acest detaliu. Tocmai anul 2020, anul lui COVID-19 este și anul cu 14 cicluri AIRAC. Mai mult, al 14-lea ciclu AIRAC din 2020 cade chiar în ajun de Anul Nou, când lumea are gânduri mai puțin operaționale.

Descoperirea mi se pare destul de filosofică din punct de vedere al testării. Acesta e un bug ce se reproduce odată la 23 ani. E o perioadă lungă, aproape cât o carieră de programator. E un bug de genul Y2K.

Sunt domenii, asigurări, aviație, etc. unde soluțiile software, spre deosebire de software-ul consumer oriented, au o viață mult mai lungă, reușind să ajungă la 30-40 de ani. Putem avea un test coverage de 100%, dar fără data coverage un bug de genul acesta nu poate fi prins decât din întâmplare, mai ales dacă programatorii sau testerii nu cunosc domeniul suficient de bine.

Din fericire, în acest caz problema a fost descoperită în pre-producție și nu a avut loc niciun incident.

Despre incidente în producție cu software pentru navigație aeriană am să vă povestesc în articole viitoare.

Concurs

Today Software Magazine și Frequentis Romania vă provoacă să rezolvați bugul din problema descrisă în articol. Trimiteți implementarea voastră pe email la adresa contact@todaysoftmag.com și soluția cea mai elegantă va fi publicată în numărul următor, iar Frequentis Romania va premia primele trei cele mai bune soluții. 

Pentru a vă ajuta, mai jos găsiți unit test:

@Test
public void testTransformAIRACtoISO() {
  assertEquals("2020-12-31T00:00:00.000Z", 
    transformAIRACDateToISO("2014"));
  assertEquals("2021-01-28T00:00:00.000Z", 
    transformAIRACDateToISO("2101"));
  assertEquals("2022-12-29T00:00:00.000Z", 
    transformAIRACDateToISO("2213"));
  assertEquals("2043-12-31T00:00:00.000Z", 
    transformAIRACDateToISO("4314"));
  assertEquals("2044-01-28T00:00:00.000Z", 
    transformAIRACDateToISO("4401"));
}

Rezolvarea problemei

LANSAREA NUMĂRULUI 149

Marți, 26 Octombrie, ora 18:00

sediul Cognizant

Facebook Meetup StreamEvent YouTube

NUMĂRUL 147 - Automotive

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects