@jjlmoya/utils-drones 1.39.0 → 1.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -0
  3. package/src/entries.ts +4 -0
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/tool_validation.test.ts +2 -2
  7. package/src/tool/fpv-drone-lap-timer/audio.ts +160 -0
  8. package/src/tool/fpv-drone-lap-timer/bibliography.astro +6 -0
  9. package/src/tool/fpv-drone-lap-timer/bibliography.ts +14 -0
  10. package/src/tool/fpv-drone-lap-timer/bootstrap.ts +20 -0
  11. package/src/tool/fpv-drone-lap-timer/component.astro +136 -0
  12. package/src/tool/fpv-drone-lap-timer/contract.test.ts +24 -0
  13. package/src/tool/fpv-drone-lap-timer/controller.ts +304 -0
  14. package/src/tool/fpv-drone-lap-timer/dom-views.ts +213 -0
  15. package/src/tool/fpv-drone-lap-timer/entry.ts +27 -0
  16. package/src/tool/fpv-drone-lap-timer/export.ts +41 -0
  17. package/src/tool/fpv-drone-lap-timer/fpv-drone-lap-timer.css +705 -0
  18. package/src/tool/fpv-drone-lap-timer/i18n/de.ts +216 -0
  19. package/src/tool/fpv-drone-lap-timer/i18n/en.ts +216 -0
  20. package/src/tool/fpv-drone-lap-timer/i18n/es.ts +216 -0
  21. package/src/tool/fpv-drone-lap-timer/i18n/fr.ts +216 -0
  22. package/src/tool/fpv-drone-lap-timer/i18n/id.ts +216 -0
  23. package/src/tool/fpv-drone-lap-timer/i18n/it.ts +216 -0
  24. package/src/tool/fpv-drone-lap-timer/i18n/ja.ts +216 -0
  25. package/src/tool/fpv-drone-lap-timer/i18n/ko.ts +216 -0
  26. package/src/tool/fpv-drone-lap-timer/i18n/nl.ts +216 -0
  27. package/src/tool/fpv-drone-lap-timer/i18n/pl.ts +216 -0
  28. package/src/tool/fpv-drone-lap-timer/i18n/pt.ts +216 -0
  29. package/src/tool/fpv-drone-lap-timer/i18n/ru.ts +216 -0
  30. package/src/tool/fpv-drone-lap-timer/i18n/sv.ts +216 -0
  31. package/src/tool/fpv-drone-lap-timer/i18n/tr.ts +216 -0
  32. package/src/tool/fpv-drone-lap-timer/i18n/zh.ts +216 -0
  33. package/src/tool/fpv-drone-lap-timer/index.ts +10 -0
  34. package/src/tool/fpv-drone-lap-timer/logic.test.ts +152 -0
  35. package/src/tool/fpv-drone-lap-timer/logic.ts +228 -0
  36. package/src/tool/fpv-drone-lap-timer/seo.astro +16 -0
  37. package/src/tool/fpv-drone-lap-timer/storage.ts +52 -0
  38. package/src/tool/fpv-drone-lap-timer/ui.ts +58 -0
  39. package/src/tools.ts +3 -0
