chip-gameV3/Assets/Scripts/Statistics/MachineCountersService.cs

326 lines
10 KiB
C#

using System;
using UnityEngine;
public static class MachineCountersService
{
private const string CountersFileName = "machine-counters.json";
private static MachineCountersData _data;
private static double _sessionStartedAt;
private static GameMode _pendingGameMode;
private static bool _sessionArmed;
private static bool _sessionActive;
public static string CountersFilePath => System.IO.Path.Combine(Application.persistentDataPath, CountersFileName);
public static void Initialize()
{
PaymentSystem.OnRevenueReceived -= RecordRevenue;
PaymentSystem.OnRevenueReceived += RecordRevenue;
PrizeSystem.PrizeSystemManager.OnPrizeIssued -= RecordPrizeIssued;
PrizeSystem.PrizeSystemManager.OnPrizeIssued += RecordPrizeIssued;
GameManager.OnGameStarted -= RecordGameStarted;
GameManager.OnGameStarted += RecordGameStarted;
GameManager.OnGameFinished -= RecordGameFinished;
GameManager.OnGameFinished += RecordGameFinished;
Load();
_sessionArmed = false;
_sessionActive = false;
}
public static MachineCounterSet GetLifetimeCounters()
{
EnsureInitialized();
return _data.lifetime.Clone();
}
public static MachineCounterSet GetResettableCounters()
{
EnsureInitialized();
return _data.resettable.Clone();
}
public static void RecordFirstMove()
{
if (_sessionArmed == false || _sessionActive)
return;
EnsureInitialized();
IncreaseGamesStarted(_data.lifetime, _pendingGameMode);
IncreaseGamesStarted(_data.resettable, _pendingGameMode);
_sessionStartedAt = Time.realtimeSinceStartupAsDouble;
_sessionActive = true;
Save();
}
public static void RecordBotResult(bool playerWon)
{
EnsureInitialized();
if (CharacterSystem.CharactersController.HasActiveCharacter == false)
return;
int botIndex = CharacterSystem.CharactersController.CharacterIndex;
int difficultyIndex = GetCurrentDifficultyIndex();
IncreaseBotResult(_data.lifetime, botIndex, difficultyIndex, playerWon);
IncreaseBotResult(_data.resettable, botIndex, difficultyIndex, playerWon);
Save();
}
public static void ResetResettableCounters()
{
EnsureInitialized();
_data.resettable = new MachineCounterSet();
PlayerPrefs.SetInt(PrefsKeyVault.CASH_COUNTER_NUL, 0);
PlayerPrefs.SetInt(PrefsKeyVault.PRIZES_GIVEN_COUNTER_NUL, 0);
PrizeSystem.PrizeSystemManager.ResetPrizeCounters();
PlayerPrefs.Save();
Save();
}
private static void RecordRevenue(int amount)
{
if (amount <= 0)
return;
EnsureInitialized();
_data.lifetime.revenue += amount;
_data.resettable.revenue += amount;
Save();
}
private static void RecordPrizeIssued()
{
EnsureInitialized();
_data.lifetime.prizesIssued++;
_data.resettable.prizesIssued++;
Save();
}
private static void RecordGameStarted(GameMode mode)
{
EnsureInitialized();
_pendingGameMode = mode;
_sessionArmed = true;
_sessionActive = false;
}
private static void RecordGameFinished(GameMode mode)
{
_sessionArmed = false;
if (_sessionActive == false)
return;
EnsureInitialized();
double duration = Math.Max(0d, Time.realtimeSinceStartupAsDouble - _sessionStartedAt);
AddCompletedSession(_data.lifetime, duration);
AddCompletedSession(_data.resettable, duration);
_sessionActive = false;
Save();
}
private static void IncreaseGamesStarted(MachineCounterSet counters, GameMode mode)
{
counters.gamesStarted++;
if (mode == GameMode.pve)
counters.pveGamesStarted++;
else
counters.pvpGamesStarted++;
}
private static void AddCompletedSession(MachineCounterSet counters, double duration)
{
counters.completedSessions++;
counters.totalSessionDurationSeconds += duration;
}
private static void IncreaseBotResult(
MachineCounterSet counters,
int botIndex,
int difficultyIndex,
bool playerWon)
{
counters.NormalizeBotCounters();
int[] values = playerWon
? counters.GetBotWins(difficultyIndex)
: counters.GetBotLosses(difficultyIndex);
values[botIndex]++;
}
private static int GetCurrentDifficultyIndex()
{
if (SettingsManager.GetString(SettingKey.DIFFICULTY_MODE) == "Заработок")
return MachineCounterSet.HardDifficultyIndex;
return SettingsManager.GetString(SettingKey.DIFFICULTY) switch
{
"Легкая" => MachineCounterSet.EasyDifficultyIndex,
"Сложная" => MachineCounterSet.HardDifficultyIndex,
_ => MachineCounterSet.MediumDifficultyIndex
};
}
private static void EnsureInitialized()
{
if (_data == null)
Load();
}
private static void Load()
{
var loadResult = FileUtil.LoadJson<MachineCountersData>(CountersFileName, FileUtil.AppDirectory.Persistent);
if (loadResult.OK && loadResult.Data != null)
{
_data = loadResult.Data;
_data.lifetime ??= new MachineCounterSet();
_data.resettable ??= new MachineCounterSet();
_data.lifetime.NormalizeBotCounters();
_data.resettable.NormalizeBotCounters();
return;
}
_data = CreateFromLegacyCounters();
Save();
}
private static MachineCountersData CreateFromLegacyCounters()
{
int lifetimePrizes = Mathf.Max(
PlayerPrefs.GetInt(PrefsKeyVault.PRIZES_GIVEN_COUNTER, 0),
GetLegacyPrizeTotal(false));
int resettablePrizes = Mathf.Max(
PlayerPrefs.GetInt(PrefsKeyVault.PRIZES_GIVEN_COUNTER_NUL, 0),
GetLegacyPrizeTotal(true));
return new MachineCountersData
{
lifetime = new MachineCounterSet
{
revenue = PlayerPrefs.GetInt(PrefsKeyVault.CASH_COUNTER, 0),
prizesIssued = lifetimePrizes
},
resettable = new MachineCounterSet
{
revenue = PlayerPrefs.GetInt(PrefsKeyVault.CASH_COUNTER_NUL, 0),
prizesIssued = resettablePrizes
}
};
}
private static int GetLegacyPrizeTotal(bool resettable)
{
string suffix = resettable ? "Nullable" : string.Empty;
return PlayerPrefs.GetInt(PrefsKeyVault.HOPPER_GIVEN_COUNTER + suffix, 0)
+ PlayerPrefs.GetInt(PrefsKeyVault.MARBLES_GIVEN_COUNTER + suffix, 0)
+ PlayerPrefs.GetInt(PrefsKeyVault.TICKET_GIVEN_COUNTER + suffix, 0)
+ PlayerPrefs.GetInt(PrefsKeyVault.SPECIAL_GIVEN_COUNTER + suffix, 0);
}
private static void Save()
{
var saveResult = FileUtil.SaveJson(CountersFileName, FileUtil.AppDirectory.Persistent, _data);
if (saveResult.OK == false)
Debug.LogError(saveResult.Message);
}
}
[Serializable]
public sealed class MachineCountersData
{
public MachineCounterSet lifetime = new MachineCounterSet();
public MachineCounterSet resettable = new MachineCounterSet();
}
[Serializable]
public sealed class MachineCounterSet
{
public const int BotCount = 5;
public const int EasyDifficultyIndex = 0;
public const int MediumDifficultyIndex = 1;
public const int HardDifficultyIndex = 2;
public long revenue;
public int prizesIssued;
public int gamesStarted;
public int pveGamesStarted;
public int pvpGamesStarted;
public int completedSessions;
public double totalSessionDurationSeconds;
public int[] easyBotWins = new int[BotCount];
public int[] easyBotLosses = new int[BotCount];
public int[] mediumBotWins = new int[BotCount];
public int[] mediumBotLosses = new int[BotCount];
public int[] hardBotWins = new int[BotCount];
public int[] hardBotLosses = new int[BotCount];
public double AverageSessionDurationSeconds
=> completedSessions == 0 ? 0d : totalSessionDurationSeconds / completedSessions;
public int[] GetBotWins(int difficultyIndex)
{
return difficultyIndex switch
{
EasyDifficultyIndex => easyBotWins,
HardDifficultyIndex => hardBotWins,
_ => mediumBotWins
};
}
public int[] GetBotLosses(int difficultyIndex)
{
return difficultyIndex switch
{
EasyDifficultyIndex => easyBotLosses,
HardDifficultyIndex => hardBotLosses,
_ => mediumBotLosses
};
}
public void NormalizeBotCounters()
{
easyBotWins = NormalizeArray(easyBotWins);
easyBotLosses = NormalizeArray(easyBotLosses);
mediumBotWins = NormalizeArray(mediumBotWins);
mediumBotLosses = NormalizeArray(mediumBotLosses);
hardBotWins = NormalizeArray(hardBotWins);
hardBotLosses = NormalizeArray(hardBotLosses);
}
public MachineCounterSet Clone()
{
return new MachineCounterSet
{
revenue = revenue,
prizesIssued = prizesIssued,
gamesStarted = gamesStarted,
pveGamesStarted = pveGamesStarted,
pvpGamesStarted = pvpGamesStarted,
completedSessions = completedSessions,
totalSessionDurationSeconds = totalSessionDurationSeconds,
easyBotWins = (int[])easyBotWins.Clone(),
easyBotLosses = (int[])easyBotLosses.Clone(),
mediumBotWins = (int[])mediumBotWins.Clone(),
mediumBotLosses = (int[])mediumBotLosses.Clone(),
hardBotWins = (int[])hardBotWins.Clone(),
hardBotLosses = (int[])hardBotLosses.Clone()
};
}
private static int[] NormalizeArray(int[] values)
{
if (values != null && values.Length == BotCount)
return values;
var normalized = new int[BotCount];
if (values != null)
Array.Copy(values, normalized, Math.Min(values.Length, normalized.Length));
return normalized;
}
}