use crate::{
entity::{RCTask, Sentence, Task},
global::Float,
inference::Truth,
parameters::{Parameters, DEFAULT_PARAMETERS},
storage::Bag,
util::{IterInnerRcSelf, ToDisplayAndBrief},
};
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
#[derive(Debug, Serialize, Deserialize)]
pub struct TaskBuffer {
new_tasks: VecDeque<Task>,
novel_tasks: Bag<Task>,
#[serde(default)] parameters: TaskBufferParameters,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
struct TaskBufferParameters {
creation_expectation: Float,
}
impl TaskBufferParameters {
fn new(parameters: &Parameters) -> Self {
Self {
creation_expectation: parameters.default_creation_expectation,
}
}
}
impl Default for TaskBufferParameters {
fn default() -> Self {
Self::new(&DEFAULT_PARAMETERS)
}
}
impl Default for TaskBuffer {
fn default() -> Self {
Self::new(&DEFAULT_PARAMETERS)
}
}
impl TaskBuffer {
pub fn new(parameters: &Parameters) -> Self {
Self {
new_tasks: Default::default(),
novel_tasks: Bag::from_parameters(
parameters.novel_task_bag_size,
parameters.novel_task_forgetting_cycle,
parameters,
),
parameters: TaskBufferParameters::new(parameters),
}
}
pub fn reset(&mut self) {
self.new_tasks.clear();
self.novel_tasks.init();
}
}
impl TaskBuffer {
fn add_new_task(&mut self, task: Task) {
self.new_tasks.push_back(task);
}
#[must_use]
fn pop_new_task(&mut self) -> Option<Task> {
self.new_tasks.pop_front()
}
#[must_use]
fn put_in_novel_tasks(&mut self, task: Task) -> Option<Task> {
self.novel_tasks.put_in(task)
}
#[must_use]
fn take_a_novel_task(&mut self) -> Option<Task> {
self.novel_tasks.take_out()
}
}
pub trait TaskBufferLoadingContext {
fn output_task(&mut self, task: Task);
fn report_comment(&mut self, message: String);
fn has_concept(&self, task: &Task) -> bool;
}
impl TaskBuffer {
pub fn add_task(&mut self, task: Task) {
self.add_new_task(task);
}
pub fn load_from_tasks(
&mut self,
has_concept: impl Fn(&Task) -> bool,
report_comment: impl FnMut(String),
) -> Vec<Task> {
let mut context = {
struct LoadingContext<HasConcept, ReportComment>
where
HasConcept: Fn(&Task) -> bool, ReportComment: FnMut(String),
{
has_concept: HasConcept,
report_comment: ReportComment,
tasks_to_process: Vec<Task>,
}
impl<HasConcept, ReportComment> TaskBufferLoadingContext
for LoadingContext<HasConcept, ReportComment>
where
HasConcept: Fn(&Task) -> bool, ReportComment: FnMut(String),
{
fn output_task(&mut self, task: Task) {
self.tasks_to_process.push(task);
}
fn report_comment(&mut self, message: String) {
(self.report_comment)(message);
}
fn has_concept(&self, task: &Task) -> bool {
(self.has_concept)(task)
}
}
LoadingContext {
has_concept,
report_comment,
tasks_to_process: vec![], }
};
self.load_from_tasks_with_context(&mut context);
context.tasks_to_process
}
pub fn load_from_tasks_with_context(&mut self, context: &mut impl TaskBufferLoadingContext) {
self.load_from_new_tasks(context);
self.load_from_novel_tasks(context);
}
fn load_from_new_tasks(&mut self, context: &mut impl TaskBufferLoadingContext) {
while let Some(task) = self.pop_new_task() {
if task.is_input() || context.has_concept(&task) {
context.output_task(task);
}
else {
let should_add_to_novel_tasks = match task.as_judgement() {
Some(judgement) => {
judgement.expectation() > self.parameters.creation_expectation
}
None => false,
};
match should_add_to_novel_tasks {
true => {
if let Some(overflowed) = self.put_in_novel_tasks(task) {
context.report_comment(format!(
"!!! NovelTasks overflowed: {}",
overflowed.to_display_long()
))
}
}
false => {
context.report_comment(format!("!!! Neglected: {}", task.to_display_long()))
}
}
}
}
}
fn load_from_novel_tasks(&mut self, context: &mut impl TaskBufferLoadingContext) {
if let Some(task) = self.take_a_novel_task() {
context.output_task(task);
}
}
}
impl TaskBuffer {
pub fn n_new_tasks(&self) -> usize {
self.new_tasks.len()
}
pub fn n_novel_tasks(&self) -> usize {
self.novel_tasks.size()
}
#[doc(alias = "len")]
pub fn size(&self) -> usize {
self.n_new_tasks() + self.n_novel_tasks()
}
pub fn iter_tasks(&self) -> impl Iterator<Item = &Task> {
let new_tasks = self.iter_new_tasks();
let novel_tasks = self.iter_novel_tasks();
new_tasks.chain(novel_tasks)
}
fn iter_new_tasks(&self) -> impl Iterator<Item = &Task> {
self.new_tasks.iter()
}
fn iter_novel_tasks(&self) -> impl Iterator<Item = &Task> {
self.novel_tasks.iter()
}
}
impl TaskBuffer {
pub(crate) fn iter_mut_task_rcs(&mut self) -> impl Iterator<Item = &mut RCTask> {
self.new_tasks
.iter_mut()
.chain(self.novel_tasks.iter_mut())
.flat_map(|t| t.iter_inner_rc_self())
}
#[cfg(test)]
pub(crate) fn iter_task_rcs(&self) -> impl Iterator<Item = &RCTask> {
self.new_tasks
.iter()
.chain(self.novel_tasks.iter())
.flat_map(Task::parent_task)
}
}
#[cfg(test)]
pub(crate) mod tests_task_buffer {
use super::*;
use crate::{
assert_eq_try, ok,
storage::tests_memory::{bag_consistent, task_consistent, zip},
util::AResult,
};
pub fn task_buffer_consistent(a: &TaskBuffer, b: &TaskBuffer) -> AResult {
task_deque_consistent(&a.new_tasks, &b.new_tasks)?;
task_bag_consistent(&a.novel_tasks, &b.novel_tasks)?;
ok!()
}
pub fn task_deque_consistent(a: &VecDeque<Task>, b: &VecDeque<Task>) -> AResult {
assert_eq_try!(a.len(), b.len(), "任务队列不一致——长度不一致");
for (a, b) in zip(a, b) {
task_consistent(a, b)?;
}
ok!()
}
pub fn task_bag_consistent(a: &Bag<Task>, b: &Bag<Task>) -> AResult {
bag_consistent(a, b, task_consistent)?;
ok!()
}
}