MediaWiki:Common.js: различия между версиями

Страница интерфейса MediaWiki
Нет описания правки
Метка: ручная отмена
Нет описания правки
 
(не показано 6 промежуточных версий этого же участника)
Строка 19: Строка 19:
      
      
     // Подключаем Tippy.js через CDN динамически
     // Подключаем Tippy.js через CDN динамически
if (!window.tippy) {
    if (!window.tippy) {
    var tippyScript = document.createElement('script');
        var tippyScript = document.createElement('script');
    tippyScript.src = "https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js";
        tippyScript.src = "https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js";
    tippyScript.onload = function() {
        tippyScript.onload = function() {
        var tippyCoreScript = document.createElement('script');
            var tippyCoreScript = document.createElement('script');
        tippyCoreScript.src = "https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.min.js";
            tippyCoreScript.src = "https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.min.js";
        tippyCoreScript.onload = initTippy;
            tippyCoreScript.onload = initTippy;
         document.head.appendChild(tippyCoreScript);
            document.head.appendChild(tippyCoreScript);
        };
        document.head.appendChild(tippyScript);
 
        // Подключаем CSS
        var tippyCSS = document.createElement('link');
        tippyCSS.rel = "stylesheet";
        tippyCSS.href = "https://unpkg.com/tippy.js@6/dist/tippy.css";
         document.head.appendChild(tippyCSS);
    } else {
        initTippy();
    }
 
    // Инициализация Tippy после загрузки скриптов
    function initTippy() {
        $('.допуск-контейнер').each(function() {
            var content = $(this).find('.допуск-подсказка').html(); // берем содержимое подсказки
            tippy(this, {
                content: content,
                allowHTML: true,
                interactive: true,
                placement: 'auto',      // автоматический выбор позиции
                maxWidth: '500px',
                minHeight: 'auto',
                theme: 'dark',          // темная тема
                arrow: true,          // без стрелки
                duration: [200, 200],  // плавное появление/исчезание
                popperOptions: {
                    modifiers: [
                        {
                            name: 'preventOverflow',
                            options: {
                                padding: 8 // отступ от краев экрана
                            }
                        },
                        {
                            name: 'flip',
                            options: {
                                fallbackPlacements: ['top', 'bottom', 'right', 'left']
                            }
                        }
                    ]
                }
            });
        });
    }
 
    // Данные о законах SS14
    window.ss14Laws = {
        '100': { name: 'Оскорбительное поведение', category: 1, minTime: 5, maxTime: 10 },
        '101': { name: 'Лёгкий ущерб здоровью', category: 1, minTime: 5, maxTime: 10 },
        '102': { name: 'Порча имущества', category: 1, minTime: 5, maxTime: 10 },
        '103': { name: 'Мелкая кража', category: 1, minTime: 5, maxTime: 10 },
        '104': { name: 'Владение регулируемыми веществами', category: 1, minTime: 5, maxTime: 10 },
        '105': { name: 'Злоупотребление экипировкой', category: 1, minTime: 5, maxTime: 10 },
        '106': { name: 'Помеха работе сотрудников', category: 1, minTime: 5, maxTime: 10 },
        '107': { name: 'Проникновение', category: 1, minTime: 5, maxTime: 10 },
        '108': { name: 'Жестокое обращение с животными', category: 1, minTime: 5, maxTime: 10 },
        '109': { name: 'Клевета', category: 1, minTime: 5, maxTime: 10 },
       
        '200': { name: 'Оскорбление власти', category: 2, minTime: 10, maxTime: 15 },
        '201': { name: 'Средний ущерб здоровью', category: 2, minTime: 10, maxTime: 15 },
        '202': { name: 'Вандализм', category: 2, minTime: 10, maxTime: 15 },
        '204': { name: 'Распространение регулируемых веществ', category: 2, minTime: 10, maxTime: 15 },
        '205': { name: 'Владение боевым приспособлением', category: 2, minTime: 10, maxTime: 15 },
        '206': { name: 'Помеха правосудию', category: 2, minTime: 10, maxTime: 15 },
        '207': { name: 'Проникновение со взломом', category: 2, minTime: 10, maxTime: 15 },
        '208': { name: 'Убийство животного', category: 2, minTime: 10, maxTime: 15 },
        '209': { name: 'Халатность', category: 2, minTime: 10, maxTime: 15 },
        '210': { name: 'Ограничение свободы', category: 2, minTime: 10, maxTime: 15 },
        '211': { name: 'Шпионаж', category: 2, minTime: 10, maxTime: 15 },
       
        '300': { name: 'Забастовка', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '301': { name: 'Тяжкий ущерб здоровью', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '302': { name: 'Саботаж', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '303': { name: 'Кража', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '304': { name: 'Оборот контрабанды', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '305': { name: 'Владение нелетальным оружием', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '306': { name: 'Мошенничество', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '307': { name: 'Проникновение в стратегическую точку', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '308': { name: 'Распространение опасной флоры и фауны', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '309': { name: 'Серьёзная халатность', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '310': { name: 'Похищение', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '311': { name: 'Проникновение в защищённый канал', category: 3, minTime: 15, maxTime: 20, dismissal: true },
       
        '400': { name: 'Бунт', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '401': { name: 'Убийство', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '403': { name: 'Крупная кража', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '404': { name: 'Производство регулируемых веществ', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '405': { name: 'Владение летальным оружием', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '406': { name: 'Растрата активов корпорации', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '408': { name: 'Убийство особого животного', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '409': { name: 'Грубая халатность', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '410': { name: 'Похищение должностного лица', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '411': { name: 'Антикорпоративный шпионаж', category: 4, minTime: 20, maxTime: 25, dismissal: true },
       
        '500': { name: 'Мятеж', category: 5, dClass: true, dismissal: true },
        '501': { name: 'Уничтожение тела', category: 5, dClass: true, dismissal: true },
        '502': { name: 'Крупный саботаж', category: 5, dClass: true, dismissal: true },
        '503': { name: 'Особая кража', category: 5, dClass: true, dismissal: true },
        '504': { name: 'Владение вражеским снаряжением', category: 5, dClass: true, dismissal: true },
        '505': { name: 'Распространение оружия', category: 5, dClass: true, dismissal: true },
        '507': { name: 'Проникновение в защищённую стратегическую точку', category: 5, dClass: true, dismissal: true },
        '510': { name: 'Похищение высокопоставленных лиц', category: 5, dClass: true, dismissal: true },
        '511': { name: 'Разглашение секретной информации', category: 5, dClass: true, dismissal: true }
     };
     };
    document.head.appendChild(tippyScript);


     // Подключаем CSS
     // Глобальные функции для SS14 калькулятора
     var tippyCSS = document.createElement('link');
     window.ss14CurrentLawCode = null;
    tippyCSS.rel = "stylesheet";
    tippyCSS.href = "https://unpkg.com/tippy.js@6/dist/tippy.css";
    document.head.appendChild(tippyCSS);
} else {
    initTippy();
}


// Инициализация Tippy после загрузки скриптов
    window.toggleCalculator = function(lawCode) {
function initTippy() {
        var calculator = document.getElementById('ss14-calculator');
    $('.допуск-контейнер').each(function() {
        window.ss14CurrentLawCode = lawCode;
         var content = $(this).find('.допуск-подсказка').html(); // берем содержимое подсказки
       
         tippy(this, {
        if (!calculator) return;
             content: content,
       
             allowHTML: true,
        if (calculator.style.display === 'none' || !calculator.classList.contains('active')) {
             interactive: true,
            calculator.classList.add('active');
             placement: 'auto',      // автоматический выбор позиции
            generateLawCheckboxes();
             maxWidth: '80vw',       // responsive
           
             theme: 'dark',         // темная тема
            // Автоматически выбираем нажатый закон
             arrow: false,          // без стрелки
            var checkbox = document.getElementById('law-' + lawCode);
             duration: [200, 200]// плавное появление/исчезание
            if (checkbox) {
             popperOptions: {
                checkbox.checked = true;
                 modifiers: [
            }
                     {
           
                        name: 'preventOverflow',
            calculateSentence();
                        options: {
        } else {
                            padding: 8, // отступ от краев экрана
            calculator.classList.remove('active');
                        },
        }
                    },
    };
                    {
 
                        name: 'flip',
    window.generateLawCheckboxes = function() {
                        options: {
         var container = document.getElementById('law-checkboxes');
                            fallbackPlacements: ['top', 'bottom', 'right', 'left'],
        if (!container) return;
                        },
       
                    },
        container.innerHTML = '';
                ],
       
             },
        // Группируем законы по категориям
         var categories = {
            1: { name: 'Лёгкие нарушения (1XX)', color: '#0F4F27' },
            2: { name: 'Средние нарушения (2XX)', color: '#414700' },
             3: { name: 'Тяжкие нарушения (3XX)', color: '#611300' },
             4: { name: 'Особо тяжкие нарушения (4XX)', color: '#57000C' },
             5: { name: 'Критические нарушения (5XX)', color: '#121212' }
        };
       
        for (var cat = 1; cat <= 5; cat++) {
            var categoryDiv = document.createElement('div');
            categoryDiv.style.marginBottom = '15px';
             categoryDiv.innerHTML = '<h5 style="color: ' + categories[cat].color + '; margin-bottom: 8px;">' + categories[cat].name + '</h5>';
           
            var lawsInCategory = Object.keys(window.ss14Laws).filter(function(code) {
                return window.ss14Laws[code].category === cat;
            });
           
            lawsInCategory.forEach(function(code) {
                var law = window.ss14Laws[code];
                var label = document.createElement('label');
                label.className = 'law-checkbox';
                label.innerHTML = '<input type="checkbox" id="law-' + code + '" onchange="calculateSentence()"> ' + code + ' - ' + law.name;
                categoryDiv.appendChild(label);
            });
           
             container.appendChild(categoryDiv);
        }
    };
 
    window.calculateSentence = function() {
        var selectedLaws = [];
        var checkboxes = document.querySelectorAll('[id^="law-"]:checked');
       
        checkboxes.forEach(function(checkbox) {
            var lawCode = checkbox.id.replace('law-', '');
            selectedLaws.push(lawCode);
        });
       
        if (selectedLaws.length === 0) {
            var resultDiv = document.getElementById('calculation-result');
            if (resultDiv) {
                resultDiv.style.display = 'none';
            }
             return;
        }
       
        var modifierSelect = document.getElementById('modifier-select');
        var repeatOffense = document.getElementById('repeat-offense');
        var cooperation = document.getElementById('cooperation');
        var dClass = document.getElementById('d-class');
       
        var modifier = modifierSelect ? modifierSelect.value : 'none';
        var isRepeat = repeatOffense ? repeatOffense.checked : false;
        var hasCooperation = cooperation ? cooperation.checked : false;
        var isDClass = dClass ? dClass.checked : false;
       
        var result = calculatePunishment(selectedLaws, modifier, isRepeat, hasCooperation, isDClass);
        displayResult(result, selectedLaws);
    };
 
    function calculatePunishment(selectedLaws, modifier, isRepeat, hasCooperation, isDClass) {
        var totalTime = 0;
        var punishmentType = 'Заключение под стражу';
        var hasDismissal = false;
        var hasDClass = false;
        var categoryGroups = {};
       
        // Группируем по категориям (одинаковые категории не складываются)
        selectedLaws.forEach(function(lawCode) {
            var law = window.ss14Laws[lawCode];
            var categoryCode = lawCode.substring(1); // получаем последние 2 цифры (тип нарушения)
           
            if (!categoryGroups[categoryCode] || law.category > window.ss14Laws[categoryGroups[categoryCode]].category) {
                categoryGroups[categoryCode] = lawCode;
             }
        });
       
        // Рассчитываем время для каждой группы
        Object.keys(categoryGroups).forEach(function(categoryCode) {
             var lawCode = categoryGroups[categoryCode];
            var law = window.ss14Laws[lawCode];
           
            if (law.dClass) {
                hasDClass = true;
                totalTime += 70; // для расчёта модификаторов
            } else {
                totalTime += law.maxTime; // берём максимальное время
            }
           
             if (law.dismissal) {
                 hasDismissal = true;
            }
        });
       
        // Применяем модификаторы
        switch (modifier) {
            case 'M-CLEM':
                // Помилование - только для категорий 3 и 4
                var hasEligibleLaws = Object.keys(categoryGroups).some(function(categoryCode) {
                    var lawCode = categoryGroups[categoryCode];
                    var law = window.ss14Laws[lawCode];
                     return law.category === 3 || law.category === 4;
                });
                if (hasEligibleLaws) {
                    totalTime = Math.max(0, totalTime - 10);
                }
                break;
               
            case 'M-SURR':
                // Немедленная капитуляция
                totalTime = Math.max(0, totalTime - 5);
                break;
               
            case 'M-DEFENSE':
            case 'M-HELP':
                // Самооборона или спасение - снимает все обвинения
                totalTime = 0;
                hasDClass = false;
                punishmentType = 'Обвинения сняты (требуется обыск)';
                break;
        }
       
        // Повторное нарушение
        if (isRepeat && totalTime > 0) {
            totalTime = Math.min(totalTime + 10, 50);
        }
       
        // Сотрудничество со следствием
        if (hasCooperation && totalTime > 0) {
            totalTime = Math.max(0, totalTime - 3);
        }
       
        // Определяем тип наказания
        if (hasDClass) {
            punishmentType = 'Перевод в Д-класс';
            if (modifier === 'M-LOW' && isDClass) {
                punishmentType = 'Условная ликвидация (M-LOW)';
            } else if (modifier === 'M-VITAL' && isDClass) {
                punishmentType = 'Взаимодействие с SCP (M-VITAL)';
            }
        } else if (totalTime >= 50) {
            punishmentType = 'Перевод в Д-класс (срок ≥50 мин)';
            if (totalTime >= 35 && isDClass) {
                punishmentType += ' или добровольный перевод';
            }
        } else if (totalTime >= 35 && isDClass) {
            punishmentType = 'Возможен добровольный перевод в Д-класс';
        }
       
        return {
            totalTime: totalTime,
            punishmentType: punishmentType,
            hasDismissal: hasDismissal,
            hasDClass: hasDClass,
             categoryGroups: categoryGroups
        };
    }
 
    function displayResult(result, selectedLaws) {
        var resultDiv = document.getElementById('calculation-result');
        if (!resultDiv) return;
       
        var html = '<h4>📋 Результат расчёта:</h4>';
       
        html += '<div><strong>Выбранные статьи:</strong><br>';
        selectedLaws.forEach(function(lawCode) {
            var law = window.ss14Laws[lawCode];
            html += '• ' + lawCode + ' - ' + law.name + '<br>';
         });
         });
    });
        html += '</div><br>';
}
       
        html += '<div class="punishment-type">Тип наказания: ' + result.punishmentType + '</div>';
       
        if (result.totalTime > 0 && !result.hasDClass) {
            html += '<div class="time-result">Время заключения: ' + result.totalTime + ' минут</div>';
        }
       
        if (result.hasDismissal) {
            html += '<div style="color: #f44336; margin-top: 10px;">⚠️ <strong>Обязательное увольнение с текущей должности</strong></div>';
        }
       
        // Дополнительная информация
        html += '<div style="margin-top: 15px; font-size: 12px; color: #666;">';
        html += '<strong>Примечания:</strong><br>';
        html += '• Статьи одной категории (одинаковые последние 2 цифры) не складываются<br>';
        html += '• Статьи разных категорий складываются<br>';
        html += '• При сроке 50+ минут - обязательный перевод в Д-класс<br>';
        html += '• При сроке 35+ минут класс Д может добровольно перейти в Д-класс';
        html += '</div>';
       
        resultDiv.innerHTML = html;
        resultDiv.style.display = 'block';
    }


    // Инициализация при загрузке страницы
    if (document.getElementById('law-checkboxes')) {
        generateLawCheckboxes();
    }
});
});

Текущая версия от 14:24, 9 сентября 2025

$(document).ready(function() {
    // Инициализация боковой панели
    $('.боковая-панель-кнопка').on('click', function() {
        var targetId = $(this).data('target');
        
        // Удаляем активный класс у всех кнопок
        $('.боковая-панель-кнопка').removeClass('active');
        // Добавляем активный класс текущей кнопке
        $(this).addClass('active');
        
        // Скрываем все разделы
        $('.боковая-панель-раздел').removeClass('default');
        // Показываем выбранный раздел
        $('#' + targetId).addClass('default');
    });
    
    // Активируем первую кнопку по умолчанию
    $('.боковая-панель-кнопка:first').click();
    
    // Подключаем Tippy.js через CDN динамически
    if (!window.tippy) {
        var tippyScript = document.createElement('script');
        tippyScript.src = "https://unpkg.com/@popperjs/core@2/dist/umd/popper.min.js";
        tippyScript.onload = function() {
            var tippyCoreScript = document.createElement('script');
            tippyCoreScript.src = "https://unpkg.com/tippy.js@6/dist/tippy-bundle.umd.min.js";
            tippyCoreScript.onload = initTippy;
            document.head.appendChild(tippyCoreScript);
        };
        document.head.appendChild(tippyScript);

        // Подключаем CSS
        var tippyCSS = document.createElement('link');
        tippyCSS.rel = "stylesheet";
        tippyCSS.href = "https://unpkg.com/tippy.js@6/dist/tippy.css";
        document.head.appendChild(tippyCSS);
    } else {
        initTippy();
    }

    // Инициализация Tippy после загрузки скриптов
    function initTippy() {
        $('.допуск-контейнер').each(function() {
            var content = $(this).find('.допуск-подсказка').html(); // берем содержимое подсказки
            tippy(this, {
                content: content,
                allowHTML: true,
                interactive: true,
                placement: 'auto',      // автоматический выбор позиции
                maxWidth: '500px',
                minHeight: 'auto',
                theme: 'dark',          // темная тема
                arrow: true,           // без стрелки
                duration: [200, 200],   // плавное появление/исчезание
                popperOptions: {
                    modifiers: [
                        {
                            name: 'preventOverflow',
                            options: {
                                padding: 8 // отступ от краев экрана
                            }
                        },
                        {
                            name: 'flip',
                            options: {
                                fallbackPlacements: ['top', 'bottom', 'right', 'left']
                            }
                        }
                    ]
                }
            });
        });
    }

    // Данные о законах SS14
    window.ss14Laws = {
        '100': { name: 'Оскорбительное поведение', category: 1, minTime: 5, maxTime: 10 },
        '101': { name: 'Лёгкий ущерб здоровью', category: 1, minTime: 5, maxTime: 10 },
        '102': { name: 'Порча имущества', category: 1, minTime: 5, maxTime: 10 },
        '103': { name: 'Мелкая кража', category: 1, minTime: 5, maxTime: 10 },
        '104': { name: 'Владение регулируемыми веществами', category: 1, minTime: 5, maxTime: 10 },
        '105': { name: 'Злоупотребление экипировкой', category: 1, minTime: 5, maxTime: 10 },
        '106': { name: 'Помеха работе сотрудников', category: 1, minTime: 5, maxTime: 10 },
        '107': { name: 'Проникновение', category: 1, minTime: 5, maxTime: 10 },
        '108': { name: 'Жестокое обращение с животными', category: 1, minTime: 5, maxTime: 10 },
        '109': { name: 'Клевета', category: 1, minTime: 5, maxTime: 10 },
        
        '200': { name: 'Оскорбление власти', category: 2, minTime: 10, maxTime: 15 },
        '201': { name: 'Средний ущерб здоровью', category: 2, minTime: 10, maxTime: 15 },
        '202': { name: 'Вандализм', category: 2, minTime: 10, maxTime: 15 },
        '204': { name: 'Распространение регулируемых веществ', category: 2, minTime: 10, maxTime: 15 },
        '205': { name: 'Владение боевым приспособлением', category: 2, minTime: 10, maxTime: 15 },
        '206': { name: 'Помеха правосудию', category: 2, minTime: 10, maxTime: 15 },
        '207': { name: 'Проникновение со взломом', category: 2, minTime: 10, maxTime: 15 },
        '208': { name: 'Убийство животного', category: 2, minTime: 10, maxTime: 15 },
        '209': { name: 'Халатность', category: 2, minTime: 10, maxTime: 15 },
        '210': { name: 'Ограничение свободы', category: 2, minTime: 10, maxTime: 15 },
        '211': { name: 'Шпионаж', category: 2, minTime: 10, maxTime: 15 },
        
        '300': { name: 'Забастовка', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '301': { name: 'Тяжкий ущерб здоровью', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '302': { name: 'Саботаж', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '303': { name: 'Кража', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '304': { name: 'Оборот контрабанды', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '305': { name: 'Владение нелетальным оружием', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '306': { name: 'Мошенничество', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '307': { name: 'Проникновение в стратегическую точку', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '308': { name: 'Распространение опасной флоры и фауны', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '309': { name: 'Серьёзная халатность', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '310': { name: 'Похищение', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        '311': { name: 'Проникновение в защищённый канал', category: 3, minTime: 15, maxTime: 20, dismissal: true },
        
        '400': { name: 'Бунт', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '401': { name: 'Убийство', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '403': { name: 'Крупная кража', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '404': { name: 'Производство регулируемых веществ', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '405': { name: 'Владение летальным оружием', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '406': { name: 'Растрата активов корпорации', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '408': { name: 'Убийство особого животного', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '409': { name: 'Грубая халатность', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '410': { name: 'Похищение должностного лица', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        '411': { name: 'Антикорпоративный шпионаж', category: 4, minTime: 20, maxTime: 25, dismissal: true },
        
        '500': { name: 'Мятеж', category: 5, dClass: true, dismissal: true },
        '501': { name: 'Уничтожение тела', category: 5, dClass: true, dismissal: true },
        '502': { name: 'Крупный саботаж', category: 5, dClass: true, dismissal: true },
        '503': { name: 'Особая кража', category: 5, dClass: true, dismissal: true },
        '504': { name: 'Владение вражеским снаряжением', category: 5, dClass: true, dismissal: true },
        '505': { name: 'Распространение оружия', category: 5, dClass: true, dismissal: true },
        '507': { name: 'Проникновение в защищённую стратегическую точку', category: 5, dClass: true, dismissal: true },
        '510': { name: 'Похищение высокопоставленных лиц', category: 5, dClass: true, dismissal: true },
        '511': { name: 'Разглашение секретной информации', category: 5, dClass: true, dismissal: true }
    };

    // Глобальные функции для SS14 калькулятора
    window.ss14CurrentLawCode = null;

    window.toggleCalculator = function(lawCode) {
        var calculator = document.getElementById('ss14-calculator');
        window.ss14CurrentLawCode = lawCode;
        
        if (!calculator) return;
        
        if (calculator.style.display === 'none' || !calculator.classList.contains('active')) {
            calculator.classList.add('active');
            generateLawCheckboxes();
            
            // Автоматически выбираем нажатый закон
            var checkbox = document.getElementById('law-' + lawCode);
            if (checkbox) {
                checkbox.checked = true;
            }
            
            calculateSentence();
        } else {
            calculator.classList.remove('active');
        }
    };

    window.generateLawCheckboxes = function() {
        var container = document.getElementById('law-checkboxes');
        if (!container) return;
        
        container.innerHTML = '';
        
        // Группируем законы по категориям
        var categories = {
            1: { name: 'Лёгкие нарушения (1XX)', color: '#0F4F27' },
            2: { name: 'Средние нарушения (2XX)', color: '#414700' },
            3: { name: 'Тяжкие нарушения (3XX)', color: '#611300' },
            4: { name: 'Особо тяжкие нарушения (4XX)', color: '#57000C' },
            5: { name: 'Критические нарушения (5XX)', color: '#121212' }
        };
        
        for (var cat = 1; cat <= 5; cat++) {
            var categoryDiv = document.createElement('div');
            categoryDiv.style.marginBottom = '15px';
            categoryDiv.innerHTML = '<h5 style="color: ' + categories[cat].color + '; margin-bottom: 8px;">' + categories[cat].name + '</h5>';
            
            var lawsInCategory = Object.keys(window.ss14Laws).filter(function(code) {
                return window.ss14Laws[code].category === cat;
            });
            
            lawsInCategory.forEach(function(code) {
                var law = window.ss14Laws[code];
                var label = document.createElement('label');
                label.className = 'law-checkbox';
                label.innerHTML = '<input type="checkbox" id="law-' + code + '" onchange="calculateSentence()"> ' + code + ' - ' + law.name;
                categoryDiv.appendChild(label);
            });
            
            container.appendChild(categoryDiv);
        }
    };

    window.calculateSentence = function() {
        var selectedLaws = [];
        var checkboxes = document.querySelectorAll('[id^="law-"]:checked');
        
        checkboxes.forEach(function(checkbox) {
            var lawCode = checkbox.id.replace('law-', '');
            selectedLaws.push(lawCode);
        });
        
        if (selectedLaws.length === 0) {
            var resultDiv = document.getElementById('calculation-result');
            if (resultDiv) {
                resultDiv.style.display = 'none';
            }
            return;
        }
        
        var modifierSelect = document.getElementById('modifier-select');
        var repeatOffense = document.getElementById('repeat-offense');
        var cooperation = document.getElementById('cooperation');
        var dClass = document.getElementById('d-class');
        
        var modifier = modifierSelect ? modifierSelect.value : 'none';
        var isRepeat = repeatOffense ? repeatOffense.checked : false;
        var hasCooperation = cooperation ? cooperation.checked : false;
        var isDClass = dClass ? dClass.checked : false;
        
        var result = calculatePunishment(selectedLaws, modifier, isRepeat, hasCooperation, isDClass);
        displayResult(result, selectedLaws);
    };

    function calculatePunishment(selectedLaws, modifier, isRepeat, hasCooperation, isDClass) {
        var totalTime = 0;
        var punishmentType = 'Заключение под стражу';
        var hasDismissal = false;
        var hasDClass = false;
        var categoryGroups = {};
        
        // Группируем по категориям (одинаковые категории не складываются)
        selectedLaws.forEach(function(lawCode) {
            var law = window.ss14Laws[lawCode];
            var categoryCode = lawCode.substring(1); // получаем последние 2 цифры (тип нарушения)
            
            if (!categoryGroups[categoryCode] || law.category > window.ss14Laws[categoryGroups[categoryCode]].category) {
                categoryGroups[categoryCode] = lawCode;
            }
        });
        
        // Рассчитываем время для каждой группы
        Object.keys(categoryGroups).forEach(function(categoryCode) {
            var lawCode = categoryGroups[categoryCode];
            var law = window.ss14Laws[lawCode];
            
            if (law.dClass) {
                hasDClass = true;
                totalTime += 70; // для расчёта модификаторов
            } else {
                totalTime += law.maxTime; // берём максимальное время
            }
            
            if (law.dismissal) {
                hasDismissal = true;
            }
        });
        
        // Применяем модификаторы
        switch (modifier) {
            case 'M-CLEM':
                // Помилование - только для категорий 3 и 4
                var hasEligibleLaws = Object.keys(categoryGroups).some(function(categoryCode) {
                    var lawCode = categoryGroups[categoryCode];
                    var law = window.ss14Laws[lawCode];
                    return law.category === 3 || law.category === 4;
                });
                if (hasEligibleLaws) {
                    totalTime = Math.max(0, totalTime - 10);
                }
                break;
                
            case 'M-SURR':
                // Немедленная капитуляция
                totalTime = Math.max(0, totalTime - 5);
                break;
                
            case 'M-DEFENSE':
            case 'M-HELP':
                // Самооборона или спасение - снимает все обвинения
                totalTime = 0;
                hasDClass = false;
                punishmentType = 'Обвинения сняты (требуется обыск)';
                break;
        }
        
        // Повторное нарушение
        if (isRepeat && totalTime > 0) {
            totalTime = Math.min(totalTime + 10, 50);
        }
        
        // Сотрудничество со следствием
        if (hasCooperation && totalTime > 0) {
            totalTime = Math.max(0, totalTime - 3);
        }
        
        // Определяем тип наказания
        if (hasDClass) {
            punishmentType = 'Перевод в Д-класс';
            if (modifier === 'M-LOW' && isDClass) {
                punishmentType = 'Условная ликвидация (M-LOW)';
            } else if (modifier === 'M-VITAL' && isDClass) {
                punishmentType = 'Взаимодействие с SCP (M-VITAL)';
            }
        } else if (totalTime >= 50) {
            punishmentType = 'Перевод в Д-класс (срок ≥50 мин)';
            if (totalTime >= 35 && isDClass) {
                punishmentType += ' или добровольный перевод';
            }
        } else if (totalTime >= 35 && isDClass) {
            punishmentType = 'Возможен добровольный перевод в Д-класс';
        }
        
        return {
            totalTime: totalTime,
            punishmentType: punishmentType,
            hasDismissal: hasDismissal,
            hasDClass: hasDClass,
            categoryGroups: categoryGroups
        };
    }

    function displayResult(result, selectedLaws) {
        var resultDiv = document.getElementById('calculation-result');
        if (!resultDiv) return;
        
        var html = '<h4>📋 Результат расчёта:</h4>';
        
        html += '<div><strong>Выбранные статьи:</strong><br>';
        selectedLaws.forEach(function(lawCode) {
            var law = window.ss14Laws[lawCode];
            html += '• ' + lawCode + ' - ' + law.name + '<br>';
        });
        html += '</div><br>';
        
        html += '<div class="punishment-type">Тип наказания: ' + result.punishmentType + '</div>';
        
        if (result.totalTime > 0 && !result.hasDClass) {
            html += '<div class="time-result">Время заключения: ' + result.totalTime + ' минут</div>';
        }
        
        if (result.hasDismissal) {
            html += '<div style="color: #f44336; margin-top: 10px;">⚠️ <strong>Обязательное увольнение с текущей должности</strong></div>';
        }
        
        // Дополнительная информация
        html += '<div style="margin-top: 15px; font-size: 12px; color: #666;">';
        html += '<strong>Примечания:</strong><br>';
        html += '• Статьи одной категории (одинаковые последние 2 цифры) не складываются<br>';
        html += '• Статьи разных категорий складываются<br>';
        html += '• При сроке 50+ минут - обязательный перевод в Д-класс<br>';
        html += '• При сроке 35+ минут класс Д может добровольно перейти в Д-класс';
        html += '</div>';
        
        resultDiv.innerHTML = html;
        resultDiv.style.display = 'block';
    }

    // Инициализация при загрузке страницы
    if (document.getElementById('law-checkboxes')) {
        generateLawCheckboxes();
    }
});