@@ -0,0 +1,216 @@
1
+ import type { FpvDroneLapTimerLocaleContent } from '../entry';
2
+ import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import type { SEOSection } from '../../../types';
4
+ import { BIBLIOGRAPHY_ITEMS } from '../bibliography';
5
+
6
+ const slug = 'chronometre-tours-course-drone-fpv';
7
+ const title = 'Chronomètre de Tours et Splits pour Course de Drone FPV';
8
+ const description = 'Chronomètre interactif pour course de drones FPV avec séquence acoustique de départ FAI, calcul des deltas, alertes de meilleur tour, indice de régularité et télémétrie de vitesse.';
9
+
10
+ const ui = {
11
+ setupHeading: 'Configuration du Circuit et de la Session',
12
+ trackLengthLabel: 'Longueur du Circuit',
13
+ trackLengthUnit: 'mètres',
14
+ targetLapsLabel: 'Nombre de Tours Cible',
15
+ targetLapsUnit: 'tours (0 pour entraînement libre)',
16
+ batteryCapacityLabel: 'Capacité de la Batterie',
17
+ batteryCapacityUnit: 'mAh',
18
+ soundEnabledLabel: 'Activer les Signaux Sonores',
19
+ debounceThresholdLabel: 'Protection Anti-rebond',
20
+ debounceThresholdUnit: 'secondes',
21
+ presetMultiGpLabel: 'Spécification MultiGP (250m / 3 Tours)',
22
+ presetWhoopLabel: 'Tiny Whoop (65m / 5 Tours)',
23
+ presetSprintLabel: 'Sprint Haute Vitesse (400m / 2 Tours)',
24
+ startCountdownButton: 'Démarrer le Compte à Rebours FAI',
25
+ pauseTimerButton: 'Mettre en Pause',
26
+ resumeTimerButton: 'Reprendre le Chrono',
27
+ resetTimerButton: 'Réinitialiser la Session',
28
+ recordLapButton: 'VALIDER LE TOUR',
29
+ spacebarHint: 'Appuyez sur ESPACE ou touchez le bouton géant pour enregistrer le passage de ligne',
30
+ statusIdle: 'Prêt pour le Départ',
31
+ statusCountdown: 'Compte à Rebours FAI en Cours',
32
+ statusRunning: 'Chronomètre de Course Actif',
33
+ statusPaused: 'Session en Pause',
34
+ statusFinished: 'Course Terminée',
35
+ currentLapHeading: 'Temps du Tour Actuel',
36
+ lapNumberPrefix: 'Tour',
37
+ lastLapHeading: 'Dernier Tour',
38
+ fastestLapHeading: 'Meilleur Tour',
39
+ averageLapHeading: 'Tour Moyen',
40
+ deltaBestHeading: 'Écart avec le Meilleur Tour',
41
+ consistencyIndexHeading: 'Indice de Régularité',
42
+ estimatedSpeedHeading: 'Vitesse Moyenne Estimée',
43
+ estimatedBatteryHeading: 'Consommation Batterie Estimée',
44
+ speedUnitKmh: 'km/h',
45
+ speedUnitMph: 'mph',
46
+ batteryUsedUnit: 'mAh',
47
+ batteryRemainingUnit: 'mAh restants',
48
+ lapHistoryHeading: 'Temps au Tour et Comparaison du Rythme',
49
+ lapColumnHeader: 'Tour #',
50
+ timeColumnHeader: 'Chrono',
51
+ splitColumnHeader: 'Écart Meilleur',
52
+ speedColumnHeader: 'Vitesse Moyenne',
53
+ batteryColumnHeader: 'Conso Batterie',
54
+ noLapsRecordedNotice: 'Aucun tour enregistré. Lancez le compte à rebours et appuyez sur Espace pour enregistrer votre premier passage.',
55
+ consistencyRatingElite: 'Régularité Élite',
56
+ consistencyRatingPro: 'Régularité Pilote Pro',
57
+ consistencyRatingClub: 'Régularité Club',
58
+ consistencyRatingNovice: 'Régularité en Apprentissage',
59
+ fastestLapBadge: 'MEILLEUR TOUR',
60
+ sessionSummaryHeading: 'Résumé de Session & Export',
61
+ totalTimeLabel: 'Durée Totale de Course',
62
+ completedLapsLabel: 'Tours Bouclés',
63
+ exportCsvButton: 'Exporter les Tours en CSV',
64
+ copySummaryButton: 'Copier le Résumé Texte',
65
+ copiedNotice: 'Résumé de session copié dans le presse-papiers !',
66
+ };
67
+
68
+ const faqItems = [
69
+ {
70
+ question: 'Comment fonctionne le départ acoustique FAI dans ce chronomètre ?',
71
+ answer: 'La séquence reproduit fidèlement les règles de course de drone F9U de la Fédération Aéronautique Internationale (FAI). Des bips préparatoires espacés d\'une seconde préparent le pilote, suivis d\'une tonalité aiguë signalant le top départ et déclenchant le chronomètre à zéro.',
72
+ },
73
+ {
74
+ question: 'Comment est calculé l\'Indice de Régularité des tours ?',
75
+ answer: 'Le score évalue l\'écart-type des tours complétés par rapport au tour moyen de la session. Un résultat supérieur à 95 pour cent reflète un pilotage extrêmement régulier et une gestion optimale des gaz.',
76
+ },
77
+ {
78
+ question: 'Puis-je utiliser un commutateur de radiocommande ou une pédale ?',
79
+ answer: 'Oui. Tout clavier sans fil, pédale Bluetooth ou bouton de radiocommande configuré pour envoyer la touche Espace enregistre instantanément le tour sans devoir quitter les lunettes des yeux.',
80
+ },
81
+ {
82
+ question: 'Pourquoi y a-t-il un délai anti-rebond sur le bouton ?',
83
+ answer: 'Les portes FPV sont franchies à grande vitesse, mais un double appui involontaire peut générer de faux tours fractionnaires. Le filtre anti-rebond rejette les déclenchements sous le seuil configuré (3 secondes par défaut).',
84
+ },
85
+ {
86
+ question: 'Quelle est la précision de la vitesse moyenne estimée ?',
87
+ answer: 'Le calcul divise la distance déclarée du circuit par le temps mesuré. En virage, la vitesse réelle du drone varie selon le rayon de trajectoire et l\'angle d\'inclinaison.',
88
+ },
89
+ ];
90
+
91
+ const howToSteps = [
92
+ {
93
+ name: 'Paramétrez la longueur de piste et le format',
94
+ text: 'Saisissez la distance du circuit en mètres et le nombre de tours, ou sélectionnez un préréglage tel que MultiGP Spec.',
95
+ },
96
+ {
97
+ name: 'Lancez le compte à rebours acoustique FAI',
98
+ text: 'Cliquez sur Démarrer le Compte à Rebours. Écoutez les tonalités de préparation puis la sonnerie de départ.',
99
+ },
100
+ {
101
+ name: 'Validez chaque tour au franchissement de la porte',
102
+ text: 'Appuyez sur la barre Espace ou cliquez sur le bouton géant dès que votre drone traverse la porte de départ/arrivée.',
103
+ },
104
+ {
105
+ name: 'Analysez la télémétrie, les deltas et la constance',
106
+ text: 'Consultez le graphique des allures, les deltas au meilleur tour et la note de constance, puis exportez les données en CSV.',
107
+ },
108
+ ];
109
+
110
+ const seoSections: SEOSection[] = [
111
+ {
112
+ type: 'title',
113
+ text: 'Principes du chronométrage haute précision pour les courses de drones FPV',
114
+ level: 2,
115
+ },
116
+ {
117
+ type: 'paragraph',
118
+ html: 'La compétition en drone racer FPV exige une précision chirurgicale au millième de seconde. Les quadricoptères 5 pouces dépassent 140 km/h au cœur d\'enchaînements d\'arches et d\'obstacles complexes. Un entraînement efficace nécessite un départ sonore normalisé, un marquage instantané des passages et une analyse de la régularité sur plusieurs tours.',
119
+ },
120
+ {
121
+ type: 'title',
122
+ text: 'Comparaison des classes de circuits FPV et paramètres de timing',
123
+ level: 2,
124
+ },
125
+ {
126
+ type: 'table',
127
+ headers: ['Classe / Spécification', 'Longueur Moyenne', 'Tours de Manche', 'Temps au Tour Moyen', 'Plage de Vitesse', 'Anti-rebond Recommandé'],
128
+ rows: [
129
+ ['Tiny Whoop (65mm 1S)', '50m à 80m', '5 tours', '8.5s à 13.0s', '35 à 55 km/h', '2.0 secondes'],
130
+ ['Micro 3.5 Pouces (4S)', '120m à 180m', '4 tours', '12.0s à 18.0s', '70 à 110 km/h', '2.5 secondes'],
131
+ ['MultiGP Spec 5 Pouces (6S)', '200m à 300m', '3 tours', '14.0s à 22.0s', '100 à 150 km/h', '3.0 secondes'],
132
+ ['Sprint Plein Champ (6S/8S)', '350m à 500m', '2 tours', '20.0s à 32.0s', '130 à 180 km/h', '4.0 secondes'],
133
+ ],
134
+ },
135
+ {
136
+ type: 'title',
137
+ text: 'Signaux sonores de départ et réglementation sportive FAI F9U',
138
+ level: 2,
139
+ },
140
+ {
141
+ type: 'paragraph',
142
+ html: 'Conformément aux règlements FAI CIAM Section 4 pour les courses de drones, les départs utilisent des signaux acoustiques standardisés pour assurer des temps de réaction équitables dans les masques vidéo. La séquence combine des tonalités à 440 Hz espacées d\'une seconde et un bip aigu à 880 Hz pour l\'armement immédiat.',
143
+ },
144
+ {
145
+ type: 'list',
146
+ items: [
147
+ 'Bips de préparation: Alertes sonores permettant de caler la position des gaz et de focaliser son attention.',
148
+ 'Tonalité de départ (Go): Signal immédiat calant le départ du chrono précisément à t = 0.',
149
+ 'Confirmation acoustique: Son de validation assurant l\'enregistrement du tour sans quitter la vue vidéo.',
150
+ 'Alerte de meilleur tour: Signal harmonique lorsque le tour améliore le record de la session.',
151
+ ],
152
+ },
153
+ {
154
+ type: 'title',
155
+ text: 'Comprendre l\'Indice de Régularité et la stratégie de course',
156
+ level: 2,
157
+ },
158
+ {
159
+ type: 'paragraph',
160
+ html: 'Un tour éclair isolé impressionne, mais les championnats se remportent sur la constance. L\'indice mesure la stabilité des chronos: un pilote régulier à moins de 0.3 seconde près gère mieux l\'usure de batterie et conserve une tension suffisante pour le tour d\'attaque final.',
161
+ },
162
+ {
163
+ type: 'tip',
164
+ title: 'Conseil pratique sur le terrain',
165
+ html: 'Installez votre smartphone ou tablette avec un volume suffisant près de votre chaise de vol. Placez un bouton poussoir Bluetooth ou un petit pavé numérique sous votre pied pour valider vos passages sans lâcher les commandes.',
166
+ },
167
+ ];
168
+
169
+ const schemas: FpvDroneLapTimerLocaleContent['schemas'] = [
170
+ {
171
+ '@context': 'https://schema.org',
172
+ '@type': 'FAQPage',
173
+ mainEntity: faqItems.map((item) => ({
174
+ '@type': 'Question',
175
+ name: item.question,
176
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
177
+ })),
178
+ } as WithContext<FAQPage>,
179
+ {
180
+ '@context': 'https://schema.org',
181
+ '@type': 'HowTo',
182
+ name: title,
183
+ description,
184
+ step: howToSteps.map((s, index) => ({
185
+ '@type': 'HowToStep',
186
+ position: index + 1,
187
+ name: s.name,
188
+ text: s.text,
189
+ })),
190
+ } as WithContext<HowTo>,
191
+ {
192
+ '@context': 'https://schema.org',
193
+ '@type': 'SoftwareApplication',
194
+ name: title,
195
+ description,
196
+ applicationCategory: 'UtilityApplication',
197
+ operatingSystem: 'All',
198
+ offers: {
199
+ '@type': 'Offer',
200
+ price: '0',
201
+ priceCurrency: 'EUR',
202
+ },
203
+ } as WithContext<SoftwareApplication>,
204
+ ];
205
+
206
+ export const content: FpvDroneLapTimerLocaleContent = {
207
+ slug,
208
+ title,
209
+ description,
210
+ ui,
211
+ seo: seoSections,
212
+ faq: faqItems,
213
+ howTo: howToSteps,
214
+ bibliography: BIBLIOGRAPHY_ITEMS,
215
+ schemas,
216
+ };
@@ -0,0 +1,216 @@
1
+ import type { FpvDroneLapTimerLocaleContent } from '../entry';
2
+ import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import type { SEOSection } from '../../../types';
4
+ import { BIBLIOGRAPHY_ITEMS } from '../bibliography';
5
+
6
+ const slug = 'penghitung-waktu-putaran-balap-drone-fpv';
7
+ const title = 'Penghitung Waktu Putaran dan Sektor Balap Drone FPV';
8
+ const description = 'Penghitung waktu interaktif untuk balapan drone FPV dengan urutan awal akustik FAI, analisis selisih sektor, notifikasi putaran tercepat, indeks konsistensi, dan telemetri kecepatan.';
9
+
10
+ const ui = {
11
+ setupHeading: 'Konfigurasi Lintasan dan Sesi',
12
+ trackLengthLabel: 'Panjang Sirkuit',
13
+ trackLengthUnit: 'meter',
14
+ targetLapsLabel: 'Target Jumlah Putaran',
15
+ targetLapsUnit: 'putaran (0 untuk latihan bebas)',
16
+ batteryCapacityLabel: 'Kapasitas Baterai',
17
+ batteryCapacityUnit: 'mAh',
18
+ soundEnabledLabel: 'Aktifkan Nada Akustik',
19
+ debounceThresholdLabel: 'Pelindung Pemicu Ganda',
20
+ debounceThresholdUnit: 'detik',
21
+ presetMultiGpLabel: 'Spek MultiGP (250m / 3 Putaran)',
22
+ presetWhoopLabel: 'Tiny Whoop (65m / 5 Putaran)',
23
+ presetSprintLabel: 'Sprint Kecepatan Tinggi (400m / 2 Putaran)',
24
+ startCountdownButton: 'Mulai Hitung Mundur FAI',
25
+ pauseTimerButton: 'Jeda Sesi',
26
+ resumeTimerButton: 'Lanjutkan Timer',
27
+ resetTimerButton: 'Atur Ulang Sesi',
28
+ recordLapButton: 'CATAT PUTARAN',
29
+ spacebarHint: 'Tekan SPASI atau ketuk tombol besar untuk menandai lintasan garis finis',
30
+ statusIdle: 'Siap untuk Mulai',
31
+ statusCountdown: 'Hitung Mundur FAI Sedang Berjalan',
32
+ statusRunning: 'Timer Balap Aktif',
33
+ statusPaused: 'Sesi Dijeda',
34
+ statusFinished: 'Balapan Selesai',
35
+ currentLapHeading: 'Waktu Putaran Saat Ini',
36
+ lapNumberPrefix: 'Putaran',
37
+ lastLapHeading: 'Putaran Terakhir',
38
+ fastestLapHeading: 'Putaran Tercepat',
39
+ averageLapHeading: 'Rata-rata Putaran',
40
+ deltaBestHeading: 'Selisih ke Terbaik',
41
+ consistencyIndexHeading: 'Indeks Konsistensi Putaran',
42
+ estimatedSpeedHeading: 'Estimasi Kecepatan Rata-rata',
43
+ estimatedBatteryHeading: 'Estimasi Konsumsi Baterai',
44
+ speedUnitKmh: 'km/jam',
45
+ speedUnitMph: 'mph',
46
+ batteryUsedUnit: 'mAh',
47
+ batteryRemainingUnit: 'mAh tersisa',
48
+ lapHistoryHeading: 'Waktu Putaran dan Perbandingan Ritme',
49
+ lapColumnHeader: 'Putaran #',
50
+ timeColumnHeader: 'Waktu',
51
+ splitColumnHeader: 'Selisih Terbaik',
52
+ speedColumnHeader: 'Kecepatan Rata-rata',
53
+ batteryColumnHeader: 'Baterai',
54
+ noLapsRecordedNotice: 'Belum ada putaran tercatat. Mulai hitung mundur dan tekan Spasi untuk merekam putaran pertama.',
55
+ consistencyRatingElite: 'Konsistensi Elite',
56
+ consistencyRatingPro: 'Konsistensi Pembalap Pro',
57
+ consistencyRatingClub: 'Konsistensi Tingkat Klub',
58
+ consistencyRatingNovice: 'Konsistensi Pemula',
59
+ fastestLapBadge: 'PUTARAN TERCEPAT',
60
+ sessionSummaryHeading: 'Ringkasan Sesi dan Ekspor',
61
+ totalTimeLabel: 'Total Durasi Balapan',
62
+ completedLapsLabel: 'Putaran Selesai',
63
+ exportCsvButton: 'Ekspor Putaran ke CSV',
64
+ copySummaryButton: 'Salin Ringkasan Teks',
65
+ copiedNotice: 'Ringkasan sesi berhasil disalin ke papan klip!',
66
+ };
67
+
68
+ const faqItems = [
69
+ {
70
+ question: 'Bagaimana urutan awal akustik FAI bekerja pada timer ini?',
71
+ answer: 'Urutan start mencerminkan aturan resmi balap drone FAI CIAM F9U. Empat nada bip awal dengan jeda satu detik mempersiapkan pembalap, diikuti dengan nada tinggi start yang memulai penghitung waktu pada titik nol mutlak.',
72
+ },
73
+ {
74
+ question: 'Bagaimana Indeks Konsistensi Putaran dihitung?',
75
+ answer: 'Skor konsistensi mengevaluasi standar deviasi waktu putaran yang diselesaikan terhadap waktu rata-rata sesi. Nilai di atas 95 persen menunjukkan pengendalian throttle dan jalur terbang yang sangat presisi.',
76
+ },
77
+ {
78
+ question: 'Bisakah memakai pedal kaki atau tombol radio kontrol?',
79
+ answer: 'Bisa. Semua keyboard nirkabel, pedal kaki Bluetooth, atau tombol pemancar yang dipetakan untuk mengirim penekanan tombol Spasi dapat mencatat putaran tanpa menyentuh layar perangkat.',
80
+ },
81
+ {
82
+ question: 'Mengapa terdapat pelindung pemicu ganda (debounce)?',
83
+ answer: 'Gerbang balap dilewati dalam kecepatan tinggi, namun sentuhan ganda yang tidak disengaja dapat mencatat waktu palsu dalam pecahan detik. Pelindung ini mengabaikan sinyal di bawah ambang batas (standar 3 detik).',
84
+ },
85
+ {
86
+ question: 'Seberapa akurat perkiraan kecepatan rata-rata?',
87
+ answer: 'Kecepatan dihitung dari pembagian panjang garis tengah sirkuit dengan waktu putaran. Kecepatan riil pada tikungan akan bervariasi bergantung pada radius jalur terbang dan sudut kemiringan drone.',
88
+ },
89
+ ];
90
+
91
+ const howToSteps = [
92
+ {
93
+ name: 'Atur jarak sirkuit dan target putaran',
94
+ text: 'Masukkan panjang sirkuit dalam meter dan jumlah putaran sasaran atau gunakan preset seperti MultiGP Spec.',
95
+ },
96
+ {
97
+ name: 'Mulai hitung mundur nada akustik FAI',
98
+ text: 'Klik Mulai Hitung Mundur. Dengarkan nada persiapan dan bunyi start lepas landas.',
99
+ },
100
+ {
101
+ name: 'Catat putaran saat melewati gerbang finis',
102
+ text: 'Tekan tombol Spasi pada keyboard atau ketuk tombol layar setiap kali drone melewati gerbang awal/akhir.',
103
+ },
104
+ {
105
+ name: 'Analisis telemetri, selisih waktu, dan konsistensi',
106
+ text: 'Periksa grafik ritme balap, selisih terhadap rekor tercepat, serta skor konsistensi, lalu ekspor ke file CSV.',
107
+ },
108
+ ];
109
+
110
+ const seoSections: SEOSection[] = [
111
+ {
112
+ type: 'title',
113
+ text: 'Prinsip pencatatan waktu putaran presisi tinggi pada balap drone multirotor FPV',
114
+ level: 2,
115
+ },
116
+ {
117
+ type: 'paragraph',
118
+ html: 'Kompetisi balap drone FPV menuntut presisi milidetik dan konsistensi manuver yang ketat. Multirotor 5 inci melaju di atas 140 km/jam melewati susunan gerbang rintangan dan tiang bendera. Latihan efektif memerlukan sinyal suara saat start, pencatatan waktu cepat saat melintas, dan pemantauan penurunan performa di setiap putaran.',
119
+ },
120
+ {
121
+ type: 'title',
122
+ text: 'Perbandingan kelas balap drone dan parameter pencatatan waktu',
123
+ level: 2,
124
+ },
125
+ {
126
+ type: 'table',
127
+ headers: ['Kelas / Standar', 'Panjang Sirkuit Lazim', 'Putaran per Sesi', 'Waktu Putaran Rata-rata', 'Rentang Kecepatan', 'Jeda Anti Ganda Disarankan'],
128
+ rows: [
129
+ ['Tiny Whoop (65mm 1S)', '50m - 80m', '5 putaran', '8.5s - 13.0s', '35 - 55 km/jam', '2.0 detik'],
130
+ ['Mikro 3.5 Inci (4S)', '120m - 180m', '4 putaran', '12.0s - 18.0s', '70 - 110 km/jam', '2.5 detik'],
131
+ ['MultiGP Spec 5 Inci (6S)', '200m - 300m', '3 putaran', '14.0s - 22.0s', '100 - 150 km/jam', '3.0 detik'],
132
+ ['Sprint Lapangan Terbuka (6S/8S)', '350m - 500m', '2 putaran', '20.0s - 32.0s', '130 - 180 km/jam', '4.0 detik'],
133
+ ],
134
+ },
135
+ {
136
+ type: 'title',
137
+ text: 'Urutan nada suara start dan regulasi olahraga FAI F9U',
138
+ level: 2,
139
+ },
140
+ {
141
+ type: 'paragraph',
142
+ html: 'Berdasarkan regulasi FAI CIAM Bagian 4 untuk balapan drone, lomba dimulai dengan sinyal suara terstandarisasi ketimbang bendera visual demi kesetaraan reaksi pilot di dalam kacamata FPV. Urutan menggunakan nada 440 Hz setiap detik dan ditutup nada 880 Hz untuk mulai terbang.',
143
+ },
144
+ {
145
+ type: 'list',
146
+ items: [
147
+ 'Nada Persiapan: Peringatan akustik guna menstabilkan posisi tuas throttle dan memusatkan fokus penglihatan.',
148
+ 'Nada Start (Go): Sinyal instan yang mengaktifkan penghitungan waktu tepat pada detik t = 0.',
149
+ 'Konfirmasi Suara: Bunyi konfirmasi saat mencatat putaran tanpa mengalihkan pandangan dari jalur terbang.',
150
+ 'Melodi Putaran Tercepat: Nada harmonik khusus saat catatan waktu melewati rekor terbaik sesi saat itu.',
151
+ ],
152
+ },
153
+ {
154
+ type: 'title',
155
+ text: 'Pentingnya Indeks Konsistensi dan strategi balapan',
156
+ level: 2,
157
+ },
158
+ {
159
+ type: 'paragraph',
160
+ html: 'Mencetak satu putaran kilat memang membanggakan, tetapi kejuaraan diraih dengan konsistensi. Indeks ini mengukur fluktuasi waktu: pilot dengan deviasi di bawah 0.3 detik mampu mengendalikan baterai lebih awet dan memiliki tenaga ekstra untuk sprint putaran akhir.',
161
+ },
162
+ {
163
+ type: 'tip',
164
+ title: 'Tips praktis di lapangan terbang',
165
+ html: 'Letakkan tablet atau ponsel dalam jangkauan suara yang jelas di samping tempat duduk Anda. Pasang pedal Bluetooth atau tombol nirkabel di lantai dekat tas penerbangan untuk merekam putaran memakai kaki tanpa melepaskan jemari dari stik kendali.',
166
+ },
167
+ ];
168
+
169
+ const schemas: FpvDroneLapTimerLocaleContent['schemas'] = [
170
+ {
171
+ '@context': 'https://schema.org',
172
+ '@type': 'FAQPage',
173
+ mainEntity: faqItems.map((item) => ({
174
+ '@type': 'Question',
175
+ name: item.question,
176
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
177
+ })),
178
+ } as WithContext<FAQPage>,
179
+ {
180
+ '@context': 'https://schema.org',
181
+ '@type': 'HowTo',
182
+ name: title,
183
+ description,
184
+ step: howToSteps.map((s, index) => ({
185
+ '@type': 'HowToStep',
186
+ position: index + 1,
187
+ name: s.name,
188
+ text: s.text,
189
+ })),
190
+ } as WithContext<HowTo>,
191
+ {
192
+ '@context': 'https://schema.org',
193
+ '@type': 'SoftwareApplication',
194
+ name: title,
195
+ description,
196
+ applicationCategory: 'UtilityApplication',
197
+ operatingSystem: 'All',
198
+ offers: {
199
+ '@type': 'Offer',
200
+ price: '0',
201
+ priceCurrency: 'IDR',
202
+ },
203
+ } as WithContext<SoftwareApplication>,
204
+ ];
205
+
206
+ export const content: FpvDroneLapTimerLocaleContent = {
207
+ slug,
208
+ title,
209
+ description,
210
+ ui,
211
+ seo: seoSections,
212
+ faq: faqItems,
213
+ howTo: howToSteps,
214
+ bibliography: BIBLIOGRAPHY_ITEMS,
215
+ schemas,
216
+ };
@@ -0,0 +1,216 @@
1
+ import type { FpvDroneLapTimerLocaleContent } from '../entry';
2
+ import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import type { SEOSection } from '../../../types';
4
+ import { BIBLIOGRAPHY_ITEMS } from '../bibliography';
5
+
6
+ const slug = 'cronometro-giri-gare-droni-fpv';
7
+ const title = 'Cronometro Giri e Intertempi per Gare di Droni FPV';
8
+ const description = 'Cronometro interattivo per gare di droni FPV con sequenza di partenza acustica FAI, ritmo degli intertempi, avvisi sul giro veloce, indice di costanza e telemetria di velocità.';
9
+
10
+ const ui = {
11
+ setupHeading: 'Configurazione Tracciato e Sessione',
12
+ trackLengthLabel: 'Lunghezza del Circuito',
13
+ trackLengthUnit: 'metri',
14
+ targetLapsLabel: 'Giri Obiettivo',
15
+ targetLapsUnit: 'giri (0 per prove libere)',
16
+ batteryCapacityLabel: 'Capacità Batteria',
17
+ batteryCapacityUnit: 'mAh',
18
+ soundEnabledLabel: 'Attiva Segnali Acustici',
19
+ debounceThresholdLabel: 'Filtro Anti-rimbalzo Giro',
20
+ debounceThresholdUnit: 'secondi',
21
+ presetMultiGpLabel: 'Specifica MultiGP (250m / 3 Giri)',
22
+ presetWhoopLabel: 'Tiny Whoop (65m / 5 Giri)',
23
+ presetSprintLabel: 'Sprint ad Alta Velocità (400m / 2 Giri)',
24
+ startCountdownButton: 'Avvia Conto alla Rovescia FAI',
25
+ pauseTimerButton: 'Sospendi Sessione',
26
+ resumeTimerButton: 'Riprendi Cronometro',
27
+ resetTimerButton: 'Azzera Sessione',
28
+ recordLapButton: 'REGISTRA GIRO',
29
+ spacebarHint: 'Premi la BARRA SPAZIATRICE o tocca il pulsante gigante al passaggio sul traguardo',
30
+ statusIdle: 'Pronto alla Partenza',
31
+ statusCountdown: 'Conto alla Rovescia FAI in Corso',
32
+ statusRunning: 'Cronometro di Gara Attivo',
33
+ statusPaused: 'Sessione Sospesa',
34
+ statusFinished: 'Gara Completata',
35
+ currentLapHeading: 'Tempo Giro Attuale',
36
+ lapNumberPrefix: 'Giro',
37
+ lastLapHeading: 'Ultimo Giro',
38
+ fastestLapHeading: 'Giro più Veloce',
39
+ averageLapHeading: 'Giro Medio',
40
+ deltaBestHeading: 'Distacco dal Miglior Giro',
41
+ consistencyIndexHeading: 'Indice di Costanza',
42
+ estimatedSpeedHeading: 'Velocità Media Stimata',
43
+ estimatedBatteryHeading: 'Consumo Batteria Stimato',
44
+ speedUnitKmh: 'km/h',
45
+ speedUnitMph: 'mph',
46
+ batteryUsedUnit: 'mAh',
47
+ batteryRemainingUnit: 'mAh residui',
48
+ lapHistoryHeading: 'Tempi sul Giro e Confronto del Passo',
49
+ lapColumnHeader: 'Giro #',
50
+ timeColumnHeader: 'Tempo',
51
+ splitColumnHeader: 'Distacco Migliore',
52
+ speedColumnHeader: 'Velocità Media',
53
+ batteryColumnHeader: 'Consumo Batteria',
54
+ noLapsRecordedNotice: 'Nessun giro registrato. Avvia il conto alla rovescia e premi la barra spaziatrice per salvare il primo passaggio.',
55
+ consistencyRatingElite: 'Costanza Élite',
56
+ consistencyRatingPro: 'Costanza Pilota Pro',
57
+ consistencyRatingClub: 'Costanza Club',
58
+ consistencyRatingNovice: 'Costanza in Addestramento',
59
+ fastestLapBadge: 'GIRO PIÙ VELOCE',
60
+ sessionSummaryHeading: 'Riepilogo Sessione ed Esportazione',
61
+ totalTimeLabel: 'Durata Totale di Gara',
62
+ completedLapsLabel: 'Giri Completati',
63
+ exportCsvButton: 'Esporta Giri in CSV',
64
+ copySummaryButton: 'Copia Riepilogo Testuale',
65
+ copiedNotice: 'Riepilogo sessione copiato negli appunti!',
66
+ };
67
+
68
+ const faqItems = [
69
+ {
70
+ question: 'Come funziona la sequenza di partenza acustica FAI in questo cronometro?',
71
+ answer: 'La sequenza riproduce le normative ufficiali di gara per droni F9U della Fédération Aéronautique Internationale (FAI). Vengono emessi quattro bip preparatori a intervalli di un secondo, seguiti da un tono acuto di partenza che azzera e attiva il cronometro al millisecondo.',
72
+ },
73
+ {
74
+ question: 'Come viene calcolato l\'Indice di Costanza sul Giro?',
75
+ answer: 'Il punteggio misura la deviazione standard dei giri percorsi rispetto al tempo medio della sessione. Un risultato superiore al 95 percento denota una precisione di traiettoria e gestione del gas di massimo livello.',
76
+ },
77
+ {
78
+ question: 'È possibile utilizzare un pedale o un tasto del radiocomando per segnare i giri?',
79
+ answer: 'Sì. Qualsiasi tastiera wireless, pedale Bluetooth o switch della radio mappato per inviare la barra spaziatrice registrerà istantaneamente il giro senza dover guardare o toccare lo schermo.',
80
+ },
81
+ {
82
+ question: 'Perché è presente una soglia di sicurezza anti-rimbalzo?',
83
+ answer: 'I gate vengono superati a velocità sostenute, ma doppi tocchi accidentali potrebbero causare false registrazioni di frazioni di secondo. Il filtro anti-rimbalzo respinge letture inferiori alla soglia (predefinita a 3 secondi).',
84
+ },
85
+ {
86
+ question: 'Quanto è attendibile la velocità media stimata?',
87
+ answer: 'La stima divide la lunghezza nominale dichiarata della linea centrale del tracciato per il tempo di percorrenza. La velocità reale in curva differirà in base alla traiettoria e all\'angolo di rollio.',
88
+ },
89
+ ];
90
+
91
+ const howToSteps = [
92
+ {
93
+ name: 'Configura lunghezza tracciato e giri',
94
+ text: 'Inserisci la lunghezza del circuito in metri e il numero di giri previsti, o seleziona un profilo pronto come MultiGP Spec.',
95
+ },
96
+ {
97
+ name: 'Avvia il conto alla rovescia acustico FAI',
98
+ text: 'Fai clic su Avvia Conto alla Rovescia. Ascolta i toni di preparazione seguiti dal segnale acuto di partenza.',
99
+ },
100
+ {
101
+ name: 'Segna ogni giro al passaggio sotto il gate',
102
+ text: 'Tocca il pulsante grande o premi la barra spaziatrice della tastiera ogni volta che il drone attraversa il gate di arrivo.',
103
+ },
104
+ {
105
+ name: 'Analizza telemetria, distacchi e costanza',
106
+ text: 'Verifica il grafico del passo, i delta rispetto al miglior giro e la valutazione di costanza, quindi esporta in CSV.',
107
+ },
108
+ ];
109
+
110
+ const seoSections: SEOSection[] = [
111
+ {
112
+ type: 'title',
113
+ text: 'Principi di cronometraggio ad alta precisione nelle gare di droni FPV',
114
+ level: 2,
115
+ },
116
+ {
117
+ type: 'paragraph',
118
+ html: 'Nelle competizioni FPV con multirotori la precisione al millesimo di secondo e la costanza nelle linee di volo fanno la differenza tra vittoria e sconfitta. I droni da 5 pollici superano i 140 km/h affrontando gate tridimensionali, bandiere e dive loop. Allenarsi con metodo richiede un segnale acustico di partenza standardizzato, rilevamento istantaneo sul traguardo e report sull\'usura delle prestazioni giro dopo giro.',
119
+ },
120
+ {
121
+ type: 'title',
122
+ text: 'Confronto tra categorie di droni multirotore e parametri di timing',
123
+ level: 2,
124
+ },
125
+ {
126
+ type: 'table',
127
+ headers: ['Categoria / Specifica', 'Lunghezza Tipica Circuito', 'Giri di Manche', 'Tempo Giro Medio', 'Gamma Velocità Massima', 'Anti-rimbalzo Consigliato'],
128
+ rows: [
129
+ ['Tiny Whoop (65mm 1S)', 'da 50m a 80m', '5 giri', 'da 8.5s a 13.0s', 'da 35 a 55 km/h', '2.0 secondi'],
130
+ ['Micro 3.5 Pollici (4S)', 'da 120m a 180m', '4 giri', 'da 12.0s a 18.0s', 'da 70 a 110 km/h', '2.5 secondi'],
131
+ ['MultiGP Spec 5 Pollici (6S)', 'da 200m a 300m', '3 giri', 'da 14.0s a 22.0s', 'da 100 a 150 km/h', '3.0 secondi'],
132
+ ['Sprint Aperto su Prato (6S/8S)', 'da 350m a 500m', '2 giri', 'da 20.0s a 32.0s', 'da 130 a 180 km/h', '4.0 secondi'],
133
+ ],
134
+ },
135
+ {
136
+ type: 'title',
137
+ text: 'Sequenze sonore di partenza e regolamento sportivo FAI F9U',
138
+ level: 2,
139
+ },
140
+ {
141
+ type: 'paragraph',
142
+ html: 'In base alle normative FAI CIAM Sezione 4 per il drone racing, le partenze adottano segnali sonori standardizzati invece di bandiere visive per assicurare pari condizioni di reazione nei visori video FPV. La sequenza include bip a 440 Hz a intervalli di un secondo, culminando nel tono a 880 Hz al quale i piloti armano e scattano.',
143
+ },
144
+ {
145
+ type: 'list',
146
+ items: [
147
+ 'Toni di preparazione: Avvisi acustici per calibrare l\'acceleratore e massimizzare la concentrazione.',
148
+ 'Tono di via (Go): Segnale acustico istantaneo che attiva il cronometro esattamente a t = 0.',
149
+ 'Conferma acustica: Suoni di riscontro che confermano la registrazione del giro senza togliere il visore.',
150
+ 'Suono giro record: Melodia armonica distintiva quando il giro attuale batte il record della sessione.',
151
+ ],
152
+ },
153
+ {
154
+ type: 'title',
155
+ text: 'Importanza dell\'Indice di Costanza e gestione della strategia',
156
+ level: 2,
157
+ },
158
+ {
159
+ type: 'paragraph',
160
+ html: 'Segnare un giro record isolato è esaltante, ma i titoli si vincono con la costanza. L\'indice valuta le oscillazioni di tempo: un pilota che varia meno di 0.3 secondi controlla meglio l\'acceleratore, riduce le turbolenze e conserva voltaggio utile per la volata finale.',
161
+ },
162
+ {
163
+ type: 'tip',
164
+ title: 'Consiglio pratico per il campo di volo',
165
+ html: 'Posiziona il dispositivo di cronometraggio a volume ben udibile vicino alla tua postazione. Un pedale Bluetooth o un tastierino wireless appoggiato sulla borsa permette di registrare i giri con il piede senza mai staccare le mani dagli stick.',
166
+ },
167
+ ];
168
+
169
+ const schemas: FpvDroneLapTimerLocaleContent['schemas'] = [
170
+ {
171
+ '@context': 'https://schema.org',
172
+ '@type': 'FAQPage',
173
+ mainEntity: faqItems.map((item) => ({
174
+ '@type': 'Question',
175
+ name: item.question,
176
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
177
+ })),
178
+ } as WithContext<FAQPage>,
179
+ {
180
+ '@context': 'https://schema.org',
181
+ '@type': 'HowTo',
182
+ name: title,
183
+ description,
184
+ step: howToSteps.map((s, index) => ({
185
+ '@type': 'HowToStep',
186
+ position: index + 1,
187
+ name: s.name,
188
+ text: s.text,
189
+ })),
190
+ } as WithContext<HowTo>,
191
+ {
192
+ '@context': 'https://schema.org',
193
+ '@type': 'SoftwareApplication',
194
+ name: title,
195
+ description,
196
+ applicationCategory: 'UtilityApplication',
197
+ operatingSystem: 'All',
198
+ offers: {
199
+ '@type': 'Offer',
200
+ price: '0',
201
+ priceCurrency: 'EUR',
202
+ },
203
+ } as WithContext<SoftwareApplication>,
204
+ ];
205
+
206
+ export const content: FpvDroneLapTimerLocaleContent = {
207
+ slug,
208
+ title,
209
+ description,
210
+ ui,
211
+ seo: seoSections,
212
+ faq: faqItems,
213
+ howTo: howToSteps,
214
+ bibliography: BIBLIOGRAPHY_ITEMS,
215
+ schemas,
216
+ };