@jjlmoya/utils-motor 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 +68 -0
- package/scripts/postinstall.mjs +27 -0
- package/src/category/i18n/de.ts +17 -0
- package/src/category/i18n/en.ts +17 -0
- package/src/category/i18n/es.ts +17 -0
- package/src/category/i18n/fr.ts +17 -0
- package/src/category/i18n/id.ts +17 -0
- package/src/category/i18n/it.ts +17 -0
- package/src/category/i18n/ja.ts +17 -0
- package/src/category/i18n/ko.ts +17 -0
- package/src/category/i18n/nl.ts +17 -0
- package/src/category/i18n/pl.ts +17 -0
- package/src/category/i18n/pt.ts +17 -0
- package/src/category/i18n/ru.ts +17 -0
- package/src/category/i18n/sv.ts +17 -0
- package/src/category/i18n/tr.ts +17 -0
- package/src/category/i18n/zh.ts +17 -0
- package/src/category/index.ts +24 -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/entries.ts +7 -0
- package/src/env.d.ts +5 -0
- package/src/index.ts +23 -0
- package/src/layouts/PreviewLayout.astro +117 -0
- package/src/pages/[locale]/[slug].astro +153 -0
- package/src/pages/[locale].astro +251 -0
- package/src/pages/index.astro +4 -0
- package/src/tests/diacritics_density.test.ts +118 -0
- package/src/tests/faq_count.test.ts +19 -0
- package/src/tests/i18n_coverage.test.ts +36 -0
- package/src/tests/inverted_punctuation.test.ts +84 -0
- package/src/tests/locale_completeness.test.ts +29 -0
- package/src/tests/mocks/astro_mock.js +2 -0
- package/src/tests/no_en_dash.test.ts +70 -0
- package/src/tests/no_h1_in_components.test.ts +48 -0
- package/src/tests/pagespeed_best_practices.test.ts +198 -0
- package/src/tests/schemas_fulfillment.test.ts +23 -0
- package/src/tests/script_density.test.ts +94 -0
- package/src/tests/seo_length.test.ts +23 -0
- package/src/tests/seo_parity.test.ts +60 -0
- package/src/tests/shared-test-helpers.ts +56 -0
- package/src/tests/slug_language_code_format.test.ts +23 -0
- package/src/tests/slug_uniqueness.test.ts +81 -0
- package/src/tests/spanish_leakage.test.ts +177 -0
- package/src/tests/title_quality.test.ts +55 -0
- package/src/tests/tool_exports.test.ts +34 -0
- package/src/tests/tool_validation.test.ts +17 -0
- package/src/tests/translation_copy.test.ts +125 -0
- package/src/tool/brakingDistanceCalculator/bibliography.astro +6 -0
- package/src/tool/brakingDistanceCalculator/bibliography.ts +12 -0
- package/src/tool/brakingDistanceCalculator/braking-distance-calculator.css +601 -0
- package/src/tool/brakingDistanceCalculator/component.astro +117 -0
- package/src/tool/brakingDistanceCalculator/controller.ts +114 -0
- package/src/tool/brakingDistanceCalculator/dom-views.ts +58 -0
- package/src/tool/brakingDistanceCalculator/entry.ts +30 -0
- package/src/tool/brakingDistanceCalculator/evaluator.ts +45 -0
- package/src/tool/brakingDistanceCalculator/i18n/de.ts +45 -0
- package/src/tool/brakingDistanceCalculator/i18n/en.ts +208 -0
- package/src/tool/brakingDistanceCalculator/i18n/es.ts +46 -0
- package/src/tool/brakingDistanceCalculator/i18n/factory.ts +114 -0
- package/src/tool/brakingDistanceCalculator/i18n/fr.ts +40 -0
- package/src/tool/brakingDistanceCalculator/i18n/id.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/it.ts +39 -0
- package/src/tool/brakingDistanceCalculator/i18n/ja.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/ko.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/nl.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/pl.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/pt.ts +39 -0
- package/src/tool/brakingDistanceCalculator/i18n/ru.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/sv.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/tr.ts +38 -0
- package/src/tool/brakingDistanceCalculator/i18n/zh.ts +38 -0
- package/src/tool/brakingDistanceCalculator/index.ts +10 -0
- package/src/tool/brakingDistanceCalculator/logic.test.ts +84 -0
- package/src/tool/brakingDistanceCalculator/logic.ts +82 -0
- package/src/tool/brakingDistanceCalculator/seo.astro +15 -0
- package/src/tool/brakingDistanceCalculator/storage.ts +28 -0
- package/src/tool/brakingDistanceCalculator/ui.ts +42 -0
- package/src/tools.ts +4 -0
- package/src/types.ts +72 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { renderBrakingResult, renderControlValues } from './dom-views';
|
|
2
|
+
import { evaluateBraking, evaluateSafetyDistance } from './evaluator';
|
|
3
|
+
import { calculateBrakingDistance, calculateSafetyDistanceScenario, type SpeedUnit, type VehicleType } from './logic';
|
|
4
|
+
import { loadBrakingState, saveBrakingState, type BrakingState } from './storage';
|
|
5
|
+
import type { BrakingDistanceCalculatorUI } from './ui';
|
|
6
|
+
|
|
7
|
+
function rangeValue(root: HTMLElement, id: string): number {
|
|
8
|
+
return Number(root.querySelector<HTMLInputElement>(`#${id}`)?.value ?? 0);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function selectedValue<T extends string>(root: HTMLElement, selector: string, fallback: T): T {
|
|
12
|
+
return (root.querySelector<HTMLElement>(`${selector}[aria-pressed="true"]`)?.dataset.value as T) ?? fallback;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function readState(root: HTMLElement): BrakingState {
|
|
16
|
+
return {
|
|
17
|
+
speed: rangeValue(root, 'bdc-speed'),
|
|
18
|
+
reactionTime: rangeValue(root, 'bdc-reaction-time'),
|
|
19
|
+
deceleration: rangeValue(root, 'bdc-deceleration'),
|
|
20
|
+
gradePercent: rangeValue(root, 'bdc-grade'),
|
|
21
|
+
gapSeconds: rangeValue(root, 'bdc-gap-seconds'),
|
|
22
|
+
unit: selectedValue<SpeedUnit>(root, '[data-unit-button]', 'kmh'),
|
|
23
|
+
vehicle: selectedValue<VehicleType>(root, '[data-vehicle-button]', 'car'),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function setPressed(buttons: NodeListOf<HTMLButtonElement>, active: HTMLButtonElement): void {
|
|
28
|
+
buttons.forEach((button) => button.setAttribute('aria-pressed', String(button === active)));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function applyRange(root: HTMLElement, id: string, value: number): void {
|
|
32
|
+
const input = root.querySelector<HTMLInputElement>(`#${id}`);
|
|
33
|
+
if (input && Number.isFinite(value)) input.value = String(value);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function applyChoice(root: HTMLElement, selector: string, value: string): void {
|
|
37
|
+
const buttons = root.querySelectorAll<HTMLButtonElement>(selector);
|
|
38
|
+
const active = Array.from(buttons).find((button) => button.dataset.value === value);
|
|
39
|
+
if (active) setPressed(buttons, active);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function applyState(root: HTMLElement, state: BrakingState): void {
|
|
43
|
+
applyRange(root, 'bdc-speed', state.speed);
|
|
44
|
+
applyRange(root, 'bdc-reaction-time', state.reactionTime);
|
|
45
|
+
applyRange(root, 'bdc-deceleration', state.deceleration);
|
|
46
|
+
applyRange(root, 'bdc-grade', state.gradePercent);
|
|
47
|
+
applyRange(root, 'bdc-gap-seconds', state.gapSeconds);
|
|
48
|
+
applyChoice(root, '[data-unit-button]', state.unit);
|
|
49
|
+
applyChoice(root, '[data-vehicle-button]', state.vehicle);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function update(root: HTMLElement, ui: BrakingDistanceCalculatorUI): void {
|
|
53
|
+
const state = readState(root);
|
|
54
|
+
const result = calculateBrakingDistance(state);
|
|
55
|
+
const scenario = calculateSafetyDistanceScenario(result, state.gapSeconds);
|
|
56
|
+
renderControlValues(root);
|
|
57
|
+
renderBrakingResult(
|
|
58
|
+
root,
|
|
59
|
+
{
|
|
60
|
+
result,
|
|
61
|
+
evaluation: evaluateBraking(result, state.vehicle),
|
|
62
|
+
scenario,
|
|
63
|
+
safetyEvaluation: evaluateSafetyDistance(scenario, result),
|
|
64
|
+
},
|
|
65
|
+
ui,
|
|
66
|
+
);
|
|
67
|
+
saveBrakingState(state);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function bindSimulation(root: HTMLElement): void {
|
|
71
|
+
const button = root.querySelector<HTMLButtonElement>('[data-bdc-simulate]');
|
|
72
|
+
const vehicle = root.querySelector<HTMLElement>('.bdc-vehicle');
|
|
73
|
+
button?.addEventListener('click', () => {
|
|
74
|
+
root.dataset.simulating = 'false';
|
|
75
|
+
window.requestAnimationFrame(() => {
|
|
76
|
+
root.dataset.simulating = 'true';
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
vehicle?.addEventListener('animationend', () => {
|
|
80
|
+
root.dataset.simulating = 'complete';
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function bindChoice(root: HTMLElement, selector: string, ui: BrakingDistanceCalculatorUI): void {
|
|
85
|
+
const buttons = root.querySelectorAll<HTMLButtonElement>(selector);
|
|
86
|
+
buttons.forEach((button) => button.addEventListener('click', () => {
|
|
87
|
+
setPressed(buttons, button);
|
|
88
|
+
update(root, ui);
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function bindSurface(root: HTMLElement, ui: BrakingDistanceCalculatorUI): void {
|
|
93
|
+
const buttons = root.querySelectorAll<HTMLButtonElement>('[data-surface-button]');
|
|
94
|
+
buttons.forEach((button) => button.addEventListener('click', () => {
|
|
95
|
+
setPressed(buttons, button);
|
|
96
|
+
applyRange(root, 'bdc-deceleration', Number(button.dataset.deceleration));
|
|
97
|
+
update(root, ui);
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function initBrakingDistanceCalculator(ui: BrakingDistanceCalculatorUI): void {
|
|
102
|
+
const root = document.querySelector<HTMLElement>('[data-braking-distance-calculator]');
|
|
103
|
+
if (!root) return;
|
|
104
|
+
const saved = loadBrakingState();
|
|
105
|
+
if (saved) applyState(root, saved);
|
|
106
|
+
root.querySelectorAll<HTMLInputElement>('input[type="range"]').forEach((input) => {
|
|
107
|
+
input.addEventListener('input', () => update(root, ui));
|
|
108
|
+
});
|
|
109
|
+
bindChoice(root, '[data-unit-button]', ui);
|
|
110
|
+
bindChoice(root, '[data-vehicle-button]', ui);
|
|
111
|
+
bindSurface(root, ui);
|
|
112
|
+
bindSimulation(root);
|
|
113
|
+
update(root, ui);
|
|
114
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { BrakingEvaluation, SafetyDistanceEvaluation } from './evaluator';
|
|
2
|
+
import type { BrakingResult, SafetyDistanceScenario } from './logic';
|
|
3
|
+
import type { BrakingDistanceCalculatorUI } from './ui';
|
|
4
|
+
|
|
5
|
+
interface BrakingRenderModel {
|
|
6
|
+
result: BrakingResult;
|
|
7
|
+
evaluation: BrakingEvaluation;
|
|
8
|
+
scenario: SafetyDistanceScenario;
|
|
9
|
+
safetyEvaluation: SafetyDistanceEvaluation;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function setText(root: HTMLElement, selector: string, value: string): void {
|
|
13
|
+
const element = root.querySelector<HTMLElement>(selector);
|
|
14
|
+
if (element) element.textContent = value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function formatDistance(value: number): string {
|
|
18
|
+
return `${value.toFixed(1)} m`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function renderRoad(root: HTMLElement, result: BrakingResult, scenario: SafetyDistanceScenario): void {
|
|
22
|
+
const extent = Math.max(result.totalDistance, scenario.gapDistance, 0.1) * 1.12;
|
|
23
|
+
const reactionShare = `${(result.reactionDistance / extent) * 100}%`;
|
|
24
|
+
const brakingShare = `${(result.brakingDistance / extent) * 100}%`;
|
|
25
|
+
root.style.setProperty('--bdc-reaction-share', reactionShare);
|
|
26
|
+
root.style.setProperty('--bdc-braking-share', brakingShare);
|
|
27
|
+
root.style.setProperty('--bdc-stop-share', `${(result.totalDistance / extent) * 100}%`);
|
|
28
|
+
root.style.setProperty('--bdc-gap-share', `${(scenario.gapDistance / extent) * 100}%`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function renderBrakingResult(
|
|
32
|
+
root: HTMLElement,
|
|
33
|
+
model: BrakingRenderModel,
|
|
34
|
+
ui: BrakingDistanceCalculatorUI,
|
|
35
|
+
): void {
|
|
36
|
+
const { result, evaluation, scenario, safetyEvaluation } = model;
|
|
37
|
+
setText(root, '[data-bdc-reaction]', formatDistance(result.reactionDistance));
|
|
38
|
+
setText(root, '[data-bdc-braking]', formatDistance(result.brakingDistance));
|
|
39
|
+
setText(root, '[data-bdc-total]', formatDistance(result.totalDistance));
|
|
40
|
+
setText(root, '[data-bdc-time]', `${result.totalTime.toFixed(1)} s`);
|
|
41
|
+
setText(root, '[data-bdc-status]', ui[evaluation.messageKey]);
|
|
42
|
+
setText(root, '[data-bdc-vehicle-note]', ui[evaluation.vehicleNoteKey]);
|
|
43
|
+
setText(root, '[data-bdc-gap-distance]', formatDistance(scenario.gapDistance));
|
|
44
|
+
setText(root, '[data-bdc-margin]', formatDistance(Math.abs(scenario.marginDistance)));
|
|
45
|
+
setText(root, '[data-bdc-margin-label]', scenario.marginDistance >= 0 ? ui.marginLabel : ui.shortfallLabel);
|
|
46
|
+
setText(root, '[data-bdc-gap-message]', ui[safetyEvaluation.messageKey]);
|
|
47
|
+
const gapLab = root.querySelector<HTMLElement>('.bdc-gap-lab');
|
|
48
|
+
if (gapLab) gapLab.dataset.gapStatus = safetyEvaluation.status;
|
|
49
|
+
root.dataset.status = evaluation.status;
|
|
50
|
+
root.dataset.simulating = 'false';
|
|
51
|
+
renderRoad(root, result, scenario);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function renderControlValues(root: HTMLElement): void {
|
|
55
|
+
root.querySelectorAll<HTMLInputElement>('input[type="range"]').forEach((input) => {
|
|
56
|
+
setText(root, `[data-output="${input.id}"]`, input.value);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MotorToolEntry, ToolLocaleContent } from '../../types';
|
|
2
|
+
import type { BrakingDistanceCalculatorUI } from './ui';
|
|
3
|
+
|
|
4
|
+
export type { BrakingDistanceCalculatorUI };
|
|
5
|
+
export type BrakingDistanceCalculatorLocaleContent = ToolLocaleContent<BrakingDistanceCalculatorUI>;
|
|
6
|
+
|
|
7
|
+
export const brakingDistanceCalculator: MotorToolEntry<BrakingDistanceCalculatorUI> = {
|
|
8
|
+
id: 'braking-distance-calculator',
|
|
9
|
+
icons: {
|
|
10
|
+
bg: 'mdi:car-brake-alert',
|
|
11
|
+
fg: 'mdi:road-variant',
|
|
12
|
+
},
|
|
13
|
+
i18n: {
|
|
14
|
+
de: () => import('./i18n/de').then((module) => module.content),
|
|
15
|
+
en: () => import('./i18n/en').then((module) => module.content),
|
|
16
|
+
es: () => import('./i18n/es').then((module) => module.content),
|
|
17
|
+
fr: () => import('./i18n/fr').then((module) => module.content),
|
|
18
|
+
id: () => import('./i18n/id').then((module) => module.content),
|
|
19
|
+
it: () => import('./i18n/it').then((module) => module.content),
|
|
20
|
+
ja: () => import('./i18n/ja').then((module) => module.content),
|
|
21
|
+
ko: () => import('./i18n/ko').then((module) => module.content),
|
|
22
|
+
nl: () => import('./i18n/nl').then((module) => module.content),
|
|
23
|
+
pl: () => import('./i18n/pl').then((module) => module.content),
|
|
24
|
+
pt: () => import('./i18n/pt').then((module) => module.content),
|
|
25
|
+
ru: () => import('./i18n/ru').then((module) => module.content),
|
|
26
|
+
sv: () => import('./i18n/sv').then((module) => module.content),
|
|
27
|
+
tr: () => import('./i18n/tr').then((module) => module.content),
|
|
28
|
+
zh: () => import('./i18n/zh').then((module) => module.content),
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { BrakingResult, SafetyDistanceScenario, VehicleType } from './logic';
|
|
2
|
+
|
|
3
|
+
export type BrakingStatus = 'normal' | 'warning' | 'critical';
|
|
4
|
+
|
|
5
|
+
export interface BrakingEvaluation {
|
|
6
|
+
status: BrakingStatus;
|
|
7
|
+
messageKey: 'normalMessage' | 'warningMessage' | 'criticalMessage';
|
|
8
|
+
vehicleNoteKey: 'carNote' | 'motorcycleNote';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type SafetyDistanceStatus = 'enough' | 'tight' | 'insufficient';
|
|
12
|
+
|
|
13
|
+
export interface SafetyDistanceEvaluation {
|
|
14
|
+
status: SafetyDistanceStatus;
|
|
15
|
+
messageKey: 'enoughGapMessage' | 'tightGapMessage' | 'insufficientGapMessage';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function statusFor(result: BrakingResult): BrakingStatus {
|
|
19
|
+
if (result.effectiveDeceleration <= 0.75 || result.totalDistance >= 200) return 'critical';
|
|
20
|
+
if (result.effectiveDeceleration <= 1.75 || result.totalDistance >= 100) return 'warning';
|
|
21
|
+
return 'normal';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function evaluateBraking(
|
|
25
|
+
result: BrakingResult,
|
|
26
|
+
vehicle: VehicleType,
|
|
27
|
+
): BrakingEvaluation {
|
|
28
|
+
const status = statusFor(result);
|
|
29
|
+
const messageKey = `${status}Message` as BrakingEvaluation['messageKey'];
|
|
30
|
+
const vehicleNoteKey = vehicle === 'motorcycle' ? 'motorcycleNote' : 'carNote';
|
|
31
|
+
return { status, messageKey, vehicleNoteKey };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function evaluateSafetyDistance(
|
|
35
|
+
scenario: SafetyDistanceScenario,
|
|
36
|
+
result: BrakingResult,
|
|
37
|
+
): SafetyDistanceEvaluation {
|
|
38
|
+
if (scenario.marginDistance < 0) {
|
|
39
|
+
return { status: 'insufficient', messageKey: 'insufficientGapMessage' };
|
|
40
|
+
}
|
|
41
|
+
if (scenario.marginDistance < result.totalDistance * 0.25) {
|
|
42
|
+
return { status: 'tight', messageKey: 'tightGapMessage' };
|
|
43
|
+
}
|
|
44
|
+
return { status: 'enough', messageKey: 'enoughGapMessage' };
|
|
45
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createLocalizedContent } from './factory';
|
|
2
|
+
|
|
3
|
+
export const content = createLocalizedContent({
|
|
4
|
+
locale: 'de',
|
|
5
|
+
slug: 'bremsweg-rechner',
|
|
6
|
+
title: 'Bremswegrechner für Autos und Motorräder',
|
|
7
|
+
description: 'Berechne Reaktionsweg, Bremsweg und Anhalteweg anhand von Geschwindigkeit, Reaktionszeit, Fahrbahngriff und Steigung.',
|
|
8
|
+
faqTitle: 'Häufig gestellte Fragen', bibliographyTitle: 'Quellen und Literatur',
|
|
9
|
+
ui: {
|
|
10
|
+
unitLabel: 'Einheiten', metricUnit: 'km/h', imperialUnit: 'mph', vehicleLabel: 'Fahrzeug', carLabel: 'Auto', motorcycleLabel: 'Motorrad',
|
|
11
|
+
speedLabel: 'Ausgangsgeschwindigkeit', reactionTimeLabel: 'Reaktionszeit', gradeLabel: 'Fahrbahnneigung', roadConditionLabel: 'Fahrbahngriff',
|
|
12
|
+
dryRoadLabel: 'Trocken', wetRoadLabel: 'Nass', snowRoadLabel: 'Schnee', iceRoadLabel: 'Eis', decelerationLabel: 'Angenommene Verzögerung',
|
|
13
|
+
reactionDistanceLabel: 'Reaktion', brakingDistanceLabel: 'Bremsung', totalDistanceLabel: 'Gesamter Anhalteweg', totalTimeLabel: 'Gesamte Anhaltezeit',
|
|
14
|
+
roadStartLabel: 'Gefahr erkannt', brakePointLabel: 'Bremsbeginn', stopPointLabel: 'Stillstand', safetyExperimentLabel: 'Sicherheitsabstand testen',
|
|
15
|
+
safetyExperimentHint: 'Konservatives Szenario: Der vorausfahrende Verkehr wird beim Erkennen zur festen Gefahr.', gapTimeLabel: 'Zeitlicher Abstand', availableDistanceLabel: 'Verfügbarer Weg',
|
|
16
|
+
marginLabel: 'Sicherheitsreserve', shortfallLabel: 'Fehlender Weg', simulateLabel: 'Anhalten simulieren', leadVehicleLabel: 'Vorausfahrendes Fahrzeug',
|
|
17
|
+
enoughGapMessage: 'Der berechnete Anhalteweg passt, und es bleibt etwas Reserve.', tightGapMessage: 'Der Anhalteweg passt nur knapp. Unter realen Bedingungen ist mehr Reserve nötig.',
|
|
18
|
+
insufficientGapMessage: 'Das Fahrzeug erreicht den vorausfahrenden Verkehr, bevor der berechnete Anhaltevorgang beendet ist.', advancedLabel: 'Erweiterte Bremsannahme',
|
|
19
|
+
normalMessage: 'Der berechnete Anhalteweg bleibt überschaubar, reale Bedingungen erfordern dennoch eine Sicherheitsreserve.', warningMessage: 'Der benötigte Fahrbahnabschnitt ist länger, als er vom Fahrersitz aus wirkt.',
|
|
20
|
+
criticalMessage: 'Sehr geringer Grip oder hohe Geschwindigkeit führen zu einem extremen Anhalteweg.', carNote: 'Das Verhalten eines Autos hängt von Reifen, Bremsenzustand, Beladung, ABS und Fahrbahnqualität ab.',
|
|
21
|
+
motorcycleNote: 'Beim Motorrad wirken sich außerdem Fahrtechnik, Bremsverteilung, Schräglage, Reifen und Fahrbahn aus.', estimateNotice: 'Nur eine Lernschätzung. Das Ergebnis ist weder ein garantierter Sicherheitsabstand noch ein Ersatz für Verkehrsregeln.',
|
|
22
|
+
},
|
|
23
|
+
faq: [
|
|
24
|
+
{ question: 'Was unterscheidet Reaktionsweg und Bremsweg?', answer: 'Der Reaktionsweg wird zurückgelegt, bevor die Bremsung beginnt. Der Bremsweg beginnt mit der Wirkung der Bremsen und endet im Stillstand. Beide zusammen ergeben den Anhalteweg.' },
|
|
25
|
+
{ question: 'Warum wächst der Anhalteweg mit der Geschwindigkeit so stark?', answer: 'Der Reaktionsweg steigt proportional zur Geschwindigkeit, der Bremsweg dagegen ungefähr mit ihrem Quadrat. Eine Verdopplung der Geschwindigkeit kann den Bremsanteil unter gleichen Bedingungen etwa vervierfachen.' },
|
|
26
|
+
{ question: 'Wie beeinflusst die Fahrbahnneigung das Ergebnis?', answer: 'Eine Steigung erhöht die effektive Verzögerung, ein Gefälle verringert sie. Der Rechner berücksichtigt die Neigung als Schwerkraftkomponente nach dem Aufbau des FHWA-Modells für die Anhaltesichtweite.' },
|
|
27
|
+
{ question: 'Ist das Ergebnis ein garantierter Sicherheitsabstand?', answer: 'Nein. Reifen, Bremsen, Aufmerksamkeit, Beladung, Wetter, Verschmutzung, ABS und Messfehler verändern den tatsächlichen Weg. Halte dich an die Verkehrsregeln und plane eine größere Reserve ein.' },
|
|
28
|
+
],
|
|
29
|
+
howTo: [
|
|
30
|
+
{ name: 'Einheit und Fahrzeug wählen', text: 'Wähle Kilometer oder Meilen pro Stunde und anschließend Auto oder Motorrad für den passenden Sicherheitshinweis.' },
|
|
31
|
+
{ name: 'Geschwindigkeit und Reaktionszeit einstellen', text: 'Passe beide Regler an das Szenario an, das du untersuchen möchtest.' },
|
|
32
|
+
{ name: 'Fahrbahn beschreiben', text: 'Wähle einen Gripwert, verfeinere bei Bedarf die Verzögerung und gib für eine Steigung einen positiven, für ein Gefälle einen negativen Wert ein.' },
|
|
33
|
+
{ name: 'Anhaltevorgang ablesen', text: 'Vergleiche den blauen Reaktionsabschnitt mit dem gelben Bremsabschnitt und prüfe Gesamtweg und Gesamtzeit.' },
|
|
34
|
+
{ name: 'Abstand erproben', text: 'Lege einen zeitlichen Abstand fest und starte die Simulation, um im konservativen Szenario zu sehen, ob das Fahrzeug rechtzeitig anhält.' },
|
|
35
|
+
],
|
|
36
|
+
seo: {
|
|
37
|
+
constructionTitle: 'So setzt sich der Anhalteweg zusammen', constructionText: 'Ein vollständiger Anhaltevorgang besteht aus zwei Phasen. Während <strong>Wahrnehmung und Reaktion</strong> fährt das Fahrzeug nahezu mit der Ausgangsgeschwindigkeit weiter. Danach müssen Reifen und Fahrbahn die Bewegungsenergie abbauen. Der Rechner zeigt beide Wege getrennt, damit Reaktionszeit und Bremsleistung nicht verwechselt werden.',
|
|
38
|
+
partsValue: '2 Phasen', partsLabel: 'Reaktion plus Bremsung', speedValue: 'Tempo²', speedLabel: 'Wachstum des Bremswegs', localValue: '100 % lokal', localLabel: 'Keine Fahrtdaten werden übertragen',
|
|
39
|
+
formulaTitle: 'Die Formel hinter der Schätzung', formulaText: 'Der Reaktionsweg entspricht der Geschwindigkeit in Metern pro Sekunde multipliziert mit der Reaktionszeit. Der Bremsweg ergibt sich aus dem Quadrat der Geschwindigkeit, geteilt durch die doppelte effektive Verzögerung. Darin sind Bremsannahme und Schwerkrafteinfluss der Neigung enthalten.',
|
|
40
|
+
tableHeaders: ['Eingabe', 'Auswirkung', 'Bedeutung'], tableRows: [['Geschwindigkeit', 'Beide Phasen', 'Der Bremsweg wächst ungefähr quadratisch'], ['Reaktionszeit', 'Reaktionsphase', 'Ablenkung und Müdigkeit verlängern den Weg vor dem Bremsen'], ['Verzögerung', 'Bremsphase', 'Grip, Reifen, Bremsen und Oberfläche bestimmen die mögliche Verzögerung'], ['Neigung', 'Bremsphase', 'Die Schwerkraft unterstützt die Talfahrt und bremst bergauf']],
|
|
41
|
+
presetsTitle: 'Fahrbahnwerte sind Szenarien, keine Zertifizierung', tipTitle: 'Im Zweifel konservativ rechnen', tipText: 'Trocken, nass, Schnee und Eis sind nachvollziehbare Modellannahmen. Sie prüfen weder Reifen noch Fahrbahn. Teste bei Unsicherheit eine geringere Verzögerung und eine längere Reaktionszeit und beachte die geltenden Abstandsregeln.',
|
|
42
|
+
experimentTitle: 'Den verfügbaren Abstand ausprobieren', experimentText: 'Das Experiment rechnet den gewählten Zeitabstand bei der eingestellten Geschwindigkeit in Meter um und vergleicht ihn mit dem gesamten Anhalteweg. Der vorausfahrende Verkehr wird bewusst als feste Gefahr behandelt. Das ist eine konservative Veranschaulichung, keine Vorhersage zweier bewegter Fahrzeuge.',
|
|
43
|
+
marginTitle: 'Autos und Motorräder brauchen reale Reserven', marginText: 'Das physikalische Modell veranschaulicht beide Fahrzeugarten, bildet aber kein bestimmtes Fahrzeug ab. Bremstemperatur, Reifenmischung, Lastverlagerung, ABS-Abstimmung, Fahrtechnik, Verschmutzung und Wetter können das reale Ergebnis deutlich verändern.',
|
|
44
|
+
},
|
|
45
|
+
});
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import { bibliographyEntries } from '../bibliography';
|
|
4
|
+
import type { BrakingDistanceCalculatorUI } from '../ui';
|
|
5
|
+
|
|
6
|
+
const slug = 'braking-distance-calculator';
|
|
7
|
+
const title = 'Braking Distance Calculator for Cars and Motorcycles';
|
|
8
|
+
const description =
|
|
9
|
+
'Estimate reaction, braking, and total stopping distance from speed, reaction time, road grip, and gradient for cars and motorcycles.';
|
|
10
|
+
|
|
11
|
+
const faqData = [
|
|
12
|
+
{
|
|
13
|
+
question: 'What is the difference between reaction distance and braking distance?',
|
|
14
|
+
answer:
|
|
15
|
+
'Reaction distance is the ground covered before braking begins. Braking distance starts when the brakes take effect and ends when the vehicle stops. Total stopping distance is the sum of both parts.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
question: 'Why does stopping distance grow so quickly with speed?',
|
|
19
|
+
answer:
|
|
20
|
+
'Reaction distance grows in direct proportion to speed, while braking distance grows approximately with speed squared. Doubling speed can therefore make the braking portion about four times longer under the same conditions.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
question: 'How does a road gradient change the estimate?',
|
|
24
|
+
answer:
|
|
25
|
+
'An uphill gradient adds to effective deceleration and a downhill gradient reduces it. The calculator applies the grade as a gravitational component, following the structure of the FHWA stopping sight distance model.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
question: 'Can this result be used as a guaranteed safe following distance?',
|
|
29
|
+
answer:
|
|
30
|
+
'No. Tires, brakes, rider or driver attention, load, weather, surface contamination, ABS behavior, and measurement error can all change the real distance. Use official road rules and leave a larger safety margin.',
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const howToData = [
|
|
35
|
+
{
|
|
36
|
+
name: 'Choose the speed unit and vehicle',
|
|
37
|
+
text: 'Select kilometers per hour or miles per hour, then choose car or motorcycle for the relevant safety reminder.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'Set speed and reaction time',
|
|
41
|
+
text: 'Move the speed and perception reaction time controls to match the scenario you want to explore.',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'Describe the road',
|
|
45
|
+
text: 'Choose a grip preset, refine the assumed deceleration if needed, and set a positive uphill or negative downhill gradient.',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'Read the stopping sequence',
|
|
49
|
+
text: 'Compare the blue reaction segment with the amber braking segment, then review total distance and total time.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'Experiment with the gap',
|
|
53
|
+
text: 'Set a following time gap and run the stop simulation to see whether the modeled vehicle stops before the vehicle ahead in this conservative fixed-hazard comparison.',
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
58
|
+
'@context': 'https://schema.org',
|
|
59
|
+
'@type': 'FAQPage',
|
|
60
|
+
mainEntity: faqData.map((item) => ({
|
|
61
|
+
'@type': 'Question',
|
|
62
|
+
name: item.question,
|
|
63
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
64
|
+
})),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const howToSchema: WithContext<HowTo> = {
|
|
68
|
+
'@context': 'https://schema.org',
|
|
69
|
+
'@type': 'HowTo',
|
|
70
|
+
name: title,
|
|
71
|
+
description,
|
|
72
|
+
step: howToData.map((step, index) => ({
|
|
73
|
+
'@type': 'HowToStep',
|
|
74
|
+
position: index + 1,
|
|
75
|
+
name: step.name,
|
|
76
|
+
text: step.text,
|
|
77
|
+
})),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
81
|
+
'@context': 'https://schema.org',
|
|
82
|
+
'@type': 'SoftwareApplication',
|
|
83
|
+
name: title,
|
|
84
|
+
description,
|
|
85
|
+
applicationCategory: 'UtilitiesApplication',
|
|
86
|
+
operatingSystem: 'All',
|
|
87
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
|
|
88
|
+
inLanguage: 'en',
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const content: ToolLocaleContent<BrakingDistanceCalculatorUI> = {
|
|
92
|
+
slug,
|
|
93
|
+
title,
|
|
94
|
+
description,
|
|
95
|
+
ui: {
|
|
96
|
+
unitLabel: 'Units',
|
|
97
|
+
metricUnit: 'km/h',
|
|
98
|
+
imperialUnit: 'mph',
|
|
99
|
+
vehicleLabel: 'Vehicle',
|
|
100
|
+
carLabel: 'Car',
|
|
101
|
+
motorcycleLabel: 'Motorcycle',
|
|
102
|
+
speedLabel: 'Initial speed',
|
|
103
|
+
reactionTimeLabel: 'Reaction time',
|
|
104
|
+
gradeLabel: 'Road gradient',
|
|
105
|
+
roadConditionLabel: 'Road grip preset',
|
|
106
|
+
dryRoadLabel: 'Dry',
|
|
107
|
+
wetRoadLabel: 'Wet',
|
|
108
|
+
snowRoadLabel: 'Snow',
|
|
109
|
+
iceRoadLabel: 'Ice',
|
|
110
|
+
decelerationLabel: 'Assumed deceleration',
|
|
111
|
+
reactionDistanceLabel: 'Reaction',
|
|
112
|
+
brakingDistanceLabel: 'Braking',
|
|
113
|
+
totalDistanceLabel: 'Total stopping distance',
|
|
114
|
+
totalTimeLabel: 'Total stopping time',
|
|
115
|
+
roadStartLabel: 'Hazard seen',
|
|
116
|
+
brakePointLabel: 'Brakes applied',
|
|
117
|
+
stopPointLabel: 'Full stop',
|
|
118
|
+
safetyExperimentLabel: 'Safety-distance experiment',
|
|
119
|
+
safetyExperimentHint: 'Conservative scenario: traffic ahead becomes a fixed hazard the moment you notice it.',
|
|
120
|
+
gapTimeLabel: 'Following time gap',
|
|
121
|
+
availableDistanceLabel: 'Space ahead',
|
|
122
|
+
marginLabel: 'Safety buffer',
|
|
123
|
+
shortfallLabel: 'Distance short',
|
|
124
|
+
simulateLabel: 'Run stop simulation',
|
|
125
|
+
leadVehicleLabel: 'Traffic ahead',
|
|
126
|
+
enoughGapMessage: 'The modeled stop fits, with some space left over.',
|
|
127
|
+
tightGapMessage: 'The modeled stop only just fits. Real conditions need more margin.',
|
|
128
|
+
insufficientGapMessage: 'The vehicle reaches the traffic ahead before the modeled stop is complete.',
|
|
129
|
+
advancedLabel: 'Advanced braking assumption',
|
|
130
|
+
normalMessage: 'The modeled stop remains compact, but real conditions still require a safety margin.',
|
|
131
|
+
warningMessage: 'The road consumed is longer than it feels from the driver seat.',
|
|
132
|
+
criticalMessage: 'Very low grip or high speed creates an extreme stopping distance.',
|
|
133
|
+
carNote: 'Car behavior varies with tires, brake condition, load, ABS, and surface quality.',
|
|
134
|
+
motorcycleNote: 'Motorcycle stopping also depends on rider technique, brake balance, lean, tires, and surface quality.',
|
|
135
|
+
estimateNotice: 'Educational estimate only. Never use this result as a guaranteed safe distance or a substitute for traffic rules.',
|
|
136
|
+
},
|
|
137
|
+
faq: faqData,
|
|
138
|
+
howTo: howToData,
|
|
139
|
+
schemas: [faqSchema, howToSchema, appSchema],
|
|
140
|
+
bibliography: bibliographyEntries,
|
|
141
|
+
seo: [
|
|
142
|
+
{
|
|
143
|
+
type: 'title',
|
|
144
|
+
text: 'How Total Stopping Distance Is Built',
|
|
145
|
+
level: 2,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: 'paragraph',
|
|
149
|
+
html: 'A complete stop has two distinct phases. During <strong>perception and reaction</strong>, the vehicle continues at nearly its initial speed. After the brakes act, kinetic energy must be removed through tire and road forces. This calculator shows both distances separately so the hidden reaction phase cannot be mistaken for braking performance.',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: 'stats',
|
|
153
|
+
columns: 3,
|
|
154
|
+
items: [
|
|
155
|
+
{ value: '2 parts', label: 'Reaction plus braking' },
|
|
156
|
+
{ value: 'Speed squared', label: 'Braking growth' },
|
|
157
|
+
{ value: '100% local', label: 'No trip data uploaded' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'title',
|
|
162
|
+
text: 'The Formula Behind the Estimate',
|
|
163
|
+
level: 2,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
type: 'paragraph',
|
|
167
|
+
html: 'Reaction distance is speed in meters per second multiplied by reaction time. Braking distance is speed squared divided by twice the effective deceleration. Effective deceleration combines the selected braking assumption with the gravitational effect of the gradient, so an uphill grade shortens the modeled brake phase while a downhill grade lengthens it.',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'table',
|
|
171
|
+
headers: ['Input', 'What it changes', 'Why it matters'],
|
|
172
|
+
rows: [
|
|
173
|
+
['Speed', 'Both phases', 'Braking distance grows approximately with speed squared'],
|
|
174
|
+
['Reaction time', 'Reaction phase', 'Distraction and fatigue add distance before braking'],
|
|
175
|
+
['Deceleration', 'Braking phase', 'Grip, tires, brakes, and surface affect achievable slowing'],
|
|
176
|
+
['Gradient', 'Braking phase', 'Gravity assists downhill motion and resists uphill motion'],
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
type: 'title',
|
|
181
|
+
text: 'Road Presets Are Scenarios, Not Certifications',
|
|
182
|
+
level: 2,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'tip',
|
|
186
|
+
title: 'Use the Conservative Side',
|
|
187
|
+
html: 'The dry, wet, snow, and ice controls are transparent modeling presets. They do not inspect your tires or road. If conditions are uncertain, explore a lower deceleration and a longer reaction time, then follow the official spacing rules where you drive.',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'title',
|
|
191
|
+
text: 'Experiment With the Space Ahead',
|
|
192
|
+
level: 2,
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
type: 'paragraph',
|
|
196
|
+
html: 'The safety-distance experiment converts a time gap into meters at the selected speed and compares that space with the modeled total stopping distance. The animation deliberately treats traffic ahead as a fixed hazard, making it a conservative illustration rather than a prediction of two moving vehicles.',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
type: 'title',
|
|
200
|
+
text: 'Cars and Motorcycles Need Real World Margin',
|
|
201
|
+
level: 2,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
type: 'paragraph',
|
|
205
|
+
html: 'The same physics framework can illustrate cars and motorcycles, but it cannot reproduce a specific vehicle. Brake temperature, tire compound, load transfer, ABS calibration, rider technique, road contamination, and weather can move the real result far from a clean mathematical estimate.',
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createLocalizedContent } from './factory';
|
|
2
|
+
|
|
3
|
+
export const content = createLocalizedContent({
|
|
4
|
+
locale: 'es',
|
|
5
|
+
slug: 'calculadora-distancia-frenado',
|
|
6
|
+
title: 'Calculadora de distancia de frenado para coches y motos',
|
|
7
|
+
description: 'Calcula la distancia de reacción, frenado y detención total según la velocidad, el tiempo de reacción, la adherencia y la pendiente.',
|
|
8
|
+
faqTitle: 'Preguntas frecuentes',
|
|
9
|
+
bibliographyTitle: 'Referencias bibliográficas',
|
|
10
|
+
ui: {
|
|
11
|
+
unitLabel: 'Unidades', metricUnit: 'km/h', imperialUnit: 'mph', vehicleLabel: 'Vehículo', carLabel: 'Coche', motorcycleLabel: 'Moto',
|
|
12
|
+
speedLabel: 'Velocidad inicial', reactionTimeLabel: 'Tiempo de reacción', gradeLabel: 'Pendiente de la vía', roadConditionLabel: 'Adherencia de la vía',
|
|
13
|
+
dryRoadLabel: 'Seca', wetRoadLabel: 'Mojada', snowRoadLabel: 'Nieve', iceRoadLabel: 'Hielo', decelerationLabel: 'Deceleración estimada',
|
|
14
|
+
reactionDistanceLabel: 'Reacción', brakingDistanceLabel: 'Frenado', totalDistanceLabel: 'Distancia total de detención', totalTimeLabel: 'Tiempo total de detención',
|
|
15
|
+
roadStartLabel: 'Peligro detectado', brakePointLabel: 'Inicio del frenado', stopPointLabel: 'Detención total', safetyExperimentLabel: 'Experimento de distancia de seguridad',
|
|
16
|
+
safetyExperimentHint: 'Escenario conservador: el tráfico precedente se convierte en un obstáculo fijo en cuanto lo detectas.', gapTimeLabel: 'Intervalo de seguimiento',
|
|
17
|
+
availableDistanceLabel: 'Espacio disponible', marginLabel: 'Margen de seguridad', shortfallLabel: 'Distancia insuficiente', simulateLabel: 'Simular la detención', leadVehicleLabel: 'Vehículo precedente',
|
|
18
|
+
enoughGapMessage: 'El vehículo se detiene dentro del espacio disponible y conserva cierto margen.', tightGapMessage: 'La detención cabe por muy poco. En condiciones reales necesitas más margen.',
|
|
19
|
+
insufficientGapMessage: 'El vehículo alcanza al tráfico precedente antes de completar la detención calculada.', advancedLabel: 'Hipótesis avanzada de frenado',
|
|
20
|
+
normalMessage: 'La detención calculada es relativamente corta, pero las condiciones reales exigen un margen de seguridad.', warningMessage: 'La distancia recorrida es mayor de lo que parece desde el puesto de conducción.',
|
|
21
|
+
criticalMessage: 'La escasa adherencia o una velocidad elevada producen una distancia de detención extrema.', carNote: 'El comportamiento del coche varía según los neumáticos, los frenos, la carga, el ABS y el estado de la vía.',
|
|
22
|
+
motorcycleNote: 'En una moto también influyen la técnica, el reparto de frenada, la inclinación, los neumáticos y el firme.', estimateNotice: 'Cálculo exclusivamente educativo. No lo utilices como distancia segura garantizada ni como sustituto de las normas de circulación.',
|
|
23
|
+
},
|
|
24
|
+
faq: [
|
|
25
|
+
{ question: '¿Qué diferencia hay entre distancia de reacción y distancia de frenado?', answer: 'La distancia de reacción es la recorrida antes de empezar a frenar. La distancia de frenado comienza cuando actúan los frenos y termina al detenerse el vehículo. La distancia total de detención es la suma de ambas.' },
|
|
26
|
+
{ question: '¿Por qué aumenta tan deprisa la distancia de detención con la velocidad?', answer: 'La distancia de reacción crece de forma proporcional a la velocidad, mientras que la de frenado lo hace aproximadamente con el cuadrado de la velocidad. En las mismas condiciones, duplicar la velocidad puede cuadruplicar la parte correspondiente al frenado.' },
|
|
27
|
+
{ question: '¿Cómo afecta la pendiente al cálculo?', answer: 'Una pendiente ascendente aumenta la deceleración efectiva y una descendente la reduce. La calculadora incorpora la pendiente como componente gravitatoria siguiendo la estructura del modelo de distancia de visibilidad de parada de la FHWA.' },
|
|
28
|
+
{ question: '¿Puedo considerar el resultado una distancia de seguridad garantizada?', answer: 'No. Los neumáticos, los frenos, la atención, la carga, el tiempo, la suciedad del firme, el ABS y los errores de medición pueden alterar la distancia real. Respeta siempre la normativa y deja un margen mayor.' },
|
|
29
|
+
],
|
|
30
|
+
howTo: [
|
|
31
|
+
{ name: 'Elige las unidades y el vehículo', text: 'Selecciona kilómetros o millas por hora y después coche o moto para mostrar la advertencia correspondiente.' },
|
|
32
|
+
{ name: 'Ajusta la velocidad y la reacción', text: 'Mueve los controles de velocidad y tiempo de percepción-reacción para representar el escenario que quieres estudiar.' },
|
|
33
|
+
{ name: 'Describe el estado de la vía', text: 'Elige un nivel de adherencia, ajusta la deceleración si lo necesitas e indica una pendiente positiva en subida o negativa en bajada.' },
|
|
34
|
+
{ name: 'Interpreta la secuencia de detención', text: 'Compara el tramo azul de reacción con el tramo ámbar de frenado y revisa la distancia y el tiempo totales.' },
|
|
35
|
+
{ name: 'Experimenta con la separación', text: 'Define un intervalo de seguimiento y ejecuta la simulación para comprobar si el vehículo se detiene antes de alcanzar al precedente en este escenario conservador.' },
|
|
36
|
+
],
|
|
37
|
+
seo: {
|
|
38
|
+
constructionTitle: 'Cómo se compone la distancia total de detención', constructionText: 'Una detención completa tiene dos fases. Durante la <strong>percepción y reacción</strong>, el vehículo continúa casi a la velocidad inicial. Cuando actúan los frenos, la energía cinética se disipa mediante las fuerzas entre neumáticos y calzada. La calculadora separa ambas distancias para no confundir el tiempo de reacción con la capacidad de frenado.',
|
|
39
|
+
partsValue: '2 fases', partsLabel: 'Reacción más frenado', speedValue: 'Velocidad²', speedLabel: 'Crecimiento del frenado', localValue: '100 % local', localLabel: 'No se envían datos del trayecto',
|
|
40
|
+
formulaTitle: 'La fórmula utilizada', formulaText: 'La distancia de reacción es la velocidad en metros por segundo multiplicada por el tiempo de reacción. La distancia de frenado es la velocidad al cuadrado dividida entre el doble de la deceleración efectiva. Esta última combina la frenada estimada con el efecto gravitatorio de la pendiente.',
|
|
41
|
+
tableHeaders: ['Dato', 'Qué modifica', 'Por qué importa'], tableRows: [['Velocidad', 'Ambas fases', 'La distancia de frenado crece aproximadamente con su cuadrado'], ['Tiempo de reacción', 'Fase de reacción', 'La distracción y la fatiga añaden metros antes de frenar'], ['Deceleración', 'Fase de frenado', 'Depende de la adherencia, los neumáticos, los frenos y el firme'], ['Pendiente', 'Fase de frenado', 'La gravedad favorece la bajada y se opone a la subida']],
|
|
42
|
+
presetsTitle: 'Los estados de la vía son escenarios, no certificados', tipTitle: 'Adopta un criterio conservador', tipText: 'Los ajustes de seco, mojado, nieve y hielo son hipótesis transparentes. No inspeccionan tus neumáticos ni la calzada. Si hay incertidumbre, prueba una deceleración menor y un tiempo de reacción mayor, y aplica siempre las reglas oficiales.',
|
|
43
|
+
experimentTitle: 'Experimenta con el espacio disponible', experimentText: 'El experimento convierte el intervalo temporal elegido en metros a la velocidad indicada y lo compara con la distancia total de detención. La animación trata deliberadamente el tráfico precedente como un obstáculo fijo: es una representación conservadora, no una predicción de dos vehículos en movimiento.',
|
|
44
|
+
marginTitle: 'Coches y motos necesitan margen real', marginText: 'El mismo modelo físico sirve para ilustrar coches y motos, pero no reproduce un vehículo concreto. La temperatura de los frenos, el compuesto del neumático, la transferencia de carga, el ABS, la técnica de conducción, la suciedad y el tiempo pueden alejar el resultado real del cálculo ideal.',
|
|
45
|
+
},
|
|
46
|
+
});
|