@jjlmoya/utils-diy 1.15.0 → 1.17.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 +1 -1
- package/src/category/i18n/fr.ts +5 -5
- package/src/entries.ts +3 -1
- package/src/index.ts +2 -0
- package/src/layouts/PreviewLayout.astro +1 -0
- package/src/tests/diacritics_density.test.ts +118 -0
- package/src/tests/inverted_punctuation.test.ts +84 -0
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/no_en_dash.test.ts +70 -0
- package/src/tests/script_density.test.ts +94 -0
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/balusterCalculator/i18n/de.ts +7 -7
- package/src/tool/balusterCalculator/i18n/en.ts +4 -4
- package/src/tool/balusterCalculator/i18n/es.ts +2 -2
- package/src/tool/balusterCalculator/i18n/fr.ts +3 -3
- package/src/tool/balusterCalculator/i18n/it.ts +16 -16
- package/src/tool/balusterCalculator/i18n/ru.ts +14 -14
- package/src/tool/balusterCalculator/i18n/tr.ts +5 -5
- package/src/tool/clayCalculator/i18n/fr.ts +3 -3
- package/src/tool/clayCalculator/i18n/ru.ts +3 -3
- package/src/tool/concreteCalculator/i18n/en.ts +4 -4
- package/src/tool/concreteCalculator/i18n/fr.ts +2 -2
- package/src/tool/concreteCalculator/i18n/ko.ts +2 -2
- package/src/tool/concreteCalculator/i18n/ru.ts +3 -3
- package/src/tool/cutOptimizer/i18n/en.ts +4 -4
- package/src/tool/cutOptimizer/i18n/fr.ts +2 -2
- package/src/tool/cutOptimizer/i18n/ru.ts +2 -2
- package/src/tool/drillCalculator/bibliography.ts +2 -2
- package/src/tool/drillCalculator/i18n/ru.ts +5 -5
- package/src/tool/drillCalculator/i18n/zh.ts +2 -2
- package/src/tool/drillSharpener/i18n/ru.ts +3 -3
- package/src/tool/epoxyCalculator/epoxy-resin-calculator.css +81 -1
- package/src/tool/epoxyCalculator/i18n/de.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/en.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/es.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/fr.ts +3 -3
- package/src/tool/epoxyCalculator/i18n/id.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/it.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/ja.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/ko.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/nl.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/pl.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/pt.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/ru.ts +5 -5
- package/src/tool/epoxyCalculator/i18n/sv.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/tr.ts +2 -2
- package/src/tool/epoxyCalculator/i18n/zh.ts +4 -4
- package/src/tool/furnitureFit/i18n/de.ts +2 -2
- package/src/tool/furnitureFit/i18n/en.ts +4 -4
- package/src/tool/furnitureFit/i18n/es.ts +2 -2
- package/src/tool/furnitureFit/i18n/fr.ts +3 -3
- package/src/tool/furnitureFit/i18n/id.ts +2 -2
- package/src/tool/furnitureFit/i18n/it.ts +2 -2
- package/src/tool/furnitureFit/i18n/ja.ts +2 -2
- package/src/tool/furnitureFit/i18n/ko.ts +2 -2
- package/src/tool/furnitureFit/i18n/nl.ts +2 -2
- package/src/tool/furnitureFit/i18n/pl.ts +2 -2
- package/src/tool/furnitureFit/i18n/pt.ts +2 -2
- package/src/tool/furnitureFit/i18n/ru.ts +6 -6
- package/src/tool/furnitureFit/i18n/sv.ts +2 -2
- package/src/tool/furnitureFit/i18n/tr.ts +2 -2
- package/src/tool/furnitureFit/i18n/zh.ts +2 -2
- package/src/tool/mortarCalculator/i18n/en.ts +3 -3
- package/src/tool/mortarCalculator/i18n/ru.ts +6 -6
- package/src/tool/mortarCalculator/i18n/zh.ts +3 -3
- package/src/tool/passepartoutCalculator/i18n/en.ts +4 -4
- package/src/tool/passepartoutCalculator/i18n/ru.ts +7 -7
- package/src/tool/passepartoutCalculator/i18n/zh.ts +6 -6
- package/src/tool/passepartoutCalculator/passepartout-calculator.css +99 -3
- package/src/tool/pythagoreanRightAngleCalculator/i18n/fr.ts +3 -3
- package/src/tool/pythagoreanRightAngleCalculator/i18n/pl.ts +2 -2
- package/src/tool/pythagoreanRightAngleCalculator/i18n/ru.ts +5 -5
- package/src/tool/stairCalculator/i18n/ru.ts +6 -6
- package/src/tool/stairCalculator/stair-calculator.css +76 -5
- package/src/tool/thermalExpansionCalculator/bibliography.ts +4 -4
- package/src/tool/thermalExpansionCalculator/i18n/en.ts +2 -2
- package/src/tool/thermalExpansionCalculator/i18n/fr.ts +3 -3
- package/src/tool/thermalExpansionCalculator/i18n/ru.ts +4 -4
- package/src/tool/twoStrokeMixtureCalculator/bibliography.astro +6 -0
- package/src/tool/twoStrokeMixtureCalculator/bibliography.ts +12 -0
- package/src/tool/twoStrokeMixtureCalculator/component.astro +266 -0
- package/src/tool/twoStrokeMixtureCalculator/entry.ts +24 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/de.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/en.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/es.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/fr.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/id.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/it.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/ja.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/ko.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/nl.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/pl.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/pt.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/ru.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/sv.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/tr.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/i18n/zh.ts +194 -0
- package/src/tool/twoStrokeMixtureCalculator/index.ts +11 -0
- package/src/tool/twoStrokeMixtureCalculator/logic.ts +92 -0
- package/src/tool/twoStrokeMixtureCalculator/seo.astro +15 -0
- package/src/tool/twoStrokeMixtureCalculator/two-stroke-fuel-mixture-calculator.css +405 -0
- package/src/tool/twoStrokeMixtureCalculator/ui.ts +81 -0
- package/src/tool/voltageDropCalculator/i18n/en.ts +2 -2
- package/src/tool/voltageDropCalculator/i18n/es.ts +4 -4
- package/src/tool/voltageDropCalculator/i18n/ru.ts +4 -4
- package/src/tool/workshopFractionConverter/bibliography.ts +2 -2
- package/src/tool/workshopFractionConverter/i18n/de.ts +2 -2
- package/src/tool/workshopFractionConverter/i18n/es.ts +2 -2
- package/src/tool/workshopFractionConverter/i18n/fr.ts +2 -2
- package/src/tool/workshopFractionConverter/i18n/ru.ts +9 -9
- package/src/tool/workshopFractionConverter/i18n/zh.ts +6 -6
- package/src/tools.ts +2 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { StairCalculatorUI } from '../ui';
|
|
4
4
|
import { bibliography } from '../bibliography';
|
|
@@ -14,7 +14,7 @@ const faqData = [
|
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
question: 'Какова максимальная высота ступени?',
|
|
17
|
-
answer: 'В жилых домах рекомендуется не превышать 18
|
|
17
|
+
answer: 'В жилых домах рекомендуется не превышать 18-19 см. Для общественных мест максимум по нормам обычно составляет 17,5 см. Более высокие ступени сильнее утомляют и могут быть опасны.',
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
question: 'Как рассчитать, если мало места?',
|
|
@@ -33,7 +33,7 @@ const faqData = [
|
|
|
33
33
|
const howToData = [
|
|
34
34
|
{ name: 'Измерить перепад высот', text: 'Измерьте общий перепад (H) от чистового пола нижнего уровня до чистового пола верхнего уровня. Это базовый параметр для всех расчетов.' },
|
|
35
35
|
{ name: 'Ввести доступную длину', text: 'Опционально: если у вас есть ограничения по месту, введите доступную горизонтальную длину. Используйте 0 для свободного расчета.' },
|
|
36
|
-
{ name: 'Настроить количество ступеней', text: 'Калькулятор предложит начальное количество, но вы можете его изменить. Следите за индикатором Блонделя: он должен быть зеленым (62
|
|
36
|
+
{ name: 'Настроить количество ступеней', text: 'Калькулятор предложит начальное количество, но вы можете его изменить. Следите за индикатором Блонделя: он должен быть зеленым (62-64 см).' },
|
|
37
37
|
{ name: 'Определить параметры объекта', text: 'Укажите толщину плиты, отделку, марку бетона и ширину лестницы. Эти данные влияют на итоговый расчет материалов.' },
|
|
38
38
|
];
|
|
39
39
|
|
|
@@ -82,17 +82,17 @@ export const content: ToolLocaleContent<StairCalculatorUI> = {
|
|
|
82
82
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
83
83
|
seo: [
|
|
84
84
|
{ type: 'title', text: 'Геометрическое проектирование лестниц: закон Блонделя', level: 2 },
|
|
85
|
-
{ type: 'paragraph', html: 'Комфорт лестницы зависит от длины человеческого шага. При подъеме или спуске тело ожидает предсказуемого ритма. Закон Блонделя гласит, что 2 высоты подступенка + 1 ширина проступи = 62
|
|
85
|
+
{ type: 'paragraph', html: 'Комфорт лестницы зависит от длины человеческого шага. При подъеме или спуске тело ожидает предсказуемого ритма. Закон Блонделя гласит, что 2 высоты подступенка + 1 ширина проступи = 62-64 см - это стандарт, гарантирующий максимальный комфорт и безопасность.' },
|
|
86
86
|
{ type: 'title', text: 'Учет конструкций и материалов', level: 3 },
|
|
87
87
|
{ type: 'paragraph', html: 'Для профессионального исполнения жизненно важно учитывать бетонную плиту основания. Игнорирование этого объема приведет к нехватке материала при заказе. Калькулятор автоматически включает этот расчет.' },
|
|
88
88
|
{ type: 'title', text: 'Разметка и накопленная ошибка', level: 3 },
|
|
89
|
-
{ type: 'paragraph', html: 'В строительстве главный враг
|
|
89
|
+
{ type: 'paragraph', html: 'В строительстве главный враг - миллиметровая ошибка. Если вы измеряете каждую ступень отдельно, сумма маленьких погрешностей может привести к тому, что последняя ступень окажется на 5 см выше или ниже первой.' },
|
|
90
90
|
],
|
|
91
91
|
ui: {
|
|
92
92
|
labelGeometry: 'Геометрия и габариты',
|
|
93
93
|
labelTotalHeight: 'Общая высота (H)',
|
|
94
94
|
labelAvailableLength: 'Доступная длина (L)',
|
|
95
|
-
labelAvailableLengthHint: '0
|
|
95
|
+
labelAvailableLengthHint: '0 - без ограничений.',
|
|
96
96
|
labelNumSteps: 'Кол-во ступеней',
|
|
97
97
|
labelOptimize: 'Оптимизация (18см)',
|
|
98
98
|
labelWork: 'Строительство и отделка',
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
.sc-stat-box {
|
|
75
|
+
min-width: 0;
|
|
75
76
|
background: rgba(255, 255, 255, 0.5);
|
|
76
77
|
padding: 0.75rem 0.5rem;
|
|
77
78
|
border-radius: 1.25rem;
|
|
@@ -93,9 +94,12 @@
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
.sc-stat-value {
|
|
97
|
+
display: inline-block;
|
|
98
|
+
max-width: 100%;
|
|
96
99
|
font-size: 1.5rem;
|
|
97
100
|
font-weight: 800;
|
|
98
101
|
color: var(--sc-neutral);
|
|
102
|
+
overflow-wrap: anywhere;
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
.sc-stat-unit {
|
|
@@ -317,7 +321,7 @@
|
|
|
317
321
|
|
|
318
322
|
.sc-table-wrapper {
|
|
319
323
|
max-height: 220px;
|
|
320
|
-
overflow
|
|
324
|
+
overflow: auto;
|
|
321
325
|
}
|
|
322
326
|
|
|
323
327
|
.sc-table-wrapper table {
|
|
@@ -370,6 +374,7 @@
|
|
|
370
374
|
|
|
371
375
|
.sc-material-row {
|
|
372
376
|
display: flex;
|
|
377
|
+
gap: 0.75rem;
|
|
373
378
|
justify-content: space-between;
|
|
374
379
|
align-items: baseline;
|
|
375
380
|
padding-bottom: 0.4rem;
|
|
@@ -384,6 +389,7 @@
|
|
|
384
389
|
.sc-material-row strong {
|
|
385
390
|
font-size: 1.15rem;
|
|
386
391
|
color: var(--sc-primary);
|
|
392
|
+
overflow-wrap: anywhere;
|
|
387
393
|
}
|
|
388
394
|
|
|
389
395
|
.sc-actions-row {
|
|
@@ -459,20 +465,85 @@
|
|
|
459
465
|
}
|
|
460
466
|
|
|
461
467
|
@media (max-width: 480px) {
|
|
468
|
+
.sc-root {
|
|
469
|
+
padding: 0 0.5rem;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.sc-card {
|
|
473
|
+
border-radius: 1rem;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.sc-sidebar,
|
|
477
|
+
.sc-main {
|
|
478
|
+
padding: 1rem;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.sc-input-grid {
|
|
482
|
+
grid-template-columns: 1fr;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.sc-step-btn {
|
|
486
|
+
width: 38px;
|
|
487
|
+
height: 38px;
|
|
488
|
+
font-size: 1.35rem;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.sc-stepper input {
|
|
492
|
+
height: 38px;
|
|
493
|
+
font-size: 1rem;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.sc-select {
|
|
497
|
+
font-size: 0.9rem;
|
|
498
|
+
padding: 0.7rem 2.5rem 0.7rem 0.85rem;
|
|
499
|
+
}
|
|
500
|
+
|
|
462
501
|
.sc-results-header {
|
|
463
|
-
|
|
502
|
+
grid-template-columns: 1fr;
|
|
503
|
+
gap: 0.5rem;
|
|
464
504
|
}
|
|
465
505
|
|
|
466
506
|
.sc-stat-box {
|
|
467
|
-
|
|
468
|
-
|
|
507
|
+
display: grid;
|
|
508
|
+
grid-template-columns: 1fr auto auto;
|
|
509
|
+
gap: 0.35rem;
|
|
510
|
+
align-items: baseline;
|
|
511
|
+
padding: 0.65rem 0.75rem;
|
|
512
|
+
text-align: left;
|
|
513
|
+
border-radius: 0.875rem;
|
|
469
514
|
}
|
|
470
515
|
|
|
471
516
|
.sc-stat-value {
|
|
472
517
|
font-size: 1.1rem;
|
|
473
518
|
}
|
|
474
519
|
|
|
520
|
+
.sc-stat-unit {
|
|
521
|
+
font-size: 0.7rem;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.sc-visualizer-container {
|
|
525
|
+
min-height: 210px;
|
|
526
|
+
padding: 0.5rem;
|
|
527
|
+
border-radius: 1rem;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
#sc-stair-svg {
|
|
531
|
+
min-width: 360px;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.sc-table-card,
|
|
535
|
+
.sc-materials-card {
|
|
536
|
+
padding: 1rem;
|
|
537
|
+
border-radius: 1rem;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.sc-material-row {
|
|
541
|
+
align-items: flex-start;
|
|
542
|
+
flex-direction: column;
|
|
543
|
+
gap: 0.25rem;
|
|
544
|
+
}
|
|
545
|
+
|
|
475
546
|
.sc-material-row strong {
|
|
476
547
|
font-size: 1rem;
|
|
477
548
|
}
|
|
478
|
-
}
|
|
549
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type { BibliographyEntry } from '../../types';
|
|
1
|
+
import type { BibliographyEntry } from '../../types';
|
|
2
2
|
|
|
3
3
|
export const bibliography: BibliographyEntry[] = [
|
|
4
4
|
{
|
|
5
|
-
name: 'Coefficient of Thermal Expansion
|
|
5
|
+
name: 'Coefficient of Thermal Expansion - Engineering Toolbox',
|
|
6
6
|
url: 'https://www.engineeringtoolbox.com/linear-expansion-coefficients-d_95.html',
|
|
7
7
|
},
|
|
8
8
|
{
|
|
9
|
-
name: 'Thermal expansion and temperature
|
|
9
|
+
name: 'Thermal expansion and temperature - Britannica',
|
|
10
10
|
url: 'https://www.britannica.com/science/thermal-expansion',
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
|
-
name: 'Linear Thermal Expansion
|
|
13
|
+
name: 'Linear Thermal Expansion - Physics Hypertextbook',
|
|
14
14
|
url: 'https://physics.info/expansion/',
|
|
15
15
|
},
|
|
16
16
|
];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { ThermalExpansionCalculatorUI } from '../ui';
|
|
4
4
|
import { bibliography } from '../bibliography';
|
|
@@ -97,7 +97,7 @@ export const content: ToolLocaleContent<ThermalExpansionCalculatorUI> = {
|
|
|
97
97
|
{ type: 'title', text: 'What is Thermal Expansion and How Does It Affect Structures', level: 2 },
|
|
98
98
|
{
|
|
99
99
|
type: 'paragraph',
|
|
100
|
-
html: '<strong>Thermal expansion</strong> is the physical process by which a material increases its length in response to a rise in temperature. At the microscopic level, particles vibrate with more energy and require a greater average spacing between them. In construction, this phenomenon is not a curiosity
|
|
100
|
+
html: '<strong>Thermal expansion</strong> is the physical process by which a material increases its length in response to a rise in temperature. At the microscopic level, particles vibrate with more energy and require a greater average spacing between them. In construction, this phenomenon is not a curiosity - it is a force that can crack concrete, deform steel beams and buckle railway tracks.',
|
|
101
101
|
},
|
|
102
102
|
{ type: 'title', text: 'The Linear Expansion Formula', level: 3 },
|
|
103
103
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { ThermalExpansionCalculatorUI } from '../ui';
|
|
4
4
|
import { bibliography } from '../bibliography';
|
|
@@ -97,14 +97,14 @@ export const content: ToolLocaleContent<ThermalExpansionCalculatorUI> = {
|
|
|
97
97
|
{ type: 'title', text: 'Qu\'est-ce que la Dilatation Thermique et comment affecte-t-elle les Structures', level: 2 },
|
|
98
98
|
{
|
|
99
99
|
type: 'paragraph',
|
|
100
|
-
html: 'La <strong>dilatation thermique</strong> est le processus physique par lequel un matériau augmente sa longueur en réponse à une élévation de température. À l\'échelle microscopique, les particules vibrent avec plus d\'énergie et nécessitent un espacement moyen plus grand entre elles. En construction, ce phénomène n\'est pas une
|
|
100
|
+
html: 'La <strong>dilatation thermique</strong> est le processus physique par lequel un matériau augmente sa longueur en réponse à une élévation de température. À l\'échelle microscopique, les particules vibrent avec plus d\'énergie et nécessitent un espacement moyen plus grand entre elles. En construction, ce phénomène n\'est pas une curiosité: c\'est une force qui peut fissurer le béton, déformer des poutres en acier et faire se tordre les rails d\'un chemin de fer.',
|
|
101
101
|
},
|
|
102
102
|
{ type: 'title', text: 'La Formule de la Dilatation Linéaire', level: 3 },
|
|
103
103
|
{
|
|
104
104
|
type: 'card',
|
|
105
105
|
icon: 'mdi:math-log',
|
|
106
106
|
title: 'Formule de Dilatation Linéaire',
|
|
107
|
-
html: '<p>L\'expansion d\'un élément structurel se calcule avec
|
|
107
|
+
html: '<p>L\'expansion d\'un élément structurel se calcule avec: <code>ΔL = L₀ · α · ΔT</code>. Où <strong>ΔL</strong> est l\'allongement total, <strong>L₀</strong> est la longueur originale, <strong>α</strong> est le coefficient de dilatation du matériau (en °C⁻¹) et <strong>ΔT</strong> est la différence de température. Cette formule est à la base du dimensionnement des joints de dilatation dans les ponts, les toitures et les façades.</p>',
|
|
108
108
|
},
|
|
109
109
|
{ type: 'title', text: 'Coefficients de Dilatation par Matériau', level: 3 },
|
|
110
110
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
1
|
+
import type { WithContext, FAQPage, HowToThing, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { ThermalExpansionCalculatorUI } from '../ui';
|
|
4
4
|
import { bibliography } from '../bibliography';
|
|
@@ -18,7 +18,7 @@ const faqData = [
|
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
question: 'Расширяется ли дерево одинаково во всех направлениях?',
|
|
21
|
-
answer: 'Нет. Дерево
|
|
21
|
+
answer: 'Нет. Дерево - анизотропный материал. Оно очень мало расширяется вдоль волокон, но значительно в поперечном направлении (в ширину и толщину).',
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
question: 'Какую температуру использовать в качестве начальной?',
|
|
@@ -78,9 +78,9 @@ export const content: ToolLocaleContent<ThermalExpansionCalculatorUI> = {
|
|
|
78
78
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
79
79
|
seo: [
|
|
80
80
|
{ type: 'title', text: 'Что такое тепловое расширение и как оно влияет на конструкции', level: 2 },
|
|
81
|
-
{ type: 'paragraph', html: '<strong>Тепловое расширение</strong>
|
|
81
|
+
{ type: 'paragraph', html: '<strong>Тепловое расширение</strong> - это физический процесс, при котором материал увеличивает свою длину в ответ на повышение температуры. В строительстве это явление - сила, способная разрушить бетон, деформировать стальные балки и искривить железнодорожные рельсы.' },
|
|
82
82
|
{ type: 'title', text: 'Формула линейного расширения', level: 3 },
|
|
83
|
-
{ type: 'card', icon: 'mdi:math-log', title: 'Формула линейного расширения', html: '<p>Расширение структурного элемента рассчитывается по формуле: <code>ΔL = L₀ · α · ΔT</code>. Где <strong>ΔL</strong>
|
|
83
|
+
{ type: 'card', icon: 'mdi:math-log', title: 'Формула линейного расширения', html: '<p>Расширение структурного элемента рассчитывается по формуле: <code>ΔL = L₀ · α · ΔT</code>. Где <strong>ΔL</strong> - общий рост, <strong>L₀</strong> - исходная длина, <strong>α</strong> - коэффициент расширения материала (в °C⁻¹), а <strong>ΔT</strong> - разница температур.</p>' },
|
|
84
84
|
],
|
|
85
85
|
ui: {
|
|
86
86
|
configTitle: 'Настройка',
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BibliographyEntry } from '../../types';
|
|
2
|
+
|
|
3
|
+
export const bibliography: BibliographyEntry[] = [
|
|
4
|
+
{
|
|
5
|
+
name: 'Two-Stroke Engine Fuel Mixture Ratios',
|
|
6
|
+
url: 'https://en.wikipedia.org/wiki/Two-stroke_engine',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: 'Gasoline and Oil Mix Ratios for Small Engines',
|
|
10
|
+
url: 'https://homelivinghandbook.com/how-much-oil-should-you-mix-with-gas-for-small-engine-tools',
|
|
11
|
+
},
|
|
12
|
+
];
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Icon } from 'astro-icon/components';
|
|
3
|
+
import type { TwoStrokeMixtureCalculatorUI } from './ui';
|
|
4
|
+
|
|
5
|
+
interface Props { ui?: TwoStrokeMixtureCalculatorUI; }
|
|
6
|
+
const { ui } = Astro.props;
|
|
7
|
+
const t = (ui ?? {}) as TwoStrokeMixtureCalculatorUI;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<div class="tsmc-root" data-tsmc-root data-ui={JSON.stringify(t)}>
|
|
11
|
+
<div class="tsmc-mission-selector">
|
|
12
|
+
<button class="tsmc-mission-btn active" data-mission="fuel">
|
|
13
|
+
<Icon name="mdi:gas-cylinder" />
|
|
14
|
+
<span>{t.copyTextFuel}</span>
|
|
15
|
+
</button>
|
|
16
|
+
<button class="tsmc-mission-btn" data-mission="oil">
|
|
17
|
+
<Icon name="mdi:beaker-outline" />
|
|
18
|
+
<span>{t.copyTextOil}</span>
|
|
19
|
+
</button>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="tsmc-container">
|
|
23
|
+
<div class="tsmc-input-section">
|
|
24
|
+
<label id="tsmc-volume-label" class="tsmc-section-label">{t.labelVolume}</label>
|
|
25
|
+
|
|
26
|
+
<div class="tsmc-slider-container">
|
|
27
|
+
<input
|
|
28
|
+
type="range"
|
|
29
|
+
id="tsmc-slider"
|
|
30
|
+
min="1"
|
|
31
|
+
max="50"
|
|
32
|
+
step="1"
|
|
33
|
+
value="5"
|
|
34
|
+
class="tsmc-slider"
|
|
35
|
+
>
|
|
36
|
+
<div class="tsmc-slider-value-display">
|
|
37
|
+
<span id="tsmc-slider-value">5</span><span id="tsmc-slider-unit" class="tsmc-unit">L</span>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="tsmc-quick-buttons">
|
|
42
|
+
<button class="tsmc-quick-btn fuel-btn" data-volume="2">2L</button>
|
|
43
|
+
<button class="tsmc-quick-btn fuel-btn active" data-volume="5">5L</button>
|
|
44
|
+
<button class="tsmc-quick-btn fuel-btn" data-volume="10">10L</button>
|
|
45
|
+
<button class="tsmc-quick-btn fuel-btn" data-volume="20">20L</button>
|
|
46
|
+
|
|
47
|
+
<button class="tsmc-quick-btn oil-btn hidden" data-volume="125">125ml</button>
|
|
48
|
+
<button class="tsmc-quick-btn oil-btn hidden" data-volume="250">250ml</button>
|
|
49
|
+
<button class="tsmc-quick-btn oil-btn hidden" data-volume="500">500ml</button>
|
|
50
|
+
<button class="tsmc-quick-btn oil-btn hidden" data-volume="1000">1L</button>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="tsmc-ratio-section">
|
|
55
|
+
<label class="tsmc-section-label">{t.labelPresets}</label>
|
|
56
|
+
<div class="tsmc-ratio-cards">
|
|
57
|
+
<button class="tsmc-ratio-card" data-ratio="25">
|
|
58
|
+
<span class="tsmc-ratio-value">1:25</span>
|
|
59
|
+
<span class="tsmc-ratio-desc">{t.ratio25Desc}</span>
|
|
60
|
+
</button>
|
|
61
|
+
<button class="tsmc-ratio-card" data-ratio="33">
|
|
62
|
+
<span class="tsmc-ratio-value">1:33</span>
|
|
63
|
+
<span class="tsmc-ratio-desc">{t.ratio33Desc}</span>
|
|
64
|
+
</button>
|
|
65
|
+
<button class="tsmc-ratio-card active" data-ratio="40">
|
|
66
|
+
<span class="tsmc-ratio-value">1:40</span>
|
|
67
|
+
<span class="tsmc-ratio-desc">{t.ratio40Desc}</span>
|
|
68
|
+
</button>
|
|
69
|
+
<button class="tsmc-ratio-card" data-ratio="50">
|
|
70
|
+
<span class="tsmc-ratio-value">1:50</span>
|
|
71
|
+
<span class="tsmc-ratio-desc">{t.ratio50Desc}</span>
|
|
72
|
+
</button>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="tsmc-mega-result">
|
|
77
|
+
<div class="tsmc-result-label">{t.labelOilRequired}</div>
|
|
78
|
+
<div class="tsmc-result-display">
|
|
79
|
+
<span id="tsmc-result-value" class="tsmc-result-big">--</span>
|
|
80
|
+
<span id="tsmc-result-unit" class="tsmc-result-unit">ml</span>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<svg id="tsmc-container-visual" class="tsmc-container-visual" viewBox="0 0 200 240">
|
|
84
|
+
<rect x="65" y="30" width="70" height="12" fill="#64748b" rx="3"/>
|
|
85
|
+
<rect x="70" y="22" width="60" height="8" fill="#475569" rx="2"/>
|
|
86
|
+
<path d="M 50 42 Q 45 50 45 70 L 45 160 Q 45 175 60 180 L 140 180 Q 155 175 155 160 L 155 70 Q 155 50 150 42 Z"
|
|
87
|
+
fill="none" stroke="#64748b" stroke-width="3" stroke-linejoin="round"/>
|
|
88
|
+
<rect id="tsmc-fuel-fill" x="50" y="160" width="100" height="0" fill="#fbbf24"/>
|
|
89
|
+
<rect id="tsmc-oil-fill" x="50" y="160" width="100" height="0" fill="#dc2626"/>
|
|
90
|
+
<text id="tsmc-ratio-display" x="100" y="105" text-anchor="middle" dominant-baseline="middle"
|
|
91
|
+
font-size="20" font-weight="bold" fill="#1e293b" />
|
|
92
|
+
</svg>
|
|
93
|
+
|
|
94
|
+
<button id="tsmc-share" class="tsmc-share-btn" title="Share">
|
|
95
|
+
<Icon name="mdi:share-variant" />
|
|
96
|
+
</button>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<style>
|
|
102
|
+
@import './two-stroke-fuel-mixture-calculator.css';
|
|
103
|
+
</style>
|
|
104
|
+
|
|
105
|
+
<script>
|
|
106
|
+
import { calculateMixture } from './logic';
|
|
107
|
+
|
|
108
|
+
const root = document.querySelector('.tsmc-root') as HTMLElement;
|
|
109
|
+
const ui = root ? JSON.parse(root.dataset.ui || '{}') : {};
|
|
110
|
+
|
|
111
|
+
const slider = document.getElementById('tsmc-slider') as HTMLInputElement;
|
|
112
|
+
const missionBtns = document.querySelectorAll('.tsmc-mission-btn');
|
|
113
|
+
const sliderUnit = document.getElementById('tsmc-slider-unit')!;
|
|
114
|
+
const sliderValue = document.getElementById('tsmc-slider-value')!;
|
|
115
|
+
const quickBtns = document.querySelectorAll('.tsmc-quick-btn');
|
|
116
|
+
const fuelBtns = document.querySelectorAll('.fuel-btn');
|
|
117
|
+
const oilBtns = document.querySelectorAll('.oil-btn');
|
|
118
|
+
const ratioCards = document.querySelectorAll('.tsmc-ratio-card');
|
|
119
|
+
const resultLabel = document.querySelector('.tsmc-result-label')!;
|
|
120
|
+
const resultValue = document.getElementById('tsmc-result-value')!;
|
|
121
|
+
const resultUnit = document.getElementById('tsmc-result-unit')!;
|
|
122
|
+
const fuelFill = document.getElementById('tsmc-fuel-fill')!;
|
|
123
|
+
const oilFill = document.getElementById('tsmc-oil-fill')!;
|
|
124
|
+
const ratioDisplay = document.getElementById('tsmc-ratio-display')!;
|
|
125
|
+
const shareBtn = document.getElementById('tsmc-share')!;
|
|
126
|
+
const volumeLabel = document.getElementById('tsmc-volume-label')!;
|
|
127
|
+
const container = document.querySelector('.tsmc-container')!;
|
|
128
|
+
|
|
129
|
+
const params = new URLSearchParams(window.location.search);
|
|
130
|
+
let currentMission: 'fuel' | 'oil' = (params.get('mode') as 'fuel' | 'oil') || 'fuel';
|
|
131
|
+
let currentVolume = parseFloat(params.get('volume') || '5');
|
|
132
|
+
let currentRatio = parseInt(params.get('ratio') || '40');
|
|
133
|
+
|
|
134
|
+
function setFuelMode(skipSliderUpdate: boolean) {
|
|
135
|
+
container.classList.remove('tsmc-oil-mode');
|
|
136
|
+
slider.min = '1';
|
|
137
|
+
slider.max = '50';
|
|
138
|
+
slider.step = '1';
|
|
139
|
+
if (!skipSliderUpdate) slider.value = '5';
|
|
140
|
+
sliderUnit.textContent = 'L';
|
|
141
|
+
volumeLabel.textContent = ui.labelVolume || 'Volume';
|
|
142
|
+
resultLabel.textContent = ui.labelOilRequired || 'Oil Required';
|
|
143
|
+
fuelBtns.forEach(btn => btn.classList.remove('hidden'));
|
|
144
|
+
oilBtns.forEach(btn => btn.classList.add('hidden'));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function setOilMode(skipSliderUpdate: boolean) {
|
|
148
|
+
container.classList.add('tsmc-oil-mode');
|
|
149
|
+
slider.min = '20';
|
|
150
|
+
slider.max = '1000';
|
|
151
|
+
slider.step = '10';
|
|
152
|
+
if (!skipSliderUpdate) slider.value = '125';
|
|
153
|
+
sliderUnit.textContent = 'ml';
|
|
154
|
+
volumeLabel.textContent = ui.labelOilRequired || 'Oil';
|
|
155
|
+
resultLabel.textContent = ui.labelFuelVolume || 'Fuel Required';
|
|
156
|
+
fuelBtns.forEach(btn => btn.classList.add('hidden'));
|
|
157
|
+
oilBtns.forEach(btn => btn.classList.remove('hidden'));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function setMission(mission: 'fuel' | 'oil', skipSliderUpdate = false) {
|
|
161
|
+
currentMission = mission;
|
|
162
|
+
missionBtns.forEach(btn => {
|
|
163
|
+
btn.classList.toggle('active', (btn as HTMLElement).getAttribute('data-mission') === mission);
|
|
164
|
+
});
|
|
165
|
+
if (mission === 'fuel') {
|
|
166
|
+
setFuelMode(skipSliderUpdate);
|
|
167
|
+
} else {
|
|
168
|
+
setOilMode(skipSliderUpdate);
|
|
169
|
+
}
|
|
170
|
+
sliderValue.textContent = currentVolume.toString();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function setVolume(volume: number) {
|
|
174
|
+
currentVolume = volume;
|
|
175
|
+
slider.value = String(volume);
|
|
176
|
+
sliderValue.textContent = volume.toFixed(1);
|
|
177
|
+
quickBtns.forEach(btn => {
|
|
178
|
+
btn.classList.toggle('active', parseFloat((btn as HTMLElement).getAttribute('data-volume') || '0') === volume);
|
|
179
|
+
});
|
|
180
|
+
calculate();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function setRatio(ratio: number) {
|
|
184
|
+
currentRatio = ratio;
|
|
185
|
+
ratioCards.forEach(card => {
|
|
186
|
+
card.classList.toggle('active', parseInt((card as HTMLElement).getAttribute('data-ratio') || '40') === ratio);
|
|
187
|
+
});
|
|
188
|
+
calculate();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function calculate() {
|
|
192
|
+
const calc = calculateMixture(currentVolume, currentRatio, ui);
|
|
193
|
+
|
|
194
|
+
if (calc.status === 'calculated') {
|
|
195
|
+
const oilMl = calc.oilRequired * (calc.displayUnit === 'ml' ? 1 : 1000);
|
|
196
|
+
|
|
197
|
+
if (oilMl < 1000) {
|
|
198
|
+
resultValue.textContent = oilMl.toFixed(0);
|
|
199
|
+
resultUnit.textContent = 'ml';
|
|
200
|
+
} else if (oilMl % 1000 === 0) {
|
|
201
|
+
resultValue.textContent = (oilMl / 1000).toFixed(0);
|
|
202
|
+
resultUnit.textContent = 'L';
|
|
203
|
+
} else {
|
|
204
|
+
resultValue.textContent = oilMl.toFixed(0);
|
|
205
|
+
resultUnit.textContent = 'ml';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
ratioDisplay.textContent = `1:${currentRatio}`;
|
|
209
|
+
|
|
210
|
+
const containerHeight = 120;
|
|
211
|
+
const oilRatioHeight = (1 / (1 + currentRatio)) * containerHeight;
|
|
212
|
+
|
|
213
|
+
fuelFill.setAttribute('y', (160 - containerHeight).toString());
|
|
214
|
+
fuelFill.setAttribute('height', containerHeight.toString());
|
|
215
|
+
|
|
216
|
+
oilFill.setAttribute('y', (160 - oilRatioHeight).toString());
|
|
217
|
+
oilFill.setAttribute('height', oilRatioHeight.toString());
|
|
218
|
+
} else {
|
|
219
|
+
resultValue.textContent = '--';
|
|
220
|
+
resultUnit.textContent = 'ml';
|
|
221
|
+
ratioDisplay.textContent = '';
|
|
222
|
+
fuelFill.setAttribute('height', '0');
|
|
223
|
+
oilFill.setAttribute('height', '0');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
missionBtns.forEach(btn => {
|
|
228
|
+
btn.addEventListener('click', () => {
|
|
229
|
+
setMission((btn as HTMLElement).getAttribute('data-mission') as 'fuel' | 'oil');
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
slider.addEventListener('input', (e) => {
|
|
234
|
+
setVolume(parseFloat((e.target as HTMLInputElement).value));
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
quickBtns.forEach(btn => {
|
|
238
|
+
btn.addEventListener('click', () => {
|
|
239
|
+
setVolume(parseFloat((btn as HTMLElement).getAttribute('data-volume') || '5'));
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
ratioCards.forEach(card => {
|
|
244
|
+
card.addEventListener('click', () => {
|
|
245
|
+
setRatio(parseInt((card as HTMLElement).getAttribute('data-ratio') || '40'));
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
shareBtn.addEventListener('click', () => {
|
|
250
|
+
const url = new URL(window.location.href);
|
|
251
|
+
url.searchParams.set('mode', currentMission);
|
|
252
|
+
url.searchParams.set('volume', String(currentVolume));
|
|
253
|
+
url.searchParams.set('ratio', String(currentRatio));
|
|
254
|
+
navigator.clipboard.writeText(url.toString()).then(() => {
|
|
255
|
+
const originalHTML = shareBtn.innerHTML;
|
|
256
|
+
shareBtn.innerHTML = '<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg>';
|
|
257
|
+
setTimeout(() => (shareBtn.innerHTML = originalHTML), 1500);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
setMission(currentMission, true);
|
|
262
|
+
setRatio(currentRatio);
|
|
263
|
+
slider.value = String(currentVolume);
|
|
264
|
+
sliderValue.textContent = currentVolume.toString();
|
|
265
|
+
calculate();
|
|
266
|
+
</script>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { DiyToolEntry } from '../../types';
|
|
2
|
+
import type { TwoStrokeMixtureCalculatorUI } from './ui';
|
|
3
|
+
|
|
4
|
+
export const twoStrokeMixtureCalculator: DiyToolEntry<TwoStrokeMixtureCalculatorUI> = {
|
|
5
|
+
id: 'two-stroke-fuel-mixture-calculator',
|
|
6
|
+
icons: { bg: 'mdi:gas-cylinder', fg: 'mdi:beaker-outline' },
|
|
7
|
+
i18n: {
|
|
8
|
+
de: () => import('./i18n/de').then((m) => m.content),
|
|
9
|
+
en: () => import('./i18n/en').then((m) => m.content),
|
|
10
|
+
es: () => import('./i18n/es').then((m) => m.content),
|
|
11
|
+
fr: () => import('./i18n/fr').then((m) => m.content),
|
|
12
|
+
id: () => import('./i18n/id').then((m) => m.content),
|
|
13
|
+
it: () => import('./i18n/it').then((m) => m.content),
|
|
14
|
+
ja: () => import('./i18n/ja').then((m) => m.content),
|
|
15
|
+
ko: () => import('./i18n/ko').then((m) => m.content),
|
|
16
|
+
nl: () => import('./i18n/nl').then((m) => m.content),
|
|
17
|
+
pl: () => import('./i18n/pl').then((m) => m.content),
|
|
18
|
+
pt: () => import('./i18n/pt').then((m) => m.content),
|
|
19
|
+
ru: () => import('./i18n/ru').then((m) => m.content),
|
|
20
|
+
sv: () => import('./i18n/sv').then((m) => m.content),
|
|
21
|
+
tr: () => import('./i18n/tr').then((m) => m.content),
|
|
22
|
+
zh: () => import('./i18n/zh').then((m) => m.content),
|
|
23
|
+
},
|
|
24
|
+
};
|