Documentation
¶
Overview ¶
Package milestones tracks subject progress toward typed criteria: events flow in, the registry routes them by Type, evaluators decide which criteria apply per subject, counters increment, and threshold crossings emit Reached records.
Common applications:
- Games — achievement systems ("kill 100 skaven warriors").
- Apps — gamified onboarding milestones, engagement KPIs.
- Trading-bot — fee-tier accumulators, personal-finance goals.
The package ships an in-memory Store backend; consumers needing durability supply a Postgres-backed Store implementing the same interface.
Index ¶
- type Criterion
- type CriterionID
- type CriterionType
- type Evaluator
- type EvaluatorFunc
- type Event
- type InMemoryStore
- type Reached
- type Registry
- type Store
- type SubjectID
- type Tracker
- func (t *Tracker) Activate(subject SubjectID, c Criterion)
- func (t *Tracker) Deactivate(subject SubjectID, criterion CriterionID)
- func (t *Tracker) Progress(ctx context.Context, subject SubjectID, criterion CriterionID) (current int64, target int64, err error)
- func (t *Tracker) Record(ctx context.Context, e Event) ([]Reached, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Criterion ¶
type Criterion struct {
ID CriterionID
Type CriterionType
Target int64
Params map[string]any // type-specific config consumed by Evaluator
}
Criterion is the durable definition of "track this kind of event for this subject until counter ≥ Target".
type CriterionID ¶
type CriterionID uint32
CriterionID is a unique identifier for one criterion instance (one achievement-row, one milestone definition).
type CriterionType ¶
type CriterionType uint16
CriterionType identifies a class of criteria evaluated together — "kill_creature", "spend_currency", "complete_quest", etc.
type Evaluator ¶
Evaluator decides whether an Event matches a Criterion's filter. For a "kill X creature" criterion, the evaluator checks e.Tags["creature"] against Criterion.Params["creature_id"]. The evaluator does not need to compare types — Tracker only routes events of matching Type.
type EvaluatorFunc ¶
EvaluatorFunc adapts a function to the Evaluator interface.
type Event ¶
type Event struct {
Type CriterionType
Subject SubjectID
Amount int64
Tags map[string]string
}
Event is a single observation that may or may not advance counters. Subject identifies who the event is for; Type routes it to matching Evaluators; Amount is the value added to any criterion that matches; Tags carry type-specific dimensions (e.g. {"creature": "skaven_warlord"}).
type InMemoryStore ¶
type InMemoryStore struct {
// contains filtered or unexported fields
}
InMemoryStore is a concurrent-safe Store backed by a map. Suitable for tests and ephemeral use; production consumers should supply a Postgres-backed store implementing the same interface.
func NewInMemoryStore ¶
func NewInMemoryStore() *InMemoryStore
NewInMemoryStore returns an empty in-memory store.
func (*InMemoryStore) Get ¶
func (s *InMemoryStore) Get(_ context.Context, subject SubjectID, criterion CriterionID) (int64, error)
Get returns the current counter for (subject, criterion).
func (*InMemoryStore) Inc ¶
func (s *InMemoryStore) Inc(_ context.Context, subject SubjectID, criterion CriterionID, by int64) (int64, error)
Inc atomically increments and returns the new value.
type Reached ¶
type Reached struct {
Subject SubjectID
Criterion CriterionID
Final int64
}
Reached is fired when a criterion crosses its target. Emitted from Tracker.Record as a slice (multiple criteria may cross from one event).
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry binds CriterionTypes to Evaluators.
func (*Registry) RegisterEvaluator ¶
func (r *Registry) RegisterEvaluator(t CriterionType, e Evaluator)
RegisterEvaluator binds an Evaluator to a CriterionType.
type Store ¶
type Store interface {
// Get returns the current counter for (subject, criterion). Returns
// 0 if no prior progress is recorded.
Get(ctx context.Context, subject SubjectID, criterion CriterionID) (int64, error)
// Inc atomically increments and returns the new value.
Inc(ctx context.Context, subject SubjectID, criterion CriterionID, by int64) (int64, error)
}
Store persists per-subject counters. The default in-memory backend is safe for tests; production consumers supply a Postgres or Redis implementation.
type SubjectID ¶
type SubjectID uint64
SubjectID is whatever the consumer treats as the bearer of progress: player, account, character, organisation — opaque to this package.
type Tracker ¶
type Tracker struct {
// contains filtered or unexported fields
}
Tracker is the runtime state: it knows which criteria are active per subject and routes events through the registry to advance counters.
func NewTracker ¶
NewTracker returns a Tracker over a registry and a store.
func (*Tracker) Deactivate ¶
func (t *Tracker) Deactivate(subject SubjectID, criterion CriterionID)
Deactivate stops tracking a criterion for a subject. The store's counter is preserved (consumers can re-Activate to resume).
func (*Tracker) Progress ¶
func (t *Tracker) Progress(ctx context.Context, subject SubjectID, criterion CriterionID) (current int64, target int64, err error)
Progress returns the current counter and target for a subject's criterion (whether or not the criterion is currently activated).