← Înapoi la transparență

Documentație în lucru: e verificată rând cu rând înainte de testarea deschisă. Nu lua nimic de-a gata.

Cum calculăm

Fiecare număr pe care ți-l arată aplicația e calculat de o funcție pe care o poți citi, cu un test lângă ea. Pagina asta le pune pe toate la vedere: formula în cuvinte, funcția exact așa cum e scrisă în cod, și un exemplu numerotat pe care îl poți verifica pe hârtie. Dacă ceva nu se potrivește cu ce îți dă federația ta, vrem să știm — și, până atunci, ultima secțiune îți spune de ce cele două numere pot să difere fără ca vreunul să fie greșit.

Inelele din exemple sunt din setul nostru de demonstrație (RO 2099 9xxxxx). Nu sunt porumbei reali.

Numerele din text sunt scrise românește, cu virgulă. Fișierul de export scrie punct — întotdeauna, în amândouă limbile. Fișierul e separat prin virgulă, așa că o virgulă zecimală ar rupe numărul în două coloane; packages/core/src/csv.ts scrie fiecare zecimală cu toFixed(3), care dă punct indiferent de limba cititorului. Exemplele de viteză și de coeficient de mai jos ies din export așa:

Race Name,Release Date,Distance (km),Bird Ring,Bird Name,Position,Field Size,Velocity (m/min),Ace Points,Clock Time,Designated
Oradea,2099-05-18,342.000,RO 2099 900021,,37,397,1030.120,93.199,11:47:00,

Viteza

Distanța împărțită la timpul de zbor, în metri pe minut. Distanța e de la punctul de lansare până la crescătoria ta, nu până la oraș — de asta fiecare crescătorie are propria distanță pentru aceeași cursă.

// packages/core/src/race.ts
export function computeVelocity(distanceKm: number, releaseAt: string, arrivalAt: string): number {
  const flightMs = new Date(arrivalAt).getTime() - new Date(releaseAt).getTime();
  if (flightMs <= 0) return 0;

  const flightMinutes = flightMs / 60_000;
  const distanceM = distanceKm * 1000;

  return Math.round((distanceM / flightMinutes) * 1000) / 1000;
}

Exemplu. RO 2099 900021, 342 km, lansare 06:15, sosire 11:47. Zborul e de 5 ore și 32 de minute, adică 332 de minute. 342 000 m ÷ 332 min = 1030,120 m/min.

Rotunjim la trei zecimale, nu mai devreme: la o cursă strânsă, diferența dintre doi porumbei e la a doua zecimală.

Testat în packages/core/src/race.test.ts.

Coeficientul

Locul împărțit la numărul de porumbei, înmulțit cu 1000. Mai mic e mai bun. E moneda comună a sportului: îți spune cât de bine a zburat porumbelul raportat la câți au zburat cu el, ca să poți compara o cursă de 400 de porumbei cu una de 4000.

// packages/core/src/race.ts
export function computeAcePoints(position: number, fieldSize: number): number {
  if (fieldSize <= 0 || position <= 0) return 0;
  return Math.round((position / fieldSize) * 1000 * 1000) / 1000;
}

Exemplu. Locul 37 din 397 de porumbei: 37 ÷ 397 × 1000 = 93,199.

Testat în packages/core/src/analytics/coefficient.test.ts. Citește și ultima secțiune a paginii — coeficientul e singurul număr de aici pe care de multe ori nu îl calculăm noi.

COI — coeficientul de consangvinitate

Cât de înrudiți sunt părinții unui porumbel, după formula lui Wright. Se adună, peste fiecare strămoș comun, contribuția fiecărui drum prin arbore. Funcția își scrie singură formula:

// packages/core/src/pedigree.ts
/**
 * Compute Wright's coefficient of inbreeding for the bird identified by
 * `rootId`. The formula sums over every common ancestor A:
 *
 *   F = Σ [ (1/2)^(n₁ + n₂ + 1) × (1 + F_A) ]
 *
 * where n₁ and n₂ are the path lengths from sire and dam to A, and F_A
 * is the inbreeding coefficient of A itself.
 */

Un strămoș comun contează de câte ori apare, pe fiecare drum. Dacă un porumbel n-are ambii părinți înregistrați, rezultatul e 0 — nu pentru că nu e consangvinizat, ci pentru că nu avem din ce să calculăm; pedigree-ul incomplet se vede ca atare în aplicație, nu ca un zero liniștitor.

Exemplu. RO 2099 900015 îl are pe același strămoș pe ambele linii, la două generații distanță de tată și două de mamă, iar acel strămoș nu e el însuși consangvinizat: (1/2)^(2+2+1) × (1+0) = (1/2)^5 = 3,125 %.

Testat în packages/core/src/pedigree.test.ts, inclusiv pe arbori cu bucle și cu părinți lipsă.

Curba de formă

Rezultatele unui porumbel dintr-un sezon, în ordinea în care s-au întâmplat. Nu e o medie și nu e un scor: e o linie, ca să vezi dacă porumbelul urcă sau coboară pe parcursul sezonului.

Seria duce două axe posibile — coeficientul și poziția procentuală în câmp — pentru că sunt întrebări diferite: prima e ce a spus federația, a doua e unde a terminat porumbelul în câmpul pe care l-am înregistrat noi.

Ține minte că mai mic e mai bun pe amândouă. O formă în creștere se vede ca o linie care coboară.

packages/core/src/analytics/form.ts, testat în packages/core/src/analytics/form.test.ts.

Decila

Rezultatele care termină în prima zecime a câmpului lor: locul împărțit la numărul de porumbei, mai mic sau egal cu 0,10.

