pub struct TutorSession {Show 13 fields
pub lesson: u32,
pub total_lessons: u32,
pub exercises: Vec<TutorExercise>,
pub current: usize,
pub attempt_count: usize,
pub anchor_lines: Vec<usize>,
pub initial_texts: Vec<String>,
pub last_version: u64,
pub lives: u8,
pub score: u32,
pub exercise_started_at: Option<Instant>,
pub state: TutorGameState,
pub high_score: u32,
}Expand description
Per-tutor-buffer state. Stored as a BufferLocal by TutorMode.
Fields§
§lesson: u32§total_lessons: u32Total lesson count in this build (5 at launch).
exercises: Vec<TutorExercise>§current: usizeIndex of the current exercise.
attempt_count: usizeFailed-attempt count since the last advance/retreat. Used to gate hint display (shows after ≥ 2).
anchor_lines: Vec<usize>Resolved line index in the buffer for each exercise’s anchor.
Parallel to exercises.
initial_texts: Vec<String>Text snapshot of each anchor line as of session load.
Parallel to exercises.
last_version: u64Last buffer version seen by the post-dispatch watcher.
lives: u8Lives remaining for the current exercise.
score: u32Cumulative score across all passed exercises this session.
exercise_started_at: Option<Instant>Wall-clock start time for the current exercise; used for speed bonuses.
state: TutorGameStateHigh-level game state.
high_score: u32All-time high score for this lesson loaded from disk at session
start. Shown in the HUD as HI:.
Implementations§
Source§impl TutorSession
impl TutorSession
Sourcepub fn load(
lesson: u32,
total_lessons: u32,
lesson_text: &str,
exercises_toml: &str,
) -> Result<Self, String>
pub fn load( lesson: u32, total_lessons: u32, lesson_text: &str, exercises_toml: &str, ) -> Result<Self, String>
Build a TutorSession by parsing the exercise sidecar and
scanning the lesson text for each anchor.
Returns Err (human-readable) if:
- the sidecar TOML is malformed, or
- any anchor text is not found in
lesson_text.
Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
true when all exercises in this lesson have been advanced past.
Sourcepub fn current_exercise(&self) -> Option<&TutorExercise>
pub fn current_exercise(&self) -> Option<&TutorExercise>
The current exercise, or None if the lesson is complete.
Sourcepub fn check(&mut self, lines: &[&str]) -> bool
pub fn check(&mut self, lines: &[&str]) -> bool
Auto-detect pass/fail against live buffer lines. Awards score
on pass (base + first-try bonus + speed bonus). Increments
attempt_count on failure. Does NOT drain lives — that only
happens on explicit <CR> presses via drain_life.
Returns false when the session is not Active or the lesson
is already complete.
Sourcepub fn is_condition_met(&self, lines: &[&str]) -> bool
pub fn is_condition_met(&self, lines: &[&str]) -> bool
Peek: is the success condition currently met? Pure read — no
side effects. Used by do_tutor_advance to decide whether an
explicit <CR> press is a valid advance or a penalised miss.
Sourcepub fn drain_life(&mut self)
pub fn drain_life(&mut self)
Drain one life on an explicit wrong attempt (<CR> press when
the condition is not met). Increments attempt_count and
transitions to GameOver when lives reach zero.
Sourcepub fn advance(&mut self) -> Option<&TutorExercise>
pub fn advance(&mut self) -> Option<&TutorExercise>
Advance to the next exercise; resets lives, attempt_count, and
restarts the exercise timer. Returns the new current exercise,
or None if the lesson is now complete.
Trait Implementations§
Source§impl BufferLocal for TutorSession
impl BufferLocal for TutorSession
Source§const NAME: &'static str = "tutor-mode.session"
const NAME: &'static str = "tutor-mode.session"
:describe-buffer row label,
debug logs). Convention: <owner-mode-name>.<key>,
e.g. "file-tree.entries". Not a registry key — locals
aren’t registered globally; the name is metadata for
inspection.Source§const DOC: &'static str = "Active tutor session: current lesson, exercise index, \
anchor line positions, attempt count."
const DOC: &'static str = "Active tutor session: current lesson, exercise index, \ anchor line positions, attempt count."
:describe-buffer when the user
expands a local for detail.Source§const OWNER_MODE: &'static str = "tutor-mode"
const OWNER_MODE: &'static str = "tutor-mode"
:describe-buffer; the write-time check the design calls for
(a ModeContext::set_local::<T> that rejects a non-owner) is not
implemented, so nothing enforces it today (see the module docs).Source§impl Clone for TutorSession
impl Clone for TutorSession
Source§fn clone(&self) -> TutorSession
fn clone(&self) -> TutorSession
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for TutorSession
impl RefUnwindSafe for TutorSession
impl Send for TutorSession
impl Sync for TutorSession
impl Unpin for TutorSession
impl UnsafeUnpin for TutorSession
impl UnwindSafe for TutorSession
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more