using System.Collections; using System.Collections.Generic; using System.Text; using UnityEngine; namespace PrizeSystem { /// /// Система управления выдачей призов и ведения статистики игры. /// Отвечает за процесс выдачи призов, подсчет запусков и наград. /// public class PrizeSystemManager : MonoBehaviour { [SerializeField] AudioClip prizeErrorSound; [SerializeField] bool SoundNotification = true; [SerializeField] List PrizeNotificationSounds; [SerializeField] Notification prizeNotification; [SerializeField] VitrinaPanel vitrinaPanel; public static string key_cash = "STARTS"; public static string key_cashNul = "STARTSNUL"; public static string key_prizesgiven = "PRIZESGIVEN"; public static string key_prizesgivenNul = "PRIZESGIVENNUL"; public static string HopperPrizeCounter = "HopperCounter"; public static string MarblesPrizeCounter = "MarblesCounter"; public static string TicketPrizeCounter = "TicketCounter"; public static string SpecialPrizeCounter = "SpecialCounter"; private static PrizeSystemManager instance; private static bool prizing = false; //Прописать тут очереди. private static Queue qrPrizes; private static Queue vitrinaPrizes; public static bool HasQrPrizeToGive => qrPrizes.Count > 0; public static bool HasVitrinaPrizeToGive => vitrinaPrizes.Count > 0; //=========================== PUBLIC API ===========================// public void Initialize() { instance = this; InitCounters(); qrPrizes = new(); vitrinaPrizes = new(); } public static QrPrize DequeueQrPrize() => HasQrPrizeToGive ? qrPrizes.Dequeue() : null; public static VitrinaPrize DequeueVitrinaPrize() => HasVitrinaPrizeToGive ? vitrinaPrizes.Dequeue() : null; public static void GivePrize(Prize prize) { if (prize == null) { Debug.Log("Приз Null"); return; } //Если призы отключены в принципе, то не выдаем. bool prizingEnabled = SettingsManager.GetBool("Prizing", false); if (!prizingEnabled) return; Debug.Log($"Поступил заказ приз: {prize.Body}"); if (prize is EmptyPrize) { Debug.Log("Пустой приз. Возврат."); return; } else if (prize is CountablePrize countablePrize) { instance.StartCoroutine(instance.PrizingProcess(countablePrize.Amount, countablePrize.Type)); } else if (prize is VitrinaPrize vitrinaPrize) { vitrinaPrizes.Enqueue(vitrinaPrize); } else if(prize is QrPrize qrPrize) { qrPrizes.Enqueue(qrPrize); } } //=========================== privates ===========================// #region Приватные методы private string StartHopperCommand => ComWrapper.BoardVersion switch { 1 => "303", 2 => "301", _ => "303" }; private string StopHopperCommand => ComWrapper.BoardVersion switch { 1 => "302", 2 => "300", _ => "302" }; private IEnumerator PrizingProcess(int amount, CountablePrizeType Type) { if (prizing) { Debug.LogError("Уже идет выдача приза. Повторная выдача отключена"); yield break; } prizing = true; Debug.Log($"Выдача приза {Type}. Количество: {amount}"); bool atLeastOnePrize = false; for (int i = 0; i < amount; i++) { bool noPrizWhenError = SettingsManager.GetBool("PrizingWhenError", true); bool errorRegistred = PlayerPrefs.GetInt(KeyVault.PRIZING_ERROR_REGISTRED, 0) == 1; if (errorRegistred && noPrizWhenError) yield break; float timeout = 10; Debug.Log($"Включаю мотор хоппера: {StartHopperCommand}"); ComWrapper.Send(StartHopperCommand);//включаем мотор float startTime = Time.time; bool success = false; PlayerPrefs.SetInt("PrizeGivenBuffer", 0);//подготовка буфера while (Time.time - startTime < timeout) { if (PlayerPrefs.GetInt("PrizeGivenBuffer", 0) == 1) { Debug.Log("Считан приз"); success = true; break; } yield return null; } //Выключаем мотор Debug.Log($"Выключаю мотор: {StopHopperCommand}"); ComWrapper.Send(StopHopperCommand); Debug.Log("Закончил. Успех: " + success); if (success) { //контроль остатков int prizesCount = PlayerPrefs.GetInt(KeyVault.PRIZES_AVAILABLE); prizesCount = Mathf.Clamp(prizesCount - 1, 0, 9999); PlayerPrefs.SetInt(KeyVault.PRIZES_AVAILABLE, prizesCount); //Счетчики IncreasePrizeCounters(Type); //хотя бы что то успешно выпало atLeastOnePrize = true; } else { PlayerPrefs.SetInt(KeyVault.PRIZING_ERROR_REGISTRED, 1); SoundManager.instance.playClip(prizeErrorSound); } } if (atLeastOnePrize) { NotificationSystem.instance.Notificate(prizeNotification); SoundNotificationIfNeeds(); } prizing = false; } void IncreasePrizeCounters(CountablePrizeType Type) { string prizeCounterKey = Type switch { CountablePrizeType.Marbles => MarblesPrizeCounter, CountablePrizeType.Hopper => HopperPrizeCounter, CountablePrizeType.Hopper2 => HopperPrizeCounter, CountablePrizeType.Ticket => TicketPrizeCounter, _ => "none" }; string prizeCounterKeyNullable = prizeCounterKey + "Nullable"; PlayerPrefs.SetInt(prizeCounterKey, PlayerPrefs.GetInt(prizeCounterKey, 0) + 1); PlayerPrefs.SetInt(prizeCounterKeyNullable, PlayerPrefs.GetInt(prizeCounterKeyNullable, 0) + 1); } public static void ResetPrizeCounters() { PlayerPrefs.SetInt(HopperPrizeCounter + "Nullable", 0); PlayerPrefs.SetInt(MarblesPrizeCounter + "Nullable", 0); PlayerPrefs.SetInt(TicketPrizeCounter + "Nullable", 0); PlayerPrefs.SetInt(SpecialPrizeCounter + "Nullable", 0); } public static string GetPrizesCounterNullableString() { StringBuilder sb = new(); sb.Append($"Х: {PlayerPrefs.GetInt(HopperPrizeCounter + "Nullable", 0)}. "); sb.Append($"Т: {PlayerPrefs.GetInt(TicketPrizeCounter + "Nullable", 0)}. "); sb.Append($"М: {PlayerPrefs.GetInt(MarblesPrizeCounter + "Nullable", 0)}. "); sb.Append($"С: {PlayerPrefs.GetInt(SpecialPrizeCounter + "Nullable", 0)}. "); return sb.ToString(); } public static string GetPrizesCounterString() { StringBuilder sb = new(); sb.Append($"Х: {PlayerPrefs.GetInt(HopperPrizeCounter, 0)}. "); sb.Append($"Т: {PlayerPrefs.GetInt(TicketPrizeCounter, 0)}. "); sb.Append($"М: {PlayerPrefs.GetInt(MarblesPrizeCounter, 0)}. "); sb.Append($"С: {PlayerPrefs.GetInt(SpecialPrizeCounter, 0)}. "); return sb.ToString(); } void InitCounters() { if (!PlayerPrefs.HasKey(key_cash)) PlayerPrefs.SetInt(key_cash, 0); if (!PlayerPrefs.HasKey(key_cashNul)) PlayerPrefs.SetInt(key_cashNul, 0); } private void SoundNotificationIfNeeds() { if (!SoundNotification) return; if (PrizeNotificationSounds == null || PrizeNotificationSounds.Count == 0) return; int random = Random.Range(0, PrizeNotificationSounds.Count); AudioClip notification = PrizeNotificationSounds[random]; SoundManager.instance.playClip(notification); } #endregion } }