@jjlmoya/utils-drones 1.16.0 → 1.18.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 (67) hide show
  1. package/package.json +1 -1
  2. package/src/category/i18n/fr.ts +9 -9
  3. package/src/category/i18n/ru.ts +5 -5
  4. package/src/entries.ts +4 -1
  5. package/src/index.ts +1 -0
  6. package/src/tests/diacritics_density.test.ts +118 -0
  7. package/src/tests/inverted_punctuation.test.ts +84 -0
  8. package/src/tests/locale_completeness.test.ts +2 -2
  9. package/src/tests/no_en_dash.test.ts +70 -0
  10. package/src/tests/script_density.test.ts +94 -0
  11. package/src/tests/tool_validation.test.ts +2 -2
  12. package/src/tool/antenna-length-calculator/i18n/de.ts +2 -2
  13. package/src/tool/antenna-length-calculator/i18n/fr.ts +12 -12
  14. package/src/tool/antenna-length-calculator/i18n/ru.ts +6 -6
  15. package/src/tool/antenna-length-calculator/i18n/tr.ts +3 -3
  16. package/src/tool/antenna-length-calculator/i18n/zh.ts +10 -10
  17. package/src/tool/drone-flight-time/drone-flight-time-calculator.css +65 -7
  18. package/src/tool/drone-flight-time/i18n/fr.ts +11 -11
  19. package/src/tool/drone-flight-time/i18n/ru.ts +9 -9
  20. package/src/tool/drone-flight-time/i18n/sv.ts +3 -3
  21. package/src/tool/drone-flight-time/i18n/zh.ts +2 -2
  22. package/src/tool/drone-power-analyzer/i18n/de.ts +10 -10
  23. package/src/tool/drone-power-analyzer/i18n/en.ts +9 -9
  24. package/src/tool/drone-power-analyzer/i18n/es.ts +6 -6
  25. package/src/tool/drone-power-analyzer/i18n/fr.ts +16 -16
  26. package/src/tool/drone-power-analyzer/i18n/id.ts +9 -9
  27. package/src/tool/drone-power-analyzer/i18n/it.ts +6 -6
  28. package/src/tool/drone-power-analyzer/i18n/ja.ts +4 -4
  29. package/src/tool/drone-power-analyzer/i18n/ko.ts +4 -4
  30. package/src/tool/drone-power-analyzer/i18n/nl.ts +9 -9
  31. package/src/tool/drone-power-analyzer/i18n/pl.ts +11 -11
  32. package/src/tool/drone-power-analyzer/i18n/pt.ts +9 -9
  33. package/src/tool/drone-power-analyzer/i18n/ru.ts +17 -17
  34. package/src/tool/drone-power-analyzer/i18n/sv.ts +9 -9
  35. package/src/tool/drone-power-analyzer/i18n/tr.ts +9 -9
  36. package/src/tool/drone-power-analyzer/i18n/zh.ts +13 -13
  37. package/src/tool/gps-coordinates-converter/i18n/fr.ts +10 -10
  38. package/src/tool/gps-coordinates-converter/i18n/it.ts +2 -2
  39. package/src/tool/gps-coordinates-converter/i18n/pt.ts +4 -4
  40. package/src/tool/gps-coordinates-converter/i18n/ru.ts +7 -7
  41. package/src/tool/gps-coordinates-converter/i18n/zh.ts +4 -4
  42. package/src/tool/gsd-flight-planner/InputsColumn.astro +108 -0
  43. package/src/tool/gsd-flight-planner/ResultsColumn.astro +90 -0
  44. package/src/tool/gsd-flight-planner/bibliography.astro +6 -0
  45. package/src/tool/gsd-flight-planner/bibliography.ts +7 -0
  46. package/src/tool/gsd-flight-planner/component.astro +22 -0
  47. package/src/tool/gsd-flight-planner/entry.ts +29 -0
  48. package/src/tool/gsd-flight-planner/gsd-flight-planner.css +515 -0
  49. package/src/tool/gsd-flight-planner/i18n/de.ts +214 -0
  50. package/src/tool/gsd-flight-planner/i18n/en.ts +214 -0
  51. package/src/tool/gsd-flight-planner/i18n/es.ts +221 -0
  52. package/src/tool/gsd-flight-planner/i18n/fr.ts +214 -0
  53. package/src/tool/gsd-flight-planner/i18n/id.ts +214 -0
  54. package/src/tool/gsd-flight-planner/i18n/it.ts +214 -0
  55. package/src/tool/gsd-flight-planner/i18n/ja.ts +214 -0
  56. package/src/tool/gsd-flight-planner/i18n/ko.ts +214 -0
  57. package/src/tool/gsd-flight-planner/i18n/nl.ts +214 -0
  58. package/src/tool/gsd-flight-planner/i18n/pl.ts +214 -0
  59. package/src/tool/gsd-flight-planner/i18n/pt.ts +214 -0
  60. package/src/tool/gsd-flight-planner/i18n/ru.ts +214 -0
  61. package/src/tool/gsd-flight-planner/i18n/sv.ts +214 -0
  62. package/src/tool/gsd-flight-planner/i18n/tr.ts +214 -0
  63. package/src/tool/gsd-flight-planner/i18n/zh.ts +214 -0
  64. package/src/tool/gsd-flight-planner/index.ts +8 -0
  65. package/src/tool/gsd-flight-planner/logic.js +326 -0
  66. package/src/tool/gsd-flight-planner/seo.astro +15 -0
  67. package/src/tools.ts +3 -0
