acdream/tests/AcDream.App.Tests/Net/RetailSkillFormulaTests.cs
Erik 557eb7ef6b refactor(net): own live session composition
Extract reset, selection, entered-world, and route construction behind LiveSessionHost while preserving the sole LiveSessionController authority. Retain partial route and subscription cleanup for retry, and replace the embedded ACE-only shortcut with the exact named-retail unsigned skill formula.

Co-authored-by: Codex <codex@openai.com>
2026-07-22 10:36:06 +02:00

112 lines
3.2 KiB
C#

using AcDream.App.Net;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Enums;
using DatReaderWriter.Types;
namespace AcDream.App.Tests.Net;
public sealed class RetailSkillFormulaTests
{
[Fact]
public void ZeroDivisorIsTheOnlyFormulaFailureGate()
{
SkillFormula invalid = Formula(w: 7, x: 1, y: 1, z: 0);
Assert.False(RetailSkillFormula.TryCalculate(invalid, 10u, 20u, out uint invalidResult));
Assert.Equal(0u, invalidResult);
SkillFormula zeroX = Formula(w: 7, x: 0, y: 2, z: 3);
Assert.True(RetailSkillFormula.TryCalculate(zeroX, 10u, 4u, out uint validResult));
Assert.Equal(5u, validResult);
}
[Theory]
[InlineData(9u, 4u, 2u)]
[InlineData(10u, 4u, 3u)]
[InlineData(11u, 4u, 3u)]
[InlineData(12u, 4u, 3u)]
public void DivisionRoundsToNearestWithExactHalvesUp(
uint numerator,
uint divisor,
uint expected)
{
SkillFormula formula = Formula(w: 0, x: 1, y: 0, z: divisor);
Assert.True(RetailSkillFormula.TryCalculate(
formula,
numerator,
0u,
out uint result));
Assert.Equal(expected, result);
}
[Fact]
public void AdditiveWordIsInsideTheNumerator()
{
SkillFormula formula = Formula(w: 3, x: 1, y: 1, z: 4);
Assert.True(RetailSkillFormula.TryCalculate(formula, 4u, 2u, out uint result));
Assert.Equal(2u, result);
}
[Fact]
public void NumeratorUsesUnsignedThirtyTwoBitWrap()
{
SkillFormula formula = Formula(w: 1, x: 2, y: 0, z: 2);
Assert.True(RetailSkillFormula.TryCalculate(
formula,
uint.MaxValue,
0u,
out uint result));
Assert.Equal(0x80000000u, result);
}
[Fact]
public void SignedDatStorageIsReinterpretedAsRetailUnsignedWords()
{
SkillFormula formula = Formula(w: -1, x: 0, y: 0, z: 1);
Assert.True(RetailSkillFormula.TryCalculate(formula, 0u, 0u, out uint result));
Assert.Equal(uint.MaxValue, result);
}
[Fact]
public void LiveResolverLooksUpTheDatFormulaAndTreatsMissingAttributesAsZero()
{
const uint skillId = 0x345u;
const uint firstAttributeId = 1u;
const uint secondAttributeId = 2u;
var skillTable = new SkillTable();
skillTable.Skills.Add((SkillId)skillId, new SkillBase
{
Formula = new SkillFormula
{
AdditiveBonus = 1,
Attribute1Multiplier = 1,
Attribute2Multiplier = 2,
Divisor = 3,
Attribute1 = (AttributeId)firstAttributeId,
Attribute2 = (AttributeId)secondAttributeId,
},
});
var resolver = new LiveSkillCreditResolver(skillTable);
uint result = resolver.Resolve(
skillId,
new Dictionary<uint, uint> { [firstAttributeId] = 8u });
Assert.Equal(3u, result);
Assert.Equal(0u, resolver.Resolve(0x999u, new Dictionary<uint, uint>()));
}
private static SkillFormula Formula(int w, int x, int y, uint z) => new()
{
AdditiveBonus = w,
Attribute1Multiplier = x,
Attribute2Multiplier = y,
Divisor = unchecked((int)z),
};
}