<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="RAID Capacity Calculator - calculate storage efficiency for RAID 0, 1, 5, 6, 10 and ZFS configurations">
    <meta name="keywords" content="RAID calculator, storage calculator, ZFS calculator, disk array, RAID capacity">
    <meta name="author" content="Karel Wintersky & Deepseek">

    <!-- Favicon SVG -->
    <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
    <rect width='100' height='100' fill='%233367D6'/>
    <rect x='20' y='30' width='60' height='40' fill='%23fff' rx='5'/>
    <rect x='25' y='35' width='50' height='10' fill='%233367D6'/>
    <circle cx='40' cy='60' r='5' fill='%233367D6'/>
    <circle cx='60' cy='60' r='5' fill='%233367D6'/>
    <path d='M30 75 L70 75 L80 85 L20 85 Z' fill='%23fff'/>
    </svg>" type="image/svg+xml">

    <!-- Open Graph / Facebook -->
    <meta property="og:type" content="website">
    <meta property="og:url" content="https://blacktower.wintersky.ru/public/raid_calc.html">
    <meta property="og:title" content="RAID Capacity Calculator">
    <meta property="og:description" content="Calculate storage efficiency for various RAID configurations">
    <meta property="og:image" content="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 630'>
    <rect width='1200' height='630' fill='%233367D6'/>
    <rect x='100' y='150' width='1000' height='330' fill='%23fff' rx='20'/>
    <rect x='150' y='200' width='900' height='80' fill='%233367D6' rx='10'/>
    <text x='150' y='300' font-family='Arial' font-size='60' fill='%23000'>RAID 0: <tspan fill='%233367D6'>4×1TB = 4TB</tspan></text>
    <text x='150' y='380' font-family='Arial' font-size='60' fill='%23000'>RAID 5: <tspan fill='%233367D6'>4×1TB = 3TB</tspan></text>
    <text x='150' y='460' font-family='Arial' font-size='60' fill='%23000'>RAID 10: <tspan fill='%233367D6'>4×1TB = 2TB</tspan></text>
    <text x='600' y='550' font-family='Arial' font-size='40' fill='%23fff'>RAID Capacity Calculator</text>
    </svg>">
    <meta property="og:image:width" content="1200">
    <meta property="og:image:height" content="630">

    <!-- Twitter -->
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="RAID Capacity Calculator">
    <meta name="twitter:description" content="Professional tool for RAID storage calculations">
    <meta name="twitter:image" content="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 630'>
    <rect width='1200' height='630' fill='%233367D6'/>
    <rect x='100' y='150' width='1000' height='330' fill='%23fff' rx='20'/>
    <rect x='150' y='200' width='900' height='80' fill='%233367D6' rx='10'/>
    <text x='150' y='300' font-family='Arial' font-size='60' fill='%23000'>RAID 0: <tspan fill='%233367D6'>4×1TB = 4TB</tspan></text>
    <text x='150' y='380' font-family='Arial' font-size='60' fill='%23000'>RAID 5: <tspan fill='%233367D6'>4×1TB = 3TB</tspan></text>
    <text x='150' y='460' font-family='Arial' font-size='60' fill='%23000'>RAID 10: <tspan fill='%233367D6'>4×1TB = 2TB</tspan></text>
    <text x='600' y='550' font-family='Arial' font-size='40' fill='%23fff'>RAID Capacity Calculator</text>
    </svg>">

    <title>RAID Capacity Calculator</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 1000px;
            margin: 0 auto;
            padding: 20px;
            line-height: 1.6;
        }
        .language-switcher {
            text-align: right;
            margin-bottom: 20px;
        }
        .language-switcher button {
            background: none;
            border: 1px solid #ccc;
            padding: 5px 10px;
            cursor: pointer;
            margin-left: 5px;
        }
        .language-switcher button.active {
            background: #eee;
        }
        .calculator-container {
            display: flex;
            gap: 20px;
            margin-bottom: 30px;
        }
        .input-section {
            flex: 1;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
        }
        .results-section {
            flex: 1;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
            background-color: #f5f5f5;
        }
        .input-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }
        input, select {
            padding: 8px;
            width: 100%;
            box-sizing: border-box;
        }
        .result-item {
            margin-bottom: 10px;
            padding: 10px;
            background-color: white;
            border-radius: 3px;
        }
        .result-label {
            font-weight: bold;
            color: #555;
        }
        .hint-section {
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 5px;
            background-color: #f9f9f9;
            margin-top: 20px;
        }
        .hint-title {
            font-weight: bold;
            margin-bottom: 10px;
            color: #333;
        }
        .hint-content {
            line-height: 1.5;
        }

        /* */
        .language-switcher {
        text-align: right;
        margin-bottom: 20px;
    }
    .language-switcher button {
        background: none;
        border: 1px solid #ccc;
        padding: 5px 10px;
        cursor: pointer;
        margin-left: 5px;
        display: inline-flex;
        align-items: center;
        gap: 5px;
    }
    .language-switcher button:hover {
        background-color: #f0f0f0;
    }
    .language-switcher button.active {
        background: #eee;
        font-weight: bold;
    }
    .language-switcher svg {
        border: 1px solid #ddd;
    }

    </style>
