# Проверки поэтапного переноса из Owniverse.U ## Производительность на сохранении ```sh godot --headless --path Owniverse.GI --script res://tests/benchmark_saved_state.gd -- /tmp/save.adventure.json ``` Читает диагностический JSON формата 4 в отдельные экземпляры мира и замеряет шесть последовательных шагов на скоростях 1, 4, 6. Запись сохранений не вызывается. Последним аргументом можно задать длительность шага в реальных секундах (по умолчанию 1/60). Это время расчёта симуляции, без отрисовки интерфейса. На диагностической копии с 120 партиями прежняя рациональная арифметика после оптимизации пустых окон давала 90–99 мс на шаг 1/60 секунды на скорости 6. После перехода на целые блоки и float-остаток повторный замер дал 58–62 мс. При шаге 0,1 секунды: 71–82 мс вместо 117–138 мс. Это замеры расчёта на данной копии, а не обещание FPS. Для сравнения старый JSON был преобразован только во временный тестовый файл; в загрузчик игры миграция не добавлена. Разреженные сценарии сравниваются с полным расчётом в `test_short_lived_events.gd`. ## Целые блоки и дробные остатки `godot --headless --path Owniverse.GI --script res://tests/test_exact_math.gd` Независимый эталон Python Fraction: 160 пар с произведением внутри E27; целые проверяются точно, дроби — с допуском 10^-12. Также границы int64/E27, сериализация, рецепты с дробными стоимостями, сохранение сумм, время и 100 циклов с меняющимися долями. Все остальные тесты используют числовое сравнение и сериализацию через `E`, а не сравнение ссылок на большие числа. Границы точности и новый формат сохранения описаны в [документации арифметики](../world/owniverse/math/README.md). ## Модули симуляции `godot --headless --path Owniverse.GI --script res://tests/test_module_lifecycle.gd` Проверяются отдельные экземпляры модулей и состояния для каждой вселенной, слабая обратная ссылка, освобождение модулей вместе с миром и защита от некорректного delta. Остальные тесты используют прямые API batches, ledger, production, automatic, stellar, life, environment и evolution; временные методы-переадресации Owniverse удалены. Описание границ модулей и порядка фаз: `../world/owniverse/README.md`. ## Математика распределений и каталог `godot --headless --path Owniverse.GI --script res://tests/test_quantity_catalog.gd` Проверяются целочисленность и границы распределения, сохранение суммы, разрешение равных остатков, накопление дробей и долгов округления, нормализация весов, размер производственной партии, загрузка каталога и его индексы. Архитектура описана в `../world/owniverse/README.md`. Сохранение игрока не используется. ## Иконки стадий жизни Тест также проверяет модуль `item_presentation.gd`: отсутствие изменений входного состояния и списка закрытых иконок, решения по разблокировке, отложенную и принудительную публикацию количеств. `godot --headless --path Owniverse.GI --script res://tests/test_life_icons.gd` Проверяются одновременная разблокировка подробных и общих иконок EON/LP и C0.0/C0, количества свободных и связанных планет без двойного учёта, переключение подпанелей и очистка счётчика при исчезновении стадии. Сохранение игрока не используется. ## Параметры мира и индикаторы ```sh godot --headless --path Owniverse.GI --script res://tests/test_world_indicators.gd ``` Проверяются сроки жизни существующих и новых звёзд при смене горючести, вероятности и мощность взрывов, влияние агрессии/порядка/просвещения на жизнь, накопление тенденций по времени и этикам, несколько событий за шаг, продолжение после сериализации, валидация сохранения, границы шкал и описания на двух языках. Сцена использует фикстуру без доступа к сохранению игрока. ## Прямой расчёт завершившихся сверхновых ```sh godot --headless --path Owniverse.GI --script res://tests/test_short_lived_events.gd ``` Сравниваются ускоренный путь и прежний путь с созданием всех партий, отключаемый только в тестовой фикстуре. Проверяются LRG, HRG, RSG и RHG на границах коротких и длинных интервалов, существующие SN, нехватка энергии, ресурсы, бласты, привязки, остатки округления и живые партии. Дополнительно проверяется, что длинный интервал создаёт не более двух живых окон и одну запись завершений, сохраняя общее количество. Сохранение игрока этот тест не использует. `test_stellar_rules.gd` также проверяет автоматическое создание HBD: долю 0,1% нового автоматического водорода, появление по одному со случайным округлением, сохранение оплаченного остатка топлива, отсутствие повторного начисления на старый запас, продолжение случайной последовательности после сериализации и переход HBD → CBD с сохранением счётчика BD. Формулы описаны в `../simulation_rules.md`. ## Фоновое сохранение и частота обновления интерфейса ```sh godot --headless --path Owniverse.GI --script res://tests/test_async_save.gd godot --headless --path Owniverse.GI --script res://tests/test_ui_updates.gd ``` Сохранение: основной поток создаёт глубокий снимок состояния и параметров. Рабочий поток проверяет данные, записывает зашифрованный временный файл, проверяет чтением и заменяет основное сохранение; диагностический JSON создаётся из того же снимка. Одновременно работает один писатель. Для каждого имени файла хранится только последний ожидающий запрос. `request_save()` подтверждает постановку в очередь; результат записи сообщает сигнал `save_completed`. При закрытии игра ждёт `saves_drained`, при приостановке приложения и уничтожении менеджера очередь завершается через `flush_saves()`. Копирование снимка остаётся в основном потоке. Тест сохранений пишет только в уникальную временную папку `/tmp`, затем удаляет собственные файлы. Проверяются независимость снимка, работа кадров при записи, объединение запросов, диагностическая копия, сохранность предыдущего файла при ошибках и завершение очереди при уничтожении менеджера. Сообщения `Invalid save`, `Save blocked` и `Cannot write` в этом тесте ожидаемы. Тест интерфейса проверяет передачу количеств из presentation в контролы, очистку очереди после публикации, отложенное и принудительное обновление, производство по нажатию и формат времени. Stage в текущей реализации применяет очередь счётчиков и время каждый кадр; интервал 0,1 секунды используется для индикаторов. Рефакторинг этот порядок не меняет. Тест использует игровую сцену с отключёнными загрузкой, сохранением и автоматической симуляцией, не обращаясь к сохранению игрока. ## Время: шаг 0,1 игрового года ```sh godot --headless --path Owniverse.GI --script res://tests/test_time.gd ``` Команда выполняется из общей папки проектов. Тесты используют искусственные состояния; сохранение игрока не читается и не перезаписывается. Проверяются границы десятых долей года, производство ресурсов на этих границах, накопление дробного остатка, скорости 1–10 000 лет/сек, продолжение после загрузки и недопустимые интервалы. Схема состояния `0.3.0` хранит: - `time.datetime` — накопленный возраст, включая необработанную дробную часть; - `time.year` — последний рассчитанный возраст с точностью до десятой доли года. Сохранения используют формат 4 и актуальную структуру состояния. Проверяются целостность данных, фоновая запись и повторная загрузка; поддержка и миграция прежних форматов отсутствуют. Файл с несовместимым номером формата при загрузке переносится в `*.adventure.incompatible.bak` (при совпадении имени добавляется числовой суффикс). Игра начинает новую сессию и может сохранять её в формате 4. Прогресс несовместимого файла не переносится, исходные байты сохраняются в архиве. Ошибка архивирования, расшифровки или повреждение данных текущего формата по-прежнему блокируют перезапись. ## Согласованные правила эволюции Сохраняются постепенные интервальные окна GI: начало преобразования — через `lifespan`, длительность окна — `lifespan / 40` при `lifespan > 10`, иначе `lifespan`. Вероятностные исходы используют накопление дробного остатка GI, без случайного округления. Этот же подход выбран для будущего создания планет. Шансы планет записаны долями (`0.01` = 1%), а альтернативные исходы звёзд — процентами (`%0.1` = 0.1%). Парсер планет сохраняет дроби и поддерживает один элемент без `&`. Уязвимость к бластам читается из `blastability` таблицы GI: HP, EON и цивилизации до C1.2 включительно; C1.3 и выше неуязвимы. Это ограничение относится к бластам уровня 1; локальное уничтожение планет уровня 2 в Unity охватывает все планеты. ```sh godot --headless --path Owniverse.GI --script res://tests/test_stellar_rules.gd ``` Проверяются парсер планет, граница уязвимости, накопление редких исходов, сериализация остатков и постепенное преобразование реальной партии RD в TWD. Создание планет подключено к ручному и автоматическому производству звёзд. Бласты обрабатываются как события, а не ресурс. Выжившие планеты переходят преемнику звезды пропорционально числу реально полученных преемников; при отсутствии преемника освобождаются. Локальное разрушение выполняется перед передачей. Дополнительно проверяются частичная передача, альтернативные преемники, уровни разрушения 1/2, накопление слабых бластов, сохранения, ручное/автоматическое создание планет и несколько поколений за длинный шаг. Правила и формулы описаны в `../simulation_rules.md`. ## Описания выбранных объектов ```sh godot --headless --path Owniverse.GI --script res://tests/test_descriptions.gd ``` Источник текста — `Global.Templates[Global.Locale]`. Заголовок берётся из `Name`, основной текст — из `Description`. Поддерживаются ключи с классом (`RD.Entity.Description`) и старые ключи без класса (`RD.Description`). `%valueN%` заменяется значением переменной, имя которой записано в поле `valueN` этой строки. Поддерживаются `amount`, `colored costs`, `lifespan`, `voids`, `he / h`, `metallicity`, показатели энергии, плотности и скорости времени. `amount1`–`amount4` сил пока отображаются как `—`; неизвестные непустые обозначения тоже дают `—`, пустые поля — пустую строку. `[p]` превращается в разделение абзацев, цветовые BBCode-теги сохраняются. Доступные требования зелёные, недоступные красные. Для объектов со связанными экземплярами выводится доступное количество и серым общее; для планет — общее количество. Скорость изменения вычисляется по реальному времени и обновляется раз в 0,25 секунды. Доли He/H вычисляются из текущих свободных запасов; при пустой смеси показывается `—`. Металличность и плотность используют расчёт среды GI. Счётчики исходной материи и этики Unity в текущей GI отсутствуют и здесь не добавляются. ## Первичная жизнь ```sh godot --headless --path Owniverse.GI --script res://tests/test_life.gd ``` Проверяются абиогенез, деградация, повторные попытки без создания дополнительных планет, появление C0.0 на прежней звезде, остатки вероятностей, сохранение/продолжение, однократная инициализация старых планет и отсутствие воскрешения после бластов. Проверка загрузки этических правил, распределений и отделения космических цивилизаций: ```sh godot --headless --path Owniverse.GI --script res://tests/test_civilization_state.gd ``` Тест цивилизаций дополнительно проверяет общий звёздный бюджет, повторное использование резерва при переходе, звёзды в структурах, массовый эквивалент SMBH, блокировку неподдержанного прогресса, каскад деградации и повторное применение ограничений без потерь. ## Полная эволюция цивилизаций ```sh godot --headless --path Owniverse.GI --script res://tests/test_civilization_evolution.gd ``` Проверяются реальные коэффициенты C0.2, войны и побочный ущерб C2.0, замена планет колониями с сохранением хозяина, дипломатическое влияние, бонус периода от структур и деградация при их отсутствии. Ускоренная модель проходит все стадии C0.2 → C4.4 → Ct. Проверки контролируют сохранение населения, целочисленность этик, валидацию сохранения и детерминированное продолжение после сериализации.