Danro-Jump/Assets/Scripts/Runtime/Prizes/PrizeFlowService.cs
Danil Iarosh 839a68aef1 Improve VFX, UI overlays, session statistics, COM reliability, audio mixer, and expand architecture guides
Подробный список изменений:
- Перенесены эффекты частиц из C#-кода в готовые префабы-ассеты (Vfx Prefabs) в папке Assets/Resources/Vfx/ с автоматической генерацией материалов в Editor.
- Исправлены ошибки duration на играющих системах частиц и розовые текстуры в GameVfxService.cs.
- Исправлена навигация и фокус кнопок на оверлеях ContinueGameOverlay и PrizeResultOverlay с автоматическим подсвечиванием кнопок лимонно-зеленым цветом при фокусе и проигрыванием звука.
- Добавлена проверка настроек в GameplayHudController.cs для скрытия ContinueGameOverlay, если продолжение игры отключено.
- Расширен сбор статистики: создана структура GameplaySessionRecord, добавлена история до 50 раундов в PrizeSessionStateService и JsonPrizeSessionStateRepository, выведен расчет средних показателей и список 5 последних раундов в сервисной статистике.
- Повышена надежность COM-транспорта: добавлен sleep (80мс) в Dispose для graceful shutdown потоков, реализован цикл переподключения до 10 попыток при обрыве связи.
- Интегрированы настройки громкости с микшером: изменен шаг изменения громкости на 5% (0.05) для удобства, добавлен статус-чек и логи в ApplyServiceVolumes, расширены юнит-тесты на GetFloat параметры.
- Созданы новые архитектурные гайды по аппаратному COM-транспорту и призовой экономике автомата в папке GUIDES/architecture/.
- Оптимизирован и обновлен RAG-индекс проекта.
2026-07-03 15:04:08 +03:00

91 lines
2.9 KiB
C#

using System;
using DanroJump.Gameplay;
using DanroJump.Settings;
namespace DanroJump.Prizes
{
/// <summary>
/// Базовый сервис призового решения. Пока использует сервисные флаги призов,
/// позже сюда подключатся таблицы уровней, QR и аппаратная витрина.
/// </summary>
public sealed class PrizeFlowService : IPrizeFlowService
{
private readonly IReadOnlyServiceSettings settings;
private readonly IPrizeSessionStateService sessionState;
public PrizeFlowService(
[Zenject.InjectOptional] IReadOnlyServiceSettings settings = null,
[Zenject.InjectOptional] IPrizeSessionStateService sessionState = null)
{
this.settings = settings;
this.sessionState = sessionState;
}
public event Action<PrizeFlowResult> PrizeFlowStarted;
public PrizeFlowResult LastResult { get; private set; }
public PrizeFlowResult EvaluateCompletedSession(GameplaySession session)
{
var score = session?.Score ?? 0;
var rewardKind = ResolveRewardKind(score);
return new PrizeFlowResult(
rewardKind,
score,
session?.Coins ?? 0,
session?.MaxRunHeight ?? 0f,
session?.SessionId);
}
public PrizeFlowResult StartPrizeFlow(GameplaySession session)
{
LastResult = EvaluateCompletedSession(session);
if (session != null && sessionState != null)
{
sessionState.RecordGameplaySession(
session.SessionId,
session.Score,
session.Coins,
session.MaxRunHeight,
session.DeathCount,
LastResult.RewardKind
);
}
if (LastResult.HasPrize && sessionState != null &&
!sessionState.TryBeginSession(LastResult, out _))
{
LastResult = default;
return LastResult;
}
PrizeFlowStarted?.Invoke(LastResult);
return LastResult;
}
private PrizeRewardKind ResolveRewardKind(int score)
{
if (settings == null)
{
return PrizeRewardKind.None;
}
var levels = PrizeLevelTable.FromJson(settings.GetString(ServiceSettingsKeys.PrizeLevels));
if (levels.Count > 0)
{
return levels.ResolveRewardKind(score);
}
if (settings.GetBool(ServiceSettingsKeys.GiveBigPrize))
{
return PrizeRewardKind.Big;
}
return settings.GetBool(ServiceSettingsKeys.GiveSmallPrize)
? PrizeRewardKind.Small
: PrizeRewardKind.None;
}
}
}