</head>
<body>
    <!-- 
    <div class="language-switcher">
        <button id="lang-en">English</button>
        <button id="lang-ru">Русский</button>
    </div>
-->
    <div class="language-switcher">
    <button id="lang-en" title="English">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="20" height="10">
            <clipPath id="s">
                <path d="M0,0 v30 h60 v-30 z"/>
            </clipPath>
            <clipPath id="t">
                <path d="M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z"/>
            </clipPath>
            <g clip-path="url(#s)">
                <path d="M0,0 v30 h60 v-30 z" fill="#012169"/>
                <path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
                <path d="M0,0 L60,30 M60,0 L0,30" stroke="#C8102E" stroke-width="4"/>
                <path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
                <path d="M30,0 v30 M0,15 h60" stroke="#C8102E" stroke-width="6"/>
            </g>
            <g clip-path="url(#t)">
                <path d="M0,0 v30 h60 v-30 z" fill="#012169"/>
                <path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
                <path d="M0,0 L60,30 M60,0 L0,30" stroke="#C8102E" stroke-width="4"/>
                <path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
                <path d="M30,0 v30 M0,15 h60" stroke="#C8102E" stroke-width="6"/>
            </g>
        </svg>
        <span>English</span>
    </button>
    <button id="lang-ru" title="Русский">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="20" height="10">
            <clipPath id="r">
                <path d="M0,0 v30 h60 v-30 z"/>
            </clipPath>
            <g clip-path="url(#r)">
                <path d="M0,0 h60 v10 h-60 z" fill="#fff"/>
                <path d="M0,10 h60 v10 h-60 z" fill="#0039A6"/>
                <path d="M0,20 h60 v10 h-60 z" fill="#D52B1E"/>
            </g>
        </svg>
        <span>Русский</span>
    </button>
