use super::*;
use crate::app::Snapshot;
use crate::binding::{Workspace, WorkspaceKind};
use crate::budgets::{BudgetSpend, StepBill};
use crate::git_tree::{Agent, AgentState, GitTree};
use crate::projects::balls::{Ball, Blocker};
use crate::projects::join::{JoinRow, JoinState};
use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Instant;
pub(super) const PROJECT: &str = "/proj";
pub(super) const WS_A: &str = "/ws/alfa";
pub(super) const WS_B: &str = "/ws/bravo";
pub(super) fn ball(id: &str, claimant: Option<&str>, blockers: Vec<Blocker>) -> Ball {
Ball {
id: id.to_owned(),
title: format!("{id} title"),
body: String::new(),
claimant: claimant.map(str::to_owned),
blockers,
parent: None,
priority: 2,
tags: vec![],
created: Some(0),
updated: Some(0),
root_commit: None,
}
}
pub(super) fn blocks(id: &str, on: &str) -> Blocker {
Blocker {
id: id.to_owned(),
on: on.to_owned(),
}
}
pub(super) fn join(
id: &str,
state: JoinState,
ws: Option<&str>,
claimant: Option<&str>,
) -> JoinRow {
JoinRow {
project: PathBuf::from(PROJECT),
ball_id: id.to_owned(),
state,
workspace: ws.map(PathBuf::from),
claimant: claimant.map(str::to_owned),
title: Some(format!("{id} title")),
}
}
pub(super) fn agent(id: &str, ball: Option<&str>, name: Option<&str>) -> Agent {
Agent {
goal_ball: ball.map(str::to_owned),
name: name.map(str::to_owned),
..crate::boundary::tests::agent(id, AgentState::Quiescent, 0)
}
}
pub(super) fn bill(conv: &str, input: u64) -> StepBill {
StepBill {
conv: conv.to_owned(),
seq: "001".to_owned(),
model: Some("opus".to_owned()),
spend: BudgetSpend {
input_tokens: input,
..BudgetSpend::default()
},
last_usage: BudgetSpend::default(),
}
}
pub(super) fn ui() -> crate::ui_state::UiState {
ui_doc(r#"{"v":1,"prices":{"opus":{"input":1}}}"#)
}
pub(super) fn ui_doc(doc: &str) -> crate::ui_state::UiState {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("ui.json");
std::fs::write(&path, doc).expect("write");
crate::ui_state::UiState::open(path)
}
pub(super) const NOW: i64 = 1_000_000;
pub(super) struct World {
pub(super) snap: Snapshot,
}
impl World {
pub(super) fn board(&self) -> Board {
build(&self.snap, &ui(), NOW)
}
}
pub(super) fn world(
balls: Vec<Ball>,
joins: Vec<JoinRow>,
agents: Vec<(&str, Vec<Agent>)>,
) -> World {
let mut trees = HashMap::new();
let mut bills = HashMap::new();
for (ws, members) in agents {
bills.insert(
PathBuf::from(ws),
members
.iter()
.map(|a| bill(&a.agent_id, 1_000_000))
.collect(),
);
trees.insert(
PathBuf::from(ws),
GitTree {
commits: vec![],
agents: members,
},
);
}
let mut balls_by_project = HashMap::new();
balls_by_project.insert(PathBuf::from(PROJECT), balls);
World {
snap: Snapshot {
windows: std::collections::BTreeMap::default(),
workspaces: vec![Workspace {
path: PathBuf::from(WS_A),
kind: WorkspaceKind::Named {
name: "alfa".to_owned(),
},
}],
trees,
bills,
balls_by_project,
closed_by_project: HashMap::new(),
join_rows: joins,
ops: vec![],
growth: vec![],
ui_bytes: None,
derived_at: Instant::now(),
cadence: crate::app::Cadence::default(),
fleet: std::collections::BTreeMap::new(),
},
}
}