Functional Weave
Code in Python

todo.summary@1.0.0

impl/rust.rs

1,831 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::dates_day_of_week::day_of_week;  ← from dates.day-of-week ^1.0.0 · built alongside by fune
use super::math_round_div::round_div;  ← from math.round-div ^1.0.0 · built alongside by fune
use super::todo_due_status::due_status;  ← from todo.due-status ^1.0.0 · built alongside by fune
use super::todo_item::Todo;  ← from todo.item ^1.0.0 · built alongside by fune
use super::todo_item_validate_todo::todos_from_value;

/// Counts for a todo list. percent_done rounds down so 100 means everything
/// is done; overdue and due_today agree with due_status.
///
/// # Panics
/// Panics on an impossible or malformed date.
pub fn summarise_todos(todos: &[Todo], today: &str) -> TodoSummary {
    day_of_week(today); // a bad today is an error even for an empty list
    let mut done = 0;
    let mut overdue = 0;
    let mut due_today = 0;
    for todo in todos {
        let status = due_status(todo, today);
        if todo.done {
            done += 1;
        }
        if status == "overdue" {
            overdue += 1;
        }
        if status == "today" {
            due_today += 1;
        }
    }
    let total = todos.len() as i64;
    let active = total - done;
    TodoSummary {
        total,
        active,
        done,
        overdue,
        due_today,
        percent_done: if total == 0 { 0 } else { round_div(done * 100, total, "down") },
        items_left: if active == 1 { "1 item left".to_string() } else { format!("{} items left", active) },
    }
}

pub fn todo_summary_to_value(s: &TodoSummary) -> Value {
    Value::obj(vec![
        ("total", Value::Int(s.total)),
        ("active", Value::Int(s.active)),
        ("done", Value::Int(s.done)),
        ("overdue", Value::Int(s.overdue)),
        ("dueToday", Value::Int(s.due_today)),
        ("percentDone", Value::Int(s.percent_done)),
        ("itemsLeft", Value::str(&s.items_left)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    todo_summary_to_value(&summarise_todos(&todos_from_value(&args[0]), args[1].as_str()))
}