</div>

    <h1 id="title">RAID Capacity Calculator</h1>
    
    <div class="calculator-container">
        <div class="input-section">
            <div class="input-group">
                <label for="disk-count" id="disk-count-label">Number of disks:</label>
                <input type="number" id="disk-count" min="1" value="4">
            </div>
            
            <div class="input-group">
                <label for="disk-size" id="disk-size-label">Disk size (GB):</label>
                <input type="number" id="disk-size" min="1" value="1000">
            </div>
            
            <div class="input-group">
                <label for="raid-type" id="raid-type-label">RAID type:</label>
                <select id="raid-type">
                    <optgroup label="Standard RAID">
                        <option value="raid0">RAID 0</option>
                        <option value="raid1">RAID 1</option>
                        <option value="raid3">RAID 3</option>
                        <option value="raid5">RAID 5</option>
                        <option value="raid6">RAID 6</option>
                        <option value="raid10">RAID 10</option>
                    </optgroup>
                    <optgroup label="ZFS">
                        <option value="zfsStripe">Stripe set</option>
                        <option value="zfsMirror">Mirror</option>
                        <option value="zfsZ1">RAID-Z1</option>
                        <option value="zfsZ2">RAID-Z2</option>
                        <option value="zfsZ3">RAID-Z3</option>
                    </optgroup>
                </select>
            </div>
        </div>
        
        <div class="results-section">
            <h2 id="results-title">Results</h2>
            <div class="result-item">
                <div class="result-label" id="total-space-label">Total space:</div>
                <div id="total-space">0</div>
            </div>
            <div class="result-item">
                <div class="result-label" id="effective-space-label">Effective space:</div>
                <div id="effective-space">0</div>
            </div>
            <div class="result-item">
                <div class="result-label" id="efficiency-label">Efficiency:</div>
                <div id="efficiency">0</div>
            </div>
            <div class="result-item">
                <div class="result-label" id="fault-tolerance-label">Fault tolerance:</div>
                <div id="fault-tolerance">None</div>
            </div>
        </div>
    </div>
    
    <div class="hint-section">
        <div class="hint-title" id="hint-title">About selected RAID type:</div>
        <div class="hint-content" id="hint-content"></div>
    </div>

    <script>
        // Language data
        const translations = {
            en: {
                title: "RAID Capacity Calculator",
                diskCountLabel: "Number of disks:",
                diskSizeLabel: "Disk size (GB):",
                raidTypeLabel: "RAID type:",
                resultsTitle: "Results",
                totalSpaceLabel: "Total space:",
                effectiveSpaceLabel: "Effective space:",
                efficiencyLabel: "Efficiency:",
                faultToleranceLabel: "Fault tolerance:",
                hintTitle: "About selected RAID type:",
                raidTypes: {
                    standard: "Standard RAID",
                    zfs: "ZFS",
                    raid0: "RAID 0",
                    raid1: "RAID 1",
                    raid3: "RAID 3",
                    raid5: "RAID 5",
                    raid6: "RAID 6",
                    raid10: "RAID 10",
                    zfsStripe: "Stripe set",
                    zfsMirror: "Mirror",
                    zfsZ1: "RAID-Z1",
                    zfsZ2: "RAID-Z2",
                    zfsZ3: "RAID-Z3"
                },
                faultTolerance: {
                    none: "None",
                    one: "1 disk failure",
                    two: "2 disk failures",
                    three: "3 disk failures",
                    half: "Up to half of disks (in mirrored pairs)"
                },
                hints: {
                    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.",
                    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.",
                    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.",
                    raid5: "RAID 5 uses block-level striping with distributed parity. Provides good balance between performance, capacity and fault tolerance. Can tolerate one disk failure.",
                    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.",
                    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).",
                    zfsStripe: "ZFS stripe is similar to RAID 0 - no redundancy but maximum capacity and performance. Data is distributed across all disks in the pool.",
                    zfsMirror: "ZFS mirror is similar to RAID 1 - data is duplicated on two or more disks. Provides redundancy at the cost of storage capacity.",
                    zfsZ1: "RAID-Z1 is similar to RAID 5 - single parity with distributed striping. Can tolerate one disk failure while providing good capacity and performance.",
                    zfsZ2: "RAID-Z2 is similar to RAID 6 - double parity with distributed striping. Can tolerate two disk failures, recommended for larger pools.",
                    zfsZ3: "RAID-Z3 provides triple parity protection, able to withstand three disk failures. Recommended for very large pools where rebuild times are long."
                }
            },
            ru: {
                title: "Калькулятор ёмкости RAID",
                diskCountLabel: "Число дисков:",
                diskSizeLabel: "Размер диска (ГБ):",
                raidTypeLabel: "Тип RAID:",
                resultsTitle: "Результаты",
                totalSpaceLabel: "Общий объем:",
                effectiveSpaceLabel: "Эффективный объем:",
                efficiencyLabel: "Эффективность использования:",
                faultToleranceLabel: "Отказоустойчивость:",
                hintTitle: "О выбранном типе RAID:",
                raidTypes: {
                    standard: "Обычный RAID",
                    zfs: "ZFS",
                    raid0: "RAID 0",
                    raid1: "RAID 1",
                    raid3: "RAID 3",
                    raid5: "RAID 5",
                    raid6: "RAID 6",
                    raid10: "RAID 10",
                    zfsStripe: "Stripe set",
                    zfsMirror: "Mirror",
                    zfsZ1: "RAID-Z1",
                    zfsZ2: "RAID-Z2",
                    zfsZ3: "RAID-Z3"
                },
                faultTolerance: {
                    none: "Нет",
                    one: "1 отказ диска",
                    two: "2 отказа диска",
                    three: "3 отказа диска",
                    half: "До половины дисков (в зеркальных парах)"
                },
                hints: {
                    raid0: "RAID 0 (чередование) объединяет несколько дисков в один логический блок с распределением данных по всем дискам. Обеспечивает повышенную производительность, но не имеет избыточности - отказ любого диска приводит к полной потере данных.",
                    raid1: "RAID 1 (зеркалирование) создает точную копию данных на двух или более дисках. Обеспечивает отказоустойчивость, но за счет уменьшения полезного объема хранилища.",
                    raid3: "RAID 3 использует чередование на уровне байтов с выделенным диском четности. Хорошо подходит для последовательного доступа к данным, но плохо для случайного. Может выдержать отказ одного диска.",
                    raid5: "RAID 5 использует чередование на уровне блоков с распределенной четностью. Обеспечивает хороший баланс между производительностью, емкостью и отказоустойчивостью. Может выдержать отказ одного диска.",
                    raid6: "RAID 6 аналогичен RAID 5, но с двойной распределенной четностью. Может выдержать отказ двух дисков, что делает его более надежным для больших массивов.",
                    raid10: "RAID 10 (1+0) сочетает зеркалирование и чередование. Требует четного количества дисков (минимум 4). Обеспечивает хорошую производительность и может выдержать отказ нескольких дисков (по одному в каждой зеркальной паре).",
                    zfsStripe: "ZFS stripe аналогичен RAID 0 - нет избыточности, но максимальная емкость и производительность. Данные распределяются по всем дискам в пуле.",
                    zfsMirror: "ZFS mirror аналогичен RAID 1 - данные дублируются на двух или более дисках. Обеспечивает избыточность за счет полезного объема хранилища.",
                    zfsZ1: "RAID-Z1 аналогичен RAID 5 - одинарная четность с распределенным чередованием. Может выдержать отказ одного диска при хорошей емкости и производительности.",
                    zfsZ2: "RAID-Z2 аналогичен RAID 6 - двойная четность с распределенным чередованием. Может выдержать отказ двух дисков, рекомендуется для больших пулов.",
                    zfsZ3: "RAID-Z3 обеспечивает тройную защиту четностью, может выдержать отказ трех дисков. Рекомендуется для очень больших пулов, где время восстановления велико."
                }
            }
        };

        // Current language
        let currentLang = 'en';

        // DOM elements
        const elements = {
            title: document.getElementById('title'),
            diskCountLabel: document.getElementById('disk-count-label'),
            diskSizeLabel: document.getElementById('disk-size-label'),
            raidTypeLabel: document.getElementById('raid-type-label'),
            resultsTitle: document.getElementById('results-title'),
            totalSpaceLabel: document.getElementById('total-space-label'),
            effectiveSpaceLabel: document.getElementById('effective-space-label'),
            efficiencyLabel: document.getElementById('efficiency-label'),
            faultToleranceLabel: document.getElementById('fault-tolerance-label'),
            hintTitle: document.getElementById('hint-title'),
            hintContent: document.getElementById('hint-content'),
            raidTypeSelect: document.getElementById('raid-type'),
            diskCountInput: document.getElementById('disk-count'),
            diskSizeInput: document.getElementById('disk-size'),
            raidTypeOptgroups: document.querySelectorAll('#raid-type optgroup'),
            raidTypeOptions: document.querySelectorAll('#raid-type option')
        };

        // Save state to URL hash
         function saveStateToHash() {
            const params = new URLSearchParams();
            params.set('lang', currentLang);
            params.set('count', elements.diskCountInput.value);
            params.set('size', elements.diskSizeInput.value);
            params.set('raid', elements.raidTypeSelect.value);
            
            window.location.hash = params.toString();
        }


        // Load state from URL hash
        function loadStateFromHash() {
            if (window.location.hash) {
                try {
                    const hash = window.location.hash.substring(1);
                    const params = new URLSearchParams(hash);
                    
                    if (params.has('lang') && translations[params.get('lang')]) {
                        currentLang = params.get('lang');
                    }
                    if (params.has('count')) {
                        elements.diskCountInput.value = params.get('count');
                    }
                    if (params.has('size')) {
                        elements.diskSizeInput.value = params.get('size');
                    }
                    if (params.has('raid')) {
                        elements.raidTypeSelect.value = params.get('raid');
                    }
                    
                    return true;
                } catch (e) {
                    console.error("Error parsing hash:", e);
                }
            }
            return false;
        }

        // Update UI language
        function updateLanguage(lang) {
            currentLang = lang;
            const t = translations[lang];
            
            // Update labels
            elements.title.textContent = t.title;
            elements.diskCountLabel.textContent = t.diskCountLabel;
            elements.diskSizeLabel.textContent = t.diskSizeLabel;
            elements.raidTypeLabel.textContent = t.raidTypeLabel;
            elements.resultsTitle.textContent = t.resultsTitle;
            elements.totalSpaceLabel.textContent = t.totalSpaceLabel;
            elements.effectiveSpaceLabel.textContent = t.effectiveSpaceLabel;
            elements.efficiencyLabel.textContent = t.efficiencyLabel;
            elements.faultToleranceLabel.textContent = t.faultToleranceLabel;
            elements.hintTitle.textContent = t.hintTitle;
            
            // Update RAID type options
            elements.raidTypeOptgroups[0].label = t.raidTypes.standard;
            elements.raidTypeOptgroups[1].label = t.raidTypes.zfs;
            
            const raidTypeOptions = [
                t.raidTypes.raid0, t.raidTypes.raid1, t.raidTypes.raid3, 
                t.raidTypes.raid5, t.raidTypes.raid6, t.raidTypes.raid10,
                t.raidTypes.zfsStripe, t.raidTypes.zfsMirror, 
                t.raidTypes.zfsZ1, t.raidTypes.zfsZ2, t.raidTypes.zfsZ3
            ];
            
            elements.raidTypeOptions.forEach((option, index) => {
                option.textContent = raidTypeOptions[index];
            });
            
            // Recalculate to update fault tolerance text and hint
            calculate();
        }

        // Update hint based on selected RAID type
        function updateHint(raidType) {
            elements.hintContent.textContent = translations[currentLang].hints[raidType] || '';
        }

        // Calculate RAID parameters
        function calculate() {
            const diskCount = parseInt(elements.diskCountInput.value) || 0;
            const diskSize = parseInt(elements.diskSizeInput.value) || 0;
            const raidType = elements.raidTypeSelect.value;
            
            let totalSpace, effectiveSpace, efficiency, faultTolerance;
            const t = translations[currentLang].faultTolerance;
            
            switch(raidType) {
                case 'raid0':
                case 'zfsStripe':
                    totalSpace = diskCount * diskSize;
                    effectiveSpace = totalSpace;
                    efficiency = 100;
                    faultTolerance = t.none;
                    break;
                    
                case 'raid1':
                case 'zfsMirror':
                    totalSpace = diskCount * diskSize;
                    effectiveSpace = diskSize;
                    efficiency = (100 / diskCount).toFixed(2);
                    faultTolerance = diskCount > 2 ? t.half : t.one;
                    break;
                    
                case 'raid3':
                case 'raid5':
                case 'zfsZ1':
                    totalSpace = diskCount * diskSize;
                    effectiveSpace = (diskCount - 1) * diskSize;
                    efficiency = ((diskCount - 1) / diskCount * 100).toFixed(2);
                    faultTolerance = t.one;
                    break;
                    
                case 'raid6':
                case 'zfsZ2':
                    totalSpace = diskCount * diskSize;
                    effectiveSpace = (diskCount - 2) * diskSize;
                    efficiency = ((diskCount - 2) / diskCount * 100).toFixed(2);
                    faultTolerance = t.two;
                    break;
                    
                case 'zfsZ3':
                    totalSpace = diskCount * diskSize;
                    effectiveSpace = (diskCount - 3) * diskSize;
                    efficiency = ((diskCount - 3) / diskCount * 100).toFixed(2);
                    faultTolerance = t.three;
                    break;
                    
                case 'raid10':
                    if (diskCount < 2 || diskCount % 2 !== 0) {
                        effectiveSpace = 0;
                        efficiency = 0;
                        faultTolerance = t.none;
                    } else {
                        totalSpace = diskCount * diskSize;
                        effectiveSpace = (diskCount / 2) * diskSize;
                        efficiency = 50;
                        faultTolerance = t.half;
                    }
                    break;
                    
                default:
                    totalSpace = effectiveSpace = efficiency = 0;
                    faultTolerance = t.none;
            }
            
            // Update results
            document.getElementById('total-space').textContent = totalSpace.toLocaleString() + ' Gb';
            document.getElementById('effective-space').textContent = effectiveSpace.toLocaleString() + ' Gb';
            document.getElementById('efficiency').textContent = efficiency + ' %';
            document.getElementById('fault-tolerance').textContent = faultTolerance;
            
            // Update hint
            updateHint(raidType);
            
            // Save state
            saveStateToHash();
        }

        // Event listeners
        function setupEventListeners() {
            elements.diskCountInput.addEventListener('input', calculate);
            elements.diskSizeInput.addEventListener('input', calculate);
            elements.raidTypeSelect.addEventListener('change', calculate);
            
            document.getElementById('lang-en').addEventListener('click', () => {
                currentLang = 'en';
                updateLanguage('en');
                saveStateToHash();
            });
            document.getElementById('lang-ru').addEventListener('click', () => {
                currentLang = 'ru';
                updateLanguage('ru');
                saveStateToHash();
            });
        }

        // Initialize
        function init() {
            // Try to load state from hash
            const stateLoaded = loadStateFromHash();
            
            // Setup event listeners
            setupEventListeners();
            
            // Update UI with current or default values
            updateLanguage(currentLang);
            
            // If no state was loaded, calculate with defaults
            if (!stateLoaded) {
                calculate();
            }
        }

        // Start the application
        init();
    </script>
</body>
</html>