Files
Genarrative/server-rs/crates/module-story/src/events.rs

60 lines
2.0 KiB
Rust

//! 剧情领域事件。
//!
//! 事件只表达 story session 已经发生的领域事实;是否写入 SpacetimeDB event table 或
//! 映射成 HTTP/SSE 输出,由外层 adapter 决定。
use crate::domain::StorySessionSnapshot;
use serde::{Deserialize, Serialize};
use shared_kernel::build_prefixed_seed_id;
#[cfg(feature = "spacetime-types")]
use spacetimedb::SpacetimeType;
/// 剧情事件 ID 的稳定前缀。
pub const STORY_EVENT_ID_PREFIX: &str = "storyevt_";
/// 剧情事件类型,当前覆盖开局和续写两条最小主链。
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum StoryEventKind {
SessionStarted,
StoryContinued,
}
impl StoryEventKind {
pub fn as_str(&self) -> &'static str {
match self {
Self::SessionStarted => "session_started",
Self::StoryContinued => "story_continued",
}
}
}
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct StoryEventSnapshot {
pub event_id: String,
pub story_session_id: String,
pub event_kind: StoryEventKind,
pub narrative_text: String,
pub choice_function_id: Option<String>,
pub created_at_micros: i64,
}
pub fn build_story_started_event(snapshot: &StorySessionSnapshot) -> StoryEventSnapshot {
StoryEventSnapshot {
event_id: generate_story_event_id(snapshot.created_at_micros),
story_session_id: snapshot.story_session_id.clone(),
event_kind: StoryEventKind::SessionStarted,
narrative_text: snapshot
.opening_summary
.clone()
.unwrap_or_else(|| snapshot.initial_prompt.clone()),
choice_function_id: None,
created_at_micros: snapshot.created_at_micros,
}
}
pub fn generate_story_event_id(seed_micros: i64) -> String {
build_prefixed_seed_id(STORY_EVENT_ID_PREFIX, seed_micros)
}