Definită pe loc și câmp, nu pe coeficientul publicat — cele două pot să difere oriunde numitorul federației nu e numărul tipărit lângă el, iar dacă am folosi coeficientul, numărul ar depinde de care importator a scris rândul.

Exemplu. Locul 37 din 397: 37 ÷ 397 = 0,0932. E sub 0,10, deci în prima decilă.

O grijă mică din cod, ca să vezi la ce nivel se lucrează: comparația se face pe poziția brută, nu pe procentul rotunjit. La un câmp de 9999 de porumbei, locul 1000 înseamnă 0,10001 — care rotunjit la patru zecimale dă 0,1000 și ar intra în decilă fără să merite.

Porumbeii nesosiți nu intră deloc aici: nu sunt nici reușite, nici rateuri măsurabile. Un porumbel care nu vine acasă nu e un loc slab — e altceva, și e numărat la constanță.

packages/core/src/analytics/consistency.ts, testat în packages/core/src/analytics/consistency.test.ts.

Constanța

Din câte curse înregistrate s-a clasat porumbelul. Numitorul e format din rezultatele clasate plus cele nesosite pe care le-ai înregistrat tu.

Nu e procentul oficial de premii și n-o dăm drept așa ceva. Cifra oficială împarte la porumbeii îmbarcați, iar foile de îmbarcare sunt date pe care nu le avem. Ce putem calcula cinstit e clasate-pe-intrări-înregistrate, iar tipul din cod duce eticheta asta cu el (basis: 'recorded_entries'), ca să n-o poată pierde un ecran din neatenție.

Exemplu. 9 rezultate clasate și 3 porumbei nesosiți, înregistrați de tine: 9 ÷ 12 = 75 %.

Și partea incomodă, pentru că e a ta, nu a noastră: dacă toate rezultatele îți vin dintr-un import de clasamente, cifra asta minte. O foaie de clasament listează porumbeii care s-au clasat și nu spune nimic despre cei care n-au venit acasă — deci fiecare rând importat e o clasare, iar rata iese 100 %. Aia nu e o măsurătoare a crescătoriei tale, e o măsurătoare a drumului pe care au intrat datele. Codul numără nesosirile separat exact ca ecranul să poată să tacă în loc să afișeze un scor perfect.

Numere publicate și numere derivate

Asta e partea pe care ai venit s-o citești, dacă ai venit să verifici.

Când federația a publicat un coeficient, îl arătăm pe al ei. Nu îl recalculăm. Când n-a publicat niciunul, îl calculăm noi din loc și câmp — și îl marcăm ca atare. Marcajul nu e o notă de subsol: e un câmp în tipul de date, lângă valoare.

// packages/core/src/analytics/coefficient.ts
export const coefficientSchema = z
  .object({
    value: z.number(),
    /** True when this engine computed it; false when the source published it. */
    derived: z.boolean(),
  })
  .readonly();

Iar când adunăm mai multe rezultate într-o medie, rezultatul spune din câte de fiecare fel e făcut — storedCount și derivedCount — pentru că o medie peste numere din surse diferite e un număr despre care ai dreptul să știi cum s-a format.

De ce contează. Toată lumea împarte locul la mărimea câmpului. Nu toată lumea împarte la același câmp:

  • UNCR (România) — locul × 1000 împărțit la numărul total de porumbei, cu trei zecimale, cel mai mic coeficient câștigă. Transcris din Regulamentul Național Columbofil, ediția 2026–2029.
  • UCPR (România) — locul × 1000 împărțit la porumbeii angajați (îmbarcați), care nu e același număr. Transcris din regulamentul propriu al UCPR; documentația noastră păstrează formula în original, fără să numească o ediție.
  • KBDB (Belgia) — locul împărțit la clasați (geklasseerden), însumat peste curse. Transcris din regulamentul KBDB, în neerlandeză, fără ediție numită.
  • RPRA (Marea Britanie) — locul împărțit la total, înmulțit cu 100, nu cu 1000. Transcris din regulamentul RPRA, fără ediție numită.

Iar pentru campionatele FCI/olimpice, numitorul e numărul de porumbei îmbarcați, plafonat la 5000.

Formulele de mai sus sunt transcrise din regulamentele federațiilor în documentația noastră de cercetare, cu textul original citat lângă fiecare — nu din memorie. Unde regulamentul își numește ediția, am scris-o; unde nu și-o numește, am spus asta în loc să inventăm una.

Și, ca să fie clar ce poate strica o schimbare de regulament: nimic din datele tale. Pentru că nu recalculăm niciodată un coeficient publicat, dacă o federație își schimbă mâine numitorul, numerele din contul tău rămân exact cele pe care ți le-a dat federația — schimbarea nu poate atinge un rând al niciunui crescător. Ce poate face e să învechească pagina asta, adică lista de mai sus să descrie o regulă care nu mai e în vigoare. De-asta e scrisă cu proveniență, și de-asta îți cerem ajutorul: dacă vezi una greșită sau depășită, scrie-ne la contact@thatpigeon.app. Pe o pagină care se numește „cum calculăm”, o formulă greșită e singura greșeală care n-are scuză.

Deci: dacă ți-am recalcula coeficientul publicat de federația ta cu o formulă pe care am ales-o noi, ți-am răspunde tăcut la altă întrebare decât cea pe care ai pus-o. De asta nu-l recalculăm. Și de asta, când comparăm rezultate din federații diferite, o spunem — un coeficient brut nu se compară între corpuri fără etichetă.

Mai departe

  • Datele tale — ce colectăm, unde stau datele și cum verifici singur, în cinci minute.
  • Securitate — modelul de securitate și testele din spatele lui.