@jjlmoya/utils-nautical 1.2.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 (74) hide show
  1. package/package.json +75 -0
  2. package/src/category/i18n/en.ts +79 -0
  3. package/src/category/i18n/es.ts +79 -0
  4. package/src/category/i18n/fr.ts +79 -0
  5. package/src/category/index.ts +13 -0
  6. package/src/components/PreviewNavSidebar.astro +116 -0
  7. package/src/components/PreviewToolbar.astro +143 -0
  8. package/src/data.ts +12 -0
  9. package/src/env.d.ts +5 -0
  10. package/src/index.ts +22 -0
  11. package/src/layouts/PreviewLayout.astro +117 -0
  12. package/src/pages/[locale]/[slug].astro +146 -0
  13. package/src/pages/[locale].astro +249 -0
  14. package/src/pages/index.astro +4 -0
  15. package/src/tests/faq_count.test.ts +30 -0
  16. package/src/tests/mocks/astro_mock.js +2 -0
  17. package/src/tests/seo_length.test.ts +29 -0
  18. package/src/tests/tool_validation.test.ts +51 -0
  19. package/src/tool/endurance/bibliography.astro +14 -0
  20. package/src/tool/endurance/component.astro +310 -0
  21. package/src/tool/endurance/i18n/en.ts +243 -0
  22. package/src/tool/endurance/i18n/es.ts +249 -0
  23. package/src/tool/endurance/i18n/fr.ts +217 -0
  24. package/src/tool/endurance/index.ts +56 -0
  25. package/src/tool/endurance/logic.ts +36 -0
  26. package/src/tool/endurance/seo.astro +55 -0
  27. package/src/tool/endurance/style.css +333 -0
  28. package/src/tool/nauticalConverter/bibliography.astro +14 -0
  29. package/src/tool/nauticalConverter/component.astro +481 -0
  30. package/src/tool/nauticalConverter/i18n/en.ts +239 -0
  31. package/src/tool/nauticalConverter/i18n/es.ts +239 -0
  32. package/src/tool/nauticalConverter/i18n/fr.ts +239 -0
  33. package/src/tool/nauticalConverter/index.ts +57 -0
  34. package/src/tool/nauticalConverter/logic.ts +52 -0
  35. package/src/tool/nauticalConverter/seo.astro +52 -0
  36. package/src/tool/nauticalConverter/style.css +205 -0
  37. package/src/tool/sailArea/bibliography.astro +14 -0
  38. package/src/tool/sailArea/component.astro +418 -0
  39. package/src/tool/sailArea/i18n/en.ts +275 -0
  40. package/src/tool/sailArea/i18n/es.ts +275 -0
  41. package/src/tool/sailArea/i18n/fr.ts +275 -0
  42. package/src/tool/sailArea/index.ts +53 -0
  43. package/src/tool/sailArea/logic.ts +55 -0
  44. package/src/tool/sailArea/seo.astro +52 -0
  45. package/src/tool/sailArea/style.css +351 -0
  46. package/src/tool/speedConverter/bibliography.astro +14 -0
  47. package/src/tool/speedConverter/component.astro +125 -0
  48. package/src/tool/speedConverter/i18n/en.ts +271 -0
  49. package/src/tool/speedConverter/i18n/es.ts +271 -0
  50. package/src/tool/speedConverter/i18n/fr.ts +271 -0
  51. package/src/tool/speedConverter/index.ts +46 -0
  52. package/src/tool/speedConverter/logic.ts +48 -0
  53. package/src/tool/speedConverter/seo.astro +43 -0
  54. package/src/tool/speedConverter/style.css +239 -0
  55. package/src/tool/tideCalculator/bibliography.astro +14 -0
  56. package/src/tool/tideCalculator/component.astro +314 -0
  57. package/src/tool/tideCalculator/i18n/en.ts +203 -0
  58. package/src/tool/tideCalculator/i18n/es.ts +225 -0
  59. package/src/tool/tideCalculator/i18n/fr.ts +190 -0
  60. package/src/tool/tideCalculator/index.ts +50 -0
  61. package/src/tool/tideCalculator/logic.ts +73 -0
  62. package/src/tool/tideCalculator/seo.astro +61 -0
  63. package/src/tool/tideCalculator/style.css +310 -0
  64. package/src/tool/underKeel/bibliography.astro +14 -0
  65. package/src/tool/underKeel/component.astro +240 -0
  66. package/src/tool/underKeel/i18n/en.ts +193 -0
  67. package/src/tool/underKeel/i18n/es.ts +206 -0
  68. package/src/tool/underKeel/i18n/fr.ts +193 -0
  69. package/src/tool/underKeel/index.ts +49 -0
  70. package/src/tool/underKeel/logic.ts +83 -0
  71. package/src/tool/underKeel/seo.astro +46 -0
  72. package/src/tool/underKeel/style.css +312 -0
  73. package/src/tools.ts +25 -0
  74. package/src/types.ts +69 -0
