@jjlmoya/utils-chrono 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.
- package/package.json +65 -0
- package/scripts/postinstall.mjs +27 -0
- package/src/category/ChronoCategorySEO.astro +8 -0
- package/src/category/i18n/de.ts +23 -0
- package/src/category/i18n/en.ts +23 -0
- package/src/category/i18n/es.ts +23 -0
- package/src/category/i18n/fr.ts +23 -0
- package/src/category/i18n/id.ts +23 -0
- package/src/category/i18n/it.ts +23 -0
- package/src/category/i18n/ja.ts +23 -0
- package/src/category/i18n/ko.ts +23 -0
- package/src/category/i18n/nl.ts +23 -0
- package/src/category/i18n/pl.ts +23 -0
- package/src/category/i18n/pt.ts +23 -0
- package/src/category/i18n/ru.ts +23 -0
- package/src/category/i18n/sv.ts +23 -0
- package/src/category/i18n/tr.ts +23 -0
- package/src/category/i18n/zh.ts +23 -0
- package/src/category/index.ts +42 -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 +32 -0
- package/src/env.d.ts +5 -0
- package/src/index.ts +28 -0
- package/src/layouts/PreviewLayout.astro +117 -0
- package/src/pages/[locale]/[slug].astro +161 -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/i18n_coverage.test.ts +36 -0
- package/src/tests/locale_completeness.test.ts +29 -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/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/title_quality.test.ts +55 -0
- package/src/tests/tool_exports.test.ts +34 -0
- package/src/tests/tool_validation.test.ts +18 -0
- package/src/tool/beat-rate-converter/beat-rate-converter.css +301 -0
- package/src/tool/beat-rate-converter/bibliography.astro +16 -0
- package/src/tool/beat-rate-converter/bibliography.ts +12 -0
- package/src/tool/beat-rate-converter/client.ts +46 -0
- package/src/tool/beat-rate-converter/component.astro +15 -0
- package/src/tool/beat-rate-converter/components/ConverterPanel.astro +87 -0
- package/src/tool/beat-rate-converter/entry.ts +42 -0
- package/src/tool/beat-rate-converter/i18n/de.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/en.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/es.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/fr.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/id.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/it.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/ja.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/ko.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/nl.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/pl.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/pt.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/ru.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/sv.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/tr.ts +138 -0
- package/src/tool/beat-rate-converter/i18n/zh.ts +138 -0
- package/src/tool/beat-rate-converter/index.ts +11 -0
- package/src/tool/beat-rate-converter/seo.astro +16 -0
- package/src/tool/crown-reference-guide/bibliography.astro +16 -0
- package/src/tool/crown-reference-guide/bibliography.ts +20 -0
- package/src/tool/crown-reference-guide/client.ts +193 -0
- package/src/tool/crown-reference-guide/component.astro +69 -0
- package/src/tool/crown-reference-guide/components/CrownView.astro +40 -0
- package/src/tool/crown-reference-guide/components/MovementSelector.astro +26 -0
- package/src/tool/crown-reference-guide/components/PositionPanel.astro +59 -0
- package/src/tool/crown-reference-guide/crown-reference-guide.css +383 -0
- package/src/tool/crown-reference-guide/entry.ts +60 -0
- package/src/tool/crown-reference-guide/i18n/de.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/en.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/es.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/fr.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/id.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/it.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/ja.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/ko.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/nl.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/pl.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/pt.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/ru.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/sv.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/tr.ts +207 -0
- package/src/tool/crown-reference-guide/i18n/zh.ts +207 -0
- package/src/tool/crown-reference-guide/index.ts +11 -0
- package/src/tool/crown-reference-guide/seo.astro +16 -0
- package/src/tool/crown-reference-guide/utils.ts +0 -0
- package/src/tool/demagnetizing-timer/bibliography.astro +16 -0
- package/src/tool/demagnetizing-timer/bibliography.ts +12 -0
- package/src/tool/demagnetizing-timer/client.ts +221 -0
- package/src/tool/demagnetizing-timer/component.astro +15 -0
- package/src/tool/demagnetizing-timer/components/TimerPanel.astro +92 -0
- package/src/tool/demagnetizing-timer/demagnetizing-timer.css +389 -0
- package/src/tool/demagnetizing-timer/entry.ts +50 -0
- package/src/tool/demagnetizing-timer/helpers/field.ts +134 -0
- package/src/tool/demagnetizing-timer/i18n/de.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/en.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/es.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/fr.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/id.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/it.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/ja.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/ko.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/nl.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/pl.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/pt.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/ru.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/sv.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/tr.ts +143 -0
- package/src/tool/demagnetizing-timer/i18n/zh.ts +143 -0
- package/src/tool/demagnetizing-timer/index.ts +11 -0
- package/src/tool/demagnetizing-timer/seo.astro +16 -0
- package/src/tool/demagnetizing-timer/utils.ts +0 -0
- package/src/tool/power-reserve-estimator/bibliography.astro +16 -0
- package/src/tool/power-reserve-estimator/bibliography.ts +16 -0
- package/src/tool/power-reserve-estimator/client.ts +139 -0
- package/src/tool/power-reserve-estimator/component.astro +15 -0
- package/src/tool/power-reserve-estimator/components/EstimatorPanel.astro +150 -0
- package/src/tool/power-reserve-estimator/entry.ts +51 -0
- package/src/tool/power-reserve-estimator/i18n/de.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/en.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/es.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/fr.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/id.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/it.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/ja.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/ko.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/nl.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/pl.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/pt.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/ru.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/sv.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/tr.ts +158 -0
- package/src/tool/power-reserve-estimator/i18n/zh.ts +158 -0
- package/src/tool/power-reserve-estimator/index.ts +11 -0
- package/src/tool/power-reserve-estimator/power-reserve-estimator.css +402 -0
- package/src/tool/power-reserve-estimator/seo.astro +16 -0
- package/src/tool/strap-taper-calculator/bibliography.astro +16 -0
- package/src/tool/strap-taper-calculator/bibliography.ts +12 -0
- package/src/tool/strap-taper-calculator/client.ts +129 -0
- package/src/tool/strap-taper-calculator/component.astro +15 -0
- package/src/tool/strap-taper-calculator/components/CalculatorPanel.astro +114 -0
- package/src/tool/strap-taper-calculator/entry.ts +56 -0
- package/src/tool/strap-taper-calculator/i18n/de.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/en.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/es.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/fr.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/id.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/it.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/ja.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/ko.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/nl.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/pl.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/pt.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/ru.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/sv.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/tr.ts +152 -0
- package/src/tool/strap-taper-calculator/i18n/zh.ts +152 -0
- package/src/tool/strap-taper-calculator/index.ts +11 -0
- package/src/tool/strap-taper-calculator/seo.astro +16 -0
- package/src/tool/strap-taper-calculator/strap-taper-calculator.css +320 -0
- package/src/tool/watch-accuracy-tracker/bibliography.astro +16 -0
- package/src/tool/watch-accuracy-tracker/bibliography.ts +12 -0
- package/src/tool/watch-accuracy-tracker/chart.ts +126 -0
- package/src/tool/watch-accuracy-tracker/client.ts +287 -0
- package/src/tool/watch-accuracy-tracker/component.astro +35 -0
- package/src/tool/watch-accuracy-tracker/components/AccuracyTracker.astro +96 -0
- package/src/tool/watch-accuracy-tracker/components/DriftPredictor.astro +126 -0
- package/src/tool/watch-accuracy-tracker/components/LogHistory.astro +66 -0
- package/src/tool/watch-accuracy-tracker/entry.ts +94 -0
- package/src/tool/watch-accuracy-tracker/i18n/de.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/en.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/es.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/fr.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/id.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/it.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/ja.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/ko.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/nl.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/pl.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/pt.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/ru.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/sv.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/tr.ts +167 -0
- package/src/tool/watch-accuracy-tracker/i18n/zh.ts +167 -0
- package/src/tool/watch-accuracy-tracker/index.ts +9 -0
- package/src/tool/watch-accuracy-tracker/logger.ts +105 -0
- package/src/tool/watch-accuracy-tracker/seo.astro +16 -0
- package/src/tool/watch-accuracy-tracker/utils.ts +99 -0
- package/src/tool/watch-accuracy-tracker/watch-accuracy-tracker.css +564 -0
- package/src/tool/watch-savings-planner/bibliography.astro +16 -0
- package/src/tool/watch-savings-planner/bibliography.ts +8 -0
- package/src/tool/watch-savings-planner/client.ts +271 -0
- package/src/tool/watch-savings-planner/component.astro +33 -0
- package/src/tool/watch-savings-planner/components/AddGoalForm.astro +49 -0
- package/src/tool/watch-savings-planner/components/GoalCard.astro +58 -0
- package/src/tool/watch-savings-planner/entry.ts +62 -0
- package/src/tool/watch-savings-planner/i18n/de.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/en.ts +155 -0
- package/src/tool/watch-savings-planner/i18n/es.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/fr.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/id.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/it.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/ja.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/ko.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/nl.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/pl.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/pt.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/ru.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/sv.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/tr.ts +153 -0
- package/src/tool/watch-savings-planner/i18n/zh.ts +153 -0
- package/src/tool/watch-savings-planner/index.ts +11 -0
- package/src/tool/watch-savings-planner/seo.astro +16 -0
- package/src/tool/watch-savings-planner/utils.ts +0 -0
- package/src/tool/watch-savings-planner/watch-savings-planner.css +460 -0
- package/src/tool/water-resistance-converter/bibliography.astro +16 -0
- package/src/tool/water-resistance-converter/bibliography.ts +16 -0
- package/src/tool/water-resistance-converter/client.ts +56 -0
- package/src/tool/water-resistance-converter/component.astro +15 -0
- package/src/tool/water-resistance-converter/components/ConverterPanel.astro +113 -0
- package/src/tool/water-resistance-converter/entry.ts +52 -0
- package/src/tool/water-resistance-converter/i18n/de.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/en.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/es.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/fr.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/id.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/it.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/ja.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/ko.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/nl.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/pl.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/pt.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/ru.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/sv.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/tr.ts +148 -0
- package/src/tool/water-resistance-converter/i18n/zh.ts +148 -0
- package/src/tool/water-resistance-converter/index.ts +11 -0
- package/src/tool/water-resistance-converter/seo.astro +16 -0
- package/src/tool/water-resistance-converter/water-resistance-converter.css +254 -0
- package/src/tool/wrist-presence-calculator/bibliography.astro +16 -0
- package/src/tool/wrist-presence-calculator/bibliography.ts +12 -0
- package/src/tool/wrist-presence-calculator/client.ts +180 -0
- package/src/tool/wrist-presence-calculator/component.astro +23 -0
- package/src/tool/wrist-presence-calculator/components/CalculatorInputs.astro +97 -0
- package/src/tool/wrist-presence-calculator/components/FitResult.astro +68 -0
- package/src/tool/wrist-presence-calculator/components/Visualizer.astro +16 -0
- package/src/tool/wrist-presence-calculator/entry.ts +59 -0
- package/src/tool/wrist-presence-calculator/helpers/canvas.ts +189 -0
- package/src/tool/wrist-presence-calculator/helpers/results.ts +78 -0
- package/src/tool/wrist-presence-calculator/i18n/de.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/en.ts +155 -0
- package/src/tool/wrist-presence-calculator/i18n/es.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/fr.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/id.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/it.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/ja.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/ko.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/nl.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/pl.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/pt.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/ru.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/sv.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/tr.ts +139 -0
- package/src/tool/wrist-presence-calculator/i18n/zh.ts +155 -0
- package/src/tool/wrist-presence-calculator/index.ts +11 -0
- package/src/tool/wrist-presence-calculator/seo.astro +16 -0
- package/src/tool/wrist-presence-calculator/utils.ts +30 -0
- package/src/tool/wrist-presence-calculator/wrist-presence-calculator.css +372 -0
- package/src/tools.ts +26 -0
- package/src/types.ts +70 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
2
|
+
import type { DemagnetizingTimerUI } from '../entry';
|
|
3
|
+
import { bibliography } from '../bibliography';
|
|
4
|
+
|
|
5
|
+
export const content: ToolLocaleContent<DemagnetizingTimerUI> = {
|
|
6
|
+
slug: 'demanyetizasyon-sureci',
|
|
7
|
+
title: 'Saat Demanyetizasyon Zamanlayıcısı',
|
|
8
|
+
description: 'DIY saat demanyetizasyonu için sesli uyarılı hassas geri sayım zamanlayıcısı. Demanyetizasyon bobininiz için gereken tam basma süresini alın.',
|
|
9
|
+
ui: {
|
|
10
|
+
title: 'Zamanlayıcı Ayarları',
|
|
11
|
+
durationLabel: 'Darbe Süresi',
|
|
12
|
+
duration1s: '1 Saniye',
|
|
13
|
+
duration2s: '2 Saniye',
|
|
14
|
+
duration3s: '3 Saniye',
|
|
15
|
+
customLabel: 'Özel',
|
|
16
|
+
startButton: 'Başlat',
|
|
17
|
+
stopButton: 'Durdur',
|
|
18
|
+
resetButton: 'Sıfırla',
|
|
19
|
+
pressPhase: 'Demanyetizatör düğmesine şimdi basın!',
|
|
20
|
+
holdPhase: 'Düğmeyi basılı tutun...',
|
|
21
|
+
releasePhase: 'Şimdi bırakın!',
|
|
22
|
+
completePhase: 'Tamam! Saati uzaklaştırın.',
|
|
23
|
+
ready: 'Hazır',
|
|
24
|
+
seconds: 'sn',
|
|
25
|
+
instructions: 'Nasıl Demanyetize Edilir',
|
|
26
|
+
step1: 'Saati demanyetizatör platformuna yerleştirin.',
|
|
27
|
+
step2: 'Başlat\'a basın ve demanyetizatör düğmesini ayarlanan süre boyunca basılı tutun.',
|
|
28
|
+
step3: 'Düğmeyi bırakın ve saati yavaşça uzaklaştırın.',
|
|
29
|
+
step4: 'Gerekirse 2–3 kez tekrarlayın, her seferinde saati döndürün.',
|
|
30
|
+
tipTitle: 'İpucu',
|
|
31
|
+
tipContent: 'Yeniden mıknatıslanmayı önlemek için saati, güç açıkken demanyetizatörden en az 1 metre uzakta tutun.',
|
|
32
|
+
},
|
|
33
|
+
seo: [
|
|
34
|
+
{ type: 'title', text: 'Saat Demanyetizasyon Zamanlayıcısı — DIY için Hassas Darbe Zamanlaması', level: 2 },
|
|
35
|
+
{ type: 'paragraph', html: 'Bir saati demanyetize etmek, hassas düğme basma zamanlaması gerektirir. Çoğu DIY demanyetizatör, azalan bir alternatif manyetik alan oluşturarak çalışır ve ideal darbe <strong>1 ila 3 saniye</strong> arasında sürer. Çok kısa basarsanız alan manyetizasyonu nötralize edemez; çok uzun basarsanız mekanizmayı doyurma riskiniz vardır.' },
|
|
36
|
+
{ type: 'title', text: 'Saat Demanyetizasyonunda Zamanlamanın Önemi', level: 3 },
|
|
37
|
+
{ type: 'paragraph', html: 'Demanyetizatördeki düğmeye bastığınızda, bobinin içinde alternatif bir manyetik alan oluşur. Alan şebeke frekansında (50/60 Hz) salınır ve bıraktığınızda söner. Amaç, saati bu sönen alana <strong>tam yeterli süre</strong> maruz bırakarak yay ve diğer çelik bileşenlerdeki manyetik alanları rastgele hale getirmektir. 1 ila 3 saniyelik bir darbe çoğu mekanizma için ideal noktadır.' },
|
|
38
|
+
{ type: 'title', text: 'Bir Demanyetizatör Nasıl Çalışır', level: 3 },
|
|
39
|
+
{ type: 'paragraph', html: 'Bir demanyetizatör, esasen enerji verildiğinde güçlü bir alternatif manyetik alan üreten bir tel bobindir. Mıknatıslanmış bir saati bu alana yerleştirmek, iç manyetik alanlarının hızla tersine dönmesine neden olur. Alan aniden kaldırıldığında (düğmeyi bırakarak), alanlar rastgele bir desende stabilize olur ve net mıknatıslanmayı etkili bir şekilde iptal eder.' },
|
|
40
|
+
{ type: 'title', text: 'Saatinizin Demanyetizasyona İhtiyacı Olduğunu Gösteren İşaretler', level: 3 },
|
|
41
|
+
{ type: 'paragraph', html: 'Mıknatıslanmış bir saatin yaygın belirtileri şunlardır: günde birkaç dakika ileri gitme, pozisyonlara göre tutarsız zaman işleyişi, duyulabilir şekilde daha hızlı tik sesi ve aşırı durumlarda saatin tamamen durması. Otomatik saatiniz aniden hızlanmaya başlarsa, genellikle mıknatıslanma suçludur ve demanyetizasyon basit bir çözümdür.' },
|
|
42
|
+
],
|
|
43
|
+
faq: [
|
|
44
|
+
{
|
|
45
|
+
question: 'Demanyetizatör düğmesine ne kadar süre basmalıyım?',
|
|
46
|
+
answer: '1 ila 3 saniye önerilen darbe süresidir. 1 saniye ile başlayın ve gerekirse artırın. Çok uzun darbeler bobini aşırı ısıtabilir ve sonuçları iyileştirmez.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
question: 'Bir saati birden fazla kez demanyetize edebilir miyim?',
|
|
50
|
+
answer: 'Evet. İşlemi 2 ila 3 kez tekrarlayın ve her seferinde saati 90 derece döndürün. Bu, tüm eksenlerin alternatif alana maruz kalmasını sağlar. Aşırı demanyetizasyon riski yoktur.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
question: 'Demanyetizasyon kuvars saatlerde işe yarar mı?',
|
|
54
|
+
answer: 'Kuvars saatler, az sayıda ferromanyetik bileşen içerdiklerinden nadiren mıknatıslanmadan etkilenir. Ancak, bazı kuvars mekanizmalarındaki step motor mıknatıslanarak ibrelerin düzensiz hareket etmesine neden olabilir. Demanyetizasyon kuvars saatler için güvenlidir.',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
bibliography,
|
|
58
|
+
howTo: [
|
|
59
|
+
{
|
|
60
|
+
name: 'Süreyi Ayarla',
|
|
61
|
+
text: 'Mıknatıslanmanın şiddetine bağlı olarak 1, 2 veya 3 saniye seçin.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'Saati Konumlandır',
|
|
65
|
+
text: 'Saati demanyetizatör platformuna düz bir şekilde, bobinin üzerine ortalanmış olarak yerleştirin.',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'Bas ve Tut',
|
|
69
|
+
text: 'Başlat düğmesine ve demanyetizatör düğmesine aynı anda basın ve ayarlanan süre boyunca basılı tutun.',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'Bırak ve Uzaklaştır',
|
|
73
|
+
text: 'Düğmeyi bırakın ve demanyetizatörü kapatmadan önce saati en az 1 metre yavaşça uzaklaştırın.',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
schemas: [
|
|
77
|
+
{
|
|
78
|
+
'@context': 'https://schema.org',
|
|
79
|
+
'@type': 'FAQPage',
|
|
80
|
+
'mainEntity': [
|
|
81
|
+
{
|
|
82
|
+
'@type': 'Question',
|
|
83
|
+
'name': 'Demanyetizatör düğmesine ne kadar süre basmalıyım?',
|
|
84
|
+
'acceptedAnswer': {
|
|
85
|
+
'@type': 'Answer',
|
|
86
|
+
'text': '1 ila 3 saniye önerilen darbe süresidir. 1 saniye ile başlayın ve gerekirse artırın. Çok uzun darbeler bobini aşırı ısıtabilir ve sonuçları iyileştirmez.',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
'@type': 'Question',
|
|
91
|
+
'name': 'Bir saati birden fazla kez demanyetize edebilir miyim?',
|
|
92
|
+
'acceptedAnswer': {
|
|
93
|
+
'@type': 'Answer',
|
|
94
|
+
'text': 'Evet. İşlemi 2 ila 3 kez tekrarlayın ve her seferinde saati 90 derece döndürün. Bu, tüm eksenlerin alternatif alana maruz kalmasını sağlar. Aşırı demanyetizasyon riski yoktur.',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
'@type': 'Question',
|
|
99
|
+
'name': 'Demanyetizasyon kuvars saatlerde işe yarar mı?',
|
|
100
|
+
'acceptedAnswer': {
|
|
101
|
+
'@type': 'Answer',
|
|
102
|
+
'text': 'Kuvars saatler, az sayıda ferromanyetik bileşen içerdiklerinden nadiren mıknatıslanmadan etkilenir. Ancak, bazı kuvars mekanizmalarındaki step motor mıknatıslanarak ibrelerin düzensiz hareket etmesine neden olabilir. Demanyetizasyon kuvars saatler için güvenlidir.',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
'@context': 'https://schema.org',
|
|
109
|
+
'@type': 'SoftwareApplication',
|
|
110
|
+
'name': 'Saat Demanyetizasyon Zamanlayıcısı',
|
|
111
|
+
'operatingSystem': 'All',
|
|
112
|
+
'applicationCategory': 'UtilitiesApplication',
|
|
113
|
+
'browserRequirements': 'Requires HTML5. Requires JavaScript.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
'@context': 'https://schema.org',
|
|
117
|
+
'@type': 'HowTo',
|
|
118
|
+
'name': 'Bir saat nasıl demanyetize edilir',
|
|
119
|
+
'step': [
|
|
120
|
+
{
|
|
121
|
+
'@type': 'HowToStep',
|
|
122
|
+
'name': 'Süreyi Ayarla',
|
|
123
|
+
'text': 'Mıknatıslanmanın şiddetine bağlı olarak 1, 2 veya 3 saniye seçin.',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
'@type': 'HowToStep',
|
|
127
|
+
'name': 'Saati Konumlandır',
|
|
128
|
+
'text': 'Saati demanyetizatör platformuna düz bir şekilde, bobinin üzerine ortalanmış olarak yerleştirin.',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
'@type': 'HowToStep',
|
|
132
|
+
'name': 'Bas ve Tut',
|
|
133
|
+
'text': 'Başlat düğmesine ve demanyetizatör düğmesine aynı anda basın ve ayarlanan süre boyunca basılı tutun.',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
'@type': 'HowToStep',
|
|
137
|
+
'name': 'Bırak ve Uzaklaştır',
|
|
138
|
+
'text': 'Düğmeyi bırakın ve demanyetizatörü kapatmadan önce saati en az 1 metre yavaşça uzaklaştırın.',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
2
|
+
import type { DemagnetizingTimerUI } from '../entry';
|
|
3
|
+
import { bibliography } from '../bibliography';
|
|
4
|
+
|
|
5
|
+
export const content: ToolLocaleContent<DemagnetizingTimerUI> = {
|
|
6
|
+
slug: 'demagnetizing-timer',
|
|
7
|
+
title: '手表消磁定时器与指南',
|
|
8
|
+
description: '一款带有声音提示的精确倒计时器,用于DIY手表消磁。为您的消磁线圈获取精确的按压时长。',
|
|
9
|
+
ui: {
|
|
10
|
+
title: '定时器设置',
|
|
11
|
+
durationLabel: '脉冲时长',
|
|
12
|
+
duration1s: '1秒',
|
|
13
|
+
duration2s: '2秒',
|
|
14
|
+
duration3s: '3秒',
|
|
15
|
+
customLabel: '自定义',
|
|
16
|
+
startButton: '开始',
|
|
17
|
+
stopButton: '停止',
|
|
18
|
+
resetButton: '重置',
|
|
19
|
+
pressPhase: '请按下消磁器按钮!',
|
|
20
|
+
holdPhase: '请按住按钮...',
|
|
21
|
+
releasePhase: '立即松开!',
|
|
22
|
+
completePhase: '完成!移开手表。',
|
|
23
|
+
ready: '就绪',
|
|
24
|
+
seconds: '秒',
|
|
25
|
+
instructions: '如何消磁',
|
|
26
|
+
step1: '将手表放在消磁器平台上。',
|
|
27
|
+
step2: '按下开始键,同时按住消磁器按钮持续设定的时长。',
|
|
28
|
+
step3: '松开按钮,缓慢移开手表。',
|
|
29
|
+
step4: '如有需要重复2-3次,每次旋转手表。',
|
|
30
|
+
tipTitle: '提示',
|
|
31
|
+
tipContent: '消磁器通电时,请将手表保持至少1米距离,避免再次磁化。',
|
|
32
|
+
},
|
|
33
|
+
seo: [
|
|
34
|
+
{ type: 'title', text: '手表消磁定时器 — DIY消磁的精确脉冲计时', level: 2 },
|
|
35
|
+
{ type: 'paragraph', html: '消磁手表需要精确的按键时机。大多数DIY消磁器通过产生衰减的交流磁场来工作,理想的脉冲持续时间为<strong>1到3秒</strong>。时间太短,磁场无法中和磁化;时间太长,则有可能使机芯饱和。' },
|
|
36
|
+
{ type: 'title', text: '为什么消磁时的时机很重要', level: 3 },
|
|
37
|
+
{ type: 'paragraph', html: '按下消磁器按钮时,线圈内部会产生一个交流磁场。磁场以电源频率(50/60赫兹)振荡,松开按钮时逐渐衰减。目标是让手表<strong>恰好足够长时间</strong>暴露于这个衰减磁场中,以使游丝和其他钢制部件中的磁畴随机化。1到3秒的脉冲对大多数机芯来说是最佳选择。' },
|
|
38
|
+
{ type: 'title', text: '消磁器的工作原理', level: 3 },
|
|
39
|
+
{ type: 'paragraph', html: '消磁器本质上是一个导线线圈,通电时会产生强大的交流磁场。将磁化的手表置于该磁场中,其内部的磁畴会快速翻转。当磁场突然消失(松开按钮)时,磁畴会在随机模式下稳定下来,从而有效抵消净磁化。' },
|
|
40
|
+
{ type: 'title', text: '手表需要消磁的迹象', level: 3 },
|
|
41
|
+
{ type: 'paragraph', html: '手表被磁化的常见症状包括:每天走快几分钟、不同位置走时不一致、滴答声明显加速,以及极端情况下手表完全停止。如果您的自动手表突然开始走快,磁化往往是罪魁祸首,而消磁是一个简单的解决方案。' },
|
|
42
|
+
],
|
|
43
|
+
faq: [
|
|
44
|
+
{
|
|
45
|
+
question: '我应该按消磁器按钮多长时间?',
|
|
46
|
+
answer: '建议脉冲时长为1到3秒。从1秒开始,根据需要增加。过长的脉冲可能导致线圈过热,且不会改善效果。',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
question: '可以多次消磁手表吗?',
|
|
50
|
+
answer: '可以。重复2到3次,每次将手表旋转90度。这样可以确保所有轴都暴露于交流磁场中。没有过度消磁的风险。',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
question: '消磁对石英表有效吗?',
|
|
54
|
+
answer: '石英表很少受磁化影响,因为它们含有的铁磁性部件较少。然而,某些石英机芯中的步进电机可能会被磁化,导致指针运动异常。消磁对石英表是安全的。',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
bibliography,
|
|
58
|
+
howTo: [
|
|
59
|
+
{
|
|
60
|
+
name: '设置时长',
|
|
61
|
+
text: '根据磁化程度选择1、2或3秒。',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: '放置手表',
|
|
65
|
+
text: '将手表平放在消磁器平台上,对准线圈中心。',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: '按下并保持',
|
|
69
|
+
text: '同时按下开始按钮和消磁器按钮,保持设定的时长。',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: '松开并移开',
|
|
73
|
+
text: '松开按钮,在关闭消磁器前将手表缓慢移开至少1米。',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
schemas: [
|
|
77
|
+
{
|
|
78
|
+
'@context': 'https://schema.org',
|
|
79
|
+
'@type': 'FAQPage',
|
|
80
|
+
'mainEntity': [
|
|
81
|
+
{
|
|
82
|
+
'@type': 'Question',
|
|
83
|
+
'name': '我应该按消磁器按钮多长时间?',
|
|
84
|
+
'acceptedAnswer': {
|
|
85
|
+
'@type': 'Answer',
|
|
86
|
+
'text': '建议脉冲时长为1到3秒。从1秒开始,根据需要增加。过长的脉冲可能导致线圈过热,且不会改善效果。',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
'@type': 'Question',
|
|
91
|
+
'name': '可以多次消磁手表吗?',
|
|
92
|
+
'acceptedAnswer': {
|
|
93
|
+
'@type': 'Answer',
|
|
94
|
+
'text': '可以。重复2到3次,每次将手表旋转90度。这样可以确保所有轴都暴露于交流磁场中。没有过度消磁的风险。',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
'@type': 'Question',
|
|
99
|
+
'name': '消磁对石英表有效吗?',
|
|
100
|
+
'acceptedAnswer': {
|
|
101
|
+
'@type': 'Answer',
|
|
102
|
+
'text': '石英表很少受磁化影响,因为它们含有的铁磁性部件较少。然而,某些石英机芯中的步进电机可能会被磁化,导致指针运动异常。消磁对石英表是安全的。',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
'@context': 'https://schema.org',
|
|
109
|
+
'@type': 'SoftwareApplication',
|
|
110
|
+
'name': '手表消磁定时器与指南',
|
|
111
|
+
'operatingSystem': 'All',
|
|
112
|
+
'applicationCategory': 'UtilitiesApplication',
|
|
113
|
+
'browserRequirements': 'Requires HTML5. Requires JavaScript.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
'@context': 'https://schema.org',
|
|
117
|
+
'@type': 'HowTo',
|
|
118
|
+
'name': '如何消磁手表',
|
|
119
|
+
'step': [
|
|
120
|
+
{
|
|
121
|
+
'@type': 'HowToStep',
|
|
122
|
+
'name': '设置时长',
|
|
123
|
+
'text': '根据磁化程度选择1、2或3秒。',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
'@type': 'HowToStep',
|
|
127
|
+
'name': '放置手表',
|
|
128
|
+
'text': '将手表平放在消磁器平台上,对准线圈中心。',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
'@type': 'HowToStep',
|
|
132
|
+
'name': '按下并保持',
|
|
133
|
+
'text': '同时按下开始按钮和消磁器按钮,保持设定的时长。',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
'@type': 'HowToStep',
|
|
137
|
+
'name': '松开并移开',
|
|
138
|
+
'text': '松开按钮,在关闭消磁器前将手表缓慢移开至少1米。',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolDefinition } from '../../types';
|
|
2
|
+
import { demagnetizingTimer } from './entry';
|
|
3
|
+
|
|
4
|
+
export * from './entry';
|
|
5
|
+
|
|
6
|
+
export const DEMAGNETIZING_TIMER_TOOL: ToolDefinition = {
|
|
7
|
+
entry: demagnetizingTimer,
|
|
8
|
+
Component: () => import('./component.astro'),
|
|
9
|
+
SEOComponent: () => import('./seo.astro'),
|
|
10
|
+
BibliographyComponent: () => import('./bibliography.astro'),
|
|
11
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { demagnetizingTimer } from './index';
|
|
4
|
+
import type { KnownLocale } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
locale?: KnownLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { locale = 'en' } = Astro.props;
|
|
11
|
+
const loader = demagnetizingTimer.i18n[locale] || demagnetizingTimer.i18n.en;
|
|
12
|
+
const content = await loader?.();
|
|
13
|
+
if (!content) return null;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
{content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { powerReserveEstimator } from './index';
|
|
4
|
+
import type { KnownLocale } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
locale?: KnownLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { locale = 'en' } = Astro.props as Props;
|
|
11
|
+
const loader = powerReserveEstimator.i18n[locale] || powerReserveEstimator.i18n.en;
|
|
12
|
+
const content = await loader?.();
|
|
13
|
+
if (!content) return null;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
{content && <SharedBibliography links={content.bibliography} />}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BibliographyEntry } from '../../types';
|
|
2
|
+
|
|
3
|
+
export const bibliography: BibliographyEntry[] = [
|
|
4
|
+
{
|
|
5
|
+
name: 'How a Watch Power Reserve Works — Crown & Caliber',
|
|
6
|
+
url: 'https://www.crownandcaliber.com/posts/how-a-watch-works-101/',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: 'What Is a Power Reserve? — Bob\'s Watches',
|
|
10
|
+
url: 'https://www.bobswatches.com/rolex-blog/resources/watch-winders-worth.html',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'Automatic Watch Winding Efficiency Explained',
|
|
14
|
+
url: 'https://www.watchfinder.com/articles/feature-what-does-automatic-mean-in-a-watch-',
|
|
15
|
+
},
|
|
16
|
+
];
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
interface MovementData {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
reserve: number;
|
|
5
|
+
turnsToFull: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const movements: MovementData[] = [
|
|
9
|
+
{ id: 'eta-2824', name: 'ETA 2824-2 / SW200', reserve: 38, turnsToFull: 40 },
|
|
10
|
+
{ id: 'eta-2892', name: 'ETA 2892-A2 / SW300', reserve: 42, turnsToFull: 40 },
|
|
11
|
+
{ id: 'valjoux-7750', name: 'Valjoux 7750 / SW500', reserve: 48, turnsToFull: 40 },
|
|
12
|
+
{ id: 'miyota-8215', name: 'Miyota 8215', reserve: 40, turnsToFull: 35 },
|
|
13
|
+
{ id: 'miyota-9015', name: 'Miyota 9015', reserve: 42, turnsToFull: 35 },
|
|
14
|
+
{ id: 'seiko-nh35', name: 'Seiko NH35 / 4R35', reserve: 41, turnsToFull: 40 },
|
|
15
|
+
{ id: 'seiko-6r35', name: 'Seiko 6R35', reserve: 70, turnsToFull: 55 },
|
|
16
|
+
{ id: 'unitas-6498', name: 'Unitas 6497 / 6498', reserve: 46, turnsToFull: 35 },
|
|
17
|
+
{ id: 'rolex-3135', name: 'Rolex 3135', reserve: 48, turnsToFull: 40 },
|
|
18
|
+
{ id: 'rolex-3235', name: 'Rolex 3235', reserve: 70, turnsToFull: 40 },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const activityFactors: Record<string, number> = {
|
|
22
|
+
low: 0.03,
|
|
23
|
+
medium: 0.06,
|
|
24
|
+
high: 0.10,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const movementSelect = document.getElementById('movement-select') as HTMLSelectElement;
|
|
28
|
+
const turnsInput = document.getElementById('turns-input') as HTMLInputElement;
|
|
29
|
+
const hoursInput = document.getElementById('hours-input') as HTMLInputElement;
|
|
30
|
+
const activityChips = document.querySelectorAll('[data-activity]') as NodeListOf<HTMLButtonElement>;
|
|
31
|
+
const customFields = document.getElementById('custom-fields') as HTMLElement;
|
|
32
|
+
const customReserve = document.getElementById('custom-reserve') as HTMLInputElement;
|
|
33
|
+
const customTurns = document.getElementById('custom-turns') as HTMLInputElement;
|
|
34
|
+
const calcBtn = document.getElementById('calc-btn') as HTMLButtonElement;
|
|
35
|
+
const resultCard = document.getElementById('result-card') as HTMLElement;
|
|
36
|
+
const gaugeFill = document.getElementById('gauge-fill') as HTMLElement;
|
|
37
|
+
const chargeValue = document.getElementById('charge-value') as HTMLElement;
|
|
38
|
+
const reserveValue = document.getElementById('reserve-value') as HTMLElement;
|
|
39
|
+
const stopValue = document.getElementById('stop-value') as HTMLElement;
|
|
40
|
+
|
|
41
|
+
let currentActivity = 'medium';
|
|
42
|
+
|
|
43
|
+
function getMovement(id: string): MovementData | null {
|
|
44
|
+
return movements.find((m) => m.id === id) || null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function calcValue(input: HTMLInputElement, delta: number) {
|
|
48
|
+
const val = parseInt(input.value, 10) || 0;
|
|
49
|
+
const min = parseInt(input.min, 10) || 0;
|
|
50
|
+
const max = parseInt(input.max, 10) || 100;
|
|
51
|
+
const step = Math.abs(delta);
|
|
52
|
+
const next = Math.round(val / step) * step + delta;
|
|
53
|
+
input.value = String(Math.max(min, Math.min(max, next)));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getMovementParams(): { reserve: number; turnsToFull: number } {
|
|
57
|
+
if (movementSelect.value === 'custom') {
|
|
58
|
+
return {
|
|
59
|
+
reserve: parseFloat(customReserve.value) || 38,
|
|
60
|
+
turnsToFull: parseFloat(customTurns.value) || 40,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const m = getMovement(movementSelect.value);
|
|
64
|
+
return m ? { reserve: m.reserve, turnsToFull: m.turnsToFull } : { reserve: 38, turnsToFull: 40 };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function formatStopTime(hoursFromNow: number): string {
|
|
68
|
+
const now = new Date();
|
|
69
|
+
const stop = new Date(now.getTime() + hoursFromNow * 3600000);
|
|
70
|
+
const sameDay = stop.getDate() === now.getDate()
|
|
71
|
+
&& stop.getMonth() === now.getMonth()
|
|
72
|
+
&& stop.getFullYear() === now.getFullYear();
|
|
73
|
+
if (sameDay) {
|
|
74
|
+
return stop.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
|
|
75
|
+
}
|
|
76
|
+
return stop.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
|
|
77
|
+
+ ' ' + stop.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function getGaugeColor(pct: number): string {
|
|
81
|
+
if (pct <= 15) return 'var(--color-danger, #ef4444)';
|
|
82
|
+
if (pct <= 40) return 'var(--color-warning, #f59e0b)';
|
|
83
|
+
return 'var(--color-success, #22c55e)';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function calculate() {
|
|
87
|
+
const { reserve, turnsToFull } = getMovementParams();
|
|
88
|
+
const turns = parseInt(turnsInput.value, 10) || 0;
|
|
89
|
+
const hours = parseFloat(hoursInput.value) || 0;
|
|
90
|
+
const activity = activityFactors[currentActivity] || 0.06;
|
|
91
|
+
|
|
92
|
+
const totalCharge = Math.min(turns / turnsToFull + hours * activity, 1);
|
|
93
|
+
const hoursRemaining = Math.round(totalCharge * reserve);
|
|
94
|
+
const percent = Math.round(totalCharge * 100);
|
|
95
|
+
const color = getGaugeColor(percent);
|
|
96
|
+
|
|
97
|
+
gaugeFill.style.width = percent + '%';
|
|
98
|
+
gaugeFill.style.background = `linear-gradient(90deg, ${color}, color-mix(in srgb, ${color} 70%, #fff 30%))`;
|
|
99
|
+
chargeValue.textContent = percent + '%';
|
|
100
|
+
reserveValue.textContent = hoursRemaining + 'h';
|
|
101
|
+
stopValue.textContent = formatStopTime(hoursRemaining);
|
|
102
|
+
resultCard.style.display = 'flex';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function toggleCustom() {
|
|
106
|
+
const show = movementSelect.value === 'custom';
|
|
107
|
+
customFields.style.display = show ? 'flex' : 'none';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
activityChips.forEach((chip) => {
|
|
111
|
+
chip.addEventListener('click', () => {
|
|
112
|
+
activityChips.forEach((c) => c.classList.remove('active'));
|
|
113
|
+
chip.classList.add('active');
|
|
114
|
+
currentActivity = chip.getAttribute('data-activity') || 'medium';
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
document.querySelectorAll('.stepper-btn').forEach((btn) => {
|
|
119
|
+
btn.addEventListener('click', () => {
|
|
120
|
+
const target = document.getElementById(btn.getAttribute('data-target') || '') as HTMLInputElement;
|
|
121
|
+
const dir = parseInt(btn.getAttribute('data-dir') || '1', 10);
|
|
122
|
+
if (target) {
|
|
123
|
+
calcValue(target, dir);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
movementSelect.addEventListener('change', toggleCustom);
|
|
129
|
+
calcBtn.addEventListener('click', calculate);
|
|
130
|
+
|
|
131
|
+
[turnsInput, hoursInput, customReserve, customTurns].forEach((el) => {
|
|
132
|
+
el.addEventListener('keydown', (e) => {
|
|
133
|
+
if ((e as KeyboardEvent).key === 'Enter') calculate();
|
|
134
|
+
});
|
|
135
|
+
el.addEventListener('input', calculate);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
toggleCustom();
|
|
139
|
+
calculate();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
import EstimatorPanel from './components/EstimatorPanel.astro';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
ui: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { ui } = Astro.props;
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<div class="tool-main-card" data-ui={JSON.stringify(ui)}>
|
|
12
|
+
<EstimatorPanel labels={ui} />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<script src="./client.ts"></script>
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
labels: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { labels } = Astro.props;
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<div class="estimator-panel">
|
|
10
|
+
<div class="panel-section">
|
|
11
|
+
<div class="section-label">{labels.movementLabel || "Movement"}</div>
|
|
12
|
+
<select class="movement-select" id="movement-select">
|
|
13
|
+
<option value="eta-2824">ETA 2824-2 / SW200 — 38h</option>
|
|
14
|
+
<option value="eta-2892">ETA 2892-A2 / SW300 — 42h</option>
|
|
15
|
+
<option value="valjoux-7750">Valjoux 7750 / SW500 — 48h</option>
|
|
16
|
+
<option value="miyota-8215">Miyota 8215 — 40h</option>
|
|
17
|
+
<option value="miyota-9015">Miyota 9015 — 42h</option>
|
|
18
|
+
<option value="seiko-nh35">Seiko NH35 / 4R35 — 41h</option>
|
|
19
|
+
<option value="seiko-6r35">Seiko 6R35 — 70h</option>
|
|
20
|
+
<option value="unitas-6498">Unitas 6497 / 6498 — 46h</option>
|
|
21
|
+
<option value="rolex-3135">Rolex 3135 — 48h</option>
|
|
22
|
+
<option value="rolex-3235">Rolex 3235 — 70h</option>
|
|
23
|
+
<option value="custom">{labels.customMovement || "Custom"}</option>
|
|
24
|
+
</select>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="panel-section" id="custom-fields" style="display: none;">
|
|
28
|
+
<div class="section-label">{labels.customMovement || "Custom"}</div>
|
|
29
|
+
<div class="input-row">
|
|
30
|
+
<div class="input-group">
|
|
31
|
+
<label class="input-label" for="custom-reserve">{labels.powerReserveHours || "Reserve (h)"}</label>
|
|
32
|
+
<div class="stepper-wrap">
|
|
33
|
+
<button type="button" class="stepper-btn" data-target="custom-reserve" data-dir="-1">−</button>
|
|
34
|
+
<input type="number" class="stepper-input" id="custom-reserve" min="1" max="336" value="38" />
|
|
35
|
+
<button type="button" class="stepper-btn" data-target="custom-reserve" data-dir="1">+</button>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="input-group">
|
|
39
|
+
<label class="input-label" for="custom-turns">{labels.fullWindTurns || "Turns to full"}</label>
|
|
40
|
+
<div class="stepper-wrap">
|
|
41
|
+
<button type="button" class="stepper-btn" data-target="custom-turns" data-dir="-1">−</button>
|
|
42
|
+
<input type="number" class="stepper-input" id="custom-turns" min="1" max="100" value="40" />
|
|
43
|
+
<button type="button" class="stepper-btn" data-target="custom-turns" data-dir="1">+</button>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="panel-section">
|
|
50
|
+
<div class="section-label">{labels.turnsLabel || "Crown Turns"} <span class="label-sub">+</span></div>
|
|
51
|
+
<div class="input-row">
|
|
52
|
+
<div class="input-group">
|
|
53
|
+
<label class="input-label" for="turns-input">{labels.turnsInput || "Turns"}</label>
|
|
54
|
+
<div class="stepper-wrap">
|
|
55
|
+
<button type="button" class="stepper-btn" data-target="turns-input" data-dir="-5">−5</button>
|
|
56
|
+
<input type="number" class="stepper-input" id="turns-input" min="0" max="100" value="0" />
|
|
57
|
+
<button type="button" class="stepper-btn" data-target="turns-input" data-dir="5">+5</button>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="panel-section">
|
|
64
|
+
<div class="section-label">{labels.hoursLabel || "Wear Time"} <span class="label-sub">+</span></div>
|
|
65
|
+
<div class="input-row">
|
|
66
|
+
<div class="input-group">
|
|
67
|
+
<label class="input-label" for="hours-input">{labels.hoursInput || "Hours"}</label>
|
|
68
|
+
<div class="stepper-wrap">
|
|
69
|
+
<button type="button" class="stepper-btn" data-target="hours-input" data-dir="-1">−</button>
|
|
70
|
+
<input type="number" class="stepper-input" id="hours-input" min="0" max="24" value="0" />
|
|
71
|
+
<button type="button" class="stepper-btn" data-target="hours-input" data-dir="1">+</button>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
<div class="input-group">
|
|
75
|
+
<label class="input-label" for="activity-select">{labels.activityLabel || "Activity"}</label>
|
|
76
|
+
<div class="chip-group">
|
|
77
|
+
<button type="button" class="chip active" data-activity="low">{labels.activityLow || "Low"}</button>
|
|
78
|
+
<button type="button" class="chip" data-activity="medium">{labels.activityMedium || "Medium"}</button>
|
|
79
|
+
<button type="button" class="chip" data-activity="high">{labels.activityHigh || "High"}</button>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<button type="button" class="calc-btn" id="calc-btn">
|
|
86
|
+
<svg viewBox="0 0 24 24" width="16" height="16">
|
|
87
|
+
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" fill="currentColor" />
|
|
88
|
+
</svg>
|
|
89
|
+
{labels.calculate || "Calculate"}
|
|
90
|
+
</button>
|
|
91
|
+
|
|
92
|
+
<div class="result-card" id="result-card" style="display: none">
|
|
93
|
+
<div class="result-header">
|
|
94
|
+
<svg viewBox="0 0 24 24" width="18" height="18">
|
|
95
|
+
<path d="M13 2.05v2.02c3.95.49 7 3.85 7 7.93 0 4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93V2.05C5.05 2.58 2 6.13 2 11c0 5.52 4.48 10 10 10s10-4.48 10-10c0-4.87-3.05-8.42-7-8.95zM12 6v5l4.28 2.54.72-1.21-3.5-2.08V6H12z" fill="currentColor" />
|
|
96
|
+
</svg>
|
|
97
|
+
<span>{labels.resultLabel || "Estimated Reserve"}</span>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div class="gauge-wrap">
|
|
101
|
+
<div class="gauge-track">
|
|
102
|
+
<div class="gauge-fill" id="gauge-fill"></div>
|
|
103
|
+
</div>
|
|
104
|
+
<div class="gauge-marks">
|
|
105
|
+
<span class="gauge-mark gauge-danger">0</span>
|
|
106
|
+
<span class="gauge-mark gauge-warning">25</span>
|
|
107
|
+
<span class="gauge-mark gauge-ok">50</span>
|
|
108
|
+
<span class="gauge-mark gauge-warning">75</span>
|
|
109
|
+
<span class="gauge-mark gauge-ok">100%</span>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<div class="charge-stats">
|
|
114
|
+
<div class="charge-stat">
|
|
115
|
+
<span class="stat-value" id="charge-value">--</span>
|
|
116
|
+
<span class="stat-label">{labels.chargePercent || "Charge"}</span>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="charge-stat">
|
|
119
|
+
<span class="stat-value" id="reserve-value">--</span>
|
|
120
|
+
<span class="stat-label">{labels.hoursRemaining || "Remaining"}</span>
|
|
121
|
+
</div>
|
|
122
|
+
<div class="charge-stat">
|
|
123
|
+
<span class="stat-value" id="stop-value">--</span>
|
|
124
|
+
<span class="stat-label">{labels.stopTimeLabel || "Runs until"}</span>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<div class="steps-section">
|
|
130
|
+
<div class="step-row">
|
|
131
|
+
<div class="step-marker">1</div>
|
|
132
|
+
<span class="step-text">{labels.step1 || "Select your movement from the dropdown."}</span>
|
|
133
|
+
</div>
|
|
134
|
+
<div class="step-row">
|
|
135
|
+
<div class="step-marker">2</div>
|
|
136
|
+
<span class="step-text">{labels.step2 || "Enter crown turns and hours worn."}</span>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="step-row">
|
|
139
|
+
<div class="step-marker">3</div>
|
|
140
|
+
<span class="step-text">{labels.step3 || "Press Calculate to see your reserve."}</span>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div class="tip-row">
|
|
145
|
+
<svg class="tip-icon" viewBox="0 0 24 24" width="16" height="16">
|
|
146
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" fill="currentColor" />
|
|
147
|
+
</svg>
|
|
148
|
+
<span class="tip-text">{labels.tipContent || "Manual-wind movements only charge when you turn the crown. Automatic movements also charge while worn."}</span>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|