@@ -1,4 +1,4 @@
1
- import type { DronePowerAnalyzerLocaleContent } from '../index';
1
+ import type { DronePowerAnalyzerLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -9,7 +9,7 @@ const description = 'Beräkna det kritiska kraft-vikt-förhållandet för ditt F
9
9
  const faqItems = [
10
10
  {
11
11
  question: 'Vad är kraft-vikt-förhållande och varför är det viktigt?',
12
- answer: 'Kraft-vikt-förhållandet (Thrust-to-Weight ratio) är den totala dragkraften din drönare kan producera delat med dess totala startvikt (AUW). Det är det enskilt viktigaste mätvärdet som avgör hur din drönare känns att flyga från långsam och stabil (cinematografi) till ultra-responsiv (racing).',
12
+ answer: 'Kraft-vikt-förhållandet (Thrust-to-Weight ratio) är den totala dragkraften din drönare kan producera delat med dess totala startvikt (AUW). Det är det enskilt viktigaste mätvärdet som avgör hur din drönare känns att flyga - från långsam och stabil (cinematografi) till ultra-responsiv (racing).',
13
13
  },
14
14
  {
15
15
  question: 'Vad är det ideala förhållandet ("sweet spot") för freestyle-flygning?',
@@ -21,11 +21,11 @@ const faqItems = [
21
21
  },
22
22
  {
23
23
  question: 'Vad händer om mitt förhållande är över 8:1?',
24
- answer: 'Över 8:1 är din drönare i praktiken en racingmaskin extremt reaktiv och krävande att flyga. Endast erfarna piloter bör försöka sig på dessa byggen. Utmärkt för racing-gates och hastighetskörningar, men farligt inomhus.',
24
+ answer: 'Över 8:1 är din drönare i praktiken en racingmaskin - extremt reaktiv och krävande att flyga. Endast erfarna piloter bör försöka sig på dessa byggen. Utmärkt för racing-gates och hastighetskörningar, men farligt inomhus.',
25
25
  },
26
26
  {
27
27
  question: 'Ska jag inkludera batterivikten i AUW?',
28
- answer: 'Ja. AUW (All-Up Weight) är den totala vikten för din drönare med alla komponenter installerade: ram, motorer, ESC:er, flight controller, kamera, batteri, propellrar allt. Använd batteri-presets för att lägga till vikt direkt.',
28
+ answer: 'Ja. AUW (All-Up Weight) är den totala vikten för din drönare med alla komponenter installerade: ram, motorer, ESC:er, flight controller, kamera, batteri, propellrar - allt. Använd batteri-presets för att lägga till vikt direkt.',
29
29
  },
30
30
  ];
31
31
 
@@ -40,7 +40,7 @@ const howToSteps = [
40
40
  },
41
41
  {
42
42
  name: 'Ställ in totalvikt',
43
- text: 'Ange din drönares totala startvikt (AUW) ram, motorer, batteri, kamera, allt. Använd batteri-presets för omedelbar viktjustering.',
43
+ text: 'Ange din drönares totala startvikt (AUW) - ram, motorer, batteri, kamera, allt. Använd batteri-presets för omedelbar viktjustering.',
44
44
  },
45
45
  {
46
46
  name: 'Läs av dina resultat',
@@ -123,7 +123,7 @@ export const content: DronePowerAnalyzerLocaleContent = {
123
123
  recommendation_cinematic: 'Med ett förhållande på {ratio}:1 är detta idealiskt för tung cinematic-flygning med mjuka, kontrollerade rörelser. Perfekt för långsamt, medvetet kameraarbete.',
124
124
  recommendation_freestyle: 'Med ett förhållande på {ratio}:1 är detta det ideala läget för freestyle-flygning. Utmärkt rörlighet med bibehållen stabilitet för trick.',
125
125
  recommendation_racing: 'Med ett förhållande på {ratio}:1 befinner vi oss i prestanda-freestyle-territorium. Gasreglering är avgörande i trånga utrymmen och vid höghastighetsmanövrer.',
126
- recommendation_extreme: 'Med ett förhållande på {ratio}:1 är detta en racingmaskin. Extremt reaktiv endast för erfarna piloter i öppna områden.',
126
+ recommendation_extreme: 'Med ett förhållande på {ratio}:1 är detta en racingmaskin. Extremt reaktiv - endast för erfarna piloter i öppna områden.',
127
127
  compareMode: 'Jämför byggen',
128
128
  scenario1: 'Bygge A',
129
129
  scenario2: 'Bygge B',
@@ -167,9 +167,9 @@ export const content: DronePowerAnalyzerLocaleContent = {
167
167
  {
168
168
  type: 'list',
169
169
  items: [
170
- '<strong>Cinematic (2:1 4:1)</strong>: Tung, stabil, långsam. Idealiskt för mjuka kamerarörelser och byggen som bär tung last.',
171
- '<strong>Freestyle (3.5:1 6.5:1)</strong>: Det balanserade idealläget. Responsivt nog för trick, stabilt nog för kontroll.',
172
- '<strong>Racing (5:1 8:1)</strong>: Snabb och rörlig. Designad för racing-gates och aggressiva manövrer.',
170
+ '<strong>Cinematic (2:1 - 4:1)</strong>: Tung, stabil, långsam. Idealiskt för mjuka kamerarörelser och byggen som bär tung last.',
171
+ '<strong>Freestyle (3.5:1 - 6.5:1)</strong>: Det balanserade idealläget. Responsivt nog för trick, stabilt nog för kontroll.',
172
+ '<strong>Racing (5:1 - 8:1)</strong>: Snabb och rörlig. Designad för racing-gates och aggressiva manövrer.',
173
173
  '<strong>Pro Racing (7:1+)</strong>: Extrem prestanda. Endast för expertpiloter i öppna områden.',
174
174
  ],
175
175
  },
@@ -1,4 +1,4 @@
1
- import type { DronePowerAnalyzerLocaleContent } from '../index';
1
+ import type { DronePowerAnalyzerLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -9,7 +9,7 @@ const description = 'FPV drone kurulumunuz için kritik itme-ağırlık oranın
9
9
  const faqItems = [
10
10
  {
11
11
  question: 'İtme-ağırlık oranı nedir ve neden önemlidir?',
12
- answer: 'İtme-ağırlık oranı, dronunuzun üretebileceği toplam itme kuvvetinin toplam kalkış ağırlığına (AUW) bölünmesidir. Dronunuzun uçuş sırasında nasıl hissettireceğini belirleyen en önemli metriktir yavaş ve stabil (sinematografi) ile ultra-tepkisel (yarış) arasında değişir.',
12
+ answer: 'İtme-ağırlık oranı, dronunuzun üretebileceği toplam itme kuvvetinin toplam kalkış ağırlığına (AUW) bölünmesidir. Dronunuzun uçuş sırasında nasıl hissettireceğini belirleyen en önemli metriktir - yavaş ve stabil (sinematografi) ile ultra-tepkisel (yarış) arasında değişir.',
13
13
  },
14
14
  {
15
15
  question: 'Freestyle uçuş için ideal oran ("sweet spot") nedir?',
@@ -21,11 +21,11 @@ const faqItems = [
21
21
  },
22
22
  {
23
23
  question: 'Oranım 8:1\'in üzerindeyse ne olur?',
24
- answer: '8:1\'in üzerindeki oranlarda dronunuz tam bir yarış makinesidir son derece tepkisel ve uçurması zordur. Sadece deneyimli pilotlar bu kurulumları denemelidir. Yarış kapıları ve hız denemeleri için harikadır, ancak iç mekanlarda tehlikelidir.',
24
+ answer: '8:1\'in üzerindeki oranlarda dronunuz tam bir yarış makinesidir - son derece tepkisel ve uçurması zordur. Sadece deneyimli pilotlar bu kurulumları denemelidir. Yarış kapıları ve hız denemeleri için harikadır, ancak iç mekanlarda tehlikelidir.',
25
25
  },
26
26
  {
27
27
  question: 'Batarya ağırlığını AUW\'ye dahil etmeli miyim?',
28
- answer: 'Evet. AUW (Toplam Kalkış Ağırlığı), tüm bileşenlerin kurulu olduğu dronun toplam ağırlığıdır: gövde, motorlar, ESC\'ler, uçuş kontrol kartı, kamera, batarya, pervaneler her şey. Anında ağırlık eklemek için batarya hazır ayarlarını kullanın.',
28
+ answer: 'Evet. AUW (Toplam Kalkış Ağırlığı), tüm bileşenlerin kurulu olduğu dronun toplam ağırlığıdır: gövde, motorlar, ESC\'ler, uçuş kontrol kartı, kamera, batarya, pervaneler - her şey. Anında ağırlık eklemek için batarya hazır ayarlarını kullanın.',
29
29
  },
30
30
  ];
31
31
 
@@ -40,7 +40,7 @@ const howToSteps = [
40
40
  },
41
41
  {
42
42
  name: 'Toplam Ağırlığı Ayarlayın',
43
- text: 'Dronunuzun toplam kalkış ağırlığını (AUW) girin gövde, motorlar, batarya, kamera, her şey. Anında ağırlık ayarı için batarya hazır ayarlarını kullanın.',
43
+ text: 'Dronunuzun toplam kalkış ağırlığını (AUW) girin - gövde, motorlar, batarya, kamera, her şey. Anında ağırlık ayarı için batarya hazır ayarlarını kullanın.',
44
44
  },
45
45
  {
46
46
  name: 'Sonuçları Okuyun',
@@ -123,7 +123,7 @@ export const content: DronePowerAnalyzerLocaleContent = {
123
123
  recommendation_cinematic: '{ratio}:1 oranıyla bu, yumuşak ve kontrollü hareketlere sahip ağır sinematik çekimler için idealdir. Yavaş ve planlı kamera çalışmaları için mükemmeldir.',
124
124
  recommendation_freestyle: '{ratio}:1 oranı, freestyle uçuş için ideal noktadır. Hareketler için stabiliteyi korurken mükemmel çeviklik sağlar.',
125
125
  recommendation_racing: '{ratio}:1 oranıyla performans freestyle alanındasınız. Dar alanlarda ve yüksek hızlı manevralarda gaz kontrolü kritiktir.',
126
- recommendation_extreme: '{ratio}:1 oranıyla bu bir yarış makinesidir. Son derece tepkiseldir sadece açık alanlarda deneyimli pilotlar içindir.',
126
+ recommendation_extreme: '{ratio}:1 oranıyla bu bir yarış makinesidir. Son derece tepkiseldir - sadece açık alanlarda deneyimli pilotlar içindir.',
127
127
  compareMode: 'Kurulumları Karşılaştır',
128
128
  scenario1: 'Kurulum A',
129
129
  scenario2: 'Kurulum B',
@@ -167,9 +167,9 @@ export const content: DronePowerAnalyzerLocaleContent = {
167
167
  {
168
168
  type: 'list',
169
169
  items: [
170
- '<strong>Sinematik (2:1 4:1)</strong>: Ağır, stabil, yavaş. Yumuşak kamera hareketleri ve yük taşıyan kurulumlar için idealdir.',
171
- '<strong>Freestyle (3.5:1 6.5:1)</strong>: Dengeli ideal nokta. Hareketler için yeterince tepkisel, kontrol için yeterince stabildir.',
172
- '<strong>Yarış (5:1 8:1)</strong>: Hızlı ve çevik. Yarış kapıları ve agresif manevralar için tasarlanmıştır.',
170
+ '<strong>Sinematik (2:1 - 4:1)</strong>: Ağır, stabil, yavaş. Yumuşak kamera hareketleri ve yük taşıyan kurulumlar için idealdir.',
171
+ '<strong>Freestyle (3.5:1 - 6.5:1)</strong>: Dengeli ideal nokta. Hareketler için yeterince tepkisel, kontrol için yeterince stabildir.',
172
+ '<strong>Yarış (5:1 - 8:1)</strong>: Hızlı ve çevik. Yarış kapıları ve agresif manevralar için tasarlanmıştır.',
173
173
  '<strong>Pro Yarış (7:1+)</strong>: Ekstrem performans. Sadece açık alanlarda uzman pilotlar içindir.',
174
174
  ],
175
175
  },
@@ -1,4 +1,4 @@
1
- import type { DronePowerAnalyzerLocaleContent } from '../index';
1
+ import type { DronePowerAnalyzerLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -9,23 +9,23 @@ const description = '计算 FPV 无人机组装的关键推重比。获取即时
9
9
  const faqItems = [
10
10
  {
11
11
  question: '什么是推重比,为什么它很重要?',
12
- answer: '推重比是指无人机能产生的总推力除以其起飞全重(AUW)。它是决定无人机飞行手感最重要的指标——从缓慢稳定(航拍)到极速响应(竞速)。',
12
+ answer: '推重比是指无人机能产生的总推力除以其起飞全重(AUW)。它是决定无人机飞行手感最重要的指标,从缓慢稳定(航拍)到极速响应(竞速)。',
13
13
  },
14
14
  {
15
- question: '花飞(Freestyle)飞行的“黄金比例”是多少?',
15
+ question: '花飞(Freestyle)飞行的"黄金比例"是多少?',
16
16
  answer: '对于流畅的花飞飞行,黄金比例在 4:1 到 6:1 之间。4:1 的比例在提供良好稳定性的同时具有出色的灵活性,而 6:1 则响应极快,但在狭窄空间内需要更精细的油门控制。',
17
17
  },
18
18
  {
19
19
  question: '我可以将其用于航拍机组装吗?',
20
- answer: '可以。对于流畅、缓慢的航拍镜头,目标比例应在 2:1 到 3:1 之间。这能保持无人机稳定且可预测。低于此比例将难以控制;高于此比例对于缓慢移动来说会显得过于“贼”。',
20
+ answer: '可以。对于流畅、缓慢的航拍镜头,目标比例应在 2:1 到 3:1 之间。这能保持无人机稳定且可预测。低于此比例将难以控制;高于此比例对于缓慢移动来说会显得过于"贼"。',
21
21
  },
22
22
  {
23
23
  question: '如果我的比例超过 8:1 会怎样?',
24
- answer: '超过 8:1 时,你的无人机实际上是一台竞速机器——响应极其灵敏,对飞行技术要求很高。只有经验丰富的飞行员才应尝试此类组装。非常适合过旗门和速度赛,但在室内飞行很危险。',
24
+ answer: '超过 8:1 时,你的无人机实际上是一台竞速机器,响应极其灵敏,对飞行技术要求很高。只有经验丰富的飞行员才应尝试此类组装。非常适合过旗门和速度赛,但在室内飞行很危险。',
25
25
  },
26
26
  {
27
27
  question: '起飞全重(AUW)需要包含电池重量吗?',
28
- answer: '需要。起飞全重(AUW)是无人机安装所有组件后的总重量:机架、电机、电调、飞控、摄像头、电池、桨叶——所有东西。使用电池预设按钮可即时添加重量。',
28
+ answer: '需要。起飞全重(AUW)是无人机安装所有组件后的总重量:机架、电机、电调、飞控、摄像头、电池、桨叶,所有东西。使用电池预设按钮可即时添加重量。',
29
29
  },
30
30
  ];
31
31
 
@@ -40,7 +40,7 @@ const howToSteps = [
40
40
  },
41
41
  {
42
42
  name: '设置总重量',
43
- text: '输入无人机的起飞全重(AUW)——机架、电机、电池、摄像头等所有重量。使用电池预设进行即时重量调整。',
43
+ text: '输入无人机的起飞全重(AUW),机架、电机、电池、摄像头等所有重量。使用电池预设进行即时重量调整。',
44
44
  },
45
45
  {
46
46
  name: '查看结果',
@@ -123,13 +123,13 @@ export const content: DronePowerAnalyzerLocaleContent = {
123
123
  recommendation_cinematic: '{ratio}:1 的比例非常适合动作平稳、受控的重载航拍。是缓慢、精准镜头工作的完美选择。',
124
124
  recommendation_freestyle: '{ratio}:1 的比例是花飞飞行的黄金比例。在保持特技飞行所需稳定性的同时,具有极佳的灵活性。',
125
125
  recommendation_racing: '{ratio}:1 的比例属于高性能花飞领域。在狭窄空间和高速机动中,油门管理至关重要。',
126
- recommendation_extreme: '{ratio}:1 的比例是一台竞速机器。响应极其灵敏——仅供经验丰富的飞行员在开阔区域飞行。',
126
+ recommendation_extreme: '{ratio}:1 的比例是一台竞速机器。响应极其灵敏,仅供经验丰富的飞行员在开阔区域飞行。',
127
127
  compareMode: '对比组装方案',
128
128
  scenario1: '方案 A',
129
129
  scenario2: '方案 B',
130
130
  addComparison: '添加对比',
131
131
  tooltipTWRatio: '推重比是总推力除以无人机重量。比例越高意味着加速度越快,操控响应越灵敏。',
132
- tooltipFreestyle: '花飞飞行的“黄金比例”是 4:1 到 6:1,这在灵活性和操控性之间提供了最佳平衡。',
132
+ tooltipFreestyle: '花飞飞行的"黄金比例"是 4:1 到 6:1,这在灵活性和操控性之间提供了最佳平衡。',
133
133
  badge_unstable: '不稳定',
134
134
  badge_cinematic: '电影级',
135
135
  badge_sweetSpot: '黄金比例',
@@ -167,9 +167,9 @@ export const content: DronePowerAnalyzerLocaleContent = {
167
167
  {
168
168
  type: 'list',
169
169
  items: [
170
- '<strong>电影级 (2:1 4:1)</strong>:重型、稳定、缓慢。非常适合平稳的相机移动和载重组装方案。',
171
- '<strong>花飞 (3.5:1 6.5:1)</strong>:均衡的黄金比例。响应足以完成特技,稳定性足以进行控制。',
172
- '<strong>竞速 (5:1 8:1)</strong>:快速且灵活。专为过旗门和激进机动而设计。',
170
+ '<strong>电影级 (2:1 - 4:1)</strong>:重型、稳定、缓慢。非常适合平稳的相机移动和载重组装方案。',
171
+ '<strong>花飞 (3.5:1 - 6.5:1)</strong>:均衡的黄金比例。响应足以完成特技,稳定性足以进行控制。',
172
+ '<strong>竞速 (5:1 - 8:1)</strong>:快速且灵活。专为过旗门和激进机动而设计。',
173
173
  '<strong>专业竞速 (7:1+)</strong>:极限性能。仅限专家级飞行员在开阔区域使用。',
174
174
  ],
175
175
  },
@@ -193,7 +193,7 @@ export const content: DronePowerAnalyzerLocaleContent = {
193
193
  },
194
194
  {
195
195
  type: 'paragraph',
196
- html: '请记住:比例越高并不代表“越好”。它代表“响应越快”。在竞速机上,这是必需的。在航拍机上,这反而可能是个负担。请根据需求审慎选择。',
196
+ html: '请记住:比例越高并不代表"越好"。它代表"响应越快"。在竞速机上,这是必需的。在航拍机上,这反而可能是个负担。请根据需求审慎选择。',
197
197
  },
198
198
  ],
199
199
  faq: faqItems,
@@ -1,4 +1,4 @@
1
- import type { GpsCoordinatesConverterLocaleContent } from '../index';
1
+ import type { GpsCoordinatesConverterLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -106,7 +106,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
106
106
  seo: [
107
107
  {
108
108
  type: 'title',
109
- text: 'Convertisseur de Coordonnées GPS : Du Décimal vers Degrés, Minutes et Secondes',
109
+ text: 'Convertisseur de Coordonnées GPS: Du Décimal vers Degrés, Minutes et Secondes',
110
110
  level: 2,
111
111
  },
112
112
  {
@@ -142,10 +142,10 @@ export const content: GpsCoordinatesConverterLocaleContent = {
142
142
  {
143
143
  type: 'list',
144
144
  items: [
145
- 'Planification de Mission : Croisement des données des applications de vol mobiles avec les cartes topographiques officielles.',
146
- 'Recherche et Sauvetage : Communication de la position d\'une cible aux équipes de secours utilisant la radiofréquence et les coordonnées DMS.',
147
- 'Photogrammétrie : Vérification des métadonnées EXIF des images capturées par le capteur du drone.',
148
- 'Navigation FPV Longue Portée : Configuration d\'antennes directionnelles basées sur les coordonnées exactes de points géographiques clés.',
145
+ 'Planification de Mission: Croisement des données des applications de vol mobiles avec les cartes topographiques officielles.',
146
+ 'Recherche et Sauvetage: Communication de la position d\'une cible aux équipes de secours utilisant la radiofréquence et les coordonnées DMS.',
147
+ 'Photogrammétrie: Vérification des métadonnées EXIF des images capturées par le capteur du drone.',
148
+ 'Navigation FPV Longue Portée: Configuration d\'antennes directionnelles basées sur les coordonnées exactes de points géographiques clés.',
149
149
  ],
150
150
  },
151
151
  {
@@ -176,7 +176,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
176
176
  },
177
177
  {
178
178
  type: 'title',
179
- text: 'Latitude et Longitude : les Axes de la Terre',
179
+ text: 'Latitude et Longitude: les Axes de la Terre',
180
180
  level: 3,
181
181
  },
182
182
  {
@@ -189,12 +189,12 @@ export const content: GpsCoordinatesConverterLocaleContent = {
189
189
  },
190
190
  {
191
191
  type: 'title',
192
- text: 'Le Format Nautique : Degrés et Minutes Décimales',
192
+ text: 'Le Format Nautique: Degrés et Minutes Décimales',
193
193
  level: 3,
194
194
  },
195
195
  {
196
196
  type: 'paragraph',
197
- html: 'Il existe un format hybride très populaire dans la communauté marine et nautique : les Degrés et Minutes Décimales (DM). Dans ce système, on conserve les degrés entiers mais le reste est exprimé en minutes avec décimales, en omettant les secondes. Exemple : 48° 51.365\' N.',
197
+ html: 'Il existe un format hybride très populaire dans la communauté marine et nautique: les Degrés et Minutes Décimales (DM). Dans ce système, on conserve les degrés entiers mais le reste est exprimé en minutes avec décimales, en omettant les secondes. Exemple: 48° 51.365\' N.',
198
198
  },
199
199
  {
200
200
  type: 'paragraph',
@@ -243,7 +243,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
243
243
  faq: [
244
244
  {
245
245
  question: 'Quelle est la différence entre DD et DMS ?',
246
- answer: 'DD (Degrés Décimaux) utilise un seul nombre avec des décimales (ex : 48.85). DMS (Degrés, Minutes, Secondes) divise le degré en fractions sexagésimales (ex : 48° 51\' 0").',
246
+ answer: 'DD (Degrés Décimaux) utilise un seul nombre avec des décimales (ex: 48.85). DMS (Degrés, Minutes, Secondes) divise le degré en fractions sexagésimales (ex: 48° 51\' 0").',
247
247
  },
248
248
  {
249
249
  question: 'Pourquoi utilise-t-on des coordonnées négatives ?',
@@ -1,4 +1,4 @@
1
- import type { GpsCoordinatesConverterLocaleContent } from '../index';
1
+ import type { GpsCoordinatesConverterLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -171,7 +171,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
171
171
  items: [
172
172
  '<strong>Ritrovarlo Al Volo (Lost Drone):</strong> A video su OSD l\'ultimazione o dalla TX RC potrete carpire DMS non decifrabili, convertite qua in numeri DD poi in un past past inseriteli in GPS Maps ed il drone è recuperato',
173
173
  '<strong>Tralasciare Il Privato - In Mission Planner O INAV </strong> Se si devono trasferire rilievi catastali a zone ristrette dalle coordinate su foglio in dms vi dovrete tramutarli qui. Se i numeri sbordano la rotta, la zona a Mappature del vostro software di piano d\'ispezione ( Mission Planning, QGround etc...) sconfinerà illegalmente il vicinato o peggio su di te. Usarlo in fase di setup traccia un rientro Sicuro.',
174
- '<strong>Scritture in firmware : </strong> In impostazioni avanzatissime nel prompt su terminal CLI , in BetaFL non v\'è spazio in memoria (RTH Rescue) ai punti fermi decimali e quindi dovete iniettargli le lunghezze a Intero Grezzo formato Raw che quest\'interfaccia da in via subitanea.',
174
+ '<strong>Scritture in firmware: </strong> In impostazioni avanzatissime nel prompt su terminal CLI , in BetaFL non v\'è spazio in memoria (RTH Rescue) ai punti fermi decimali e quindi dovete iniettargli le lunghezze a Intero Grezzo formato Raw che quest\'interfaccia da in via subitanea.',
175
175
  ],
176
176
  },
177
177
  {
@@ -1,4 +1,4 @@
1
- import type { GpsCoordinatesConverterLocaleContent } from '../index';
1
+ import type { GpsCoordinatesConverterLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -181,15 +181,15 @@ export const content: GpsCoordinatesConverterLocaleContent = {
181
181
  },
182
182
  {
183
183
  type: 'paragraph',
184
- html: 'Um erro minúsculo em que o decimal final fuja qual seria afinal sua implicação ? Olhe para esta grelha prática avaliando a zona do Equador e o fator em precisão da medição GPS : ',
184
+ html: 'Um erro minúsculo em que o decimal final fuja qual seria afinal sua implicação ? Olhe para esta grelha prática avaliando a zona do Equador e o fator em precisão da medição GPS: ',
185
185
  },
186
186
  {
187
187
  type: 'list',
188
188
  items: [
189
- '<strong>Precisão Apenas À Primeira Cada ( 1 só decimal):</strong> (ex 40.1 ) , este ponto no horizonte significa uma gigantesca margem de desvio no mundo num alcance e erro tolerado num desfecho enorme até na faixa ao entorno de um total aproximado superior a generosos : De Cento E Onze Km de imprecisão !!.',
189
+ '<strong>Precisão Apenas À Primeira Cada ( 1 só decimal):</strong> (ex 40.1 ) , este ponto no horizonte significa uma gigantesca margem de desvio no mundo num alcance e erro tolerado num desfecho enorme até na faixa ao entorno de um total aproximado superior a generosos: De Cento E Onze Km de imprecisão !!.',
190
190
  '<strong>Com Um Precisão Levada Na Três Casas ( 3 Decimais):</strong> ( P.exe: ... 40.123), Agora limitamos e restringimos para estarmos em busca do seu multirotor ao menos entre vizinhanças ou limites com erros que abrandam se a já 110. ( metros ).',
191
191
  '<strong>Com As Precisões Levadas E Trabalhadas no patamar Cinco Zero ou Cincos Cifras numéricas :</strong> Avançamos largamente para o limiar em que uma medição afere distâncias a mais ou menos cerca entre um raio e área não maior num de total com aproximação do valor do 1.1 / 1.5 metros de margens de dúvida e exatidão.',
192
- '<strong>O Standard Super Avançado E O Que Vai Com os números e casas Decimais Na Patamar e Base 7 ao 8 ! :</strong> Quando visualizamos numéricas coordenadas estendendo o registro muito na base ( ex : 40.1234567 ) falamos dum mundo restrito usado no mapeamento profissional a nível cirúrgico em centímetro usado em RTK de levantamentos a precisões que contêm níveis incríveis com erros reduzidíssimos da ordem dos 11 ou 10 Milímetros em acerto !!.',
192
+ '<strong>O Standard Super Avançado E O Que Vai Com os números e casas Decimais Na Patamar e Base 7 ao 8 ! :</strong> Quando visualizamos numéricas coordenadas estendendo o registro muito na base ( ex: 40.1234567 ) falamos dum mundo restrito usado no mapeamento profissional a nível cirúrgico em centímetro usado em RTK de levantamentos a precisões que contêm níveis incríveis com erros reduzidíssimos da ordem dos 11 ou 10 Milímetros em acerto !!.',
193
193
  ],
194
194
  },
195
195
  {
@@ -1,4 +1,4 @@
1
- import type { GpsCoordinatesConverterLocaleContent } from '../index';
1
+ import type { GpsCoordinatesConverterLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -131,8 +131,8 @@ export const content: GpsCoordinatesConverterLocaleContent = {
131
131
  {
132
132
  type: 'list',
133
133
  items: [
134
- 'Положительная широта находится в северном полушарии; отрицательная в южном.',
135
- 'Положительная долгота находится к востоку от нулевого меридиана; отрицательная к западу.',
134
+ 'Положительная широта находится в северном полушарии; отрицательная - в южном.',
135
+ 'Положительная долгота находится к востоку от нулевого меридиана; отрицательная - к западу.',
136
136
  ],
137
137
  },
138
138
  {
@@ -142,7 +142,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
142
142
  },
143
143
  {
144
144
  type: 'paragraph',
145
- html: 'Это традиционный формат, используемый в морской и воздушной навигации, а также на старых топографических картах (например, <code>40° 42\' 46.08" N, 74° 0\' 21.6" W</code>). Он более интуитивно понятен для навигации человека по печатным картам (деление Земли на 360 градусов, где каждый градус делится на 60 минут, а каждая минута на 60 секунд), но специальные символы делают его ввод в системы программирования полетов громоздким.',
145
+ html: 'Это традиционный формат, используемый в морской и воздушной навигации, а также на старых топографических картах (например, <code>40° 42\' 46.08" N, 74° 0\' 21.6" W</code>). Он более интуитивно понятен для навигации человека по печатным картам (деление Земли на 360 градусов, где каждый градус делится на 60 минут, а каждая минута - на 60 секунд), но специальные символы делают его ввод в системы программирования полетов громоздким.',
146
146
  },
147
147
  {
148
148
  type: 'title',
@@ -202,7 +202,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
202
202
  howTo: [
203
203
  {
204
204
  name: 'Определите текущий формат',
205
- text: 'Посмотрите, как выглядят ваши координаты. Если они выглядят как 40.7128, -74.0060 это DD. Если они содержат градусы, минуты и секунды (40°42\'46"N) это DMS. Если это просто большое число, например 407128000 это аппаратный (Raw) формат.',
205
+ text: 'Посмотрите, как выглядят ваши координаты. Если они выглядят как 40.7128, -74.0060 - это DD. Если они содержат градусы, минуты и секунды (40°42\'46"N) - это DMS. Если это просто большое число, например 407128000 - это аппаратный (Raw) формат.',
206
206
  },
207
207
  {
208
208
  name: 'Введите координаты',
@@ -210,11 +210,11 @@ export const content: GpsCoordinatesConverterLocaleContent = {
210
210
  },
211
211
  {
212
212
  name: 'Мгновенная конвертация',
213
- text: 'Обратите внимание на другие поля конвертер автоматически рассчитает и отобразит другие форматы в реальном времени.',
213
+ text: 'Обратите внимание на другие поля - конвертер автоматически рассчитает и отобразит другие форматы в реальном времени.',
214
214
  },
215
215
  {
216
216
  name: 'Копировать результат',
217
- text: 'Нажмите кнопку «Копировать» рядом с форматом, который вы хотите использовать, чтобы скопировать данные в буфер обмена.',
217
+ text: 'Нажмите кнопку "Копировать" рядом с форматом, который вы хотите использовать, чтобы скопировать данные в буфер обмена.',
218
218
  },
219
219
  ],
220
220
  schemas,
@@ -1,4 +1,4 @@
1
- import type { GpsCoordinatesConverterLocaleContent } from '../index';
1
+ import type { GpsCoordinatesConverterLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
3
  import { bibliography } from '../bibliography';
4
4
 
@@ -155,7 +155,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
155
155
  },
156
156
  {
157
157
  type: 'paragraph',
158
- html: '发生这种“魔变”源于电路底层最淳朴的机理 —— 单片微处理器(MCU控制器)们处理纯粹“整数(Integer)”的能力和精准度其实远比对付带有小数点位那些“浮点数(Float)”的效能要快上、强上无数倍之多。他们常常选择干脆直接把前面科普过的那个十进制标准DD里的核心值去暴增乘上个 <strong>一千万倍 (即 10,000,000 会经常被简写作 1e7)</strong>,然后就此存活并互相倒腾。我们的计算器系统能在这极度复杂的纯机械无脑大整数堆里和常人能看懂的地标数据之间无缝衔接且随意进出切换重组!绝对可以说是分析拆解深奥航点及黑匣子信息的最强利器助手。',
158
+ html: '发生这种"魔变"源于电路底层最淳朴的机理,单片微处理器(MCU控制器)们处理纯粹"整数(Integer)"的能力和精准度其实远比对付带有小数点位那些"浮点数(Float)"的效能要快上、强上无数倍之多。他们常常选择干脆直接把前面科普过的那个十进制标准DD里的核心值去暴增乘上个 <strong>一千万倍 (即 10,000,000 会经常被简写作 1e7)</strong>,然后就此存活并互相倒腾。我们的计算器系统能在这极度复杂的纯机械无脑大整数堆里和常人能看懂的地标数据之间无缝衔接且随意进出切换重组!绝对可以说是分析拆解深奥航点及黑匣子信息的最强利器助手。',
159
159
  },
160
160
  {
161
161
  type: 'title',
@@ -171,7 +171,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
171
171
  items: [
172
172
  '<strong>悲情上演炸机之后的捞机寻找大作战 (Lost Drone Recovery):</strong> 当图传雪花甚至直接黑屏后,OSD(图传屏幕信息叠加展示)界面或是像睿思博得(Radiomaster)、黑羊Taranis接收控上的最终抢救显示数据界面内,经常停留着以原始DD或是比较别扭的组合 DMS 为形态残喘的遗留断点数据。飞手在现场极其迫切迅速将其还原调拨输入回通用易打点的Google 卫星视图好去把那昂贵的电子宠物从草丛灌木堆里打救回巢。',
173
173
  '<strong>大刀阔斧的航点勘察布局 (Waypoint Mission Planning):</strong> 在使用 QGroundControl、Mission Planner(MP地面站)一类的重型武装去布局飞行大业之时,零瑕疵是它的不二底线。若是能把从传统国土地理资源库的或者地方测量处手写得来的那种满布着D M S的材料坐标通通严丝合缝转化导入到地面站内指定的数字格式系统,那就相当于给自己规划上好一道确保飞机飞完地界同时不致以跨入违法非受权空域从而招引官司警察的完美保底屏障。',
174
- '<strong>硬汉风格操作的固件底端注入:</strong> 部分对UI操控并不完善甚至硬核的机器在进行固件里手动于最基本端(CLI内)死死锁死“一键归巢指令(RTH)”标的源地时就非要认死理仅仅吃那些长如乱码、苛刻到精确至近千万分一地步那原始全长硬件型巨大整形数(Raw integer)。',
174
+ '<strong>硬汉风格操作的固件底端注入:</strong> 部分对UI操控并不完善甚至硬核的机器在进行固件里手动于最基本端(CLI内)死死锁死"一键归巢指令(RTH)"标的源地时就非要认死理仅仅吃那些长如乱码、苛刻到精确至近千万分一地步那原始全长硬件型巨大整形数(Raw integer)。',
175
175
  ],
176
176
  },
177
177
  {
@@ -214,7 +214,7 @@ export const content: GpsCoordinatesConverterLocaleContent = {
214
214
  },
215
215
  {
216
216
  name: '打包提取收获果实供去使用',
217
- text: '最后这一击就是直击于紧挨着您梦寐索求该心仪的终极样式右旁那个专有的便携提取按键上点上这这么一压,“嗒”地一下这宝贵的指令字符全数自动打包给进了我们剪贴记录里边去准备去奔袭诸如 Google地图导航框或者地面控MP里再或就是填回去向底层黑色深渊。',
217
+ text: '最后这一击就是直击于紧挨着您梦寐索求该心仪的终极样式右旁那个专有的便携提取按键上点上这这么一压,"嗒"地一下这宝贵的指令字符全数自动打包给进了我们剪贴记录里边去准备去奔袭诸如 Google地图导航框或者地面控MP里再或就是填回去向底层黑色深渊。',
218
218
  },
219
219
  ],
220
220
  schemas,
@@ -0,0 +1,108 @@
1
+ ---
2
+ const { ui } = Astro.props;
3
+ ---
4
+
5
+ <div class="column column-inputs">
6
+ <h2 class="column-title">{ui.configuration || "Configuration"}</h2>
7
+
8
+ <div class="section">
9
+ <label class="section-label">{ui.cameraSelection || "Camera Selection"}</label>
10
+ <select id="cameraPreset" class="input-field">
11
+ <option value="">{ui.manualMode || "Manual Mode"}</option>
12
+ <option value="mavic3e">{ui.presetDjiMavic3e || "DJI Mavic 3E"}</option>
13
+ <option value="matrice300">{ui.presetDjiMatrice300 || "DJI Matrice 300 RTK"}</option>
14
+ <option value="autelevoii">{ui.presetAutelEvoII || "Autel EVO II"}</option>
15
+ <option value="air3s">{ui.presetDjiAir3s || "DJI Air 3S"}</option>
16
+ </select>
17
+ </div>
18
+
19
+ <div class="section">
20
+ <label class="section-label">{ui.sensorConfig || "Sensor Configuration"}</label>
21
+ <div class="input-row">
22
+ <div class="input-item">
23
+ <span class="input-label">{ui.width || "Width"}</span>
24
+ <input id="sensorWidth" type="number" min="1" max="100" step="0.1" value="23.5" class="input-field" />
25
+ <span class="unit-hint">mm</span>
26
+ </div>
27
+ <div class="input-item">
28
+ <span class="input-label">{ui.height || "Height"}</span>
29
+ <input id="sensorHeight" type="number" min="1" max="100" step="0.1" value="15.6" class="input-field" />
30
+ <span class="unit-hint">mm</span>
31
+ </div>
32
+ </div>
33
+ </div>
34
+
35
+ <div class="section">
36
+ <label class="section-label">{ui.focalLength || "Focal Length"}</label>
37
+ <div class="input-item">
38
+ <input id="focalLength" type="number" min="1" max="1000" step="0.1" value="35" class="input-field" />
39
+ <span class="unit-hint" id="focalLengthUnit">mm</span>
40
+ </div>
41
+ </div>
42
+
43
+ <div class="section">
44
+ <label class="section-label">{ui.imageResolution || "Image Resolution"}</label>
45
+ <div class="input-row">
46
+ <div class="input-item">
47
+ <span class="input-label">{ui.w || "W"}</span>
48
+ <input id="imageWidth" type="number" min="100" max="50000" step="1" value="5472" class="input-field" />
49
+ <span class="unit-hint">{ui.px || "px"}</span>
50
+ </div>
51
+ <div class="input-item">
52
+ <span class="input-label">{ui.h || "H"}</span>
53
+ <input id="imageHeight" type="number" min="100" max="50000" step="1" value="3648" class="input-field" />
54
+ <span class="unit-hint">{ui.px || "px"}</span>
55
+ </div>
56
+ </div>
57
+ </div>
58
+
59
+ <div class="section">
60
+ <label class="section-label">{ui.altitudeAgl || "Altitude (AGL)"}</label>
61
+ <div class="input-item">
62
+ <input id="altitudeAgl" type="number" min="10" max="500" step="5" value="100" class="input-field" />
63
+ <span class="unit-hint" id="altUnit">m</span>
64
+ </div>
65
+ <input id="altitudeSlider" type="range" min="10" max="500" step="5" value="100" class="slider" />
66
+ </div>
67
+
68
+ <div class="section">
69
+ <label class="section-label">{ui.overlapSettings || "Overlap Configuration"}</label>
70
+ <div class="input-row">
71
+ <div class="input-item">
72
+ <span class="input-label">{ui.forward || "Forward"}</span>
73
+ <input id="forwardOverlap" type="number" min="0" max="95" step="5" value="75" class="input-field" />
74
+ <span class="unit-hint">%</span>
75
+ </div>
76
+ <div class="input-item">
77
+ <span class="input-label">{ui.lateral || "Lateral"}</span>
78
+ <input id="lateralOverlap" type="number" min="0" max="95" step="5" value="65" class="input-field" />
79
+ <span class="unit-hint">%</span>
80
+ </div>
81
+ </div>
82
+ </div>
83
+
84
+ <div class="section">
85
+ <label class="section-label">{ui.missionArea || "Mission Area"}</label>
86
+ <div class="input-item">
87
+ <span class="input-label">{ui.totalAreaToSurvey || "Total Area to Survey"}</span>
88
+ <input id="missionArea" type="number" min="0.1" max="10000000" step="0.1" value="100" class="input-field" />
89
+ <span class="unit-hint" id="areaInputUnit">m²</span>
90
+ <span class="unit-hint" style="font-size: 0.65rem; margin-top: 0.25rem;">{ui.hectareHint || "1 ha = 10,000 m²"}</span>
91
+ </div>
92
+ </div>
93
+
94
+ <div class="section">
95
+ <label class="section-label">{ui.inverseCalc || "Reverse Calculation"}</label>
96
+ <div class="input-item">
97
+ <span class="input-label">{ui.targetGsd || "Target GSD"}</span>
98
+ <input id="desiredGsd" type="number" min="0.1" max="50" step="0.1" value="2" class="input-field" />
99
+ <span class="unit-hint" id="desiredGsdUnit">cm/px</span>
100
+ </div>
101
+ <div class="result-box">
102
+ <span class="result-label">{ui.maxAltitude || "Max Altitude"}</span>
103
+ <span class="result-value" id="maxAltResult">0.00 m</span>
104
+ </div>
105
+ </div>
106
+
107
+ <button id="resetBtn" class="btn-secondary">{ui.reset || "Reset"}</button>
108
+ </div>
@@ -0,0 +1,90 @@
1
+ ---
2
+ const { ui } = Astro.props;
3
+ ---
4
+
5
+ <div class="column column-results">
6
+ <h2 class="column-title">{ui.results || "Results"}</h2>
7
+
8
+ <div class="result-section">
9
+ <div class="result-header">{ui.gsdResult || "Ground Sample Distance"}</div>
10
+ <div class="gsd-large">
11
+ <div class="gsd-number" id="gsdNumberLarge">0.00</div>
12
+ <div class="gsd-label" id="gsdUnitLabel">{ui.gsdUnit || "cm/px"}</div>
13
+ </div>
14
+
15
+ <div class="precision-bar">
16
+ <div class="bar-track">
17
+ <div class="bar-fill" id="scaleFill"></div>
18
+ </div>
19
+ <div class="bar-labels">
20
+ <span class="bar-label-item" title={ui.classHighPrecision}>{ui.highPrec || "High Prec."}</span>
21
+ <span class="bar-label-item" title={ui.classStandard}>{ui.standard || "Standard"}</span>
22
+ <span class="bar-label-item" title={ui.classInspection}>{ui.inspection || "Inspection"}</span>
23
+ <span class="bar-label-item" title={ui.classVisual}>{ui.visual || "Visual"}</span>
24
+ </div>
25
+ </div>
26
+
27
+ <div class="classification" id="classificationBadge">—</div>
28
+ </div>
29
+
30
+ <div class="result-section">
31
+ <div class="result-header">{ui.coveragePerImage || "Coverage per Image"}</div>
32
+ <div class="coverage-display">
33
+ <div class="coverage-stat">
34
+ <span class="stat-label">{ui.area || "Area"}</span>
35
+ <span class="stat-value" id="areaDisplay">0</span>
36
+ <span class="stat-unit" id="areaUnit">m²</span>
37
+ </div>
38
+ <div class="coverage-stat">
39
+ <span class="stat-label">{ui.spacing || "Spacing"}</span>
40
+ <span class="stat-value" id="spacingDisplay">0</span>
41
+ <span class="stat-unit" id="spacingUnit">m</span>
42
+ </div>
43
+ </div>
44
+
45
+ <svg class="coverage-visual" viewBox="0 0 220 100">
46
+ <defs>
47
+ <pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse">
48
+ <path d="M 10 0 L 0 0 0 10" fill="none" stroke="currentColor" stroke-width="0.5" opacity="0.1"/>
49
+ </pattern>
50
+ </defs>
51
+ <rect width="220" height="100" fill="url(#grid)"/>
52
+ <text x="10" y="95" font-size="8" opacity="0.4">{ui.flightDir || "Flight →"}</text>
53
+ <rect id="photo1Rect" x="20" y="30" width="80" height="40" fill="currentColor" opacity="0.25" stroke="currentColor" stroke-width="1.5" stroke-dasharray="2,2"/>
54
+ <rect id="photo2Rect" x="70" y="30" width="80" height="40" fill="currentColor" opacity="0.15" stroke="currentColor" stroke-width="1.5"/>
55
+ <rect id="overlapRect" x="70" y="30" width="30" height="40" fill="currentColor" opacity="0.4" stroke="none"/>
56
+ <text id="overlapText" x="85" y="58" font-size="9" text-anchor="middle" fill="currentColor" font-weight="bold" opacity="0.8">70%</text>
57
+ </svg>
58
+ </div>
59
+
60
+ <div class="result-section">
61
+ <div class="result-header">{ui.missionMetrics || "Mission Metrics"}</div>
62
+ <div class="metrics-display">
63
+ <div class="metric-item">
64
+ <span class="metric-label">{ui.images || "Images"}</span>
65
+ <span class="metric-number" id="totalImages">0</span>
66
+ <span class="metric-unit">{ui.shots || "shots"}</span>
67
+ </div>
68
+ <div class="metric-item">
69
+ <span class="metric-label">{ui.flightLines || "Flight Lines"}</span>
70
+ <span class="metric-number" id="flightLines">0</span>
71
+ <span class="metric-unit">{ui.lines || "lines"}</span>
72
+ </div>
73
+ <div class="metric-item">
74
+ <span class="metric-label">{ui.flightTime || "Flight Time"}</span>
75
+ <span class="metric-number" id="flightTime">0</span>
76
+ <span class="metric-unit">{ui.min || "min"}</span>
77
+ </div>
78
+ <div class="metric-item">
79
+ <span class="metric-label">{ui.dataVolume || "Data Volume"}</span>
80
+ <span class="metric-number" id="dataVolume">0</span>
81
+ <span class="metric-unit">{ui.gb || "GB"}</span>
82
+ </div>
83
+ </div>
84
+ </div>
85
+
86
+ <div id="alertsContainer" class="alerts-container"></div>
87
+
88
+ <button id="shareBtn" class="btn-primary" style="margin-bottom: 0.75rem;">{ui.copyShareLink || "Copy Share Link"}</button>
89
+ <button id="exportBtn" class="btn-secondary">{ui.downloadReport || "Download Report"}</button>
90
+ </div>
@@ -0,0 +1,6 @@
1
+ ---
2
+ import { Bibliography as BibliographyComponent } from '@jjlmoya/utils-shared';
3
+ import { bibliography } from './bibliography';
4
+ ---
5
+
6
+ <BibliographyComponent links={bibliography} />
@@ -0,0 +1,7 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ { name: 'Pix4D - Understanding Ground Sample Distance (GSD)', url: 'https://support.pix4d.com/hc/en-us/articles/202559809' },
5
+ { name: 'DJI - Photogrammetry Basics & GSD Calculator', url: 'https://enterprise-insights.dji.com/blog/ground-sample-distance' },
6
+ { name: 'OpenDroneMap - Flight Planning Guide', url: 'https://docs.opendronemap.org/flying/' }
7
+ ];