turnframe_core/plan/
mod.rs1pub mod limits;
6
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9
10use crate::understanding::ActTarget;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
14#[serde(rename_all = "snake_case")]
15pub enum TargetPolicy {
16 RequiresExistingCase,
18 RequiresCatalogedCase,
20 AllowsNewCase,
22 NewCaseOnly,
24 ActiveInteractionOnly,
26 None,
28}
29
30impl TargetPolicy {
31 #[must_use]
33 pub const fn permits(self, target: &ActTarget) -> bool {
34 match self {
35 Self::RequiresExistingCase => matches!(
36 target,
37 ActTarget::Record { .. }
38 | ActTarget::SameTurn { .. }
39 | ActTarget::NotListed { .. }
40 | ActTarget::Ambiguous { .. }
41 ),
42 Self::RequiresCatalogedCase => matches!(
43 target,
44 ActTarget::Record { .. }
45 | ActTarget::SameTurn { .. }
46 | ActTarget::Ambiguous { .. }
47 | ActTarget::Card
48 ),
49 Self::AllowsNewCase => !matches!(target, ActTarget::Card | ActTarget::Nothing),
50 Self::NewCaseOnly => matches!(target, ActTarget::New { .. }),
51 Self::ActiveInteractionOnly => matches!(target, ActTarget::Card),
52 Self::None => true,
53 }
54 }
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize, JsonSchema)]
63#[serde(rename_all = "snake_case")]
64pub enum ActAvailability {
65 #[default]
67 Proposable,
68 CardOnly,
70}
71
72impl ActAvailability {
73 #[must_use]
75 pub const fn is_proposable(self) -> bool {
76 matches!(self, Self::Proposable)
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
82#[serde(rename_all = "snake_case")]
83pub enum ActMutability {
84 ReadOnly,
86 Mutating,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
92#[serde(rename_all = "snake_case")]
93pub enum AnswerBasis {
94 CurrentCommittedState,
96 ProposedState,
98 CommittedStateAfterTurn,
100 GeneralDomainKnowledge,
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use crate::understanding::{ActId, UnitId};
108
109 #[test]
110 fn a_policy_admits_exactly_its_targets() {
111 let record = ActTarget::Record { token: "t".into() };
112 let same_turn = ActTarget::SameTurn {
113 act: ActId::new(UnitId(1), 1),
114 };
115 let new = ActTarget::New {
116 workflow: "w".into(),
117 };
118 assert!(TargetPolicy::RequiresExistingCase.permits(&record));
119 assert!(TargetPolicy::RequiresExistingCase.permits(&same_turn));
120 assert!(!TargetPolicy::RequiresExistingCase.permits(&new));
121 assert!(
122 !TargetPolicy::RequiresCatalogedCase.permits(&ActTarget::NotListed {
123 workflow: "w".into(),
124 words: None,
125 })
126 );
127 assert!(TargetPolicy::NewCaseOnly.permits(&new));
128 assert!(!TargetPolicy::NewCaseOnly.permits(&record));
129 assert!(TargetPolicy::ActiveInteractionOnly.permits(&ActTarget::Card));
130 assert!(!TargetPolicy::AllowsNewCase.permits(&ActTarget::Card));
131 }
132}