最后活跃于 1746986465

Калькулятор RAID'ов большинства используемых типов ( https://blacktower.wintersky.ru/public/raid_calc.html )

KarelWintersky 修订了这个 Gist 1746986465. 转到此修订

没有任何变更

KarelWintersky 修订了这个 Gist 1746986248. 转到此修订

1 file changed, 45 insertions

gistfile1.txt

@@ -3,6 +3,51 @@
3 3 <head>
4 4 <meta charset="UTF-8">
5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 + <meta name="description" content="RAID Capacity Calculator - calculate storage efficiency for RAID 0, 1, 5, 6, 10 and ZFS configurations">
7 + <meta name="keywords" content="RAID calculator, storage calculator, ZFS calculator, disk array, RAID capacity">
8 + <meta name="author" content="Karel Wintersky & Deepseek">
9 +
10 + <!-- Favicon SVG -->
11 + <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
12 + <rect width='100' height='100' fill='%233367D6'/>
13 + <rect x='20' y='30' width='60' height='40' fill='%23fff' rx='5'/>
14 + <rect x='25' y='35' width='50' height='10' fill='%233367D6'/>
15 + <circle cx='40' cy='60' r='5' fill='%233367D6'/>
16 + <circle cx='60' cy='60' r='5' fill='%233367D6'/>
17 + <path d='M30 75 L70 75 L80 85 L20 85 Z' fill='%23fff'/>
18 + </svg>" type="image/svg+xml">
19 +
20 + <!-- Open Graph / Facebook -->
21 + <meta property="og:type" content="website">
22 + <meta property="og:url" content="https://blacktower.wintersky.ru/public/raid_calc.html">
23 + <meta property="og:title" content="RAID Capacity Calculator">
24 + <meta property="og:description" content="Calculate storage efficiency for various RAID configurations">
25 + <meta property="og:image" content="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 630'>
26 + <rect width='1200' height='630' fill='%233367D6'/>
27 + <rect x='100' y='150' width='1000' height='330' fill='%23fff' rx='20'/>
28 + <rect x='150' y='200' width='900' height='80' fill='%233367D6' rx='10'/>
29 + <text x='150' y='300' font-family='Arial' font-size='60' fill='%23000'>RAID 0: <tspan fill='%233367D6'>4×1TB = 4TB</tspan></text>
30 + <text x='150' y='380' font-family='Arial' font-size='60' fill='%23000'>RAID 5: <tspan fill='%233367D6'>4×1TB = 3TB</tspan></text>
31 + <text x='150' y='460' font-family='Arial' font-size='60' fill='%23000'>RAID 10: <tspan fill='%233367D6'>4×1TB = 2TB</tspan></text>
32 + <text x='600' y='550' font-family='Arial' font-size='40' fill='%23fff'>RAID Capacity Calculator</text>
33 + </svg>">
34 + <meta property="og:image:width" content="1200">
35 + <meta property="og:image:height" content="630">
36 +
37 + <!-- Twitter -->
38 + <meta name="twitter:card" content="summary_large_image">
39 + <meta name="twitter:title" content="RAID Capacity Calculator">
40 + <meta name="twitter:description" content="Professional tool for RAID storage calculations">
41 + <meta name="twitter:image" content="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 630'>
42 + <rect width='1200' height='630' fill='%233367D6'/>
43 + <rect x='100' y='150' width='1000' height='330' fill='%23fff' rx='20'/>
44 + <rect x='150' y='200' width='900' height='80' fill='%233367D6' rx='10'/>
45 + <text x='150' y='300' font-family='Arial' font-size='60' fill='%23000'>RAID 0: <tspan fill='%233367D6'>4×1TB = 4TB</tspan></text>
46 + <text x='150' y='380' font-family='Arial' font-size='60' fill='%23000'>RAID 5: <tspan fill='%233367D6'>4×1TB = 3TB</tspan></text>
47 + <text x='150' y='460' font-family='Arial' font-size='60' fill='%23000'>RAID 10: <tspan fill='%233367D6'>4×1TB = 2TB</tspan></text>
48 + <text x='600' y='550' font-family='Arial' font-size='40' fill='%23fff'>RAID Capacity Calculator</text>
49 + </svg>">
50 +
6 51 <title>RAID Capacity Calculator</title>
7 52 <style>
8 53 body {

KarelWintersky 修订了这个 Gist 1746984152. 转到此修订

1 file changed, 547 insertions

gistfile1.txt(文件已创建)

@@ -0,0 +1,547 @@
1 + <!DOCTYPE html>
2 + <html lang="en">
3 + <head>
4 + <meta charset="UTF-8">
5 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 + <title>RAID Capacity Calculator</title>
7 + <style>
8 + body {
9 + font-family: Arial, sans-serif;
10 + max-width: 1000px;
11 + margin: 0 auto;
12 + padding: 20px;
13 + line-height: 1.6;
14 + }
15 + .language-switcher {
16 + text-align: right;
17 + margin-bottom: 20px;
18 + }
19 + .language-switcher button {
20 + background: none;
21 + border: 1px solid #ccc;
22 + padding: 5px 10px;
23 + cursor: pointer;
24 + margin-left: 5px;
25 + }
26 + .language-switcher button.active {
27 + background: #eee;
28 + }
29 + .calculator-container {
30 + display: flex;
31 + gap: 20px;
32 + margin-bottom: 30px;
33 + }
34 + .input-section {
35 + flex: 1;
36 + padding: 15px;
37 + border: 1px solid #ddd;
38 + border-radius: 5px;
39 + }
40 + .results-section {
41 + flex: 1;
42 + padding: 15px;
43 + border: 1px solid #ddd;
44 + border-radius: 5px;
45 + background-color: #f5f5f5;
46 + }
47 + .input-group {
48 + margin-bottom: 15px;
49 + }
50 + label {
51 + display: block;
52 + margin-bottom: 5px;
53 + font-weight: bold;
54 + }
55 + input, select {
56 + padding: 8px;
57 + width: 100%;
58 + box-sizing: border-box;
59 + }
60 + .result-item {
61 + margin-bottom: 10px;
62 + padding: 10px;
63 + background-color: white;
64 + border-radius: 3px;
65 + }
66 + .result-label {
67 + font-weight: bold;
68 + color: #555;
69 + }
70 + .hint-section {
71 + padding: 20px;
72 + border: 1px solid #ddd;
73 + border-radius: 5px;
74 + background-color: #f9f9f9;
75 + margin-top: 20px;
76 + }
77 + .hint-title {
78 + font-weight: bold;
79 + margin-bottom: 10px;
80 + color: #333;
81 + }
82 + .hint-content {
83 + line-height: 1.5;
84 + }
85 +
86 + /* */
87 + .language-switcher {
88 + text-align: right;
89 + margin-bottom: 20px;
90 + }
91 + .language-switcher button {
92 + background: none;
93 + border: 1px solid #ccc;
94 + padding: 5px 10px;
95 + cursor: pointer;
96 + margin-left: 5px;
97 + display: inline-flex;
98 + align-items: center;
99 + gap: 5px;
100 + }
101 + .language-switcher button:hover {
102 + background-color: #f0f0f0;
103 + }
104 + .language-switcher button.active {
105 + background: #eee;
106 + font-weight: bold;
107 + }
108 + .language-switcher svg {
109 + border: 1px solid #ddd;
110 + }
111 +
112 + </style>
113 + </head>
114 + <body>
115 + <!--
116 + <div class="language-switcher">
117 + <button id="lang-en">English</button>
118 + <button id="lang-ru">Русский</button>
119 + </div>
120 + -->
121 + <div class="language-switcher">
122 + <button id="lang-en" title="English">
123 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="20" height="10">
124 + <clipPath id="s">
125 + <path d="M0,0 v30 h60 v-30 z"/>
126 + </clipPath>
127 + <clipPath id="t">
128 + <path d="M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z"/>
129 + </clipPath>
130 + <g clip-path="url(#s)">
131 + <path d="M0,0 v30 h60 v-30 z" fill="#012169"/>
132 + <path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
133 + <path d="M0,0 L60,30 M60,0 L0,30" stroke="#C8102E" stroke-width="4"/>
134 + <path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
135 + <path d="M30,0 v30 M0,15 h60" stroke="#C8102E" stroke-width="6"/>
136 + </g>
137 + <g clip-path="url(#t)">
138 + <path d="M0,0 v30 h60 v-30 z" fill="#012169"/>
139 + <path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
140 + <path d="M0,0 L60,30 M60,0 L0,30" stroke="#C8102E" stroke-width="4"/>
141 + <path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
142 + <path d="M30,0 v30 M0,15 h60" stroke="#C8102E" stroke-width="6"/>
143 + </g>
144 + </svg>
145 + <span>English</span>
146 + </button>
147 + <button id="lang-ru" title="Русский">
148 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="20" height="10">
149 + <clipPath id="r">
150 + <path d="M0,0 v30 h60 v-30 z"/>
151 + </clipPath>
152 + <g clip-path="url(#r)">
153 + <path d="M0,0 h60 v10 h-60 z" fill="#fff"/>
154 + <path d="M0,10 h60 v10 h-60 z" fill="#0039A6"/>
155 + <path d="M0,20 h60 v10 h-60 z" fill="#D52B1E"/>
156 + </g>
157 + </svg>
158 + <span>Русский</span>
159 + </button>
160 + </div>
161 +
162 + <h1 id="title">RAID Capacity Calculator</h1>
163 +
164 + <div class="calculator-container">
165 + <div class="input-section">
166 + <div class="input-group">
167 + <label for="disk-count" id="disk-count-label">Number of disks:</label>
168 + <input type="number" id="disk-count" min="1" value="4">
169 + </div>
170 +
171 + <div class="input-group">
172 + <label for="disk-size" id="disk-size-label">Disk size (GB):</label>
173 + <input type="number" id="disk-size" min="1" value="1000">
174 + </div>
175 +
176 + <div class="input-group">
177 + <label for="raid-type" id="raid-type-label">RAID type:</label>
178 + <select id="raid-type">
179 + <optgroup label="Standard RAID">
180 + <option value="raid0">RAID 0</option>
181 + <option value="raid1">RAID 1</option>
182 + <option value="raid3">RAID 3</option>
183 + <option value="raid5">RAID 5</option>
184 + <option value="raid6">RAID 6</option>
185 + <option value="raid10">RAID 10</option>
186 + </optgroup>
187 + <optgroup label="ZFS">
188 + <option value="zfsStripe">Stripe set</option>
189 + <option value="zfsMirror">Mirror</option>
190 + <option value="zfsZ1">RAID-Z1</option>
191 + <option value="zfsZ2">RAID-Z2</option>
192 + <option value="zfsZ3">RAID-Z3</option>
193 + </optgroup>
194 + </select>
195 + </div>
196 + </div>
197 +
198 + <div class="results-section">
199 + <h2 id="results-title">Results</h2>
200 + <div class="result-item">
201 + <div class="result-label" id="total-space-label">Total space:</div>
202 + <div id="total-space">0</div>
203 + </div>
204 + <div class="result-item">
205 + <div class="result-label" id="effective-space-label">Effective space:</div>
206 + <div id="effective-space">0</div>
207 + </div>
208 + <div class="result-item">
209 + <div class="result-label" id="efficiency-label">Efficiency:</div>
210 + <div id="efficiency">0</div>
211 + </div>
212 + <div class="result-item">
213 + <div class="result-label" id="fault-tolerance-label">Fault tolerance:</div>
214 + <div id="fault-tolerance">None</div>
215 + </div>
216 + </div>
217 + </div>
218 +
219 + <div class="hint-section">
220 + <div class="hint-title" id="hint-title">About selected RAID type:</div>
221 + <div class="hint-content" id="hint-content"></div>
222 + </div>
223 +
224 + <script>
225 + // Language data
226 + const translations = {
227 + en: {
228 + title: "RAID Capacity Calculator",
229 + diskCountLabel: "Number of disks:",
230 + diskSizeLabel: "Disk size (GB):",
231 + raidTypeLabel: "RAID type:",
232 + resultsTitle: "Results",
233 + totalSpaceLabel: "Total space:",
234 + effectiveSpaceLabel: "Effective space:",
235 + efficiencyLabel: "Efficiency:",
236 + faultToleranceLabel: "Fault tolerance:",
237 + hintTitle: "About selected RAID type:",
238 + raidTypes: {
239 + standard: "Standard RAID",
240 + zfs: "ZFS",
241 + raid0: "RAID 0",
242 + raid1: "RAID 1",
243 + raid3: "RAID 3",
244 + raid5: "RAID 5",
245 + raid6: "RAID 6",
246 + raid10: "RAID 10",
247 + zfsStripe: "Stripe set",
248 + zfsMirror: "Mirror",
249 + zfsZ1: "RAID-Z1",
250 + zfsZ2: "RAID-Z2",
251 + zfsZ3: "RAID-Z3"
252 + },
253 + faultTolerance: {
254 + none: "None",
255 + one: "1 disk failure",
256 + two: "2 disk failures",
257 + three: "3 disk failures",
258 + half: "Up to half of disks (in mirrored pairs)"
259 + },
260 + hints: {
261 + raid0: "RAID 0 (striping) combines multiple disks into one logical unit with data distributed across all disks. Provides improved performance but no redundancy - failure of any disk results in total data loss.",
262 + raid1: "RAID 1 (mirroring) creates an exact copy of data on two or more disks. Provides fault tolerance but at the cost of reduced storage capacity.",
263 + raid3: "RAID 3 uses byte-level striping with a dedicated parity disk. Good for sequential data access but poor for random access. Can tolerate one disk failure.",
264 + raid5: "RAID 5 uses block-level striping with distributed parity. Provides good balance between performance, capacity and fault tolerance. Can tolerate one disk failure.",
265 + raid6: "RAID 6 is similar to RAID 5 but with double distributed parity. Can tolerate two disk failures, making it more reliable for large arrays.",
266 + raid10: "RAID 10 (1+0) combines mirroring and striping. Requires even number of disks (minimum 4). Provides good performance and can tolerate multiple disk failures (one per mirrored pair).",
267 + zfsStripe: "ZFS stripe is similar to RAID 0 - no redundancy but maximum capacity and performance. Data is distributed across all disks in the pool.",
268 + zfsMirror: "ZFS mirror is similar to RAID 1 - data is duplicated on two or more disks. Provides redundancy at the cost of storage capacity.",
269 + zfsZ1: "RAID-Z1 is similar to RAID 5 - single parity with distributed striping. Can tolerate one disk failure while providing good capacity and performance.",
270 + zfsZ2: "RAID-Z2 is similar to RAID 6 - double parity with distributed striping. Can tolerate two disk failures, recommended for larger pools.",
271 + zfsZ3: "RAID-Z3 provides triple parity protection, able to withstand three disk failures. Recommended for very large pools where rebuild times are long."
272 + }
273 + },
274 + ru: {
275 + title: "Калькулятор ёмкости RAID",
276 + diskCountLabel: "Число дисков:",
277 + diskSizeLabel: "Размер диска (ГБ):",
278 + raidTypeLabel: "Тип RAID:",
279 + resultsTitle: "Результаты",
280 + totalSpaceLabel: "Общий объем:",
281 + effectiveSpaceLabel: "Эффективный объем:",
282 + efficiencyLabel: "Эффективность использования:",
283 + faultToleranceLabel: "Отказоустойчивость:",
284 + hintTitle: "О выбранном типе RAID:",
285 + raidTypes: {
286 + standard: "Обычный RAID",
287 + zfs: "ZFS",
288 + raid0: "RAID 0",
289 + raid1: "RAID 1",
290 + raid3: "RAID 3",
291 + raid5: "RAID 5",
292 + raid6: "RAID 6",
293 + raid10: "RAID 10",
294 + zfsStripe: "Stripe set",
295 + zfsMirror: "Mirror",
296 + zfsZ1: "RAID-Z1",
297 + zfsZ2: "RAID-Z2",
298 + zfsZ3: "RAID-Z3"
299 + },
300 + faultTolerance: {
301 + none: "Нет",
302 + one: "1 отказ диска",
303 + two: "2 отказа диска",
304 + three: "3 отказа диска",
305 + half: "До половины дисков (в зеркальных парах)"
306 + },
307 + hints: {
308 + raid0: "RAID 0 (чередование) объединяет несколько дисков в один логический блок с распределением данных по всем дискам. Обеспечивает повышенную производительность, но не имеет избыточности - отказ любого диска приводит к полной потере данных.",
309 + raid1: "RAID 1 (зеркалирование) создает точную копию данных на двух или более дисках. Обеспечивает отказоустойчивость, но за счет уменьшения полезного объема хранилища.",
310 + raid3: "RAID 3 использует чередование на уровне байтов с выделенным диском четности. Хорошо подходит для последовательного доступа к данным, но плохо для случайного. Может выдержать отказ одного диска.",
311 + raid5: "RAID 5 использует чередование на уровне блоков с распределенной четностью. Обеспечивает хороший баланс между производительностью, емкостью и отказоустойчивостью. Может выдержать отказ одного диска.",
312 + raid6: "RAID 6 аналогичен RAID 5, но с двойной распределенной четностью. Может выдержать отказ двух дисков, что делает его более надежным для больших массивов.",
313 + raid10: "RAID 10 (1+0) сочетает зеркалирование и чередование. Требует четного количества дисков (минимум 4). Обеспечивает хорошую производительность и может выдержать отказ нескольких дисков (по одному в каждой зеркальной паре).",
314 + zfsStripe: "ZFS stripe аналогичен RAID 0 - нет избыточности, но максимальная емкость и производительность. Данные распределяются по всем дискам в пуле.",
315 + zfsMirror: "ZFS mirror аналогичен RAID 1 - данные дублируются на двух или более дисках. Обеспечивает избыточность за счет полезного объема хранилища.",
316 + zfsZ1: "RAID-Z1 аналогичен RAID 5 - одинарная четность с распределенным чередованием. Может выдержать отказ одного диска при хорошей емкости и производительности.",
317 + zfsZ2: "RAID-Z2 аналогичен RAID 6 - двойная четность с распределенным чередованием. Может выдержать отказ двух дисков, рекомендуется для больших пулов.",
318 + zfsZ3: "RAID-Z3 обеспечивает тройную защиту четностью, может выдержать отказ трех дисков. Рекомендуется для очень больших пулов, где время восстановления велико."
319 + }
320 + }
321 + };
322 +
323 + // Current language
324 + let currentLang = 'en';
325 +
326 + // DOM elements
327 + const elements = {
328 + title: document.getElementById('title'),
329 + diskCountLabel: document.getElementById('disk-count-label'),
330 + diskSizeLabel: document.getElementById('disk-size-label'),
331 + raidTypeLabel: document.getElementById('raid-type-label'),
332 + resultsTitle: document.getElementById('results-title'),
333 + totalSpaceLabel: document.getElementById('total-space-label'),
334 + effectiveSpaceLabel: document.getElementById('effective-space-label'),
335 + efficiencyLabel: document.getElementById('efficiency-label'),
336 + faultToleranceLabel: document.getElementById('fault-tolerance-label'),
337 + hintTitle: document.getElementById('hint-title'),
338 + hintContent: document.getElementById('hint-content'),
339 + raidTypeSelect: document.getElementById('raid-type'),
340 + diskCountInput: document.getElementById('disk-count'),
341 + diskSizeInput: document.getElementById('disk-size'),
342 + raidTypeOptgroups: document.querySelectorAll('#raid-type optgroup'),
343 + raidTypeOptions: document.querySelectorAll('#raid-type option')
344 + };
345 +
346 + // Save state to URL hash
347 + function saveStateToHash() {
348 + const params = new URLSearchParams();
349 + params.set('lang', currentLang);
350 + params.set('count', elements.diskCountInput.value);
351 + params.set('size', elements.diskSizeInput.value);
352 + params.set('raid', elements.raidTypeSelect.value);
353 +
354 + window.location.hash = params.toString();
355 + }
356 +
357 +
358 + // Load state from URL hash
359 + function loadStateFromHash() {
360 + if (window.location.hash) {
361 + try {
362 + const hash = window.location.hash.substring(1);
363 + const params = new URLSearchParams(hash);
364 +
365 + if (params.has('lang') && translations[params.get('lang')]) {
366 + currentLang = params.get('lang');
367 + }
368 + if (params.has('count')) {
369 + elements.diskCountInput.value = params.get('count');
370 + }
371 + if (params.has('size')) {
372 + elements.diskSizeInput.value = params.get('size');
373 + }
374 + if (params.has('raid')) {
375 + elements.raidTypeSelect.value = params.get('raid');
376 + }
377 +
378 + return true;
379 + } catch (e) {
380 + console.error("Error parsing hash:", e);
381 + }
382 + }
383 + return false;
384 + }
385 +
386 + // Update UI language
387 + function updateLanguage(lang) {
388 + currentLang = lang;
389 + const t = translations[lang];
390 +
391 + // Update labels
392 + elements.title.textContent = t.title;
393 + elements.diskCountLabel.textContent = t.diskCountLabel;
394 + elements.diskSizeLabel.textContent = t.diskSizeLabel;
395 + elements.raidTypeLabel.textContent = t.raidTypeLabel;
396 + elements.resultsTitle.textContent = t.resultsTitle;
397 + elements.totalSpaceLabel.textContent = t.totalSpaceLabel;
398 + elements.effectiveSpaceLabel.textContent = t.effectiveSpaceLabel;
399 + elements.efficiencyLabel.textContent = t.efficiencyLabel;
400 + elements.faultToleranceLabel.textContent = t.faultToleranceLabel;
401 + elements.hintTitle.textContent = t.hintTitle;
402 +
403 + // Update RAID type options
404 + elements.raidTypeOptgroups[0].label = t.raidTypes.standard;
405 + elements.raidTypeOptgroups[1].label = t.raidTypes.zfs;
406 +
407 + const raidTypeOptions = [
408 + t.raidTypes.raid0, t.raidTypes.raid1, t.raidTypes.raid3,
409 + t.raidTypes.raid5, t.raidTypes.raid6, t.raidTypes.raid10,
410 + t.raidTypes.zfsStripe, t.raidTypes.zfsMirror,
411 + t.raidTypes.zfsZ1, t.raidTypes.zfsZ2, t.raidTypes.zfsZ3
412 + ];
413 +
414 + elements.raidTypeOptions.forEach((option, index) => {
415 + option.textContent = raidTypeOptions[index];
416 + });
417 +
418 + // Recalculate to update fault tolerance text and hint
419 + calculate();
420 + }
421 +
422 + // Update hint based on selected RAID type
423 + function updateHint(raidType) {
424 + elements.hintContent.textContent = translations[currentLang].hints[raidType] || '';
425 + }
426 +
427 + // Calculate RAID parameters
428 + function calculate() {
429 + const diskCount = parseInt(elements.diskCountInput.value) || 0;
430 + const diskSize = parseInt(elements.diskSizeInput.value) || 0;
431 + const raidType = elements.raidTypeSelect.value;
432 +
433 + let totalSpace, effectiveSpace, efficiency, faultTolerance;
434 + const t = translations[currentLang].faultTolerance;
435 +
436 + switch(raidType) {
437 + case 'raid0':
438 + case 'zfsStripe':
439 + totalSpace = diskCount * diskSize;
440 + effectiveSpace = totalSpace;
441 + efficiency = 100;
442 + faultTolerance = t.none;
443 + break;
444 +
445 + case 'raid1':
446 + case 'zfsMirror':
447 + totalSpace = diskCount * diskSize;
448 + effectiveSpace = diskSize;
449 + efficiency = (100 / diskCount).toFixed(2);
450 + faultTolerance = diskCount > 2 ? t.half : t.one;
451 + break;
452 +
453 + case 'raid3':
454 + case 'raid5':
455 + case 'zfsZ1':
456 + totalSpace = diskCount * diskSize;
457 + effectiveSpace = (diskCount - 1) * diskSize;
458 + efficiency = ((diskCount - 1) / diskCount * 100).toFixed(2);
459 + faultTolerance = t.one;
460 + break;
461 +
462 + case 'raid6':
463 + case 'zfsZ2':
464 + totalSpace = diskCount * diskSize;
465 + effectiveSpace = (diskCount - 2) * diskSize;
466 + efficiency = ((diskCount - 2) / diskCount * 100).toFixed(2);
467 + faultTolerance = t.two;
468 + break;
469 +
470 + case 'zfsZ3':
471 + totalSpace = diskCount * diskSize;
472 + effectiveSpace = (diskCount - 3) * diskSize;
473 + efficiency = ((diskCount - 3) / diskCount * 100).toFixed(2);
474 + faultTolerance = t.three;
475 + break;
476 +
477 + case 'raid10':
478 + if (diskCount < 2 || diskCount % 2 !== 0) {
479 + effectiveSpace = 0;
480 + efficiency = 0;
481 + faultTolerance = t.none;
482 + } else {
483 + totalSpace = diskCount * diskSize;
484 + effectiveSpace = (diskCount / 2) * diskSize;
485 + efficiency = 50;
486 + faultTolerance = t.half;
487 + }
488 + break;
489 +
490 + default:
491 + totalSpace = effectiveSpace = efficiency = 0;
492 + faultTolerance = t.none;
493 + }
494 +
495 + // Update results
496 + document.getElementById('total-space').textContent = totalSpace.toLocaleString() + ' Gb';
497 + document.getElementById('effective-space').textContent = effectiveSpace.toLocaleString() + ' Gb';
498 + document.getElementById('efficiency').textContent = efficiency + ' %';
499 + document.getElementById('fault-tolerance').textContent = faultTolerance;
500 +
501 + // Update hint
502 + updateHint(raidType);
503 +
504 + // Save state
505 + saveStateToHash();
506 + }
507 +
508 + // Event listeners
509 + function setupEventListeners() {
510 + elements.diskCountInput.addEventListener('input', calculate);
511 + elements.diskSizeInput.addEventListener('input', calculate);
512 + elements.raidTypeSelect.addEventListener('change', calculate);
513 +
514 + document.getElementById('lang-en').addEventListener('click', () => {
515 + currentLang = 'en';
516 + updateLanguage('en');
517 + saveStateToHash();
518 + });
519 + document.getElementById('lang-ru').addEventListener('click', () => {
520 + currentLang = 'ru';
521 + updateLanguage('ru');
522 + saveStateToHash();
523 + });
524 + }
525 +
526 + // Initialize
527 + function init() {
528 + // Try to load state from hash
529 + const stateLoaded = loadStateFromHash();
530 +
531 + // Setup event listeners
532 + setupEventListeners();
533 +
534 + // Update UI with current or default values
535 + updateLanguage(currentLang);
536 +
537 + // If no state was loaded, calculate with defaults
538 + if (!stateLoaded) {
539 + calculate();
540 + }
541 + }
542 +
543 + // Start the application
544 + init();
545 + </script>
546 + </body>
547 + </html>
上一页 下一页