@jjlmoya/utils-sports 1.1.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.
- package/package.json +62 -0
- package/src/category/i18n/en.ts +108 -0
- package/src/category/i18n/es.ts +108 -0
- package/src/category/i18n/fr.ts +95 -0
- package/src/category/index.ts +21 -0
- package/src/category/seo.astro +15 -0
- package/src/components/PreviewNavSidebar.astro +116 -0
- package/src/components/PreviewToolbar.astro +143 -0
- package/src/data.ts +11 -0
- package/src/env.d.ts +5 -0
- package/src/index.ts +55 -0
- package/src/layouts/PreviewLayout.astro +117 -0
- package/src/pages/[locale]/[slug].astro +146 -0
- package/src/pages/[locale].astro +251 -0
- package/src/pages/index.astro +4 -0
- package/src/tests/faq_count.test.ts +19 -0
- package/src/tests/locale_completeness.test.ts +42 -0
- package/src/tests/mocks/astro_mock.js +2 -0
- package/src/tests/no_h1_in_components.test.ts +48 -0
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/seo_length.test.ts +22 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tests/tool_validation.test.ts +17 -0
- package/src/tool/gymTracker/bibliography.astro +15 -0
- package/src/tool/gymTracker/component.astro +835 -0
- package/src/tool/gymTracker/exercises.ts +28 -0
- package/src/tool/gymTracker/i18n/en.ts +225 -0
- package/src/tool/gymTracker/i18n/es.ts +225 -0
- package/src/tool/gymTracker/i18n/fr.ts +225 -0
- package/src/tool/gymTracker/index.ts +34 -0
- package/src/tool/gymTracker/logic.ts +169 -0
- package/src/tool/gymTracker/seo.astro +15 -0
- package/src/tool/gymTracker/storage.ts +43 -0
- package/src/tool/gymTracker/timer.ts +126 -0
- package/src/tool/gymTracker/types.ts +11 -0
- package/src/tool/gymTracker/ui-utils.ts +59 -0
- package/src/tool/gymTracker/ui.ts +27 -0
- package/src/tool/reactionTester/bibliography.astro +2 -0
- package/src/tool/reactionTester/component.astro +1074 -0
- package/src/tool/reactionTester/i18n/en.ts +144 -0
- package/src/tool/reactionTester/i18n/es.ts +144 -0
- package/src/tool/reactionTester/i18n/fr.ts +144 -0
- package/src/tool/reactionTester/index.ts +34 -0
- package/src/tool/reactionTester/seo.astro +12 -0
- package/src/tool/reactionTester/ui.ts +43 -0
- package/src/tool/scoreKeeper/bibliography.astro +14 -0
- package/src/tool/scoreKeeper/component.astro +858 -0
- package/src/tool/scoreKeeper/i18n/en.ts +207 -0
- package/src/tool/scoreKeeper/i18n/es.ts +207 -0
- package/src/tool/scoreKeeper/i18n/fr.ts +207 -0
- package/src/tool/scoreKeeper/index.ts +35 -0
- package/src/tool/scoreKeeper/logic.ts +275 -0
- package/src/tool/scoreKeeper/seo.astro +15 -0
- package/src/tool/scoreKeeper/sports.ts +70 -0
- package/src/tool/scoreKeeper/ui.ts +19 -0
- package/src/tool/tournamentBracket/bibliography.astro +10 -0
- package/src/tool/tournamentBracket/component.astro +1092 -0
- package/src/tool/tournamentBracket/i18n/en.ts +160 -0
- package/src/tool/tournamentBracket/i18n/es.ts +178 -0
- package/src/tool/tournamentBracket/i18n/fr.ts +160 -0
- package/src/tool/tournamentBracket/index.ts +34 -0
- package/src/tool/tournamentBracket/logic/active.controller.ts +106 -0
- package/src/tool/tournamentBracket/logic/generator.ts +71 -0
- package/src/tool/tournamentBracket/logic/manager.ts +165 -0
- package/src/tool/tournamentBracket/logic/setup.controller.ts +84 -0
- package/src/tool/tournamentBracket/logic/sharing.ts +81 -0
- package/src/tool/tournamentBracket/logic/storage.ts +56 -0
- package/src/tool/tournamentBracket/models.ts +34 -0
- package/src/tool/tournamentBracket/seo.astro +12 -0
- package/src/tool/tournamentBracket/tournament.controller.ts +65 -0
- package/src/tool/tournamentBracket/tournament.renderer.ts +45 -0
- package/src/tool/tournamentBracket/ui/bracket-desktop.ts +143 -0
- package/src/tool/tournamentBracket/ui/bracket-mobile.ts +82 -0
- package/src/tool/tournamentBracket/ui/mediator.ts +96 -0
- package/src/tool/tournamentBracket/ui/navigator.ts +84 -0
- package/src/tool/tournamentBracket/ui/setup.ts +120 -0
- package/src/tool/tournamentBracket/ui.ts +42 -0
- package/src/tools.ts +13 -0
- package/src/types.ts +72 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { ScoreKeeperUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'sports-scoreboard';
|
|
6
|
+
const title = 'Sports Scoreboard Online: Free Score Counter (2026)';
|
|
7
|
+
const description =
|
|
8
|
+
'Digital scoreboard with giant buttons for mobile. Ideal for padel, ping-pong and football. No annoying ads in the middle of the game. Simple and fast.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: 'Does it work without an internet connection?',
|
|
13
|
+
answer:
|
|
14
|
+
'Yes, once the page is loaded, the scoreboard works completely offline. You do not need data or WiFi during the match. Everything is saved locally in your browser.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'Can I use the scoreboard for tennis and padel?',
|
|
18
|
+
answer:
|
|
19
|
+
'Yes, the Tennis/Padel mode automatically handles the 15-30-40-AD sequence and keeps track of sets and games according to the official rules. Perfect for friendly matches.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'Can it be put in full screen?',
|
|
23
|
+
answer:
|
|
24
|
+
'Yes, you can activate full screen mode from your browser (F11 on PC, or the full screen button on mobile). Numbers take up 80% of the screen for maximum visibility.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: 'How do I correct a point if I make a mistake?',
|
|
28
|
+
answer:
|
|
29
|
+
'There is a separate button to subtract points on each player card. You can quickly correct mistakes without having to restart the entire scoreboard.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
question: 'Does it work for basketball with 1, 2 and 3 point baskets?',
|
|
33
|
+
answer:
|
|
34
|
+
'Yes, in Basketball mode dedicated +1, +2 and +3 buttons appear to score any play quickly without extra taps.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: 'Does the scoreboard automatically handle service in ping-pong?',
|
|
38
|
+
answer:
|
|
39
|
+
'Yes, in Ping Pong mode the service indicator rotates automatically every 2 points (or every point in deuce), following the official ITTF rules.',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const howToData = [
|
|
44
|
+
{
|
|
45
|
+
name: 'Select your sport',
|
|
46
|
+
text: 'Choose the sport from the selector at the top: Free, Tennis, Padel, Ping Pong, Volleyball or Basketball.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Customize names',
|
|
50
|
+
text: 'Tap on "HOME" or "AWAY" to change the player or team names.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Add points with one tap',
|
|
54
|
+
text: 'Tap the large scoreboard area to add a point. In basketball, use the +1, +2 or +3 buttons.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Indicate serve',
|
|
58
|
+
text: 'Use the serve button in the bottom corner to mark who is serving. The yellow indicator appears automatically.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Correct mistakes',
|
|
62
|
+
text: 'Use the "−" button if you added a point by mistake. No need to restart the entire scoreboard.',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
67
|
+
'@context': 'https://schema.org',
|
|
68
|
+
'@type': 'FAQPage',
|
|
69
|
+
mainEntity: faqData.map((item) => ({
|
|
70
|
+
'@type': 'Question',
|
|
71
|
+
name: item.question,
|
|
72
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
73
|
+
})),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const howToSchema: WithContext<HowTo> = {
|
|
77
|
+
'@context': 'https://schema.org',
|
|
78
|
+
'@type': 'HowTo',
|
|
79
|
+
name: title,
|
|
80
|
+
description,
|
|
81
|
+
step: howToData.map((step, i) => ({
|
|
82
|
+
'@type': 'HowToStep',
|
|
83
|
+
position: i + 1,
|
|
84
|
+
name: step.name,
|
|
85
|
+
text: step.text,
|
|
86
|
+
})),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
90
|
+
'@context': 'https://schema.org',
|
|
91
|
+
'@type': 'SoftwareApplication',
|
|
92
|
+
name: title,
|
|
93
|
+
description,
|
|
94
|
+
applicationCategory: 'UtilityApplication',
|
|
95
|
+
operatingSystem: 'All',
|
|
96
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
|
97
|
+
inLanguage: 'en',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const content: ToolLocaleContent<ScoreKeeperUI> = {
|
|
101
|
+
slug,
|
|
102
|
+
title,
|
|
103
|
+
description,
|
|
104
|
+
faqTitle: 'Frequently Asked Questions',
|
|
105
|
+
faq: faqData,
|
|
106
|
+
bibliographyTitle: 'Official Rules and References',
|
|
107
|
+
bibliography: [
|
|
108
|
+
{
|
|
109
|
+
name: 'ITTF: Official Table Tennis (Ping Pong) Rules',
|
|
110
|
+
url: 'https://www.ittf.com/handbook/',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'ITF: Official Tennis Rules',
|
|
114
|
+
url: 'https://www.itftennis.com/en/about-us/governance/rules-and-regulations/',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'FIP: Official Padel Regulations',
|
|
118
|
+
url: 'https://www.padelfip.com/es/regulaciones/',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'FIVB: Official Volleyball Rules',
|
|
122
|
+
url: 'https://www.fivb.com/en/volleyball/thegame_volleyball/rulesofthegame_volleyball',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'FIBA: Official Basketball Rules',
|
|
126
|
+
url: 'https://www.fiba.basketball/en/official-basketball-rules',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
howTo: howToData,
|
|
130
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
131
|
+
seo: [
|
|
132
|
+
{
|
|
133
|
+
type: 'title',
|
|
134
|
+
text: 'Your Digital Referee in Your Pocket',
|
|
135
|
+
level: 2,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'paragraph',
|
|
139
|
+
html: 'In the heat of the match, it\'s easy to lose count. "Was it 4-3 or 3-4?". This scoreboard is designed to settle those disputes before they start. With an interface of <strong>giant buttons</strong> that take up almost the entire card, you can add points without looking at the screen, just reaching out your arm to the phone on the bench.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
text: 'Smart Sport Selector',
|
|
144
|
+
level: 2,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'comparative',
|
|
148
|
+
columns: 3,
|
|
149
|
+
items: [
|
|
150
|
+
{
|
|
151
|
+
title: 'Tennis / Padel Mode',
|
|
152
|
+
description:
|
|
153
|
+
'Adapted interface with Sets and Games counters. The system automatically handles the 15-30-40-AD sequence.',
|
|
154
|
+
icon: 'mdi:tennis',
|
|
155
|
+
points: ['Official rules', 'Advantage management', 'Sets counter'],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
title: 'Basketball Mode',
|
|
159
|
+
description:
|
|
160
|
+
'The scoreboard detects the sport and changes its interface. Dedicated +1, +2 and +3 buttons.',
|
|
161
|
+
icon: 'mdi:basketball',
|
|
162
|
+
points: ['Quick triples', 'Free throws', 'No extra taps'],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
title: 'Ping Pong Mode',
|
|
166
|
+
description:
|
|
167
|
+
'Forget about memorizing whose turn it is to serve. The visual indicator rotates automatically every 2 points.',
|
|
168
|
+
icon: 'mdi:table-tennis',
|
|
169
|
+
points: ['ITTF rules', 'Serve rotation', 'Deuce mode (11 pts)'],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: 'title',
|
|
175
|
+
text: 'Features Designed for Sport',
|
|
176
|
+
level: 2,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'list',
|
|
180
|
+
items: [
|
|
181
|
+
'<strong>High Visibility Mode:</strong> Numbers that take up 80% of the screen for maximum readability in the sun.',
|
|
182
|
+
'<strong>Editable Names:</strong> Tap on "HOME" or "AWAY" to set the player names.',
|
|
183
|
+
'<strong>Error Prevention:</strong> Separate minus button to quickly correct mistakes without restarting.',
|
|
184
|
+
'<strong>Works Offline:</strong> Once loaded, no internet is needed during the match.',
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
ui: {
|
|
189
|
+
playerA: 'HOME',
|
|
190
|
+
playerB: 'AWAY',
|
|
191
|
+
swapSides: 'Swap Sides',
|
|
192
|
+
reset: 'Reset',
|
|
193
|
+
serve: 'Serve',
|
|
194
|
+
sets: 'Sets',
|
|
195
|
+
games: 'Games',
|
|
196
|
+
victory: 'VICTORY!',
|
|
197
|
+
newGame: 'New Game',
|
|
198
|
+
continueGame: 'Keep Playing',
|
|
199
|
+
resetConfirm: 'Reset scoreboard?',
|
|
200
|
+
sportSimple: 'Free (Football, Tic-Tac-Toe...)',
|
|
201
|
+
sportTennis: 'Tennis',
|
|
202
|
+
sportPadel: 'Padel',
|
|
203
|
+
sportPingpong: 'Ping Pong',
|
|
204
|
+
sportVolleyball: 'Volleyball',
|
|
205
|
+
sportBasket: 'Basketball',
|
|
206
|
+
},
|
|
207
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { ScoreKeeperUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'marcador';
|
|
6
|
+
const title = 'Marcador Deportivo Online: Contador de Puntos Gratis (2026)';
|
|
7
|
+
const description =
|
|
8
|
+
'Marcador digital con botones gigantes para móvil. Ideal para pádel, ping-pong y fútbol. Sin anuncios que molesten en mitad del partido. Simple y rápido.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: '¿Funciona sin conexión a internet?',
|
|
13
|
+
answer:
|
|
14
|
+
'Sí, una vez cargada la página, el marcador funciona completamente offline. No necesitas datos ni WiFi durante el partido. Todo se guarda localmente en tu navegador.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: '¿Puedo usar el marcador para tenis y pádel?',
|
|
18
|
+
answer:
|
|
19
|
+
'Sí, el modo Tenis/Pádel gestiona automáticamente la secuencia 15-30-40-AD y lleva la cuenta de sets y juegos según el reglamento oficial. Perfecto para partidos amistosos.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: '¿Se puede poner en pantalla completa?',
|
|
23
|
+
answer:
|
|
24
|
+
'Sí, puedes activar el modo pantalla completa desde tu navegador (F11 en PC, o botón de pantalla completa en móvil). Los números ocupan el 80% de la pantalla para máxima visibilidad.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: '¿Cómo corrijo un punto si me equivoco?',
|
|
28
|
+
answer:
|
|
29
|
+
'Hay un botón separado para restar puntos en cada tarjeta de jugador. Puedes corregir errores rápidamente sin tener que reiniciar el marcador completo.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
question: '¿Funciona para baloncesto con canastas de 1, 2 y 3 puntos?',
|
|
33
|
+
answer:
|
|
34
|
+
'Sí, en el modo Baloncesto aparecen botones dedicados de +1, +2 y +3 para anotar cualquier jugada rápidamente sin pulsaciones extra.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: '¿El marcador gestiona automáticamente el saque en ping-pong?',
|
|
38
|
+
answer:
|
|
39
|
+
'Sí, en el modo Ping Pong el indicador de saque rota automáticamente cada 2 puntos (o cada punto en deuce), siguiendo las reglas oficiales de la ITTF.',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const howToData = [
|
|
44
|
+
{
|
|
45
|
+
name: 'Selecciona tu deporte',
|
|
46
|
+
text: 'Elige el deporte desde el selector en la parte superior: Libre, Tenis, Pádel, Ping Pong, Voleibol o Baloncesto.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Personaliza los nombres',
|
|
50
|
+
text: 'Toca sobre "LOCAL" o "VISITANTE" para cambiar los nombres de los jugadores o equipos.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Suma puntos con un toque',
|
|
54
|
+
text: 'Toca la zona grande del marcador para sumar un punto. En baloncesto usa los botones +1, +2 o +3.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Indica el saque',
|
|
58
|
+
text: 'Usa el botón de saque en la esquina inferior para marcar quién saca. El indicador amarillo aparece automáticamente.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Corrige errores',
|
|
62
|
+
text: 'Usa el botón "−" si sumaste un punto por error. No es necesario reiniciar el marcador completo.',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
67
|
+
'@context': 'https://schema.org',
|
|
68
|
+
'@type': 'FAQPage',
|
|
69
|
+
mainEntity: faqData.map((item) => ({
|
|
70
|
+
'@type': 'Question',
|
|
71
|
+
name: item.question,
|
|
72
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
73
|
+
})),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const howToSchema: WithContext<HowTo> = {
|
|
77
|
+
'@context': 'https://schema.org',
|
|
78
|
+
'@type': 'HowTo',
|
|
79
|
+
name: title,
|
|
80
|
+
description,
|
|
81
|
+
step: howToData.map((step, i) => ({
|
|
82
|
+
'@type': 'HowToStep',
|
|
83
|
+
position: i + 1,
|
|
84
|
+
name: step.name,
|
|
85
|
+
text: step.text,
|
|
86
|
+
})),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
90
|
+
'@context': 'https://schema.org',
|
|
91
|
+
'@type': 'SoftwareApplication',
|
|
92
|
+
name: title,
|
|
93
|
+
description,
|
|
94
|
+
applicationCategory: 'UtilityApplication',
|
|
95
|
+
operatingSystem: 'All',
|
|
96
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
97
|
+
inLanguage: 'es',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const content: ToolLocaleContent<ScoreKeeperUI> = {
|
|
101
|
+
slug,
|
|
102
|
+
title,
|
|
103
|
+
description,
|
|
104
|
+
faqTitle: 'Preguntas Frecuentes',
|
|
105
|
+
faq: faqData,
|
|
106
|
+
bibliographyTitle: 'Referencias y Reglamentos Oficiales',
|
|
107
|
+
bibliography: [
|
|
108
|
+
{
|
|
109
|
+
name: 'ITTF: Reglamento oficial de tenis de mesa (Ping Pong)',
|
|
110
|
+
url: 'https://www.ittf.com/handbook/',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'ITF: Reglas oficiales del tenis',
|
|
114
|
+
url: 'https://www.itftennis.com/en/about-us/governance/rules-and-regulations/',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'FIP: Reglamento oficial del pádel',
|
|
118
|
+
url: 'https://www.padelfip.com/es/regulaciones/',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'FIVB: Reglas oficiales del voleibol',
|
|
122
|
+
url: 'https://www.fivb.com/en/volleyball/thegame_volleyball/rulesofthegame_volleyball',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'FIBA: Reglas oficiales del baloncesto',
|
|
126
|
+
url: 'https://www.fiba.basketball/en/official-basketball-rules',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
howTo: howToData,
|
|
130
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
131
|
+
seo: [
|
|
132
|
+
{
|
|
133
|
+
type: 'title',
|
|
134
|
+
text: 'Tu Árbitro Digital de Bolsillo',
|
|
135
|
+
level: 2,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'paragraph',
|
|
139
|
+
html: 'En el calor del partido, es fácil perder la cuenta. "¿Íbamos 4-3 o 3-4?". Este marcador está diseñado para resolver esas discusiones antes de que empiecen. Con una interfaz de <strong>botones gigantes</strong> que ocupan casi toda la tarjeta, puedes sumar puntos sin mirar la pantalla, solo estirando el brazo hacia el móvil en el banco.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
text: 'Selector de Deporte Inteligente',
|
|
144
|
+
level: 2,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'comparative',
|
|
148
|
+
columns: 3,
|
|
149
|
+
items: [
|
|
150
|
+
{
|
|
151
|
+
title: 'Modo Tenis / Pádel',
|
|
152
|
+
description:
|
|
153
|
+
'Interfaz adaptada con contadores de Sets y Juegos. El sistema gestiona automáticamente la secuencia 15-30-40-AD.',
|
|
154
|
+
icon: 'mdi:tennis',
|
|
155
|
+
points: ['Reglamento oficial', 'Gestión de Advantage', 'Contador de Sets'],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
title: 'Modo Baloncesto',
|
|
159
|
+
description:
|
|
160
|
+
'El marcador detecta el deporte y cambia su interfaz. Tendrás botones dedicados de +1, +2 y +3.',
|
|
161
|
+
icon: 'mdi:basketball',
|
|
162
|
+
points: ['Triples rápidos', 'Tiros libres', 'Sin pulsaciones extra'],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
title: 'Modo Ping Pong',
|
|
166
|
+
description:
|
|
167
|
+
'Olvídate de memorizar a quién le toca sacar. El indicador visual rota automáticamente cada 2 puntos.',
|
|
168
|
+
icon: 'mdi:table-tennis',
|
|
169
|
+
points: ['Reglas ITTF', 'Rotación de saque', 'Modo Deuce (11 pts)'],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: 'title',
|
|
175
|
+
text: 'Características Pensadas para el Deporte',
|
|
176
|
+
level: 2,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'list',
|
|
180
|
+
items: [
|
|
181
|
+
'<strong>Modo Alta Visibilidad:</strong> Números que ocupan el 80% de la pantalla para máxima legibilidad bajo el sol.',
|
|
182
|
+
'<strong>Nombres Editables:</strong> Toca sobre "LOCAL" o "VISITANTE" para poner los nombres de los jugadores.',
|
|
183
|
+
'<strong>Prevención de Errores:</strong> Botón de restar puntos separado para corregir fallos rápidamente sin reiniciar.',
|
|
184
|
+
'<strong>Funciona Offline:</strong> Una vez cargado, no necesitas internet durante el partido.',
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
ui: {
|
|
189
|
+
playerA: 'LOCAL',
|
|
190
|
+
playerB: 'VISITANTE',
|
|
191
|
+
swapSides: 'Cambiar Lado',
|
|
192
|
+
reset: 'Reiniciar',
|
|
193
|
+
serve: 'Saque',
|
|
194
|
+
sets: 'Sets',
|
|
195
|
+
games: 'Juegos',
|
|
196
|
+
victory: '¡VICTORIA!',
|
|
197
|
+
newGame: 'Nueva Partida',
|
|
198
|
+
continueGame: 'Continuar Jugando',
|
|
199
|
+
resetConfirm: '¿Reiniciar marcador?',
|
|
200
|
+
sportSimple: 'Libre (Fútbol, 3 en Raya...)',
|
|
201
|
+
sportTennis: 'Tenis',
|
|
202
|
+
sportPadel: 'Pádel',
|
|
203
|
+
sportPingpong: 'Ping Pong',
|
|
204
|
+
sportVolleyball: 'Voleibol',
|
|
205
|
+
sportBasket: 'Baloncesto',
|
|
206
|
+
},
|
|
207
|
+
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { ScoreKeeperUI } from '../ui';
|
|
4
|
+
|
|
5
|
+
const slug = 'tableau-de-score-sportif';
|
|
6
|
+
const title = 'Tableau de Score Sportif en Ligne : Compteur de Points Gratuit (2026)';
|
|
7
|
+
const description =
|
|
8
|
+
'Tableau de score numérique avec grands boutons pour mobile. Idéal pour le padel, le ping-pong et le football. Sans publicités pendant le match. Simple et rapide.';
|
|
9
|
+
|
|
10
|
+
const faqData = [
|
|
11
|
+
{
|
|
12
|
+
question: 'Fonctionne-t-il sans connexion internet ?',
|
|
13
|
+
answer:
|
|
14
|
+
'Oui, une fois la page chargée, le tableau de score fonctionne entièrement hors ligne. Vous n\'avez pas besoin de données ni de WiFi pendant le match. Tout est sauvegardé localement dans votre navigateur.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'Puis-je utiliser le tableau de score pour le tennis et le padel ?',
|
|
18
|
+
answer:
|
|
19
|
+
'Oui, le mode Tennis/Padel gère automatiquement la séquence 15-30-40-AD et comptabilise les sets et les jeux selon le règlement officiel. Parfait pour les matchs amicaux.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
question: 'Peut-il être mis en plein écran ?',
|
|
23
|
+
answer:
|
|
24
|
+
'Oui, vous pouvez activer le mode plein écran depuis votre navigateur (F11 sur PC, ou le bouton plein écran sur mobile). Les chiffres occupent 80% de l\'écran pour une visibilité maximale.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
question: 'Comment corriger un point si je me trompe ?',
|
|
28
|
+
answer:
|
|
29
|
+
'Il y a un bouton séparé pour soustraire des points sur chaque carte de joueur. Vous pouvez corriger rapidement les erreurs sans avoir à redémarrer le tableau de score complet.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
question: 'Fonctionne-t-il pour le basketball avec des paniers de 1, 2 et 3 points ?',
|
|
33
|
+
answer:
|
|
34
|
+
'Oui, en mode Basketball, des boutons dédiés +1, +2 et +3 apparaissent pour marquer n\'importe quelle action rapidement sans appuis supplémentaires.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: 'Le tableau de score gère-t-il automatiquement le service au ping-pong ?',
|
|
38
|
+
answer:
|
|
39
|
+
'Oui, en mode Ping Pong, l\'indicateur de service tourne automatiquement tous les 2 points (ou à chaque point en deuce), suivant les règles officielles de l\'ITTF.',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const howToData = [
|
|
44
|
+
{
|
|
45
|
+
name: 'Sélectionnez votre sport',
|
|
46
|
+
text: 'Choisissez le sport dans le sélecteur en haut : Libre, Tennis, Padel, Ping Pong, Volleyball ou Basketball.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Personnalisez les noms',
|
|
50
|
+
text: 'Appuyez sur "DOMICILE" ou "VISITEUR" pour changer les noms des joueurs ou des équipes.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Ajoutez des points en un toucher',
|
|
54
|
+
text: 'Appuyez sur la grande zone du tableau de score pour ajouter un point. Au basketball, utilisez les boutons +1, +2 ou +3.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'Indiquez le service',
|
|
58
|
+
text: 'Utilisez le bouton de service dans le coin inférieur pour indiquer qui sert. L\'indicateur jaune apparaît automatiquement.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'Corrigez les erreurs',
|
|
62
|
+
text: 'Utilisez le bouton "−" si vous avez ajouté un point par erreur. Il n\'est pas nécessaire de redémarrer le tableau de score complet.',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
67
|
+
'@context': 'https://schema.org',
|
|
68
|
+
'@type': 'FAQPage',
|
|
69
|
+
mainEntity: faqData.map((item) => ({
|
|
70
|
+
'@type': 'Question',
|
|
71
|
+
name: item.question,
|
|
72
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
73
|
+
})),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const howToSchema: WithContext<HowTo> = {
|
|
77
|
+
'@context': 'https://schema.org',
|
|
78
|
+
'@type': 'HowTo',
|
|
79
|
+
name: title,
|
|
80
|
+
description,
|
|
81
|
+
step: howToData.map((step, i) => ({
|
|
82
|
+
'@type': 'HowToStep',
|
|
83
|
+
position: i + 1,
|
|
84
|
+
name: step.name,
|
|
85
|
+
text: step.text,
|
|
86
|
+
})),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
90
|
+
'@context': 'https://schema.org',
|
|
91
|
+
'@type': 'SoftwareApplication',
|
|
92
|
+
name: title,
|
|
93
|
+
description,
|
|
94
|
+
applicationCategory: 'UtilityApplication',
|
|
95
|
+
operatingSystem: 'All',
|
|
96
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
97
|
+
inLanguage: 'fr',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const content: ToolLocaleContent<ScoreKeeperUI> = {
|
|
101
|
+
slug,
|
|
102
|
+
title,
|
|
103
|
+
description,
|
|
104
|
+
faqTitle: 'Questions Fréquentes',
|
|
105
|
+
faq: faqData,
|
|
106
|
+
bibliographyTitle: 'Règlements Officiels et Références',
|
|
107
|
+
bibliography: [
|
|
108
|
+
{
|
|
109
|
+
name: 'ITTF : Règlement officiel du tennis de table (Ping Pong)',
|
|
110
|
+
url: 'https://www.ittf.com/handbook/',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'ITF : Règles officielles du tennis',
|
|
114
|
+
url: 'https://www.itftennis.com/en/about-us/governance/rules-and-regulations/',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'FIP : Règlement officiel du padel',
|
|
118
|
+
url: 'https://www.padelfip.com/es/regulaciones/',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'FIVB : Règles officielles du volleyball',
|
|
122
|
+
url: 'https://www.fivb.com/en/volleyball/thegame_volleyball/rulesofthegame_volleyball',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'FIBA : Règles officielles du basketball',
|
|
126
|
+
url: 'https://www.fiba.basketball/en/official-basketball-rules',
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
howTo: howToData,
|
|
130
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
131
|
+
seo: [
|
|
132
|
+
{
|
|
133
|
+
type: 'title',
|
|
134
|
+
text: 'Votre Arbitre Numérique de Poche',
|
|
135
|
+
level: 2,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'paragraph',
|
|
139
|
+
html: 'Dans le feu du match, il est facile de perdre le compte. "On était à 4-3 ou 3-4 ?". Ce tableau de score est conçu pour régler ces disputes avant qu\'elles ne commencent. Avec une interface de <strong>grands boutons</strong> qui occupent presque toute la carte, vous pouvez ajouter des points sans regarder l\'écran, en tendant simplement le bras vers le téléphone sur le banc.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
text: 'Sélecteur de Sport Intelligent',
|
|
144
|
+
level: 2,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'comparative',
|
|
148
|
+
columns: 3,
|
|
149
|
+
items: [
|
|
150
|
+
{
|
|
151
|
+
title: 'Mode Tennis / Padel',
|
|
152
|
+
description:
|
|
153
|
+
'Interface adaptée avec compteurs de Sets et Jeux. Le système gère automatiquement la séquence 15-30-40-AD.',
|
|
154
|
+
icon: 'mdi:tennis',
|
|
155
|
+
points: ['Règlement officiel', 'Gestion des avantages', 'Compteur de sets'],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
title: 'Mode Basketball',
|
|
159
|
+
description:
|
|
160
|
+
'Le tableau de score détecte le sport et change son interface. Boutons dédiés +1, +2 et +3.',
|
|
161
|
+
icon: 'mdi:basketball',
|
|
162
|
+
points: ['Paniers à 3 pts', 'Lancers francs', 'Sans appuis superflus'],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
title: 'Mode Ping Pong',
|
|
166
|
+
description:
|
|
167
|
+
'Oubliez de mémoriser à qui le tour de servir. L\'indicateur visuel tourne automatiquement tous les 2 points.',
|
|
168
|
+
icon: 'mdi:table-tennis',
|
|
169
|
+
points: ['Règles ITTF', 'Rotation du service', 'Mode Deuce (11 pts)'],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: 'title',
|
|
175
|
+
text: 'Fonctionnalités Conçues pour le Sport',
|
|
176
|
+
level: 2,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: 'list',
|
|
180
|
+
items: [
|
|
181
|
+
'<strong>Mode Haute Visibilité :</strong> Des chiffres qui occupent 80% de l\'écran pour une lisibilité maximale en plein soleil.',
|
|
182
|
+
'<strong>Noms Modifiables :</strong> Appuyez sur "DOMICILE" ou "VISITEUR" pour définir les noms des joueurs.',
|
|
183
|
+
'<strong>Prévention des Erreurs :</strong> Bouton moins séparé pour corriger rapidement les erreurs sans redémarrer.',
|
|
184
|
+
'<strong>Fonctionne Hors Ligne :</strong> Une fois chargé, aucune connexion internet n\'est nécessaire pendant le match.',
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
ui: {
|
|
189
|
+
playerA: 'DOMICILE',
|
|
190
|
+
playerB: 'VISITEUR',
|
|
191
|
+
swapSides: 'Changer de Côté',
|
|
192
|
+
reset: 'Réinitialiser',
|
|
193
|
+
serve: 'Service',
|
|
194
|
+
sets: 'Sets',
|
|
195
|
+
games: 'Jeux',
|
|
196
|
+
victory: 'VICTOIRE !',
|
|
197
|
+
newGame: 'Nouvelle Partie',
|
|
198
|
+
continueGame: 'Continuer à Jouer',
|
|
199
|
+
resetConfirm: 'Réinitialiser le tableau de score ?',
|
|
200
|
+
sportSimple: 'Libre (Football, Morpion...)',
|
|
201
|
+
sportTennis: 'Tennis',
|
|
202
|
+
sportPadel: 'Padel',
|
|
203
|
+
sportPingpong: 'Ping Pong',
|
|
204
|
+
sportVolleyball: 'Volleyball',
|
|
205
|
+
sportBasket: 'Basketball',
|
|
206
|
+
},
|
|
207
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { SportsToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
|
|
2
|
+
import ScoreKeeperComponent from './component.astro';
|
|
3
|
+
import ScoreKeeperSEO from './seo.astro';
|
|
4
|
+
import ScoreKeeperBibliography from './bibliography.astro';
|
|
5
|
+
|
|
6
|
+
import type { ScoreKeeperUI } from './ui';
|
|
7
|
+
|
|
8
|
+
export type { ScoreKeeperUI };
|
|
9
|
+
export type ScoreKeeperLocaleContent = ToolLocaleContent<ScoreKeeperUI>;
|
|
10
|
+
|
|
11
|
+
import { content as es } from './i18n/es';
|
|
12
|
+
import { content as en } from './i18n/en';
|
|
13
|
+
import { content as fr } from './i18n/fr';
|
|
14
|
+
|
|
15
|
+
export const scoreKeeper: SportsToolEntry<ScoreKeeperUI> = {
|
|
16
|
+
id: 'score-keeper',
|
|
17
|
+
icons: {
|
|
18
|
+
bg: 'mdi:scoreboard-outline',
|
|
19
|
+
fg: 'mdi:trophy-variant-outline',
|
|
20
|
+
},
|
|
21
|
+
i18n: {
|
|
22
|
+
es: async () => es,
|
|
23
|
+
en: async () => en,
|
|
24
|
+
fr: async () => fr,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { ScoreKeeperComponent, ScoreKeeperSEO, ScoreKeeperBibliography };
|
|
29
|
+
|
|
30
|
+
export const SCORE_KEEPER_TOOL: ToolDefinition = {
|
|
31
|
+
entry: scoreKeeper,
|
|
32
|
+
Component: ScoreKeeperComponent,
|
|
33
|
+
SEOComponent: ScoreKeeperSEO,
|
|
34
|
+
BibliographyComponent: ScoreKeeperBibliography,
|
|
35
|
+
};
|