221 lines
7.6 KiB
C#
221 lines
7.6 KiB
C#
using System.Collections.Generic;
|
|
using NUnit.Framework;
|
|
using UnityEngine;
|
|
using YachtDice.Categories;
|
|
using YachtDice.Dice;
|
|
using YachtDice.Economy;
|
|
using YachtDice.Run;
|
|
using YachtDice.Scoring;
|
|
|
|
namespace YachtDice.Tests
|
|
{
|
|
public sealed class RunLoopServiceTests
|
|
{
|
|
private readonly List<Object> _createdAssets = new();
|
|
private readonly IReadOnlyList<IDice> _emptyDice = new IDice[0];
|
|
|
|
private CurrencyBank _currencyBank;
|
|
private ScoringSystem _scoringSystem;
|
|
private StoredRollBank _storedRollBank;
|
|
private RunBalanceConfigSO _config;
|
|
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
var bankGo = new GameObject("CurrencyBank");
|
|
_currencyBank = bankGo.AddComponent<CurrencyBank>();
|
|
_currencyBank.SetBalance(0);
|
|
|
|
var scoringGo = new GameObject("ScoringSystem");
|
|
_scoringSystem = scoringGo.AddComponent<ScoringSystem>();
|
|
|
|
_storedRollBank = new StoredRollBank();
|
|
_config = RunBalanceConfigSO.CreateDefault();
|
|
_createdAssets.Add(_config);
|
|
}
|
|
|
|
[TearDown]
|
|
public void TearDown()
|
|
{
|
|
foreach (var scoring in Object.FindObjectsByType<ScoringSystem>(FindObjectsSortMode.None))
|
|
Object.DestroyImmediate(scoring.gameObject);
|
|
|
|
foreach (var bank in Object.FindObjectsByType<CurrencyBank>(FindObjectsSortMode.None))
|
|
Object.DestroyImmediate(bank.gameObject);
|
|
|
|
for (var i = 0; i < _createdAssets.Count; i++)
|
|
{
|
|
if (_createdAssets[i] != null)
|
|
Object.DestroyImmediate(_createdAssets[i]);
|
|
}
|
|
|
|
_createdAssets.Clear();
|
|
}
|
|
|
|
[Test]
|
|
public void StartNewRun_EntersShopWithConfigQuota()
|
|
{
|
|
var categories = CreateFixedCatalog(100, 100, 100);
|
|
var service = CreateService(categories);
|
|
|
|
service.StartNewRun();
|
|
|
|
Assert.AreEqual(30, service.State.BaseQuota);
|
|
Assert.AreEqual(1, service.State.BetIndex);
|
|
Assert.AreEqual(RunPhase.Shop, service.State.Phase);
|
|
Assert.AreEqual(0, service.State.StoredRolls);
|
|
}
|
|
|
|
[Test]
|
|
public void ClearedStage_AwardsCurrencyAndBanksUnusedRolls()
|
|
{
|
|
var categories = CreateFixedCatalog(100, 100, 100);
|
|
var service = CreateService(categories);
|
|
|
|
service.StartNewRun();
|
|
service.CompleteShop();
|
|
service.TryBeginRoll();
|
|
service.NotifyRollResolved(_emptyDice);
|
|
|
|
var cleared = service.TryScoreCategoryAsync(_emptyDice, categories.All[0]).GetAwaiter().GetResult();
|
|
|
|
Assert.IsTrue(cleared);
|
|
Assert.AreEqual(25, _currencyBank.Balance);
|
|
Assert.AreEqual(2, service.State.StoredRolls);
|
|
Assert.AreEqual(2, service.State.StageNumber);
|
|
Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
|
|
}
|
|
|
|
[Test]
|
|
public void StoredRolls_CanBeConsumedOnLaterStage()
|
|
{
|
|
var categories = CreateFixedCatalog(100, 100, 100);
|
|
var service = CreateService(categories);
|
|
|
|
service.StartNewRun();
|
|
service.CompleteShop();
|
|
service.TryBeginRoll();
|
|
service.NotifyRollResolved(_emptyDice);
|
|
service.TryScoreCategoryAsync(_emptyDice, categories.All[0]).GetAwaiter().GetResult();
|
|
|
|
for (var i = 0; i < 4; i++)
|
|
{
|
|
Assert.IsTrue(service.TryBeginRoll());
|
|
service.NotifyRollResolved(_emptyDice);
|
|
}
|
|
|
|
service.TryScoreCategoryAsync(_emptyDice, categories.All[1]).GetAwaiter().GetResult();
|
|
|
|
Assert.AreEqual(1, service.State.StoredRolls);
|
|
Assert.AreEqual(50, _currencyBank.Balance);
|
|
}
|
|
|
|
[Test]
|
|
public void CompletedCycle_GrantsBonusRaisesQuotaAndStartsNextBet()
|
|
{
|
|
var categories = CreateFixedCatalog(100, 100, 100);
|
|
var service = CreateService(categories);
|
|
|
|
service.StartNewRun();
|
|
service.CompleteShop();
|
|
|
|
ClearStageInOneRoll(service, categories.All[0]);
|
|
ClearStageInOneRoll(service, categories.All[1]);
|
|
ClearStageInOneRoll(service, categories.All[2]);
|
|
|
|
Assert.AreEqual(135, _currencyBank.Balance);
|
|
Assert.AreEqual(60, service.State.BaseQuota);
|
|
Assert.AreEqual(2, service.State.BetIndex);
|
|
Assert.AreEqual(RunPhase.Shop, service.State.Phase);
|
|
Assert.AreEqual(6, service.State.StoredRolls);
|
|
Assert.AreEqual(0, _scoringSystem.CategoriesFilledCount);
|
|
}
|
|
|
|
[Test]
|
|
public void FailedStage_EndsRunWhenNoTargetCanBeMet()
|
|
{
|
|
var categories = CreateFixedCatalog(10);
|
|
var service = CreateService(categories);
|
|
|
|
service.StartNewRun();
|
|
service.CompleteShop();
|
|
|
|
for (var i = 0; i < 3; i++)
|
|
{
|
|
Assert.IsTrue(service.TryBeginRoll());
|
|
service.NotifyRollResolved(_emptyDice);
|
|
}
|
|
|
|
Assert.IsTrue(service.State.IsFailed);
|
|
Assert.AreEqual(RunPhase.RunFailed, service.State.Phase);
|
|
}
|
|
|
|
[Test]
|
|
public void Shop_ReopensOnlyAtStartOfNextBet()
|
|
{
|
|
var categories = CreateFixedCatalog(100, 100, 100, 100);
|
|
var service = CreateService(categories);
|
|
|
|
service.StartNewRun();
|
|
Assert.AreEqual(RunPhase.Shop, service.State.Phase);
|
|
|
|
service.CompleteShop();
|
|
ClearStageInOneRoll(service, categories.All[0]);
|
|
Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
|
|
|
|
ClearStageInOneRoll(service, categories.All[1]);
|
|
Assert.AreEqual(RunPhase.StageStart, service.State.Phase);
|
|
|
|
ClearStageInOneRoll(service, categories.All[2]);
|
|
Assert.AreEqual(RunPhase.Shop, service.State.Phase);
|
|
Assert.AreEqual(2, service.State.BetIndex);
|
|
}
|
|
|
|
private RunLoopService CreateService(CategoryCatalog catalog)
|
|
{
|
|
_scoringSystem.Construct(null, null, catalog, _currencyBank);
|
|
return new RunLoopService(_config, _scoringSystem, _currencyBank, _storedRollBank);
|
|
}
|
|
|
|
private CategoryCatalog CreateFixedCatalog(params int[] scores)
|
|
{
|
|
var categories = new List<CategoryDefinition>();
|
|
for (var i = 0; i < scores.Length; i++)
|
|
{
|
|
var category = FixedScoreCategory.Create($"cat_{i}", scores[i]);
|
|
_createdAssets.Add(category);
|
|
categories.Add(category);
|
|
}
|
|
|
|
var catalog = CategoryCatalog.CreateForTest(categories);
|
|
_createdAssets.Add(catalog);
|
|
return catalog;
|
|
}
|
|
|
|
private void ClearStageInOneRoll(RunLoopService service, CategoryDefinition category)
|
|
{
|
|
Assert.IsTrue(service.TryBeginRoll());
|
|
service.NotifyRollResolved(_emptyDice);
|
|
Assert.IsTrue(service.TryScoreCategoryAsync(_emptyDice, category).GetAwaiter().GetResult());
|
|
}
|
|
|
|
private sealed class FixedScoreCategory : CategoryDefinition
|
|
{
|
|
[SerializeField] private int fixedScore;
|
|
|
|
public override int Calculate(IReadOnlyList<IDice> dice)
|
|
{
|
|
return fixedScore;
|
|
}
|
|
|
|
public static FixedScoreCategory Create(string id, int score)
|
|
{
|
|
var category = CreateInstance<FixedScoreCategory>();
|
|
category.SetTestData(id, id);
|
|
category.fixedScore = score;
|
|
return category;
|
|
}
|
|
}
|
|
}
|
|
}
|