@@ -0,0 +1,225 @@
1
+ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import type { TideCalculatorUI, TideCalculatorLocaleContent } from '../index';
3
+
4
+ const slug = 'calculadora-altura-marea';
5
+ const title = 'Calculadora de Altura de Marea';
6
+ const description =
7
+ 'Estima el nivel del agua en cualquier instante del ciclo mareal utilizando el metodo nautico de la Regla de los Dozavos. Ideal para planificacion costera y estudio del PER.';
8
+
9
+ const ui: TideCalculatorUI = {
10
+ parametersLabel: 'Parametros',
11
+ highTideLabel: 'Pleamar',
12
+ lowTideLabel: 'Bajamar',
13
+ targetTimeLabel: 'Hora de consulta',
14
+ estimatedHeightLabel: 'Altura Estimada',
15
+ metersLabel: 'metros',
16
+ amplitudeLabel: 'Amplitud',
17
+ durationLabel: 'Duracion',
18
+ tableBreakdownLabel: 'Desglose por Dozavos',
19
+ tableHourLabel: 'Hora',
20
+ tableStateLabel: 'Estado',
21
+ tableStartLabel: 'Inicio',
22
+ tableEndLabel: 'Final',
23
+ statusUpLabel: 'Subiendo',
24
+ statusDownLabel: 'Bajando',
25
+ statusOutOfRange: 'Fuera de rango',
26
+ faqTitle: 'Preguntas Frecuentes',
27
+ bibliographyTitle: 'Referencias Bibliograficas',
28
+ };
29
+
30
+ const faq: TideCalculatorLocaleContent['faq'] = [
31
+ {
32
+ question: '¿Que es la Regla de los Dozavos y para que sirve?',
33
+ answer:
34
+ 'La Regla de los Dozavos es un metodo matematico simplificado utilizado en nautica para estimar la altura de la marea en cualquier momento entre la pleamar y la bajamar. Se basa en que el flujo del agua sigue una curva sinusoidal aproximada, dividiendo la amplitud total en 12 partes repartidas en 6 horas (1/12, 2/12, 3/12, 3/12, 2/12, 1/12).',
35
+ },
36
+ {
37
+ question: '¿Es fiable este metodo para la navegacion real?',
38
+ answer:
39
+ 'Es un metodo de estimacion teorica muy util para planificacion rapida y fines educativos. Sin embargo, no tiene en cuenta factores meteorologicos como la presion atmosferica o el viento, que pueden alterar el nivel del mar varios decimetros. Para navegacion real, consulta siempre las tablas oficiales de Puertos del Estado.',
40
+ },
41
+ {
42
+ question: '¿Que datos necesito para calcular la altura de la marea?',
43
+ answer:
44
+ 'Necesitas conocer la hora y la altura (en metros) de la pleamar y la bajamar mas cercanas al momento que quieres consultar. Estos datos se encuentran en los anuarios de mareas o aplicaciones meteorologicas marinas.',
45
+ },
46
+ {
47
+ question: '¿Por que la marea no sube siempre a la misma velocidad?',
48
+ answer:
49
+ 'Debido a la inercia de las grandes masas de agua y la configuracion de las cuencas oceanicas. La marea comienza a subir lentamente tras la bajamar, alcanza su velocidad maxima en las horas centrales (las horas del 3/12) y vuelve a frenarse al aproximarse a la pleamar.',
50
+ },
51
+ {
52
+ question: '¿Como afecta la presion atmosferica a la marea?',
53
+ answer:
54
+ 'La presion alta (anticiclon) empuja el agua hacia abajo, reduciendo la altura real. La presion baja (borrasca) permite que el agua suba mas. Por norma general, una variacion de 1 hPa respecto a la media supone un cambio de aproximadamente 1 cm en el nivel del mar.',
55
+ },
56
+ {
57
+ question: '¿Que es la amplitud de marea?',
58
+ answer:
59
+ 'Es la diferencia vertical de altura entre una pleamar y la bajamar inmediatamente anterior o posterior. Esta medida varia segun la fase lunar (mareas vivas y muertas) y la ubicacion geografica.',
60
+ },
61
+ ];
62
+
63
+ const howTo: TideCalculatorLocaleContent['howTo'] = [
64
+ {
65
+ name: 'Identifica la pleamar y bajamar',
66
+ text: 'Consulta tu anuario de mareas para obtener las horas y alturas del ciclo de marea que te interesa.',
67
+ },
68
+ {
69
+ name: 'Introduce los datos en la calculadora',
70
+ text: 'Ingresa la hora y altura de la pleamar y la bajamar. La herramienta determinara la duracion y amplitud automaticamente.',
71
+ },
72
+ {
73
+ name: 'Establece la hora de consulta',
74
+ text: 'Ajusta la hora para la que deseas conocer el nivel del agua. Veras el punto exacto resaltado en la grafica.',
75
+ },
76
+ {
77
+ name: 'Analiza la tabla de dozavos',
78
+ text: 'Revisa el desglose hora por hora para entender como fluctuara el nivel del agua durante todo el periodo.',
79
+ },
80
+ ];
81
+
82
+ const bibliography: TideCalculatorLocaleContent['bibliography'] = [
83
+ {
84
+ name: 'Puertos del Estado - Prediccion de Mareas',
85
+ url: 'https://portus.puertos.es/#/',
86
+ },
87
+ {
88
+ name: 'Instituto Hidrografico de la Marina',
89
+ url: 'https://armada.defensa.gob.es/ihm/',
90
+ },
91
+ ];
92
+
93
+ const seo: TideCalculatorLocaleContent['seo'] = [
94
+ {
95
+ type: 'title',
96
+ text: 'Dominando la Marea: La Regla de los Dozavos en la Navegacion',
97
+ level: 2,
98
+ },
99
+ {
100
+ type: 'paragraph',
101
+ html: 'La navegacion costera y la entrada en puertos con calado restringido requieren un conocimiento preciso de la altura del agua en cada momento. Aunque hoy en dia disponemos de aplicaciones digitales y GPS que proporcionan datos en tiempo real, la <strong>Regla de los Dozavos</strong> sigue siendo una herramienta fundamental en la formacion de cualquier patron de embarcacion de recreo (PER) o capitan de yate. Esta regla es un metodo de estimacion matematica que permite calcular, de forma aproximada y sin necesidad de calculadoras complejas, la altura de la marea en cualquier punto de un ciclo mareal.',
102
+ },
103
+ {
104
+ type: 'title',
105
+ text: '¿Que es exactamente la Regla de los Dozavos?',
106
+ level: 3,
107
+ },
108
+ {
109
+ type: 'paragraph',
110
+ html: 'La Regla de los Dozavos se basa en la observacion de que el flujo de la marea no es constante. El agua no sube ni baja a la misma velocidad durante las seis horas (aproximadamente) que dura el periodo entre una pleamar y una bajamar. En su lugar, el movimiento sigue una curva sinusoidal. Durante la primera hora, la marea se mueve lentamente; acelera en las horas centrales y vuelve a frenar a medida que se acerca al siguiente extremo.',
111
+ },
112
+ {
113
+ type: 'table',
114
+ headers: ['Hora del Ciclo', 'Proporcion', 'Estado del Flujo'],
115
+ rows: [
116
+ ['<strong>1ª Hora</strong>', '1/12 de la amplitud', 'Inicio lento (Repunte)'],
117
+ ['<strong>2ª Hora</strong>', '2/12 de la amplitud', 'Aceleracion del flujo'],
118
+ ['<strong>3ª Hora</strong>', '3/12 de la amplitud', 'Flujo maximo (Corriente fuerte)'],
119
+ ['<strong>4ª Hora</strong>', '3/12 de la amplitud', 'Mantenimiento del flujo'],
120
+ ['<strong>5ª Hora</strong>', '2/12 de la amplitud', 'Desaceleracion notable'],
121
+ ['<strong>6ª Hora</strong>', '1/12 de la amplitud', 'Frenado final (Hacia el estrepunte)'],
122
+ ],
123
+ },
124
+ {
125
+ type: 'title',
126
+ text: '¿Como utilizar esta calculadora de altura de marea?',
127
+ level: 3,
128
+ },
129
+ {
130
+ type: 'paragraph',
131
+ html: 'Nuestra herramienta automatiza este proceso para ofrecerte una visualizacion clara y rapida. Solo necesitas los datos que encontraras en cualquier anuario de mareas u oficialia de puerto: la <strong>hora y altura de la pleamar</strong>, la <strong>hora y altura de la bajamar</strong>, y la <strong>hora de consulta</strong> para la que deseas conocer la profundidad disponible.',
132
+ },
133
+ {
134
+ type: 'title',
135
+ text: 'Limitaciones tecnicas: Factores que afectan a la marea real',
136
+ level: 3,
137
+ },
138
+ {
139
+ type: 'paragraph',
140
+ html: 'Es crucial entender que ningun metodo matematico, incluida la Regla de los Dozavos, es infalible. Existen diversos factores meteorologicos que pueden alterar significativamente la altura real del agua.',
141
+ },
142
+ {
143
+ type: 'glossary',
144
+ items: [
145
+ { term: 'Presion Atmosferica', definition: 'Una borrasca eleva el nivel del mar; un anticiclon lo reduce. Por norma general, ~1 cm de variacion por cada hPa de diferencia respecto a la media.' },
146
+ { term: 'Viento costero', definition: 'Vientos sostenidos hacia la costa (onshore) pueden apilar agua y elevar la marea por encima de lo previsto en las tablas.' },
147
+ { term: 'Orografia local', definition: 'La forma de la costa, la profundidad del fondo y la presencia de estuarios o rías pueden retrasar o acelerar significativamente el flujo mareal.' },
148
+ ],
149
+ },
150
+ {
151
+ type: 'tip',
152
+ title: 'Nota de Seguridad',
153
+ html: 'Esta herramienta utiliza un metodo de estimacion matematica. No tiene en cuenta factores meteorologicos ni la orografia local. Para navegacion real, consulte siempre las tablas oficiales de Puertos del Estado.',
154
+ },
155
+ {
156
+ type: 'title',
157
+ text: 'Conceptos clave para navegantes noveles',
158
+ level: 3,
159
+ },
160
+ {
161
+ type: 'glossary',
162
+ items: [
163
+ {
164
+ term: 'Amplitud de marea',
165
+ definition: 'Diferencia vertical entre la pleamar y la bajamar. En el Cantabrico puede ser de varios metros; en el Mediterraneo es casi insignificante.',
166
+ },
167
+ {
168
+ term: 'Duracion de la marea',
169
+ definition: 'Intervalo de tiempo entre una marea alta y la siguiente marea baja. Normalmente ronda las 6 horas y 12 minutos (ciclo semidiurno).',
170
+ },
171
+ {
172
+ term: 'Cero de la carta (Datum)',
173
+ definition: 'Nivel de referencia a partir del cual se miden todas las profundidades en las cartas nauticas. Las sondas reales casi nunca son menores a las indicadas.',
174
+ },
175
+ ],
176
+ },
177
+ {
178
+ type: 'title',
179
+ text: 'Uso educativo y practico',
180
+ level: 3,
181
+ },
182
+ {
183
+ type: 'paragraph',
184
+ html: 'Esta calculadora ha sido diseñada como un recurso de apoyo para estudiantes de nautica y navegantes que buscan una forma rapida de visualizar el ciclo mareal. Al mostrar la grafica de la curva estimada, permite comprender visualmente en que fase se encuentra el puerto y con que rapidez esta cambiando la profundidad, algo esencial para decidir si es seguro fondear en una cala o si es mejor esperar a que suba la marea para entrar a puerto o cruzar un bajo.',
185
+ },
186
+ ];
187
+
188
+ const schemas: TideCalculatorLocaleContent['schemas'] = [
189
+ {
190
+ '@context': 'https://schema.org',
191
+ '@type': 'SoftwareApplication',
192
+ name: title,
193
+ description,
194
+ applicationCategory: 'UtilityApplication',
195
+ operatingSystem: 'Web',
196
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
197
+ } as WithContext<SoftwareApplication>,
198
+ {
199
+ '@context': 'https://schema.org',
200
+ '@type': 'FAQPage',
201
+ mainEntity: faq.map((item) => ({
202
+ '@type': 'Question',
203
+ name: item.question,
204
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
205
+ })),
206
+ } as WithContext<FAQPage>,
207
+ {
208
+ '@context': 'https://schema.org',
209
+ '@type': 'HowTo',
210
+ name: `Como usar: ${title}`,
211
+ step: howTo.map((s) => ({ '@type': 'HowToStep', name: s.name, text: s.text })),
212
+ } as WithContext<HowTo>,
213
+ ];
214
+
215
+ export const content: TideCalculatorLocaleContent = {
216
+ slug,
217
+ title,
218
+ description,
219
+ ui,
220
+ seo,
221
+ faq,
222
+ bibliography,
223
+ howTo,
224
+ schemas,
225
+ };
@@ -0,0 +1,190 @@
1
+ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import type { TideCalculatorUI, TideCalculatorLocaleContent } from '../index';
3
+
4
+ const slug = 'calculateur-hauteur-maree';
5
+ const title = 'Calculateur de Hauteur de Maree';
6
+ const description =
7
+ "Estimez le niveau de l'eau a n'importe quel moment du cycle de maree en utilisant la methode nautique de la Regle des Douzaines. Ideal pour la planification cotiere et l'etude du permis bateau.";
8
+
9
+ const ui: TideCalculatorUI = {
10
+ parametersLabel: 'Parametres',
11
+ highTideLabel: 'Pleine mer',
12
+ lowTideLabel: 'Basse mer',
13
+ targetTimeLabel: 'Heure de consultation',
14
+ estimatedHeightLabel: 'Hauteur estimee',
15
+ metersLabel: 'metres',
16
+ amplitudeLabel: 'Amplitude',
17
+ durationLabel: 'Duree',
18
+ tableBreakdownLabel: 'Tableau des douzaines',
19
+ tableHourLabel: 'Heure',
20
+ tableStateLabel: 'Etat',
21
+ tableStartLabel: 'Debut',
22
+ tableEndLabel: 'Fin',
23
+ statusUpLabel: 'Montante',
24
+ statusDownLabel: 'Descendante',
25
+ statusOutOfRange: 'Hors plage',
26
+ faqTitle: 'Questions Frequentes',
27
+ bibliographyTitle: 'Bibliographie',
28
+ };
29
+
30
+ const faq: TideCalculatorLocaleContent['faq'] = [
31
+ {
32
+ question: "Qu'est-ce que la Regle des Douzaines et a quoi sert-elle?",
33
+ answer:
34
+ "La Regle des Douzaines est une methode mathematique simplifiee utilisee en navigation pour estimer la hauteur de la maree a tout moment entre la pleine mer et la basse mer. Elle repose sur l'observation que le flux de maree suit une courbe sinusoidale approximative, divisant l'amplitude totale en 12 parties reparties sur 6 heures (1/12, 2/12, 3/12, 3/12, 2/12, 1/12).",
35
+ },
36
+ {
37
+ question: 'Cette methode est-elle fiable pour la navigation reelle?',
38
+ answer:
39
+ "C'est une methode d'estimation theorique tres utile pour la planification rapide et les besoins pedagogiques. Cependant, elle ne tient pas compte des facteurs meteorologiques comme la pression atmospherique ou le vent, qui peuvent modifier le niveau de la mer de plusieurs decimetres. Pour la navigation reelle, consultez toujours les tables officielles des marees.",
40
+ },
41
+ {
42
+ question: 'Quelles donnees faut-il pour calculer la hauteur de la maree?',
43
+ answer:
44
+ "Vous avez besoin de l'heure et de la hauteur (en metres) de la pleine mer et de la basse mer les plus proches du moment que vous souhaitez consulter. Ces donnees se trouvent dans les annuaires des marees ou les applications meteorologiques marines.",
45
+ },
46
+ {
47
+ question: "Pourquoi la maree ne monte-t-elle pas toujours a la meme vitesse?",
48
+ answer:
49
+ "En raison de l'inertie des grandes masses d'eau et de la configuration des bassins oceaniques. La maree commence a monter lentement apres la basse mer, atteint sa vitesse maximale dans les heures centrales (les heures du 3/12) et ralentit a nouveau en s'approchant de la pleine mer.",
50
+ },
51
+ {
52
+ question: 'Comment la pression atmospherique affecte-t-elle la maree?',
53
+ answer:
54
+ "La haute pression (anticyclone) pousse l'eau vers le bas, reduisant la hauteur reelle. La basse pression (depression) permet a l'eau de monter davantage. En regle generale, une variation de 1 hPa par rapport a la moyenne correspond a un changement d'environ 1 cm du niveau de la mer.",
55
+ },
56
+ {
57
+ question: "Qu'est-ce que le marnage?",
58
+ answer:
59
+ "C'est la difference verticale de hauteur entre une pleine mer et la basse mer immediatement precedente ou suivante. Cette mesure varie selon la phase lunaire (marees de vives-eaux et de mortes-eaux) et la situation geographique.",
60
+ },
61
+ ];
62
+
63
+ const howTo: TideCalculatorLocaleContent['howTo'] = [
64
+ {
65
+ name: 'Identifier la pleine mer et la basse mer',
66
+ text: "Consultez votre annuaire des marees pour obtenir les heures et hauteurs du cycle de maree qui vous interesse.",
67
+ },
68
+ {
69
+ name: 'Saisir les donnees dans le calculateur',
70
+ text: "Entrez l'heure et la hauteur de la pleine mer et de la basse mer. L'outil determinera automatiquement la duree et l'amplitude.",
71
+ },
72
+ {
73
+ name: "Definir l'heure de consultation",
74
+ text: "Ajustez l'heure pour laquelle vous souhaitez connaitre le niveau de l'eau. Vous verrez le point exact mis en evidence sur le graphique.",
75
+ },
76
+ {
77
+ name: 'Analyser le tableau des douzaines',
78
+ text: "Examinez la ventilation heure par heure pour comprendre comment le niveau de l'eau va fluctuer pendant toute la periode.",
79
+ },
80
+ ];
81
+
82
+ const bibliography: TideCalculatorLocaleContent['bibliography'] = [
83
+ {
84
+ name: 'Puertos del Estado - Prediction des marees',
85
+ url: 'https://portus.puertos.es/#/',
86
+ },
87
+ {
88
+ name: 'Instituto Hidrografico de la Marina',
89
+ url: 'https://armada.defensa.gob.es/ihm/',
90
+ },
91
+ ];
92
+
93
+ const seo: TideCalculatorLocaleContent['seo'] = [
94
+ {
95
+ type: 'title',
96
+ text: 'Maitriser la maree : La Regle des Douzaines en navigation',
97
+ level: 2,
98
+ },
99
+ {
100
+ type: 'paragraph',
101
+ html: "La navigation cotiere et l'entree dans des ports a tirant d'eau restreint necessitent une connaissance precise de la hauteur de l'eau a tout moment. Bien qu'aujourd'hui des applications numeriques et des GPS fournissent des donnees en temps reel, la <strong>Regle des Douzaines</strong> reste un outil fondamental dans la formation de tout skipper ou capitaine de yacht. Cette regle est une methode d'estimation mathematique qui permet de calculer, de facon approximative et sans calculatrices complexes, la hauteur de la maree a n'importe quel point d'un cycle mareal.",
102
+ },
103
+ {
104
+ type: 'title',
105
+ text: "Qu'est-ce que la Regle des Douzaines?",
106
+ level: 3,
107
+ },
108
+ {
109
+ type: 'paragraph',
110
+ html: "La Regle des Douzaines repose sur l'observation que le flux de maree n'est pas constant. L'eau ne monte ni ne descend a la meme vitesse pendant les six heures (environ) qui separent une pleine mer d'une basse mer. Le mouvement suit plutot une courbe sinusoidale. Pendant la premiere heure, la maree se deplace lentement; elle accelere dans les heures centrales et ralentit a nouveau en s'approchant de l'extremum suivant.",
111
+ },
112
+ {
113
+ type: 'table',
114
+ headers: ['Heure du cycle', 'Proportion', 'Etat du flux'],
115
+ rows: [
116
+ ['<strong>1re heure</strong>', '1/12 du marnage', 'Depart lent (Etale)'],
117
+ ['<strong>2e heure</strong>', '2/12 du marnage', 'Acceleration du flux'],
118
+ ['<strong>3e heure</strong>', '3/12 du marnage', 'Flux maximum (Courant fort)'],
119
+ ['<strong>4e heure</strong>', '3/12 du marnage', 'Flux soutenu'],
120
+ ['<strong>5e heure</strong>', '2/12 du marnage', 'Deceleration notable'],
121
+ ['<strong>6e heure</strong>', '1/12 du marnage', 'Freinage final (Vers l\'etale)'],
122
+ ],
123
+ },
124
+ {
125
+ type: 'tip',
126
+ title: 'Note de securite',
127
+ html: "Cet outil utilise une methode d'estimation mathematique. Il ne tient pas compte des facteurs meteorologiques ni de la topographie locale. Pour la navigation reelle, consultez toujours les tables officielles des marees.",
128
+ },
129
+ {
130
+ type: 'title',
131
+ text: 'Concepts cles pour les nouveaux navigateurs',
132
+ level: 3,
133
+ },
134
+ {
135
+ type: 'glossary',
136
+ items: [
137
+ {
138
+ term: 'Marnage',
139
+ definition: "Difference verticale entre la pleine mer et la basse mer. Dans le golfe de Gascogne il peut atteindre plusieurs metres; en Mediterranee il est presque negligeable.",
140
+ },
141
+ {
142
+ term: 'Duree de la maree',
143
+ definition: "Intervalle de temps entre la pleine mer et la prochaine basse mer. Environ 6 heures et 12 minutes (cycle semi-diurne).",
144
+ },
145
+ {
146
+ term: 'Zero hydrographique',
147
+ definition: "Niveau de reference a partir duquel toutes les profondeurs sur les cartes nautiques sont mesurees. Les profondeurs reelles sont presque toujours superieures.",
148
+ },
149
+ ],
150
+ },
151
+ ];
152
+
153
+ const schemas: TideCalculatorLocaleContent['schemas'] = [
154
+ {
155
+ '@context': 'https://schema.org',
156
+ '@type': 'SoftwareApplication',
157
+ name: title,
158
+ description,
159
+ applicationCategory: 'UtilityApplication',
160
+ operatingSystem: 'Web',
161
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
162
+ } as WithContext<SoftwareApplication>,
163
+ {
164
+ '@context': 'https://schema.org',
165
+ '@type': 'FAQPage',
166
+ mainEntity: faq.map((item) => ({
167
+ '@type': 'Question',
168
+ name: item.question,
169
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
170
+ })),
171
+ } as WithContext<FAQPage>,
172
+ {
173
+ '@context': 'https://schema.org',
174
+ '@type': 'HowTo',
175
+ name: `Comment utiliser : ${title}`,
176
+ step: howTo.map((s) => ({ '@type': 'HowToStep', name: s.name, text: s.text })),
177
+ } as WithContext<HowTo>,
178
+ ];
179
+
180
+ export const content: TideCalculatorLocaleContent = {
181
+ slug,
182
+ title,
183
+ description,
184
+ ui,
185
+ seo,
186
+ faq,
187
+ bibliography,
188
+ howTo,
189
+ schemas,
190
+ };
@@ -0,0 +1,50 @@
1
+ import type { NauticalToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
+ import TideCalculatorCalculator from './component.astro';
3
+ import TideCalculatorSEO from './seo.astro';
4
+ import TideCalculatorBibliography from './bibliography.astro';
5
+
6
+ export interface TideCalculatorUI {
7
+ [key: string]: string;
8
+ parametersLabel: string;
9
+ highTideLabel: string;
10
+ lowTideLabel: string;
11
+ targetTimeLabel: string;
12
+ estimatedHeightLabel: string;
13
+ metersLabel: string;
14
+ amplitudeLabel: string;
15
+ durationLabel: string;
16
+ tableBreakdownLabel: string;
17
+ tableHourLabel: string;
18
+ tableStateLabel: string;
19
+ tableStartLabel: string;
20
+ tableEndLabel: string;
21
+ statusUpLabel: string;
22
+ statusDownLabel: string;
23
+ statusOutOfRange: string;
24
+ faqTitle: string;
25
+ bibliographyTitle: string;
26
+ }
27
+
28
+ export type TideCalculatorLocaleContent = ToolLocaleContent<TideCalculatorUI>;
29
+
30
+ export const tideCalculator: NauticalToolEntry<TideCalculatorUI> = {
31
+ id: 'tide-calculator',
32
+ icons: {
33
+ bg: 'mdi:waves',
34
+ fg: 'mdi:sailing',
35
+ },
36
+ i18n: {
37
+ es: () => import('./i18n/es').then((m) => m.content),
38
+ en: () => import('./i18n/en').then((m) => m.content),
39
+ fr: () => import('./i18n/fr').then((m) => m.content),
40
+ },
41
+ };
42
+
43
+ export { TideCalculatorCalculator, TideCalculatorSEO, TideCalculatorBibliography };
44
+
45
+ export const TIDE_CALCULATOR_TOOL: ToolDefinition = {
46
+ entry: tideCalculator,
47
+ Component: TideCalculatorCalculator,
48
+ SEOComponent: TideCalculatorSEO,
49
+ BibliographyComponent: TideCalculatorBibliography,
50
+ };
@@ -0,0 +1,73 @@
1
+ export const DOZ = [1 / 12, 2 / 12, 3 / 12, 3 / 12, 2 / 12, 1 / 12] as const;
2
+
3
+ export function timeToMins(s: string): number {
4
+ const [h, m] = s.split(':').map(Number);
5
+ return h * 60 + m;
6
+ }
7
+
8
+ export function minsToTime(m: number): string {
9
+ let mins = Math.round(m) % 1440;
10
+ if (mins < 0) mins += 1440;
11
+ return `${String(Math.floor(mins / 60)).padStart(2, '0')}:${String(mins % 60).padStart(2, '0')}`;
12
+ }
13
+
14
+ export interface CyclePoint {
15
+ t: number;
16
+ h: number;
17
+ p: string;
18
+ }
19
+
20
+ export interface CycleParams {
21
+ sT: number;
22
+ dur: number;
23
+ amp: number;
24
+ sH: number;
25
+ mult: number;
26
+ }
27
+
28
+ export function generateCycle({ sT, dur, amp, sH, mult }: CycleParams): CyclePoint[] {
29
+ const step = dur / 6;
30
+ let curH = sH;
31
+ const pts: CyclePoint[] = [{ t: sT, h: sH, p: '0%' }];
32
+ let cum = 0;
33
+ for (let i = 0; i < 6; i++) {
34
+ cum += DOZ[i];
35
+ curH = sH + cum * amp * mult;
36
+ pts.push({ t: sT + step * (i + 1), h: curH, p: `${Math.round(cum * 100)}%` });
37
+ }
38
+ return pts;
39
+ }
40
+
41
+ export interface InterpolationResult {
42
+ height: number | null;
43
+ status: 'up' | 'down' | 'out';
44
+ }
45
+
46
+ export interface InterpolationParams {
47
+ tT: number;
48
+ sT: number;
49
+ dur: number;
50
+ amp: number;
51
+ sH: number;
52
+ mult: number;
53
+ }
54
+
55
+ export function interpolateHeight({
56
+ tT,
57
+ sT,
58
+ dur,
59
+ amp,
60
+ sH,
61
+ mult,
62
+ }: InterpolationParams): InterpolationResult {
63
+ const rel = tT - sT;
64
+ if (rel < 0 || rel > dur) return { height: null, status: 'out' };
65
+ const step = dur / 6;
66
+ const idx = Math.floor(rel / step);
67
+ let cum = 0;
68
+ for (let i = 0; i < idx; i++) cum += DOZ[i];
69
+ const rem = (rel % step) / step;
70
+ const curD = idx < 6 ? DOZ[idx] : 0;
71
+ const h = sH + (cum + curD * rem) * amp * mult;
72
+ return { height: h, status: mult > 0 ? 'up' : 'down' };
73
+ }
@@ -0,0 +1,61 @@
1
+ ---
2
+ import {
3
+ SEOTitle,
4
+ SEOTable,
5
+ SEOTip,
6
+ SEOCard,
7
+ SEOStats,
8
+ SEOGlossary,
9
+ SEOProsCons,
10
+ SEOSummary,
11
+ SEODiagnostic,
12
+ SEOArticle,
13
+ } from '@jjlmoya/utils-shared';
14
+ import { tideCalculator } from './index';
15
+ import type { KnownLocale } from '../../types';
16
+
17
+ interface Props {
18
+ locale?: KnownLocale;
19
+ }
20
+
21
+ const { locale = 'es' } = Astro.props;
22
+ const content = await tideCalculator.i18n[locale]?.();
23
+ if (!content) return null;
24
+
25
+ const { seo } = content;
26
+ ---
27
+
28
+ <SEOArticle>
29
+ {seo.map((section: any) => {
30
+ switch (section.type) {
31
+ case 'summary':
32
+ return <SEOSummary title={section.title} items={section.items} />;
33
+ case 'title':
34
+ return <SEOTitle title={section.text} level={section.level || 2} />;
35
+ case 'paragraph':
36
+ return <p set:html={section.html} />;
37
+ case 'stats':
38
+ return <SEOStats stats={section.items} columns={section.columns} />;
39
+ case 'card':
40
+ return <SEOCard title={section.title} icon={section.icon}><Fragment set:html={section.html} /></SEOCard>;
41
+ case 'tip':
42
+ return <SEOTip title={section.title}><Fragment set:html={section.html} /></SEOTip>;
43
+ case 'table':
44
+ return (
45
+ <SEOTable headers={section.headers}>
46
+ {section.rows.map((row: string[]) => (
47
+ <tr>{row.map((cell: string) => <td set:html={cell} />)}</tr>
48
+ ))}
49
+ </SEOTable>
50
+ );
51
+ case 'proscons':
52
+ return <SEOProsCons title={section.title} items={section.items} />;
53
+ case 'diagnostic':
54
+ return <SEODiagnostic title={section.title} icon={section.icon} type={section.variant} badge={section.badge}><Fragment set:html={section.html} /></SEODiagnostic>;
55
+ case 'glossary':
56
+ return <SEOGlossary items={section.items} />;
57
+ default:
58
+ return null;
59
+ }
60
+ })}
61
+ </SEOArticle>