use super::attention;
use crate::git_tree::{Agent, AgentState, descent_order};
use crate::ui_state::SeenKind;
fn rank(agent: &Agent, ws: &str, seen: &dyn Fn(SeenKind, &str, &str, &str) -> bool) -> u8 {
if attention(agent, ws, seen).any() {
0
} else if matches!(agent.state, AgentState::Live | AgentState::InFlight) {
1
} else {
2
}
}
pub fn sorted_roster(
agents: &[Agent],
ws: &str,
seen: &dyn Fn(SeenKind, &str, &str, &str) -> bool,
) -> Vec<usize> {
let mut order: Vec<usize> = descent_order(agents)
.into_iter()
.map(|row| row.index)
.collect();
order.sort_by_key(|&i| agents.get(i).map(|a| rank(a, ws, seen)));
order
}
pub fn workspace_count(
agents: &[Agent],
ws: &str,
seen: &dyn Fn(SeenKind, &str, &str, &str) -> bool,
) -> usize {
agents
.iter()
.filter(|a| attention(a, ws, seen).any())
.count()
}
pub fn strip_total(
workspaces: &[(&str, &[Agent])],
seen: &dyn Fn(SeenKind, &str, &str, &str) -> bool,
) -> usize {
workspaces
.iter()
.map(|(path, agents)| workspace_count(agents, path, seen))
.sum()
}
#[derive(Clone)]
pub struct RosterKey {
pub ws: String,
pub agent_id: String,
pub attention: bool,
}
impl RosterKey {
fn is_at(&self, focus: (&str, &str)) -> bool {
self.ws == focus.0 && self.agent_id == focus.1
}
}
pub fn roster_order(
workspaces: &[(&str, &[Agent])],
seen: &dyn Fn(SeenKind, &str, &str, &str) -> bool,
) -> Vec<RosterKey> {
let mut wss: Vec<(&str, &[Agent])> = workspaces.to_vec();
wss.sort_by_key(|(path, _)| *path);
let mut out = Vec::new();
for (path, agents) in wss {
out.extend(
sorted_roster(agents, path, seen)
.into_iter()
.filter_map(|i| agents.get(i))
.map(|agent| RosterKey {
ws: path.to_string(),
agent_id: agent.agent_id.clone(),
attention: attention(agent, path, seen).any(),
}),
);
}
out
}
pub fn next_attention(roster: &[RosterKey], focus: Option<(&str, &str)>) -> Option<RosterKey> {
let n = roster.len();
if n == 0 {
return None;
}
let mut start = 0;
if let Some(f) = focus
&& let Some(i) = roster.iter().position(|e| e.is_at(f))
{
start = i + 1;
}
(0..n)
.filter_map(|step| roster.get((start + step) % n))
.find(|e| e.attention)
.cloned()
}