@jjlmoya/utils-aquarium 1.56.0 → 1.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +4 -1
  4. package/src/index.ts +2 -0
  5. package/src/layouts/PreviewLayout.astro +14 -1
  6. package/src/tests/i18n_coverage.test.ts +3 -1
  7. package/src/tests/seo_translation_completeness.test.ts +1 -1
  8. package/src/tests/tool_validation.test.ts +7 -4
  9. package/src/tool/aquariumFilterTurnoverStockingPlanner/aquarium-filter-turnover-stocking-planner.css +404 -0
  10. package/src/tool/aquariumFilterTurnoverStockingPlanner/bibliography.astro +7 -0
  11. package/src/tool/aquariumFilterTurnoverStockingPlanner/bibliography.ts +16 -0
  12. package/src/tool/aquariumFilterTurnoverStockingPlanner/component.astro +140 -0
  13. package/src/tool/aquariumFilterTurnoverStockingPlanner/content-builder.ts +43 -0
  14. package/src/tool/aquariumFilterTurnoverStockingPlanner/controller.ts +94 -0
  15. package/src/tool/aquariumFilterTurnoverStockingPlanner/dom-views.ts +63 -0
  16. package/src/tool/aquariumFilterTurnoverStockingPlanner/entry.ts +27 -0
  17. package/src/tool/aquariumFilterTurnoverStockingPlanner/evaluator.ts +17 -0
  18. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/de.ts +48 -0
  19. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/en.ts +124 -0
  20. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/es.ts +41 -0
  21. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/fr.ts +36 -0
  22. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/id.ts +36 -0
  23. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/it.ts +36 -0
  24. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/ja.ts +36 -0
  25. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/ko.ts +36 -0
  26. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/nl.ts +36 -0
  27. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/pl.ts +36 -0
  28. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/pt.ts +36 -0
  29. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/ru.ts +36 -0
  30. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/sv.ts +36 -0
  31. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/tr.ts +36 -0
  32. package/src/tool/aquariumFilterTurnoverStockingPlanner/i18n/zh.ts +36 -0
  33. package/src/tool/aquariumFilterTurnoverStockingPlanner/index.ts +11 -0
  34. package/src/tool/aquariumFilterTurnoverStockingPlanner/logic.test.ts +78 -0
  35. package/src/tool/aquariumFilterTurnoverStockingPlanner/logic.ts +99 -0
  36. package/src/tool/aquariumFilterTurnoverStockingPlanner/seo.astro +14 -0
  37. package/src/tool/aquariumFilterTurnoverStockingPlanner/storage.ts +21 -0
  38. package/src/tool/aquariumFilterTurnoverStockingPlanner/ui.ts +40 -0
  39. package/src/tools.ts +6 -0
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'aquarium-filter-turnover-stocking-planner',
5
+ title: '水槽フィルターの換水回転と飼育数プランナー',
6
+ description: '流量損失を考慮した実効ろ過流量を見積もり、水槽容量、環境、成魚の負荷が計画に与える影響を確認します。',
7
+ ui: {
8
+ presetsLabel: 'セットアップから始める', presetCommunity: '混泳水槽の例', presetPlanted: '水草水槽の例', presetHighWaste: '高負荷水槽の例', tankVolumeLabel: '水槽容量(リットル)', tankVolumeHint: '分かる場合は実際に使える水量を入力してください。', ratedFlowLabel: 'フィルター定格流量(リットル毎時)', ratedFlowHint: 'ポンプまたはフィルターの仕様値を使ってください。', flowLossLabel: '推定流量損失', flowLossHint: '揚程、ホース、曲がり、ろ材の抵抗を考慮します。', fishCountLabel: '成魚時の魚の数', averageLengthLabel: '成魚の平均体長(センチメートル)', setupLabel: '水槽タイプ', setupCommunity: '混泳', setupPlanted: '水草', setupHighWaste: '高負荷', resultEyebrow: '実効フィルター回転数', effectiveTurnoverLabel: '実効回転数', targetLabel: '計画目安', effectiveFlowLabel: '損失後の流量', stockingProxyLabel: '飼育負荷の目安', currentTitle: '水流の軌跡を見る', currentDescription: '水流はフィルターから出て水槽を横切り、吸水口へ戻ります。速度は実効回転数に応じて変わります。', statusUnder: '目安未満', statusTarget: '目安の範囲内', statusHigh: '目安超過', loadLight: '軽い負荷の目安', loadModerate: '中程度の負荷の目安', loadHeavy: '重い負荷の目安', cautionTitle: '最後は水質検査で確認', bandSignalInside: '計画目安の範囲内', bandSignalBelow: '目安より不足', bandSignalAbove: '目安より超過', maintenanceText: '損失が大きい場合は、大型フィルターを選ぶ前に吸水口、ホース、ろ材を点検してください。', useTestKits: '回転数は生物ろ過能力を測るものではありません。アンモニア、亜硝酸、硝酸を検査し、各種の魚に合う水流にしてください。', metricLiters: 'L', metricPerHour: '毎時', metricCentimetersPerLiter: 'cm/L',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: 'ポンプの表示だけでなく実効流量で計画する' },
12
+ { type: 'paragraph', html: 'フィルター回転数は、水流量と水槽容量の比率です。100リットルの水槽に毎時600リットルのフィルターなら、損失前は毎時6回の回転になります。揚程、ホース、ろ材で25パーセント失われると、実効値は毎時450リットル、4.5回になります。' },
13
+ { type: 'title', level: 2, text: '計画目安の読み方' },
14
+ { type: 'table', headers: ['水槽タイプ', '計画目安', '意味'], rows: [['混泳', '毎時4から6回', '中程度の水流を考える出発点'], ['水草', '毎時3から5回', '水草水槽向けの穏やかな出発点'], ['高負荷', '毎時6から10回', '排出物が多い環境の強めの水流目安']] },
15
+ { type: 'paragraph', html: 'これらはこのプランナーに組み込んだ目安であり、すべての水槽に適用できる規則ではありません。魚種によって泳ぎ方や水流への耐性は異なります。高い回転数だけで、生物ろ過の成熟や安全な飼育数を証明することはできません。' },
16
+ { type: 'title', level: 2, text: '流量損失を別の入力にする理由' },
17
+ { type: 'paragraph', html: 'フィルターに表示された流量は、決められた条件で測定された値かもしれません。揚程、ホースの経路、汚れたスポンジ、詰まった吸水口、詰め込みすぎたろ材は、実際に水槽へ戻る流量を変えます。可能なら出口の流量を測り、難しければ損失の仮定を明示してメンテナンス後に見直してください。' },
18
+ { type: 'title', level: 2, text: '飼育数の数値は警告サインとして使う' },
19
+ { type: 'paragraph', html: '飼育負荷の目安は、成魚の数に平均体長を掛け、水槽のリットル数で割った単純な値です。確認しやすい一方で、意図的に不完全です。体型、活動量、縄張り、給餌量、酸素需要、相性、レイアウトや底床の占有量は含みません。' },
20
+ { type: 'tip', title: '水質で判断する', html: '魚を追加した後や給餌量を増やした後は、特にアンモニアと亜硝酸を定期的に測定してください。水質が安定していなければ、回転数の計算を変えても追加の魚を迎える準備にはなりません。' },
21
+ { type: 'diagnostic', variant: 'warning', title: '結果を飼育数の保証にしない', badge: '限界', html: '魚種ごとの飼育条件、成魚サイズ、行動、水質、フィルターの成熟度は、この計画結果より優先されます。珍しい魚種や環境では経験のある専門家に相談してください。' },
22
+ ],
23
+ faq: [
24
+ { question: 'フィルター回転数とは何ですか?', answer: '1時間にフィルターが水槽容量を何回動かすかの推定値です。このプランナーはポンプ定格だけでなく、推定損失後の流量を使います。' },
25
+ { question: '定格流量と実際の流量が違うのはなぜですか?', answer: 'メーカー値は条件を決めて測定されることがあります。揚程、ホースの長さ、曲がり、詰まったろ材、汚れたスポンジによって水槽に届く流量は減ります。' },
26
+ { question: '飼える魚の数を教えてくれますか?', answer: 'いいえ。魚の入力欄は、成魚の体長を1リットルあたりで見る透明な負荷目安を作るだけです。魚種、行動、成長後の大きさ、相性、給餌、水質、ろ過の成熟度は別に調べる必要があります。' },
27
+ { question: '結果が目安未満ならどうしますか?', answer: 'ろ材の詰まり、折れたホース、過大な揚程を確認し、可能なら出口を測定してください。数値を補うために魚を増やさず、アンモニア、亜硝酸、硝酸を検査してください。' },
28
+ { question: '回転数が高いほど良いのですか?', answer: 'いいえ。強い水流は、穏やかな水を好む魚や水草に合わない場合があります。各魚種の飼育情報と目安を比較してください。' },
29
+ ],
30
+ howTo: [
31
+ { name: '水槽容量を入力する', text: '計画の基準にする水量を入力します。外寸ではなく、できれば実際に使える水量を使います。' },
32
+ { name: 'フィルター定格を入力する', text: 'メーカーの毎時流量を入力し、ホース、高さ、ろ材による低下を見積もります。' },
33
+ { name: '魚の負荷を入力する', text: '魚の数と成魚の平均体長を入力します。ツールはcm毎リットルの目安を作りますが、飼育数の保証ではありません。' },
34
+ { name: '水流の軌跡を読む', text: '実効回転数を水槽タイプの目安と比較し、機材や魚を変更する前に警告と水質検査の案内を確認します。' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'aquarium-filter-turnover-stocking-planner',
5
+ title: '수족관 여과기 순환량과 사육 밀도 계획기',
6
+ description: '유량 손실을 반영한 실제 여과기 순환량을 추정하고 수조 용량, 환경, 성어의 부담이 계획에 미치는 영향을 확인합니다.',
7
+ ui: {
8
+ presetsLabel: '환경 예시로 시작', presetCommunity: '커뮤니티 예시', presetPlanted: '수초 예시', presetHighWaste: '고부하 예시', tankVolumeLabel: '수조 용량(리터)', tankVolumeHint: '알고 있다면 실제 사용 수량을 입력하세요.', ratedFlowLabel: '여과기 정격 유량(시간당 리터)', ratedFlowHint: '펌프나 여과기의 사양을 사용하세요.', flowLossLabel: '예상 유량 손실', flowLossHint: '양정, 호스, 굴곡과 여과재 저항을 고려하세요.', fishCountLabel: '성어 기준 물고기 수', averageLengthLabel: '성어 평균 길이(센티미터)', setupLabel: '수조 유형', setupCommunity: '커뮤니티', setupPlanted: '수초', setupHighWaste: '고부하', resultEyebrow: '실효 여과기 순환량', effectiveTurnoverLabel: '실효 순환량', targetLabel: '계획 범위', effectiveFlowLabel: '손실 후 유량', stockingProxyLabel: '사육 부담 참고값', currentTitle: '물살의 흐름 보기', currentDescription: '물살은 여과기에서 나와 수조를 가로지른 뒤 흡수구로 돌아옵니다. 속도는 실효 순환량에 따라 달라집니다.', statusUnder: '범위 미만', statusTarget: '범위 안', statusHigh: '범위 초과', loadLight: '낮은 부담 참고값', loadModerate: '중간 부담 참고값', loadHeavy: '높은 부담 참고값', cautionTitle: '마지막 확인은 수질 검사', bandSignalInside: '계획 범위 안', bandSignalBelow: '범위보다 부족', bandSignalAbove: '범위보다 초과', maintenanceText: '손실 추정치가 높다면 더 큰 여과기를 고르기 전에 흡수구, 호스와 여과재를 점검하세요.', useTestKits: '순환량은 생물학적 여과 능력을 측정하지 않습니다. 암모니아, 아질산염, 질산염을 검사하고 모든 종의 물살 선호에 맞추세요.', metricLiters: 'L', metricPerHour: '시간당', metricCentimetersPerLiter: 'cm/L',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: '펌프 표시만이 아니라 실효 유량으로 계획하기' },
12
+ { type: 'paragraph', html: '여과기 순환량은 물의 유량을 수조 용량으로 나눈 값입니다. 100리터 수조에 시간당 600리터로 표시된 여과기는 손실 전 시간당 6회 순환을 뜻합니다. 양정, 호스, 여과재로 25퍼센트가 줄면 실제 계획값은 시간당 450리터와 4.5회 순환입니다.' },
13
+ { type: 'title', level: 2, text: '계획 범위를 읽는 방법' },
14
+ { type: 'table', headers: ['수조 유형', '계획 범위', '의미'], rows: [['커뮤니티', '시간당 4에서 6회', '중간 정도 물살을 위한 시작점'], ['수초', '시간당 3에서 5회', '수초 수조를 위한 더 부드러운 시작점'], ['고부하', '시간당 6에서 10회', '배설물 부담이 큰 환경을 위한 강한 물살 신호']] },
15
+ { type: 'paragraph', html: '이 범위는 이 도구에 내장된 경험적 기준이며 모든 수조에 적용되는 규칙은 아닙니다. 종마다 헤엄치는 방식과 물살 내성이 다릅니다. 순환량이 높다고 생물학적 여과가 성숙했거나 사육이 안전하다는 뜻은 아닙니다.' },
16
+ { type: 'title', level: 2, text: '유량 손실을 별도 입력으로 두는 이유' },
17
+ { type: 'paragraph', html: '여과기에 적힌 유량은 정해진 조건에서 측정된 값일 수 있습니다. 양정, 호스 경로, 더러운 스펀지, 막힌 흡수구와 빽빽한 여과재는 실제 수조로 돌아오는 유량을 바꿉니다. 가능하면 출수 유량을 측정하고, 그렇지 않다면 손실 가정을 표시한 뒤 관리 후 다시 확인하세요.' },
18
+ { type: 'title', level: 2, text: '사육 수치는 경고 신호로 사용하기' },
19
+ { type: 'paragraph', html: '사육 부담 참고값은 성어 수에 평균 성어 길이를 곱한 뒤 수조 리터로 나눈 값입니다. 확인하기 쉽지만 의도적으로 불완전합니다. 체형, 활동량, 영역, 먹이량, 산소 수요, 합사 가능성, 장식과 바닥재가 차지하는 공간은 포함하지 않습니다.' },
20
+ { type: 'tip', title: '수질로 판단하기', html: '물고기를 추가하거나 먹이를 늘린 뒤에는 특히 암모니아와 아질산염을 정기적으로 검사하세요. 수질이 안정되지 않았다면 순환량 계산을 바꿔도 추가 생물을 들일 준비가 된 것은 아닙니다.' },
21
+ { type: 'diagnostic', variant: 'warning', title: '결과를 사육 보장으로 바꾸지 않기', badge: '한계', html: '종별 관리법, 성어 크기, 행동, 수질 조건과 여과기 성숙도는 이 계획 결과보다 우선할 수 있습니다. 특이한 종이나 환경이라면 수생 생물 전문가에게 상담하세요.' },
22
+ ],
23
+ faq: [
24
+ { question: '여과기 순환량은 무엇인가요?', answer: '한 시간 동안 여과기가 수조 용량을 몇 번 이동시키는지 추정한 값입니다. 이 도구는 펌프 정격뿐 아니라 예상 손실 후 유량을 사용합니다.' },
25
+ { question: '정격 유량과 실제 유량은 왜 다른가요?', answer: '제조사 수치는 특정 조건에서 측정될 수 있습니다. 양정, 호스 길이, 굴곡, 막힌 여과재와 더러운 스펀지가 수조에 도달하는 유량을 줄일 수 있습니다.' },
26
+ { question: '몇 마리의 물고기를 키울 수 있는지 알려주나요?', answer: '아니요. 물고기 입력값은 성어 길이를 리터로 나눈 투명한 부담 참고값을 만들 뿐입니다. 종, 행동, 성어 크기, 합사, 먹이, 수질과 여과기 성숙도는 별도로 확인해야 합니다.' },
27
+ { question: '결과가 범위보다 낮으면 어떻게 하나요?', answer: '막힌 여과재, 꺾인 호스와 과도한 양정을 확인하고 가능하면 출수를 측정하세요. 낮은 수치를 보충하려고 물고기를 추가하지 말고 암모니아, 아질산염과 질산염을 검사하세요.' },
28
+ { question: '순환량이 높을수록 항상 좋은가요?', answer: '아니요. 강한 물살은 잔잔한 물을 선호하는 종이나 수초에 맞지 않을 수 있습니다. 각 종의 관리 정보를 범위와 비교하세요.' },
29
+ ],
30
+ howTo: [
31
+ { name: '수조 용량 입력하기', text: '계획에 사용할 물의 양을 입력합니다. 유리 외부 치수보다 실제 사용 수량을 우선하세요.' },
32
+ { name: '여과기 정격 추가하기', text: '제조사가 표시한 시간당 유량을 입력하고 호스, 높이와 여과재로 인한 감소를 추정합니다.' },
33
+ { name: '물고기 부담 설명하기', text: '물고기 수와 성어 평균 길이를 입력합니다. 도구는 cm/리터 참고값을 만들며 사육 보장은 하지 않습니다.' },
34
+ { name: '물살 흐름 읽기', text: '실효 순환량을 수조 유형의 범위와 비교하고 장비나 생물을 바꾸기 전에 경고와 수질 안내를 확인합니다.' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'aquarium-filter-doorstroming-bezettingsplanner',
5
+ title: 'Planner voor filterdoorstroming en visbezetting in het aquarium',
6
+ description: 'Schat de werkelijke filterdoorstroming na stromingsverlies en bekijk hoe volume, inrichting en volwassen vissen de planning beïnvloeden.',
7
+ ui: {
8
+ presetsLabel: 'Begin met een opstelling', presetCommunity: 'Voorbeeld gezelschapsbak', presetPlanted: 'Voorbeeld plantenbak', presetHighWaste: 'Voorbeeld hoge afvalbelasting', tankVolumeLabel: 'Inhoud van de bak in liter', tankVolumeHint: 'Gebruik de bruikbare waterinhoud als je die kent.', ratedFlowLabel: 'Nominale filterdoorstroming in liter per uur', ratedFlowHint: 'Gebruik de specificatie van pomp of filter.', flowLossLabel: 'Geschat stromingsverlies', flowLossHint: 'Houd rekening met opvoerhoogte, slangen, bochten en filtermateriaal.', fishCountLabel: 'Aantal volwassen vissen', averageLengthLabel: 'Gemiddelde volwassen lengte in centimeter', setupLabel: 'Profiel van de opstelling', setupCommunity: 'Gezelschapsbak', setupPlanted: 'Plantenbak', setupHighWaste: 'Hoge belasting', resultEyebrow: 'Effectieve filterdoorstroming', effectiveTurnoverLabel: 'Effectieve doorstroming', targetLabel: 'Planningsbereik', effectiveFlowLabel: 'Doorstroming na verlies', stockingProxyLabel: 'Indicatieve bezettingsindex', currentTitle: 'Volg het stromingsspoor', currentDescription: 'De stroming verlaat het filter, gaat door de bak en keert terug naar de aanzuiging. De snelheid reageert op de effectieve doorstroming.', statusUnder: 'Onder het bereik', statusTarget: 'Binnen het bereik', statusHigh: 'Boven het bereik', loadLight: 'Lichte bezettingsindex', loadModerate: 'Gemiddelde bezettingsindex', loadHeavy: 'Hoge bezettingsindex', cautionTitle: 'De watertest is de laatste controle', bandSignalInside: 'Binnen het planningsbereik', bandSignalBelow: 'Onder het bereik met', bandSignalAbove: 'Boven het bereik met', maintenanceText: 'Als het verlies hoog wordt geschat, controleer dan aanzuiging, slangen en filtermateriaal voordat je een groter filter kiest.', useTestKits: 'Doorstroming meet geen biologische capaciteit. Test ammoniak, nitriet en nitraat en stem de stroming af op elke soort.', metricLiters: 'L', metricPerHour: 'per uur', metricCentimetersPerLiter: 'cm/L',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: 'Plan met effectieve doorstroming en niet alleen met het pompplaatje' },
12
+ { type: 'paragraph', html: 'Filterdoorstroming is de verhouding tussen waterstroom en bakinhoud. Een filter met een opgegeven capaciteit van 600 liter per uur op een bak van 100 liter geeft vóór verlies 6 omwentelingen per uur. Bij 25 procent verlies door opvoerhoogte, slangen en filtermateriaal wordt de werkinschatting 450 liter per uur en 4,5 omwentelingen.' },
13
+ { type: 'title', level: 2, text: 'Het planningsbereik lezen' },
14
+ { type: 'table', headers: ['Profiel', 'Planningsbereik', 'Wat het voorstelt'], rows: [['Gezelschapsbak', '4 tot 6 keer per uur', 'Een gematigd startpunt voor stroming'], ['Plantenbak', '3 tot 5 keer per uur', 'Een zachter startpunt voor beplante bakken'], ['Hoge belasting', '6 tot 10 keer per uur', 'Een sterker signaal bij meer afval']] },
15
+ { type: 'paragraph', html: 'Deze bereiken zijn heuristieken van de planner en geen universele aquariumregels. Soorten verschillen in zwemgedrag en tolerantie voor stroming. Een hoog getal bewijst niet dat biologische filtering rijp is of dat de bezetting veilig is.' },
16
+ { type: 'title', level: 2, text: 'Waarom stromingsverlies een eigen invoer verdient' },
17
+ { type: 'paragraph', html: 'Het getal op een filter kan onder vastgelegde omstandigheden zijn gemeten. Opvoerhoogte, slangtraject, vuile sponzen, verstopte aanzuigroosters en samengeperst materiaal veranderen de stroom die werkelijk in de bak terugkomt. Meet de uitlaat als dat kan; maak anders je aanname zichtbaar en controleer haar na onderhoud opnieuw.' },
18
+ { type: 'title', level: 2, text: 'Gebruik het bezettingsgetal als waarschuwingssignaal' },
19
+ { type: 'paragraph', html: 'De bezettingsindex is het aantal volwassen vissen maal hun gemiddelde volwassen lengte, gedeeld door het aantal liter. Hij is eenvoudig te controleren maar bewust onvolledig. Lichaamsvorm, activiteit, territorium, voeding, zuurstofbehoefte, verenigbaarheid en ruimte voor decoratie en bodem zijn niet meegenomen.' },
20
+ { type: 'tip', title: 'Laat waterchemie de beslissing sturen', html: 'Test ammoniak en nitriet regelmatig, vooral na het toevoegen van vissen of extra voer. Als de waterchemie niet stabiel is, maakt een andere doorstromingsinschatting de bak niet klaar voor meer dieren.' },
21
+ { type: 'diagnostic', variant: 'warning', title: 'Maak van de uitkomst geen bezettingsgarantie', badge: 'Beperking', html: 'Soortspecifieke verzorging, volwassen formaat, gedrag, waterwaarden en filterrijping kunnen belangrijker zijn dan deze planning. Vraag deskundig advies bij een ongebruikelijke soort of opstelling.' },
22
+ ],
23
+ faq: [
24
+ { question: 'Wat betekent filterdoorstroming?', answer: 'Het is een schatting van hoe vaak het filter de bakinhoud in een uur verplaatst. Deze planner gebruikt de stroom na een geschat verlies, niet alleen de pompwaarde.' },
25
+ { question: 'Waarom is nominale filterstroom niet gelijk aan echte stroom?', answer: 'Fabrikantwaarden kunnen onder bepaalde omstandigheden zijn gemeten. Opvoerhoogte, slanglengte, bochten, verstopt materiaal en vuile sponzen verminderen de stroom die de bak bereikt.' },
26
+ { question: 'Vertelt dit hoeveel vissen ik kan houden?', answer: 'Nee. De visvelden maken een transparante bezettingsindex op basis van volwassen lengte per liter. Soort, gedrag, formaat, verenigbaarheid, voeding, waterkwaliteit en filterrijping moeten apart worden onderzocht.' },
27
+ { question: 'Wat doe ik als de uitkomst onder het bereik ligt?', answer: 'Controleer verstopt materiaal, geknikte slangen en te veel opvoerhoogte en meet de uitlaat als dat kan. Voeg geen vissen toe om een laag getal te compenseren en test ammoniak, nitriet en nitraat.' },
28
+ { question: 'Is meer doorstroming altijd beter?', answer: 'Nee. Sterke stroming kan ongeschikt zijn voor soorten of planten die rustiger water nodig hebben. Vergelijk het bereik met de verzorgingsinformatie per soort.' },
29
+ ],
30
+ howTo: [
31
+ { name: 'Vul de bakinhoud in', text: 'Gebruik het watervolume waarop je wilt plannen, bij voorkeur de bruikbare inhoud en niet de buitenmaten van het glas.' },
32
+ { name: 'Voeg de filterwaarde toe', text: 'Vul de opgegeven doorstroming in liter per uur in en schat de vermindering door slangen, hoogte en filtermateriaal.' },
33
+ { name: 'Beschrijf de visbelasting', text: 'Vul het aantal vissen en hun gemiddelde volwassen lengte in. De tool maakt een cm per liter index, geen bezettingsgarantie.' },
34
+ { name: 'Lees het stromingsspoor', text: 'Vergelijk de effectieve doorstroming met het profiel en gebruik waarschuwing en watertestadvies voordat je techniek of dieren wijzigt.' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'planowanie-przeplywu-filtra-i-zarybienia-akwarium',
5
+ title: 'Planer przepływu filtra i obsady akwarium',
6
+ description: 'Oszacuj rzeczywisty przepływ filtra po uwzględnieniu strat i sprawdź, jak objętość, aranżacja oraz dorosłe ryby wpływają na plan.',
7
+ ui: {
8
+ presetsLabel: 'Zacznij od konfiguracji', presetCommunity: 'Przykład akwarium towarzyskiego', presetPlanted: 'Przykład akwarium roślinnego', presetHighWaste: 'Przykład dużego obciążenia', tankVolumeLabel: 'Objętość akwarium w litrach', tankVolumeHint: 'Jeśli ją znasz, podaj użyteczną objętość wody.', ratedFlowLabel: 'Znamionowy przepływ filtra w litrach na godzinę', ratedFlowHint: 'Użyj danych pompy lub filtra.', flowLossLabel: 'Szacowana strata przepływu', flowLossHint: 'Uwzględnij wysokość podnoszenia, węże, kolanka i opór mediów.', fishCountLabel: 'Liczba dorosłych ryb', averageLengthLabel: 'Średnia długość dorosłej ryby w centymetrach', setupLabel: 'Profil akwarium', setupCommunity: 'Towarzyskie', setupPlanted: 'Roślinne', setupHighWaste: 'Duże obciążenie', resultEyebrow: 'Efektywny przepływ filtra', effectiveTurnoverLabel: 'Efektywny przepływ', targetLabel: 'Zakres planowania', effectiveFlowLabel: 'Przepływ po stracie', stockingProxyLabel: 'Wskaźnik obciążenia obsadą', currentTitle: 'Śledź ścieżkę prądu', currentDescription: 'Prąd wypływa z filtra, przechodzi przez akwarium i wraca do wlotu. Jego prędkość reaguje na efektywny przepływ.', statusUnder: 'Poniżej zakresu', statusTarget: 'W zakresie', statusHigh: 'Powyżej zakresu', loadLight: 'Niskie obciążenie', loadModerate: 'Średnie obciążenie', loadHeavy: 'Wysokie obciążenie', cautionTitle: 'Test wody jest ostatnim sprawdzeniem', bandSignalInside: 'W zakresie planowania', bandSignalBelow: 'Poniżej zakresu o', bandSignalAbove: 'Powyżej zakresu o', maintenanceText: 'Jeśli strata jest wysoka, sprawdź wlot, węże i media, zanim wybierzesz większy filtr.', useTestKits: 'Przepływ nie mierzy wydajności biologicznej. Sprawdzaj amoniak, azotyny i azotany i dopasuj prąd do potrzeb każdego gatunku.', metricLiters: 'l', metricPerHour: 'na godzinę', metricCentimetersPerLiter: 'cm/l',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: 'Planuj według efektywnego przepływu, nie tylko etykiety pompy' },
12
+ { type: 'paragraph', html: 'Przepływ filtra to stosunek przepływu wody do objętości akwarium. Filtr o deklarowanym przepływie 600 litrów na godzinę w akwarium o objętości 100 litrów daje przed stratami 6 obiegów na godzinę. Przy stracie 25 procent przez wysokość, węże i media szacowany przepływ roboczy wynosi 450 litrów na godzinę i 4,5 obiegu.' },
13
+ { type: 'title', level: 2, text: 'Jak czytać zakres planowania' },
14
+ { type: 'table', headers: ['Profil', 'Zakres planowania', 'Co oznacza'], rows: [['Towarzyskie', '4 do 6 razy na godzinę', 'Umiarkowany punkt wyjścia dla cyrkulacji'], ['Roślinne', '3 do 5 razy na godzinę', 'Łagodniejszy punkt wyjścia dla akwarium z roślinami'], ['Duże obciążenie', '6 do 10 razy na godzinę', 'Silniejszy sygnał przy większej ilości odpadów']] },
15
+ { type: 'paragraph', html: 'Te zakresy są heurystykami wbudowanymi w planer, a nie uniwersalnymi zasadami akwarystyki. Gatunki różnią się zachowaniem i tolerancją prądu. Wysoka liczba nie dowodzi dojrzałości filtracji biologicznej ani bezpieczeństwa obsady.' },
16
+ { type: 'title', level: 2, text: 'Dlaczego strata przepływu ma osobne pole' },
17
+ { type: 'paragraph', html: 'Wartość podana na filtrze może być mierzona w określonych warunkach. Wysokość, prowadzenie węży, brudne gąbki, zatkane kosze wlotowe i zbyt ciasno ułożone media zmieniają przepływ, który faktycznie wraca do akwarium. Jeśli możesz, zmierz wylot; w przeciwnym razie pokaż założenie straty i sprawdź je ponownie po konserwacji.' },
18
+ { type: 'title', level: 2, text: 'Traktuj liczbę obsady jako sygnał ostrzegawczy' },
19
+ { type: 'paragraph', html: 'Wskaźnik obciążenia obsadą to liczba dorosłych ryb pomnożona przez ich średnią długość i podzielona przez liczbę litrów. Jest łatwy do sprawdzenia, ale celowo niepełny. Nie uwzględnia kształtu, aktywności, terytorium, karmienia, zapotrzebowania na tlen, zgodności ani miejsca zajętego przez dekoracje i podłoże.' },
20
+ { type: 'tip', title: 'Decyzję oprzyj na chemii wody', html: 'Regularnie sprawdzaj amoniak i azotyny, szczególnie po dodaniu ryb lub zwiększeniu karmienia. Jeśli parametry nie są stabilne, zmiana szacunku przepływu nie przygotuje akwarium na dodatkowe zwierzęta.' },
21
+ { type: 'diagnostic', variant: 'warning', title: 'Nie zamieniaj wyniku w gwarancję obsady', badge: 'Ograniczenie', html: 'Wymagania gatunku, rozmiar dorosły, zachowanie, parametry wody i dojrzałość filtra mogą być ważniejsze od tego wyniku. Przy nietypowym gatunku lub układzie zasięgnij porady specjalisty.' },
22
+ ],
23
+ faq: [
24
+ { question: 'Co oznacza przepływ filtra?', answer: 'To szacunek, ile razy filtr przenosi objętość akwarium w ciągu godziny. Planer używa przepływu po szacowanej stracie, a nie tylko wartości pompy.' },
25
+ { question: 'Dlaczego przepływ znamionowy różni się od rzeczywistego?', answer: 'Dane producenta mogą być mierzone w konkretnych warunkach. Wysokość, długość węży, kolanka, zatkane media i brudne gąbki zmniejszają przepływ docierający do akwarium.' },
26
+ { question: 'Czy narzędzie mówi, ile ryb mogę trzymać?', answer: 'Nie. Pola ryb tworzą przejrzysty wskaźnik obciążenia na podstawie długości dorosłej ryby na litr. Gatunek, zachowanie, rozmiar, zgodność, karmienie, jakość wody i dojrzałość filtra trzeba sprawdzić osobno.' },
27
+ { question: 'Co zrobić, gdy wynik jest poniżej zakresu?', answer: 'Sprawdź zatkane media, zagięte węże i zbyt dużą wysokość podnoszenia, a jeśli możesz zmierz wylot. Nie dodawaj ryb, aby wyrównać niski wynik, i sprawdź amoniak, azotyny oraz azotany.' },
28
+ { question: 'Czy większy przepływ zawsze jest lepszy?', answer: 'Nie. Silny prąd może nie pasować gatunkom lub roślinom preferującym spokojniejszą wodę. Porównaj zakres z wymaganiami konkretnego gatunku.' },
29
+ ],
30
+ howTo: [
31
+ { name: 'Wpisz objętość akwarium', text: 'Podaj objętość wody, dla której planujesz, najlepiej użyteczną objętość zamiast zewnętrznych wymiarów szkła.' },
32
+ { name: 'Dodaj wydajność filtra', text: 'Wpisz przepływ producenta w litrach na godzinę i oszacuj spadek wywołany przez węże, wysokość i media.' },
33
+ { name: 'Opisz obciążenie rybami', text: 'Wpisz liczbę ryb i ich średnią długość dorosłą. Narzędzie tworzy wskaźnik cm na litr, a nie gwarancję obsady.' },
34
+ { name: 'Odczytaj ścieżkę prądu', text: 'Porównaj efektywny przepływ z profilem akwarium i użyj ostrzeżenia oraz wskazówek dotyczących wody przed zmianą sprzętu lub zwierząt.' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'planejador-vazao-filtro-e-povoamento-aquario',
5
+ title: 'Planejador de vazão do filtro e povoamento do aquário',
6
+ description: 'Estime a vazão real do filtro depois das perdas e veja como o volume, a montagem e os peixes adultos alteram o planejamento.',
7
+ ui: {
8
+ presetsLabel: 'Comece com uma montagem', presetCommunity: 'Exemplo comunitário', presetPlanted: 'Exemplo plantado', presetHighWaste: 'Exemplo de alta carga', tankVolumeLabel: 'Volume do aquário em litros', tankVolumeHint: 'Use o volume de água útil quando souber.', ratedFlowLabel: 'Vazão nominal do filtro em litros por hora', ratedFlowHint: 'Use a especificação da bomba ou do filtro.', flowLossLabel: 'Perda de vazão estimada', flowLossHint: 'Considere altura, mangueiras, curvas e resistência das mídias.', fishCountLabel: 'Quantidade de peixes adultos', averageLengthLabel: 'Comprimento médio adulto em centímetros', setupLabel: 'Perfil da montagem', setupCommunity: 'Comunitário', setupPlanted: 'Plantado', setupHighWaste: 'Alta carga', resultEyebrow: 'Vazão efetiva do filtro', effectiveTurnoverLabel: 'Vazão efetiva', targetLabel: 'Faixa de planejamento', effectiveFlowLabel: 'Vazão após a perda', stockingProxyLabel: 'Índice indicativo de povoamento', currentTitle: 'Siga o trajeto da correnteza', currentDescription: 'A correnteza sai do filtro, atravessa o aquário e retorna à entrada. Sua velocidade responde à vazão efetiva.', statusUnder: 'Abaixo da faixa', statusTarget: 'Dentro da faixa', statusHigh: 'Acima da faixa', loadLight: 'Índice de carga leve', loadModerate: 'Índice de carga moderada', loadHeavy: 'Índice de carga alta', cautionTitle: 'O teste da água é a verificação final', bandSignalInside: 'Dentro da faixa de planejamento', bandSignalBelow: 'Abaixo da faixa por', bandSignalAbove: 'Acima da faixa por', maintenanceText: 'Se a perda estimada for alta, verifique a entrada, as mangueiras e as mídias antes de escolher um filtro maior.', useTestKits: 'A vazão não mede a capacidade biológica. Teste amônia, nitrito e nitrato e ajuste a correnteza às necessidades de cada espécie.', metricLiters: 'L', metricPerHour: 'por hora', metricCentimetersPerLiter: 'cm/L',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: 'Planeje com a vazão efetiva e não apenas com a etiqueta da bomba' },
12
+ { type: 'paragraph', html: 'A vazão do filtro é a relação entre o fluxo de água e o volume do aquário. Um filtro anunciado com 600 litros por hora em um aquário de 100 litros sugere 6 renovações por hora antes das perdas. Se a montagem perder 25 por cento por altura, mangueiras e mídias, a estimativa de trabalho passa a 450 litros por hora e 4,5 renovações.' },
13
+ { type: 'title', level: 2, text: 'Como ler a faixa de planejamento' },
14
+ { type: 'table', headers: ['Perfil', 'Faixa de planejamento', 'O que representa'], rows: [['Comunitário', '4 a 6 vezes por hora', 'Um ponto de partida para correnteza moderada'], ['Plantado', '3 a 5 vezes por hora', 'Um ponto de partida mais suave para aquários com plantas'], ['Alta carga', '6 a 10 vezes por hora', 'Um sinal de correnteza mais forte para mais resíduos']] },
15
+ { type: 'paragraph', html: 'Essas faixas são heurísticas do planejador, não regras universais para aquários. As espécies diferem no comportamento de natação e na tolerância à correnteza. Um número alto não prova que a filtragem biológica está madura ou que o povoamento é seguro.' },
16
+ { type: 'title', level: 2, text: 'Por que a perda de vazão merece um campo próprio' },
17
+ { type: 'paragraph', html: 'O número impresso no filtro pode ter sido medido em condições definidas. Altura, percurso das mangueiras, esponjas sujas, entradas obstruídas e mídias compactadas alteram a água que realmente retorna ao aquário. Meça a saída quando possível; caso contrário, deixe a suposição visível e reveja depois da manutenção.' },
18
+ { type: 'title', level: 2, text: 'Trate o número de povoamento como sinal de alerta' },
19
+ { type: 'paragraph', html: 'O índice indicativo multiplica a quantidade de peixes adultos pelo comprimento adulto médio e divide pelo volume em litros. É fácil de verificar, mas deliberadamente incompleto. Não considera formato, atividade, território, alimentação, demanda de oxigênio, compatibilidade ou o espaço ocupado por decoração e substrato.' },
20
+ { type: 'tip', title: 'Use a química da água para decidir', html: 'Teste amônia e nitrito regularmente, especialmente depois de adicionar peixes ou aumentar a alimentação. Se a química não estiver estável, mudar a estimativa de vazão não prepara o aquário para mais animais.' },
21
+ { type: 'diagnostic', variant: 'warning', title: 'Não transforme o resultado em garantia de povoamento', badge: 'Limite', html: 'Cuidados específicos, tamanho adulto, comportamento, parâmetros da água e maturidade do filtro podem ser mais importantes que este resultado. Procure orientação especializada quando a espécie ou a montagem for incomum.' },
22
+ ],
23
+ faq: [
24
+ { question: 'O que significa a vazão do filtro?', answer: 'É a estimativa de quantas vezes o filtro movimenta o volume do aquário em uma hora. Este planejador usa a vazão depois de uma perda estimada, não apenas o valor da bomba.' },
25
+ { question: 'Por que a vazão nominal não é igual à vazão real?', answer: 'Os valores do fabricante podem ser medidos em condições específicas. Altura, comprimento das mangueiras, curvas, mídias obstruídas e esponjas sujas reduzem a vazão que chega ao aquário.' },
26
+ { question: 'A ferramenta diz quantos peixes posso manter?', answer: 'Não. Os campos de peixes criam um índice transparente baseado no comprimento adulto por litro. Espécie, comportamento, tamanho, compatibilidade, alimentação, qualidade da água e maturidade do filtro precisam de pesquisa separada.' },
27
+ { question: 'O que fazer se o resultado ficar abaixo da faixa?', answer: 'Verifique mídias obstruídas, mangueiras dobradas e altura excessiva e meça a saída se possível. Não adicione peixes para compensar um número baixo e teste amônia, nitrito e nitrato.' },
28
+ { question: 'Uma vazão maior é sempre melhor?', answer: 'Não. Uma correnteza forte pode ser inadequada para espécies ou plantas que preferem água mais calma. Compare a faixa com os cuidados indicados para cada espécie.' },
29
+ ],
30
+ howTo: [
31
+ { name: 'Informe o volume do aquário', text: 'Use o volume de água que deseja planejar, de preferência o volume útil e não as dimensões externas do vidro.' },
32
+ { name: 'Adicione a capacidade do filtro', text: 'Informe a vazão do fabricante em litros por hora e estime a redução causada por mangueiras, altura e mídias.' },
33
+ { name: 'Descreva a carga de peixes', text: 'Informe a quantidade e o comprimento adulto médio. A ferramenta cria um índice de cm por litro, não uma garantia de povoamento.' },
34
+ { name: 'Leia o trajeto da correnteza', text: 'Compare a vazão efetiva com o perfil e use o alerta e as orientações de teste antes de mudar equipamentos ou animais.' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'planirovshchik-oborota-filtra-i-zarybleniya-akvariuma',
5
+ title: 'Планировщик оборота фильтра и заселения аквариума',
6
+ description: 'Оцените реальный поток фильтра с учётом потерь и посмотрите, как объём, оформление и взрослые рыбы меняют план содержания.',
7
+ ui: {
8
+ presetsLabel: 'Начните с готового профиля', presetCommunity: 'Пример общего аквариума', presetPlanted: 'Пример растительного аквариума', presetHighWaste: 'Пример высокой нагрузки', tankVolumeLabel: 'Объём аквариума в литрах', tankVolumeHint: 'Если знаете его, укажите полезный объём воды.', ratedFlowLabel: 'Номинальный поток фильтра в литрах в час', ratedFlowHint: 'Используйте данные насоса или фильтра.', flowLossLabel: 'Расчётная потеря потока', flowLossHint: 'Учтите высоту подъёма, шланги, изгибы и сопротивление наполнителей.', fishCountLabel: 'Количество взрослых рыб', averageLengthLabel: 'Средняя длина взрослой рыбы в сантиметрах', setupLabel: 'Профиль аквариума', setupCommunity: 'Общий', setupPlanted: 'Растительный', setupHighWaste: 'Высокая нагрузка', resultEyebrow: 'Эффективный оборот фильтра', effectiveTurnoverLabel: 'Эффективный оборот', targetLabel: 'Диапазон планирования', effectiveFlowLabel: 'Поток после потерь', stockingProxyLabel: 'Ориентир нагрузки рыбами', currentTitle: 'Следите за траекторией потока', currentDescription: 'Поток выходит из фильтра, проходит через аквариум и возвращается к забору. Его скорость зависит от эффективного оборота.', statusUnder: 'Ниже диапазона', statusTarget: 'В диапазоне', statusHigh: 'Выше диапазона', loadLight: 'Низкая ориентировочная нагрузка', loadModerate: 'Средняя ориентировочная нагрузка', loadHeavy: 'Высокая ориентировочная нагрузка', cautionTitle: 'Последняя проверка, анализ воды', bandSignalInside: 'В диапазоне планирования', bandSignalBelow: 'Ниже диапазона на', bandSignalAbove: 'Выше диапазона на', maintenanceText: 'Если потеря оценивается как высокой, проверьте забор, шланги и наполнители, прежде чем выбирать фильтр большего размера.', useTestKits: 'Оборот не измеряет биологическую производительность. Проверяйте аммиак, нитриты и нитраты и подбирайте поток под потребности каждого вида.', metricLiters: 'л', metricPerHour: 'в час', metricCentimetersPerLiter: 'см/л',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: 'Планируйте по эффективному потоку, а не только по этикетке насоса' },
12
+ { type: 'paragraph', html: 'Оборот фильтра, это отношение потока воды к объёму аквариума. Фильтр с заявленным потоком 600 литров в час на аквариуме 100 литров даёт 6 оборотов в час до учёта потерь. При потере 25 процентов из-за высоты, шлангов и наполнителей рабочая оценка составит 450 литров в час и 4,5 оборота.' },
13
+ { type: 'title', level: 2, text: 'Как читать диапазон планирования' },
14
+ { type: 'table', headers: ['Профиль', 'Диапазон', 'Что он означает'], rows: [['Общий', '4 до 6 раз в час', 'Отправная точка для умеренного течения'], ['Растительный', '3 до 5 раз в час', 'Более мягкая отправная точка для аквариума с растениями'], ['Высокая нагрузка', '6 до 10 раз в час', 'Сигнал более сильного течения при большем количестве отходов']] },
15
+ { type: 'paragraph', html: 'Это эвристические диапазоны планировщика, а не универсальные правила для аквариумов. Виды отличаются поведением и переносимостью течения. Высокое число не доказывает зрелость биофильтрации или безопасность заселения.' },
16
+ { type: 'title', level: 2, text: 'Почему потеря потока выделена в отдельное поле' },
17
+ { type: 'paragraph', html: 'Число на фильтре может быть измерено в заданных условиях. Высота, прокладка шлангов, грязные губки, забитые решётки забора и слишком плотные наполнители меняют поток, который действительно возвращается в аквариум. По возможности измерьте выход; иначе укажите допущение и проверьте его после обслуживания.' },
18
+ { type: 'title', level: 2, text: 'Считайте показатель рыб предупредительным сигналом' },
19
+ { type: 'paragraph', html: 'Ориентир нагрузки, это количество взрослых рыб, умноженное на их среднюю взрослую длину и разделённое на объём в литрах. Его легко проверить, но он намеренно неполный. В нём нет формы тела, активности, территории, количества корма, потребности в кислороде, совместимости и места для декора и грунта.' },
20
+ { type: 'tip', title: 'Принимайте решение по химии воды', html: 'Регулярно проверяйте аммиак и нитриты, особенно после добавления рыб или увеличения кормления. Нестабильная вода означает, что изменение расчётного оборота не подготовило аквариум к новым животным.' },
21
+ { type: 'diagnostic', variant: 'warning', title: 'Не превращайте результат в гарантию заселения', badge: 'Ограничение', html: 'Требования вида, взрослый размер, поведение, параметры воды и зрелость фильтра могут быть важнее этого результата. При необычном виде или оформлении обратитесь к специалисту.' },
22
+ ],
23
+ faq: [
24
+ { question: 'Что означает оборот фильтра?', answer: 'Это оценка того, сколько раз фильтр перемещает объём аквариума за час. Планировщик использует поток после расчётной потери, а не только значение насоса.' },
25
+ { question: 'Почему номинальный поток отличается от реального?', answer: 'Данные производителя могут измеряться в определённых условиях. Высота, длина шлангов, изгибы, забитые наполнители и грязные губки уменьшают поток, доходящий до аквариума.' },
26
+ { question: 'Говорит ли инструмент, сколько рыб можно содержать?', answer: 'Нет. Поля рыб создают прозрачный ориентир по взрослой длине на литр. Вид, поведение, размер, совместимость, кормление, качество воды и зрелость фильтра нужно оценивать отдельно.' },
27
+ { question: 'Что делать, если результат ниже диапазона?', answer: 'Проверьте забитые наполнители, перегнутые шланги и слишком большую высоту подъёма, а затем измерьте выход, если возможно. Не добавляйте рыб для компенсации и проверьте аммиак, нитриты и нитраты.' },
28
+ { question: 'Всегда ли больший оборот лучше?', answer: 'Нет. Сильное течение может не подойти видам или растениям, предпочитающим спокойную воду. Сравните диапазон с рекомендациями для конкретного вида.' },
29
+ ],
30
+ howTo: [
31
+ { name: 'Введите объём аквариума', text: 'Укажите объём воды, для которого строите план, лучше полезный объём, а не внешние размеры стекла.' },
32
+ { name: 'Добавьте данные фильтра', text: 'Введите поток производителя в литрах в час и оцените снижение из-за шлангов, высоты и наполнителей.' },
33
+ { name: 'Опишите нагрузку рыбами', text: 'Введите количество рыб и их среднюю взрослую длину. Инструмент создаёт ориентир см на литр, а не гарантию заселения.' },
34
+ { name: 'Прочитайте траекторию потока', text: 'Сравните эффективный оборот с профилем и используйте предупреждение и советы по воде до изменения оборудования или состава животных.' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'akvariefilter-genomstromning-och-besattningsplanerare',
5
+ title: 'Planerare för akvariefiltrets genomströmning och fiskbestånd',
6
+ description: 'Uppskatta filtrets verkliga genomströmning efter flödesförluster och se hur volym, inredning och vuxna fiskar påverkar planeringen.',
7
+ ui: {
8
+ presetsLabel: 'Börja med en uppsättning', presetCommunity: 'Exempel med sällskapsfiskar', presetPlanted: 'Exempel med växter', presetHighWaste: 'Exempel med hög belastning', tankVolumeLabel: 'Akvariets volym i liter', tankVolumeHint: 'Använd den användbara vattenvolymen när du känner till den.', ratedFlowLabel: 'Filtrets nominella flöde i liter per timme', ratedFlowHint: 'Använd pumpens eller filtrets specifikation.', flowLossLabel: 'Uppskattad flödesförlust', flowLossHint: 'Räkna med lyfthöjd, slangar, böjar och motstånd i filtermaterialet.', fishCountLabel: 'Antal vuxna fiskar', averageLengthLabel: 'Genomsnittlig vuxen längd i centimeter', setupLabel: 'Akvarieprofil', setupCommunity: 'Sällskapsakvarium', setupPlanted: 'Växtakvarium', setupHighWaste: 'Hög belastning', resultEyebrow: 'Effektiv filtergenomströmning', effectiveTurnoverLabel: 'Effektiv genomströmning', targetLabel: 'Planeringsintervall', effectiveFlowLabel: 'Flöde efter förlust', stockingProxyLabel: 'Vägledande beståndsindex', currentTitle: 'Följ strömmens bana', currentDescription: 'Strömmen lämnar filtret, går genom akvariet och återvänder till insuget. Hastigheten följer den effektiva genomströmningen.', statusUnder: 'Under intervallet', statusTarget: 'Inom intervallet', statusHigh: 'Över intervallet', loadLight: 'Låg vägledande belastning', loadModerate: 'Måttlig vägledande belastning', loadHeavy: 'Hög vägledande belastning', cautionTitle: 'Vattentestet är den sista kontrollen', bandSignalInside: 'Inom planeringsintervallet', bandSignalBelow: 'Under intervallet med', bandSignalAbove: 'Över intervallet med', maintenanceText: 'Om förlusten uppskattas vara hög bör du kontrollera insug, slangar och filtermaterial innan du väljer ett större filter.', useTestKits: 'Genomströmning mäter inte biologisk kapacitet. Testa ammoniak, nitrit och nitrat och anpassa strömmen efter varje arts behov.', metricLiters: 'l', metricPerHour: 'per timme', metricCentimetersPerLiter: 'cm/l',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: 'Planera med effektivt flöde och inte bara pumpens etikett' },
12
+ { type: 'paragraph', html: 'Filtergenomströmning är förhållandet mellan vattenflöde och akvariets volym. Ett filter som anges till 600 liter per timme på ett akvarium på 100 liter ger 6 omsättningar per timme före förluster. Om uppsättningen förlorar 25 procent genom lyfthöjd, slangar och material blir arbetsvärdet 450 liter per timme och 4,5 omsättningar.' },
13
+ { type: 'title', level: 2, text: 'Så läser du planeringsintervallet' },
14
+ { type: 'table', headers: ['Profil', 'Planeringsintervall', 'Vad det representerar'], rows: [['Sällskapsakvarium', '4 till 6 gånger per timme', 'En startpunkt för måttlig cirkulation'], ['Växtakvarium', '3 till 5 gånger per timme', 'En mjukare startpunkt för planterade akvarier'], ['Hög belastning', '6 till 10 gånger per timme', 'En starkare signal vid större avfallsbelastning']] },
15
+ { type: 'paragraph', html: 'Intervallen är tumregler som byggts in i planeraren, inte universella akvarieregler. Arter skiljer sig åt i simbeteende och tålighet för ström. Ett högt tal bevisar inte att den biologiska filtreringen är mogen eller att beståndet är säkert.' },
16
+ { type: 'title', level: 2, text: 'Varför flödesförlust har ett eget fält' },
17
+ { type: 'paragraph', html: 'Talet på filtret kan vara uppmätt under bestämda förhållanden. Lyfthöjd, slangdragning, smutsiga svampar, igensatta insug och tätt packat material ändrar flödet som faktiskt återvänder till akvariet. Mät utloppet om du kan; annars gör antagandet synligt och kontrollera det efter underhåll.' },
18
+ { type: 'title', level: 2, text: 'Använd beståndsvärdet som en varningssignal' },
19
+ { type: 'paragraph', html: 'Beståndsindexet är antalet vuxna fiskar multiplicerat med deras genomsnittliga vuxenlängd, delat med antalet liter. Det är lätt att kontrollera men avsiktligt ofullständigt. Kroppsform, aktivitet, revir, utfodring, syrebehov, kompatibilitet och plats för inredning och bottenmaterial räknas inte med.' },
20
+ { type: 'tip', title: 'Låt vattenkemin avgöra', html: 'Testa ammoniak och nitrit regelbundet, särskilt efter att du lagt till fisk eller ökat utfodringen. Om vattenkemin inte är stabil gör en ändrad flödesuppskattning inte akvariet redo för fler djur.' },
21
+ { type: 'diagnostic', variant: 'warning', title: 'Gör inte resultatet till en garanti för beståndet', badge: 'Begränsning', html: 'Artspecifik skötsel, vuxen storlek, beteende, vattenvärden och filtrets mognad kan väga tyngre än detta resultat. Sök kunnig rådgivning vid ovanliga arter eller uppsättningar.' },
22
+ ],
23
+ faq: [
24
+ { question: 'Vad betyder filtergenomströmning?', answer: 'Det är en uppskattning av hur många gånger filtret flyttar akvariets volym under en timme. Planeraren använder flödet efter en uppskattad förlust, inte bara pumpens värde.' },
25
+ { question: 'Varför är nominellt filterflöde inte samma som verkligt flöde?', answer: 'Tillverkarens värden kan vara uppmätta under särskilda förhållanden. Lyfthöjd, slanglängd, böjar, igensatt material och smutsiga svampar kan minska flödet som når akvariet.' },
26
+ { question: 'Talar verktyget om hur många fiskar jag kan ha?', answer: 'Nej. Fiskfälten skapar ett transparent index baserat på vuxen längd per liter. Art, beteende, storlek, kompatibilitet, utfodring, vattenkvalitet och filtrets mognad måste undersökas separat.' },
27
+ { question: 'Vad gör jag om resultatet ligger under intervallet?', answer: 'Kontrollera igensatt material, böjda slangar och för stor lyfthöjd och mät utloppet om möjligt. Lägg inte till fisk för att kompensera och testa ammoniak, nitrit och nitrat.' },
28
+ { question: 'Är högre genomströmning alltid bättre?', answer: 'Nej. Stark ström kan vara olämplig för arter eller växter som föredrar lugnare vatten. Jämför intervallet med skötselråden för varje art.' },
29
+ ],
30
+ howTo: [
31
+ { name: 'Ange akvariets volym', text: 'Använd den vattenvolym du vill planera för, helst den användbara volymen och inte glasets yttermått.' },
32
+ { name: 'Lägg till filtervärdet', text: 'Ange tillverkarens flöde i liter per timme och uppskatta minskningen från slangar, höjd och filtermaterial.' },
33
+ { name: 'Beskriv fiskbelastningen', text: 'Ange antal fiskar och genomsnittlig vuxenlängd. Verktyget skapar ett cm per liter index, inte en beståndsgaranti.' },
34
+ { name: 'Läs strömmens bana', text: 'Jämför den effektiva genomströmningen med profilen och följ varningen och råden om vattenprov innan du ändrar utrustning eller djur.' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'akvaryum-filtre-devir-ve-balik-yukleme-plani',
5
+ title: 'Akvaryum filtre devri ve balık yükü planlayıcısı',
6
+ description: 'Akış kayıplarından sonra filtrenin gerçek devrini tahmin edin ve hacim, kurulum ile yetişkin balık yükünün planı nasıl değiştirdiğini görün.',
7
+ ui: {
8
+ presetsLabel: 'Bir kurulumla başlayın', presetCommunity: 'Topluluk akvaryumu örneği', presetPlanted: 'Bitkili akvaryum örneği', presetHighWaste: 'Yüksek atık örneği', tankVolumeLabel: 'Akvaryum hacmi, litre', tankVolumeHint: 'Biliyorsanız kullanılabilir su hacmini kullanın.', ratedFlowLabel: 'Filtrenin nominal debisi, litre/saat', ratedFlowHint: 'Pompa veya filtre teknik değerini kullanın.', flowLossLabel: 'Tahmini debi kaybı', flowLossHint: 'Basma yüksekliği, hortumlar, dirsekler ve filtre malzemesi direncini hesaba katın.', fishCountLabel: 'Yetişkin balık sayısı', averageLengthLabel: 'Yetişkin ortalama uzunluğu, santimetre', setupLabel: 'Kurulum profili', setupCommunity: 'Topluluk', setupPlanted: 'Bitkili', setupHighWaste: 'Yüksek atık', resultEyebrow: 'Etkin filtre devri', effectiveTurnoverLabel: 'Etkin devir', targetLabel: 'Planlama aralığı', effectiveFlowLabel: 'Kayıp sonrası debi', stockingProxyLabel: 'Gösterge balık yükü', currentTitle: 'Akıntının izini takip edin', currentDescription: 'Akıntı filtreden çıkar, akvaryumu geçer ve emişe döner. Hızı etkin devre göre değişir.', statusUnder: 'Aralığın altında', statusTarget: 'Aralık içinde', statusHigh: 'Aralığın üstünde', loadLight: 'Hafif yük göstergesi', loadModerate: 'Orta yük göstergesi', loadHeavy: 'Yüksek yük göstergesi', cautionTitle: 'Son kontrol su testidir', bandSignalInside: 'Planlama aralığı içinde', bandSignalBelow: 'Aralığın altında fark', bandSignalAbove: 'Aralığın üstünde fark', maintenanceText: 'Kayıp tahmini yüksekse daha büyük filtre seçmeden önce emişi, hortumları ve filtre malzemesini kontrol edin.', useTestKits: 'Devir biyolojik kapasiteyi ölçmez. Amonyak, nitrit ve nitratı test edin ve akıntıyı her türün ihtiyacına göre ayarlayın.', metricLiters: 'L', metricPerHour: 'saatte', metricCentimetersPerLiter: 'cm/L',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: 'Sadece pompa etiketine değil etkin debiye göre planlayın' },
12
+ { type: 'paragraph', html: 'Filtre devri, su debisinin akvaryum hacmine oranıdır. 100 litrelik akvaryumda saatte 600 litre değerli filtre, kayıplardan önce saatte 6 devir anlamına gelir. Basma yüksekliği, hortum ve malzeme nedeniyle yüzde 25 kayıp varsa çalışma tahmini saatte 450 litre ve 4,5 devirdir.' },
13
+ { type: 'title', level: 2, text: 'Planlama aralığı nasıl okunur' },
14
+ { type: 'table', headers: ['Profil', 'Planlama aralığı', 'Temsil ettiği şey'], rows: [['Topluluk', 'Saatte 4 ile 6 kez', 'Orta düzey akıntı için başlangıç noktası'], ['Bitkili', 'Saatte 3 ile 5 kez', 'Bitkili akvaryumlar için daha yumuşak başlangıç'], ['Yüksek atık', 'Saatte 6 ile 10 kez', 'Daha fazla atık yükü için daha güçlü akıntı sinyali']] },
15
+ { type: 'paragraph', html: 'Bu aralıklar planlayıcıya eklenmiş pratik tahminlerdir, evrensel akvaryum kuralları değildir. Türler yüzme davranışı ve akıntı toleransı bakımından farklıdır. Yüksek bir sayı biyolojik filtrenin olgunlaştığını veya canlı yükünün güvenli olduğunu kanıtlamaz.' },
16
+ { type: 'title', level: 2, text: 'Debi kaybı neden ayrı bir giriş olmalı' },
17
+ { type: 'paragraph', html: 'Filtre üzerindeki değer belirli koşullarda ölçülmüş olabilir. Basma yüksekliği, hortum güzergâhı, kirli süngerler, tıkalı emiş ızgaraları ve sıkışık malzeme akvaryuma gerçekten dönen debiyi değiştirir. Mümkünse çıkış debisini ölçün; değilse kayıp varsayımını görünür kılın ve bakımdan sonra yeniden değerlendirin.' },
18
+ { type: 'title', level: 2, text: 'Balık sayısını uyarı sinyali olarak görün' },
19
+ { type: 'paragraph', html: 'Balık yükü göstergesi, yetişkin balık sayısının ortalama yetişkin uzunluğuyla çarpılıp litreye bölünmesidir. Denetlenmesi kolaydır ancak bilerek eksiktir. Vücut şekli, hareketlilik, bölge ihtiyacı, yem miktarı, oksijen talebi, uyumluluk ve dekor ile tabanın kapladığı alan hesaba katılmaz.' },
20
+ { type: 'tip', title: 'Kararı su kimyasına göre verin', html: 'Özellikle balık ekledikten veya yemlemeyi artırdıktan sonra amonyak ve nitriti düzenli test edin. Su kimyası dengeli değilse devir tahminini değiştirmek akvaryumu yeni canlılara hazır hâle getirmez.' },
21
+ { type: 'diagnostic', variant: 'warning', title: 'Sonucu canlı yükü garantisine dönüştürmeyin', badge: 'Sınır', html: 'Türe özel bakım, yetişkin boyu, davranış, su değerleri ve filtrenin olgunluğu bu planlama sonucundan daha önemli olabilir. Alışılmadık tür veya kurulumlarda uzman görüşü alın.' },
22
+ ],
23
+ faq: [
24
+ { question: 'Filtre devri ne anlama gelir?', answer: 'Filtrenin akvaryum hacmini bir saatte kaç kez hareket ettirdiğine dair tahmindir. Bu planlayıcı yalnızca pompa değerini değil, tahmini kayıptan sonraki debiyi kullanır.' },
25
+ { question: 'Nominal filtre debisi gerçek debiden neden farklıdır?', answer: 'Üretici değerleri belirli koşullarda ölçülmüş olabilir. Yükseklik, hortum uzunluğu, dirsekler, tıkalı malzeme ve kirli süngerler akvaryuma ulaşan debiyi azaltır.' },
26
+ { question: 'Kaç balık besleyebileceğimi söyler mi?', answer: 'Hayır. Balık alanları yetişkin uzunluğunu litre başına kullanan şeffaf bir yük göstergesi oluşturur. Tür, davranış, boy, uyumluluk, yemleme, su kalitesi ve filtre olgunluğu ayrıca incelenmelidir.' },
27
+ { question: 'Sonuç aralığın altındaysa ne yapmalıyım?', answer: 'Tıkalı malzemeyi, kıvrılmış hortumları ve aşırı basma yüksekliğini kontrol edin, mümkünse çıkışı ölçün. Düşük sayıyı telafi etmek için balık eklemeyin ve amonyak, nitrit ile nitratı test edin.' },
28
+ { question: 'Daha yüksek devir her zaman daha mı iyidir?', answer: 'Hayır. Güçlü akıntı sakin suyu seven türler veya bitkiler için uygun olmayabilir. Aralığı her türün bakım bilgisiyle karşılaştırın.' },
29
+ ],
30
+ howTo: [
31
+ { name: 'Akvaryum hacmini girin', text: 'Plan yapmak istediğiniz su hacmini, mümkünse camın dış ölçüleri yerine kullanılabilir hacmi kullanın.' },
32
+ { name: 'Filtre değerini ekleyin', text: 'Üreticinin litre/saat debisini girin ve hortum, yükseklik ile malzemeden kaynaklanan azalmayı tahmin edin.' },
33
+ { name: 'Balık yükünü tanımlayın', text: 'Balık sayısını ve ortalama yetişkin uzunluğunu girin. Araç cm/litre göstergesi oluşturur, canlı yükü garantisi vermez.' },
34
+ { name: 'Akıntı izini okuyun', text: 'Etkin devri profil aralığıyla karşılaştırın ve ekipman ya da canlıları değiştirmeden önce uyarı ile su testi yönlendirmesini kullanın.' },
35
+ ],
36
+ });
@@ -0,0 +1,36 @@
1
+ import { buildPlannerContent } from '../content-builder';
2
+
3
+ export const content = buildPlannerContent({
4
+ slug: 'aquarium-filter-turnover-stocking-planner',
5
+ title: '水族箱过滤流量与鱼类饲养密度规划器',
6
+ description: '考虑流量损失后估算过滤器的实际循环量,并查看水箱容量、造景和成鱼负荷如何影响规划。',
7
+ ui: {
8
+ presetsLabel: '从一个设置开始', presetCommunity: '混养示例', presetPlanted: '水草缸示例', presetHighWaste: '高废物负荷示例', tankVolumeLabel: '水箱容量(升)', tankVolumeHint: '如果知道,请使用实际可用的水量。', ratedFlowLabel: '过滤器额定流量(升每小时)', ratedFlowHint: '使用水泵或过滤器的规格数据。', flowLossLabel: '预计流量损失', flowLossHint: '考虑扬程、软管、弯头和滤材阻力。', fishCountLabel: '成鱼数量', averageLengthLabel: '成鱼平均体长(厘米)', setupLabel: '水箱类型', setupCommunity: '混养', setupPlanted: '水草', setupHighWaste: '高负荷', resultEyebrow: '过滤器有效循环量', effectiveTurnoverLabel: '有效循环量', targetLabel: '规划范围', effectiveFlowLabel: '损失后的流量', stockingProxyLabel: '饲养负荷参考值', currentTitle: '查看水流轨迹', currentDescription: '水流从过滤器流出,穿过水箱后回到进水口。水流速度会随有效循环量变化。', statusUnder: '低于范围', statusTarget: '处于范围内', statusHigh: '高于范围', loadLight: '轻度负荷参考值', loadModerate: '中度负荷参考值', loadHeavy: '重度负荷参考值', cautionTitle: '最后要用水质测试确认', bandSignalInside: '处于规划范围内', bandSignalBelow: '低于范围', bandSignalAbove: '高于范围', maintenanceText: '如果预计损失较大,请在选择更大的过滤器前检查进水口、软管和滤材。', useTestKits: '循环量不能代表生物过滤能力。请检测氨、亚硝酸盐和硝酸盐,并根据每个物种的需求调整水流。', metricLiters: 'L', metricPerHour: '每小时', metricCentimetersPerLiter: 'cm/L',
9
+ },
10
+ seo: [
11
+ { type: 'title', level: 2, text: '根据有效流量规划,而不只是看水泵标签' },
12
+ { type: 'paragraph', html: '过滤循环量是水流量与水箱容量的比值。一个标称每小时600升的过滤器用于100升水箱时,损失前相当于每小时循环6次。如果扬程、软管和滤材造成百分之25的损失,工作估算值就是每小时450升和4.5次循环。' },
13
+ { type: 'title', level: 2, text: '如何阅读规划范围' },
14
+ { type: 'table', headers: ['水箱类型', '规划范围', '代表含义'], rows: [['混养', '每小时4到6次', '中等水流的起始参考点'], ['水草', '每小时3到5次', '适合水草缸的较温和起始参考点'], ['高负荷', '每小时6到10次', '面对较多废物时的较强水流信号']] },
15
+ { type: 'paragraph', html: '这些范围是规划器内置的经验参考,并不是适用于所有水族箱的通用规则。不同物种的游泳行为和耐流能力不同。较高的循环数字不能证明生物过滤已经成熟,也不能证明饲养数量安全。' },
16
+ { type: 'title', level: 2, text: '为什么要单独输入流量损失' },
17
+ { type: 'paragraph', html: '过滤器上的数字可能是在规定条件下测得的。扬程、软管走向、脏海绵、堵塞的进水格栅和过于紧密的滤材,都会改变真正回到水箱的流量。如果可以,请测量出水流量;否则请明确损失假设,并在维护后重新检查。' },
18
+ { type: 'title', level: 2, text: '把饲养数字当作警告信号' },
19
+ { type: 'paragraph', html: '饲养负荷参考值就是成鱼数量乘以平均成鱼体长,再除以水箱升数。它容易核对,但有意保持不完整。它没有计算体型、活动量、领地、喂食量、耗氧量、混养相容性以及装饰和底床占用的空间。' },
20
+ { type: 'tip', title: '用水质决定下一步', html: '请定期检测氨和亚硝酸盐,尤其是在增加鱼只或喂食量之后。如果水质不稳定,改变循环量估算并不会让水箱适合继续增加生物。' },
21
+ { type: 'diagnostic', variant: 'warning', title: '不要把结果变成饲养保证', badge: '限制', html: '物种护理要求、成鱼体型、行为、水质参数和过滤器成熟度都可能比这个规划结果更重要。遇到特殊物种或设置时,请咨询有经验的水族专业人士。' },
22
+ ],
23
+ faq: [
24
+ { question: '过滤循环量是什么意思?', answer: '它估算过滤器在一小时内移动水箱容量的次数。本规划器使用预计损失后的流量,而不只是水泵标称值。' },
25
+ { question: '为什么额定流量不等于实际流量?', answer: '制造商数据可能是在特定条件下测量的。扬程、软管长度、弯头、堵塞的滤材和脏海绵都会降低到达水箱的流量。' },
26
+ { question: '它能告诉我可以养多少条鱼吗?', answer: '不能。鱼只输入项会根据成鱼体长和每升水量生成透明的负荷参考值。物种、行为、成鱼尺寸、相容性、喂食、水质和过滤器成熟度仍需单独研究。' },
27
+ { question: '如果结果低于范围,我该怎么办?', answer: '检查堵塞的滤材、弯折的软管和过大的扬程,并在可能时测量出水。不要为了补足低数值而增加鱼只,同时检测氨、亚硝酸盐和硝酸盐。' },
28
+ { question: '循环量越高就一定越好吗?', answer: '不一定。强水流可能不适合喜欢平缓水流的物种或植物。请把规划范围与每个物种的护理要求进行比较。' },
29
+ ],
30
+ howTo: [
31
+ { name: '输入水箱容量', text: '输入你要规划的水量,最好使用实际可用水量,而不是玻璃外部尺寸。' },
32
+ { name: '添加过滤器额定值', text: '输入制造商提供的每小时流量,并估算软管、扬程和滤材造成的降低。' },
33
+ { name: '描述鱼只负荷', text: '输入鱼只数量和平均成鱼体长。工具会生成每升厘米数参考值,而不是饲养保证。' },
34
+ { name: '阅读水流轨迹', text: '将有效循环量与水箱类型范围比较,并在更换设备或生物前参考警告和水质测试建议。' },
35
+ ],
36
+ });
@@ -0,0 +1,11 @@
1
+ import { aquariumFilterTurnoverStockingPlanner } from './entry';
2
+ import type { ToolDefinition } from '../../types';
3
+
4
+ export * from './entry';
5
+
6
+ export const AQUARIUM_FILTER_TURNOVER_STOCKING_PLANNER_TOOL: ToolDefinition = {
7
+ entry: aquariumFilterTurnoverStockingPlanner,
8
+ Component: () => import('./component.astro'),
9
+ SEOComponent: () => import('./seo.astro'),
10
+ BibliographyComponent: () => import('./bibliography.astro'),
11
+ };
@@ -0,0 +1,78 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { calculatePlanner, getSetupProfile, normalizeInput } from './logic';
3
+
4
+ describe('aquarium filter turnover planner logic', () => {
5
+ it('calculates effective flow after losses and turnover', () => {
6
+ const result = calculatePlanner({
7
+ tankVolumeLiters: 100,
8
+ ratedFlowLitersPerHour: 600,
9
+ flowLossPercent: 25,
10
+ fishCount: 10,
11
+ averageAdultLengthCm: 5,
12
+ setup: 'community',
13
+ });
14
+
15
+ expect(result.effectiveFlowLitersPerHour).toBe(450);
16
+ expect(result.ratedTurnover).toBe(6);
17
+ expect(result.effectiveTurnover).toBe(4.5);
18
+ expect(result.turnoverStatus).toBe('target');
19
+ expect(result.stockingLoad).toBe('light');
20
+ });
21
+
22
+ it('reports the flow gap for an under-target setup', () => {
23
+ const result = calculatePlanner({
24
+ tankVolumeLiters: 200,
25
+ ratedFlowLitersPerHour: 500,
26
+ flowLossPercent: 40,
27
+ fishCount: 20,
28
+ averageAdultLengthCm: 8,
29
+ setup: 'highWaste',
30
+ });
31
+
32
+ expect(result.effectiveTurnover).toBe(1.5);
33
+ expect(result.turnoverStatus).toBe('under');
34
+ expect(result.flowGapLitersPerHour).toBe(900);
35
+ expect(result.stockingLoad).toBe('moderate');
36
+ });
37
+
38
+ it('keeps high flow distinct from a target match', () => {
39
+ const result = calculatePlanner({
40
+ tankVolumeLiters: 40,
41
+ ratedFlowLitersPerHour: 800,
42
+ flowLossPercent: 0,
43
+ fishCount: 4,
44
+ averageAdultLengthCm: 3,
45
+ setup: 'planted',
46
+ });
47
+
48
+ expect(result.effectiveTurnover).toBe(20);
49
+ expect(result.turnoverStatus).toBe('high');
50
+ expect(result.flowAboveTargetLitersPerHour).toBe(600);
51
+ });
52
+
53
+ it('normalizes unsafe and invalid input without producing NaN', () => {
54
+ const input = normalizeInput({
55
+ tankVolumeLiters: -1,
56
+ ratedFlowLitersPerHour: Number.NaN,
57
+ flowLossPercent: 150,
58
+ fishCount: -5,
59
+ averageAdultLengthCm: 100,
60
+ setup: 'unknown' as never,
61
+ });
62
+
63
+ expect(input).toEqual({
64
+ tankVolumeLiters: 1,
65
+ ratedFlowLitersPerHour: 1,
66
+ flowLossPercent: 90,
67
+ fishCount: 0,
68
+ averageAdultLengthCm: 80,
69
+ setup: 'community',
70
+ });
71
+ });
72
+
73
+ it('exposes transparent setup bands', () => {
74
+ expect(getSetupProfile('community')).toEqual({ min: 4, max: 6 });
75
+ expect(getSetupProfile('planted')).toEqual({ min: 3, max: 5 });
76
+ expect(getSetupProfile('highWaste')).toEqual({ min: 6, max: 10 });
77
+ });
78
+ });