use super::types::{ConnectionPattern, DungeonConfig, DungeonState, RoomId};
#[derive(crate::Service, Debug, Clone)]
#[service(name = "dungeon_service")]
pub struct DungeonService;
impl DungeonService {
pub fn new() -> Self {
Self
}
pub fn available_rooms(&self, config: &DungeonConfig, state: &DungeonState) -> Vec<u32> {
match config.connection_pattern {
ConnectionPattern::Linear => {
if state.current_room < config.rooms_per_floor {
vec![state.current_room + 1]
} else {
vec![]
}
}
ConnectionPattern::Branching => {
let mut rooms = Vec::new();
if state.current_room < config.rooms_per_floor {
rooms.push(state.current_room + 1);
}
if state.current_room + 2 <= config.rooms_per_floor {
rooms.push(state.current_room + 2);
}
rooms
}
ConnectionPattern::Graph => {
state
.unlocked_connections
.iter()
.filter(|conn| {
conn.from.floor == state.current_floor
&& conn.from.room == state.current_room
})
.map(|conn| conn.to.room)
.collect()
}
}
}
pub fn can_advance_floor(&self, config: &DungeonConfig, state: &DungeonState) -> bool {
state.current_room >= config.rooms_per_floor && state.current_floor < config.total_floors
}
pub fn is_completed(&self, config: &DungeonConfig, state: &DungeonState) -> bool {
state.current_floor >= config.total_floors && state.current_room >= config.rooms_per_floor
}
pub fn is_room_visited(&self, state: &DungeonState, room_id: &RoomId) -> bool {
state.visited_rooms.contains(room_id)
}
pub fn progress_percentage(&self, config: &DungeonConfig, state: &DungeonState) -> f32 {
let total_rooms = config.total_floors * config.rooms_per_floor;
let completed_rooms =
(state.current_floor - 1) * config.rooms_per_floor + state.current_room;
(completed_rooms as f32 / total_rooms as f32) * 100.0
}
}
impl Default for DungeonService {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_linear_available_rooms() {
let service = DungeonService::new();
let config = DungeonConfig {
total_floors: 3,
rooms_per_floor: 3,
connection_pattern: ConnectionPattern::Linear,
};
let state = DungeonState {
current_floor: 1,
current_room: 1,
..Default::default()
};
let available = service.available_rooms(&config, &state);
assert_eq!(available, vec![2]);
}
#[test]
fn test_can_advance_floor() {
let service = DungeonService::new();
let config = DungeonConfig::default();
let state = DungeonState {
current_floor: 1,
current_room: 3,
..Default::default()
};
assert!(service.can_advance_floor(&config, &state));
}
#[test]
fn test_progress_percentage() {
let service = DungeonService::new();
let config = DungeonConfig {
total_floors: 5,
rooms_per_floor: 3,
connection_pattern: ConnectionPattern::Linear,
};
let state = DungeonState {
current_floor: 3,
current_room: 2,
..Default::default()
};
let progress = service.progress_percentage(&config, &state);
assert!((progress - 53.33).abs() < 0.1);
}
}