Синие кристаллы (регламент 05.11, пп. 1 и 3): не сверх 50 и без потерь, ожидание наград (не больше 2), задания -- 1-2 кристалла

- CrystalRewards (без Unity) + 6 тестов из раздела 6 регламента
- Задания: сколько помещается, остаток ждёт в задании («Забрать»); третья не помещающаяся награда не выдаётся
- Остальные награды: не поместившееся -- письмом «Кристаллы ждут места», из письма -- сколько помещается
- Награды заданий 1-2 вместо 20-250, ежедневные -- без кристаллов

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Alexander
2026-11-05 18:29:31 +01:00
co-authored by Claude Opus 5.5
parent f78eb7ea7e
commit 0ebbf56306
8 changed files with 321 additions and 26 deletions
@@ -359,3 +359,73 @@ public class ProductionTests
Assert.AreEqual(7, times.Count, "6 шагов по 10 минут + конец");
}
}
// Синие кристаллы при пределе 50 (Регламент редкости синих кристаллов от 05.11.2026, ред. 1.1, раздел 6)
public class CrystalRewardsTests
{
const float Cap = 50f;
[Test]
public void Crystals_49of50_Reward2_OneGiven_OneWaits()
{
var r = new CrystalRewards();
Assert.AreEqual(1, r.Claim("q1", 2, 49, Cap), "49/50 + 2 -> выдан 1");
Assert.AreEqual(1, r.Left("q1"), "1 ждёт места");
}
[Test]
public void Crystals_Full_OldReward15_NothingGiven_NothingLost()
{
var r = new CrystalRewards();
Assert.AreEqual(0, r.Claim("old", 15, 50, Cap), "50/50 + 15 из старых данных -> 0 выдано");
Assert.AreEqual(15, r.Left("old"), "награда ждёт целиком, ничего не исчезло");
Assert.AreEqual(10, r.Claim("old", 15, 40, Cap), "освободили 10 -- выдано 10");
Assert.AreEqual(5, r.Left("old"));
}
[Test]
public void Crystals_RepeatClaim_NeverGivesTwice()
{
var r = new CrystalRewards();
r.Claim("q", 2, 49, Cap); // выдан 1, ждёт 1
Assert.AreEqual(0, r.Claim("q", 2, 50, Cap), "повторное «Забрать» при 50/50 -- ничего");
Assert.AreEqual(1, r.Left("q"), "остаток не вырос: награда одна");
Assert.AreEqual(1, r.Claim("q", 2, 30, Cap), "место есть -- выдан только остаток 1, а не 2");
Assert.AreEqual(0, r.Left("q"));
}
[Test]
public void Crystals_AtMostTwoWaiting_ThirdNotStarted_FittingAlwaysOk()
{
var r = new CrystalRewards();
r.Claim("a", 2, 50, Cap);
r.Claim("b", 2, 50, Cap);
Assert.AreEqual(2, r.WaitingCount);
Assert.IsFalse(r.CanStart("c", 2, 50, Cap), "третья награда при 50/50 не выдаётся -- задание остаётся «Забрать»");
Assert.IsTrue(r.CanStart("a", 2, 50, Cap), "ждущую можно дозабирать");
Assert.IsTrue(r.CanStart("c", 2, 40, Cap), "помещается целиком -- место ожидания не нужно");
Assert.IsTrue(r.CanStart("d", 0, 50, Cap), "награда без кристаллов -- всегда");
}
[Test]
public void Crystals_Waiting_SurvivesSaveAndLoad()
{
var r = new CrystalRewards();
r.Claim("m:m_th_3", 2, 50, Cap);
r.Claim("mail_7", 5, 48, Cap);
var copy = new CrystalRewards();
copy.Load(r.ToLines());
Assert.AreEqual(2, copy.Left("m:m_th_3"));
Assert.AreEqual(3, copy.Left("mail_7"));
Assert.AreEqual(2, copy.WaitingCount);
}
[Test]
public void Crystals_NeverAboveCap()
{
Assert.AreEqual(0, CrystalRewards.Free(50, Cap));
Assert.AreEqual(0, CrystalRewards.Free(51, Cap), "выше предела (старые данные) -- места нет, а не минус");
Assert.AreEqual(3, CrystalRewards.Fits(10, 47, Cap));
Assert.AreEqual(10, CrystalRewards.Fits(10, 0, float.PositiveInfinity), "без предела -- целиком");
}
}