using System; using Cysharp.Threading.Tasks; using UnityEngine; namespace DanieleMarotta.RiversongCodeShowcase { [GameSystemGroup(typeof(CommonServicesSystemGroup))] [InitializeAfter(typeof(AnalyticsInitializationSystem))] public class DemoAnalyticsSystem : GameSystem, IInitializable, IDisposable, IUpdatable { private const float HeartbeatIntervalSeconds = 300; [InjectService] private IAnalyticsService _analyticsService; [InjectService] private ISignalBus _signalBus; [InjectService] private World _world; private AnalyticsSessionState _sessionState = new(); public DemoAnalyticsSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public UniTask InitializeAsync() { _signalBus.Subscribe(OnWorldReady); _signalBus.Subscribe(OnBuildingCreated); _signalBus.Subscribe(OnBuildingUpgraded); _signalBus.Subscribe(OnDemoCompleted); return UniTask.CompletedTask; } public void Dispose() { _signalBus.Unsubscribe(OnWorldReady); _signalBus.Unsubscribe(OnBuildingCreated); _signalBus.Unsubscribe(OnBuildingUpgraded); _signalBus.Unsubscribe(OnDemoCompleted); } public void Update() { var realtimeSeconds = Time.realtimeSinceStartup; while (_sessionState.TryAdvanceHeartbeat(realtimeSeconds, HeartbeatIntervalSeconds, out var heartbeatIndex, out var playtimeSeconds)) _analyticsService.RecordHeartbeat(_sessionState.SessionId, heartbeatIndex, playtimeSeconds, _sessionState.TotalBuildingsPlaced, _world.PopulationState.Population); } private void OnWorldReady(WorldReadySignal signal) { _sessionState.Begin(Time.realtimeSinceStartup); _analyticsService.RecordSessionStarted(_sessionState.SessionId); } private void OnBuildingCreated(BuildingCreatedSignal signal) { var definition = signal.Building?.Definition; if (!_sessionState.TryRecordBuildingConstruction(definition)) return; _analyticsService.RecordBuildingConstructionCompleted(_sessionState.SessionId, definition.name); } private void OnBuildingUpgraded(BuildingUpgradedSignal signal) { var building = signal.Building; if (!_sessionState.CanRecordHouseUpgrade(building)) return; _analyticsService.RecordHouseUpgraded(_sessionState.SessionId, building.Definition.name, building.TierIndex, building.TierIndex + 1); } private void OnDemoCompleted(DemoCompletedSignal signal) { if (!_sessionState.TryMarkDemoCompleted()) return; var playtimeSeconds = _sessionState.GetPlaytimeSeconds(Time.realtimeSinceStartup); _analyticsService.RecordDemoCompleted( _sessionState.SessionId, playtimeSeconds, _world.TimeState.TotalWeeks, _world.PopulationState.Population, _world.PopulationState.Happiness); } } }