MediaWiki:Calculators/LawCalculator.js

Страница интерфейса MediaWiki
Версия от 19:13, 23 сентября 2025; PERed (обсуждение | вклад) (Новая страница: « // Базовые сроки по статьям const basePenalties = { '100':10,'101':10,'102':10,'103':10,'104':10,'105':10,'106':10,'107':10,'200':15,'201':15,'202':15,'203':15,'204':15, '205':15,'206':15,'207':15,'300':25,'301':25,'302':25,'303':25,'304':25,'305':25,'306':25,'307':25,'400':40,'401':40, '402':40,'403':40,'404':40,'405':40,'406':40,'407':40,'500':65,'501':65,'502':65,'503':65,'504':65,'505':65,'506':65, '507':65...»)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)

Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.

  • Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
  • Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
  • Internet Explorer / Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
  • Opera: Нажмите Ctrl+F5.
    // Базовые сроки по статьям
    const basePenalties = {
      '100':10,'101':10,'102':10,'103':10,'104':10,'105':10,'106':10,'107':10,'200':15,'201':15,'202':15,'203':15,'204':15,
	  '205':15,'206':15,'207':15,'300':25,'301':25,'302':25,'303':25,'304':25,'305':25,'306':25,'307':25,'400':40,'401':40,
	  '402':40,'403':40,'404':40,'405':40,'406':40,'407':40,'500':65,'501':65,'502':65,'503':65,'504':65,'505':65,'506':65,
	  '507':65
    };

    // Модификаторы
    const modifiers = {
      'Крайняя необходимость': 0,
      'Явка с повинной': 0.5,
      'Сделка со следствием': 0.5,
      'Отсутствие умысла': 1,
      'Помеха следствию': 1.5,
      'Должностное преступление': 1.5,
    };

    function calculate() {
      const selectedArticles = Array.from(
        document.querySelectorAll('input[name="article"]:checked')
      ).map(cb => cb.value);

      const selectedModifiers = Array.from(
        document.querySelectorAll('input[name="modifier"]:checked')
      ).map(cb => cb.value);
	  

	// Проверка на наличие статей 5xx (пожизненных)
	const hasLifeSentenceArticles = selectedArticles.some(code => code.startsWith('5'));

	// Проверка на наличие модификаторов, отменяющих пожизненное
	const hasNoIntent = selectedModifiers.includes('Отсутствие умысла');
	const hasExtremeNecessity = selectedModifiers.includes('Крайняя необходимость');

	// Если выбрано "Крайняя необходимость" — сразу отмена наказания, независимо от статей
	if (hasExtremeNecessity) {
	  document.getElementById('result').innerHTML = "✅ <b>Заключение отменено (обвинения сняты: Крайняя необходимость)</b>";
	  return;
	}

// Если есть статьи 5xx и НЕТ "Отсутствия умысла" → пожизненное (т.к. "Крайняя необходимость" уже исключена выше)
if (hasLifeSentenceArticles && !hasNoIntent) {
  document.getElementById('result').innerHTML = "📌 <b>Пожизненное заключение</b>";
  return; // Прекращаем дальнейший расчёт
}


      if (selectedArticles.length === 0) {
        document.getElementById('result').innerHTML = 
          "⚠️ Выберите хотя бы одну статью.";
        return;
      }

      // Группировка по категориям (третья цифра кода)
      const categories = {};
      selectedArticles.forEach(code => {
        const category = code[2];
        if (!categories[category]) categories[category] = [];
        categories[category].push(code);
      });
	  console.log("Категории: ", categories);

      // Из каждой категории выбираем самую тяжкую статью
      let mainArticles = [];
      for (const cat in categories) {
        const heaviest = categories[cat].reduce((a, b) => 
          basePenalties[a] > basePenalties[b] ? a : b
        );
        mainArticles.push(heaviest);
      }
	  console.log("Самые тяжелые статьи в категориях: ", mainArticles);

      // Определяем самую тяжкую из всех
      const mainArticle = mainArticles.reduce((a, b) => 
        basePenalties[a] > basePenalties[b] ? a : b
	  );
	  console.log("Самая тежелая статья: ", mainArticle);

	let effectiveMainPenalty = basePenalties[mainArticle];

	if (hasNoIntent) {
	  // Применяем понижение ко ВСЕМ основным статьям из категорий
	  const loweredArticles = mainArticles.map(code => {
		const category = parseInt(code[0]);
		if (category <= 1) {
		  // Статьи 1xx и ниже — снимаются (возвращаем null или флаг снятия)
		  return null; // обозначаем, что статья аннулирована
		} else {
		  // Понижаем категорию на 1: 201 → 101, 305 → 205 и т.д.
		  const lowerCategory = category - 1;
		  const loweredCode = lowerCategory + code.slice(1);
		  return loweredCode;
		}
	  }).filter(code => code !== null); // Убираем аннулированные статьи

	  // Если после понижения не осталось ни одной статьи — наказание снимается
	  if (loweredArticles.length === 0) {
		effectiveMainPenalty = 0;
	  } else {
		// Находим самую тяжкую из пониженных статей
		const newMainArticle = loweredArticles.reduce((a, b) => 
		  basePenalties[a] > basePenalties[b] ? a : b
		);
		effectiveMainPenalty = basePenalties[newMainArticle];
	  }
	} else {
	  // Без модификатора — обычный срок
	  effectiveMainPenalty = basePenalties[mainArticle];
	}

      // Основной штраф — с учётом модификаторов (например, понижения по "отсутствию умысла")
      const mainPenalty = effectiveMainPenalty;

      // Максимальная добавка — 50% от ОСНОВНОГО штрафа (уже модифицированного)
      const maxAdditional = mainPenalty * 0.5;
      let additional = 0;

      // Определяем, какие статьи использовать для добавки — оригинальные или пониженные
      let articlesForAdditional = mainArticles.filter(code => code !== mainArticle);

      // Если применён "Отсутствие умысла", нужно использовать ПОНИЖЕННЫЕ версии статей
      if (hasNoIntent) {
        articlesForAdditional = articlesForAdditional
          .map(code => {
            const category = parseInt(code[0]);
            if (category <= 1) return null; // снимается
            return (category - 1) + code.slice(1); // понижаем
          })
          .filter(code => code !== null && basePenalties[code] !== undefined); // оставляем только валидные
      }

      // Рассчитываем добавку
      articlesForAdditional.forEach(code => {
        const penalty = basePenalties[code];
        if (additional + penalty <= maxAdditional) {
          additional += penalty;
        } else if (additional < maxAdditional) {
          additional = maxAdditional; // Доводим до лимита
        }
      });

      let total = mainPenalty + additional;

      // Применяем модификаторы: один положительный, один отрицательный
      let posMod = 1, negMod = 1;
      selectedModifiers.forEach(mod => {
        const value = modifiers[mod];
		// Послабления — это значения МЕНЬШЕ или РАВНЫ 1 (но не 1.5)
		  if (value <= 1) {
			posMod = value; // перезаписываем, т.к. в группе только один выбор
		  }
		  
		  // Ухудшения — это значения БОЛЬШЕ 1
		  if (value > 1) {
			negMod = value; // тоже только один может быть выбран
		  }
		});
	  console.log("Срок и модификаторы: ", total, posMod, negMod);
      total *= posMod * negMod;

	// Считываем количество рецидивов
	const recidivismInput = document.getElementById('recidivismCount');
	const recidivismCount = parseInt(recidivismInput.value) || 0; // на случай, если не число

	// Добавляем 5 минут за каждый рецидив
	total += recidivismCount * 5;

	console.log("С учётом рецидивов: ", total);

      // Проверка на пожизненное
      if (total >= 65) {
        document.getElementById('result').innerHTML = 
          "📌 <b>Пожизненное заключение</b>";
      } else if (total <= 0) {
        document.getElementById('result').innerHTML = 
          "✅ <b>Заключение отменено(обвинения сняты согласно модификаторам)</b>";
      } else if (total <= 10) {
        document.getElementById('result').innerHTML = 
          `⏱️ <b>Срок: ${total} минут или предупреждение</b>`;
	  } else if (total >=40 && total < 65) {
        document.getElementById('result').innerHTML = 
          `⏱️ <b>Срок: ${total} минут с отбыванием в пермабриге</b>`;
	  } else {
        document.getElementById('result').innerHTML = 
          `⏱️ <b>Срок: ${total} минут</b>`;
      }
    }