Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions internal/core/domain/config.go
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
package domain

import "time"

// Config represents the parameters of the dungeon challenge.
// It dictates the rules and time boundaries for a successful completion.
type Config struct {
// Floors defines the total number of regular floors in the dungeon
// before reaching the boss room.
Floors int

// Monsters defines the exact number of monsters that must be defeated
// on each regular floor to consider it cleared.
Monsters int

// OpenAt specifies the exact time of day the dungeon becomes accessible.
OpenAt time.Time

// Duration represents the total active time window during which
// players can complete the challenge.
Duration time.Duration
}
4 changes: 4 additions & 0 deletions internal/core/domain/doc.go
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
// Package domain provides the core entities for the dungeon challenge.
//
// It contains the fundamental models such as Config, Player, and Event,
// which are strictly isolated from any external frameworks, databases, or delivery mechanisms.
package domain
21 changes: 21 additions & 0 deletions internal/core/domain/errors.go
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
package domain

import "errors"

// Domain-level errors representing business rule violations.
var (
// ErrPlayerNotRegistered indicates an action was attempted by an unknown player.
ErrPlayerNotRegistered = errors.New("player is not registered")

// ErrPlayerDead indicates the player's health has reached zero or below.
ErrPlayerDead = errors.New("player is dead")

// ErrDungeonClosed indicates the action occurred after the allowed duration.
ErrDungeonClosed = errors.New("dungeon opening time has expired")

// ErrInvalidMove indicates an action that violates the physical rules
// of the dungeon (e.g., going back a floor).
ErrInvalidMove = errors.New("impossible move")

// ErrDisqualified indicates the player has explicitly stated they cannot continue.
ErrDisqualified = errors.New("player cannot continue")
)
44 changes: 44 additions & 0 deletions internal/core/domain/event.go
Original file line number Diff line number Diff line change
@@ -1 +1,45 @@
package domain

import "time"

// EventID represents the unique identifier for incoming and outgoing challenge events.
type EventID int

// Incoming events generated by the player actions.
const (
_ EventID = iota
EventRegistered // 1: Player registered
EventEntered // 2: Player entered the dungeon
EventKilledMonster // 3: Player killed a monster
EventNextFloor // 4: Player went to the next floor
EventPrevFloor // 5: Player went to the previous floor
EventEnteredBoss // 6: Player entered the boss's floor
EventKilledBoss // 7: Player killed the boss
EventLeftDungeon // 8: Player left the dungeon
EventCannotContinue // 9: Player cannot continue due to some reason
EventRestoredHealth // 10: Player has restored health
EventReceivedDamage // 11: Player received damage
)

// Outgoing events generated by the system in response to player actions.
const (
OutEventDisqualified EventID = iota + 31 // 31: Player disqualified
OutEventDead // 32: Player is dead
OutEventInvalidMove // 33: Player makes an impossible move
)

// Event represents a single action or occurrence within the dungeon timeline.
type Event struct {
// ID is the numeric identifier of the event type.
ID EventID

// PlayerID is the unique identifier of the participant.
PlayerID int

// ExtraParam holds additional contextual data, such as damage amounts,
// health restored, or text reasons for being unable to continue.
ExtraParam string

// Time is the exact moment the event occurred.
Time time.Time
}
51 changes: 51 additions & 0 deletions internal/core/domain/player.go
Original file line number Diff line number Diff line change
@@ -1 +1,52 @@
package domain

import "time"

// State represents the current standing of a player in the challenge.
type State string

const (
StateOutside State = "OUTSIDE"
StateInDungeon State = "IN_DUNGEON"
StateSuccess State = "SUCCESS"
StateFail State = "FAIL"
StateDisqual State = "DISQUAL"
)

// Player encapsulates the state, health, and progression metrics of a participant
// navigating the dungeon.
type Player struct {
ID int
State State

// Health represents the player's current hit points.
// It is capped at 100 and cannot drop below 0.
Health int

// CurrentFloor indicates where the player is currently located.
// 0 implies the player is outside or in the lobby.
CurrentFloor int

// MonstersKilled tracks the number of defeated monsters per floor.
// The slice index corresponds to the floor number (1-based, index 0 is unused).
MonstersKilled []int

// Progression timestamps
EnterTime time.Time
LeaveTime time.Time
DeathTime time.Time

// Floor tracking metrics
FloorEnterTime time.Time
FloorClearTimes []time.Duration

// Boss encounter metrics
BossEnterTime time.Time
BossKilled bool
BossKillTime time.Duration
}

// IsDead returns true if the player's health has dropped to zero or below.
func (p *Player) IsDead() bool {
return p.Health <= 0
}
Loading