Class AchievementEvaluator
Drives the authored condition trees: evaluates the ones a dispatched signal can advance, ticks the ones that advance with time, and writes back progress, condition state and unlocks through the achievement service.
Implements
Inherited Members
Namespace: Serenity.Achievements.Application.Services
Assembly: Serenity.Achievements.Application.dll
Syntax
public class AchievementEvaluator : IDisposable
Remarks
Two rules keep the cost proportional to what actually changed. A signal only evaluates the trees that name it, through AchievementConditionIndex; and an achievement leaves both working sets the moment it unlocks.
Every source is optional. A project with no Score service still evaluates its signal and progress rules, because the evaluator reads the sources through delegates that may hand it nothing rather than through services it would have to have.
Nothing an authored tree does can stop the others: one achievement's evaluation is contained and reported, and the rest of the pass continues. A custom condition is project code running inside a framework loop, so "it threw" is a case, not an accident.
The evaluator starts paused and does nothing until RestoreStates(IReadOnlyDictionary<AchievementId, string>) has been
called, because evaluating before the stored tallies are back would compare a fresh tree
against a loaded store and write zeroes over real progress. The composition root calls it
once, after IAchievementService.LoadAsync, with an empty dictionary when there is
nothing to restore.
Constructors
AchievementEvaluator(IReadOnlyDictionary<AchievementId, AchievementDefinition>, IReadOnlyDictionary<AchievementId, AchievementCondition>, IAchievementService, Func<ScoreSnapshot>, Func<GameProgressData>, IAchievementCustomConditionResolver, ILogService)
Initializes a new instance of the AchievementEvaluator class.
Declaration
public AchievementEvaluator(IReadOnlyDictionary<AchievementId, AchievementDefinition> definitions, IReadOnlyDictionary<AchievementId, AchievementCondition> conditions, IAchievementService service, Func<ScoreSnapshot> readScores, Func<GameProgressData> readProgress, IAchievementCustomConditionResolver customConditionResolver, ILogService logService)
Parameters
| Type | Name | Description |
|---|---|---|
| IReadOnlyDictionary<AchievementId, AchievementDefinition> | definitions | Every achievement this project declares, by id. |
| IReadOnlyDictionary<AchievementId, AchievementCondition> | conditions | The authored condition of each achievement that has one. |
| IAchievementService | service | The service every unlock and progress write goes through. |
| Func<ScoreSnapshot> | readScores | Reads the current score metrics. May be |
| Func<GameProgressData> | readProgress | Reads the current global progress. May be |
| IAchievementCustomConditionResolver | customConditionResolver | Resolves custom conditions. May be |
| ILogService | logService | Logging service. May be |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when a required collaborator is |
Properties
FailedEvaluationCount
How many evaluations have failed, across every achievement, since construction.
Declaration
public int FailedEvaluationCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
FailureCountsByAchievement
How many evaluations have failed, per achievement, since construction.
Declaration
public IReadOnlyDictionary<AchievementId, int> FailureCountsByAchievement { get; }
Property Value
| Type | Description |
|---|---|
| IReadOnlyDictionary<AchievementId, int> |
LogService
Logging service used to report a failed write or evaluation. May be null.
Declaration
public ILogService LogService { get; set; }
Property Value
| Type | Description |
|---|---|
| ILogService |
SignalTypeNames
Every distinct signal type name the authored trees listen for, as authored. What the subscription binder resolves and subscribes to.
Declaration
public IReadOnlyList<string> SignalTypeNames { get; }
Property Value
| Type | Description |
|---|---|
| IReadOnlyList<string> |
Methods
Dispose()
Unsubscribes from StateReset. Safe to call more than once.
Declaration
public void Dispose()
Remarks
Without this, a re-installed module leaves the retired evaluator subscribed to the old service instance for as long as that instance lives — a leaked handler that keeps resetting a tree set nothing else reads any more.
OnSignal(EventDispatcherSignal)
Evaluates every tree a dispatched signal can advance.
Declaration
public void OnSignal(EventDispatcherSignal signal)
Parameters
| Type | Name | Description |
|---|---|---|
| EventDispatcherSignal | signal | The dispatched signal. |
RestoreStates(IReadOnlyDictionary<AchievementId, string>)
Hands each tree back the counters it captured before the last shutdown, and starts the evaluator. Must be called once, after the achievement service has loaded; an empty dictionary is the correct argument when there is nothing stored.
Declaration
public void RestoreStates(IReadOnlyDictionary<AchievementId, string> conditionStates)
Parameters
| Type | Name | Description |
|---|---|---|
| IReadOnlyDictionary<AchievementId, string> | conditionStates | The stored condition state of each achievement that has one. |
Tick(float, float)
Advances every tree that measures time or polls state it is never told about.
Declaration
public void Tick(float scaledDeltaSeconds, float unscaledDeltaSeconds)
Parameters
| Type | Name | Description |
|---|---|---|
| float | scaledDeltaSeconds | Seconds elapsed, affected by the game's time scale. |
| float | unscaledDeltaSeconds | Seconds elapsed, ignoring the game's time scale. |