use super::prelude::*;
pub type IndexedJob<'a> = (usize, &'a Job);
#[derive(Debug, Clone)]
pub struct JobList<'a> {
jobs: Vec<IndexedJob<'a>>,
pub configuration: &'a Configuration,
}
impl<'a> IntoIterator for JobList<'a> {
type Item = IndexedJob<'a>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.jobs.into_iter()
}
}
impl<'a> From<&'a JobListOwned> for JobList<'a> {
fn from(list: &'a JobListOwned) -> Self {
Self {
configuration: &list.configuration,
jobs: list.iter().map(|(n, j)| (*n, j)).collect(),
}
}
}
impl<'a> std::fmt::Display for JobList<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f)?;
let mut count = 0;
for (pos, job) in self.iter() {
writeln!(f, " Pos: {}", pos + 1)?;
job.writeln(f, self.configuration.get(&job.tags))?;
writeln!(f)?;
count += 1;
}
let pay = {
if let Some(pay) = self.pay_overall() {
format!(" = ${}", format::pay_pure(pay))
} else {
String::new()
}
};
if count > 1 {
writeln!(
f,
"Total: {} job(s), {} hours{}",
self.len(),
format::hours_pure(self.hours_overall()),
pay,
)?;
}
Ok(())
}
}
impl<'a> JobList<'a> {
pub fn new(jobs: Vec<(usize, &'a Job)>, configuration: &'a Configuration) -> Self {
Self {
jobs,
configuration,
}
}
pub fn new_from(jobs: &'a Jobs) -> Self {
Self {
jobs: Vec::new(),
configuration: &jobs.configuration,
}
}
pub fn push(&mut self, pos: usize, job: &'a Job) {
self.jobs.push((pos, job))
}
pub fn iter(&self) -> core::slice::Iter<'_, IndexedJob> {
self.jobs.iter()
}
pub fn is_empty(&self) -> bool {
self.jobs.is_empty()
}
pub fn len(&self) -> usize {
self.jobs.len()
}
pub fn drain(&mut self, count: usize) -> Result<(), Error> {
if count > self.jobs.len() {
return Err(Error::ToFewJobs(count, self.jobs.len()));
}
self.jobs.drain(0..(self.jobs.len() - count));
Ok(())
}
pub fn tags(&self) -> TagSet {
let mut tags = TagSet::new();
for (_, job) in &self.jobs {
tags.insert_many(job.tags.clone());
}
tags
}
pub fn positions(&self) -> Positions {
Positions::from_iter(self.jobs.iter().map(|(n, _)| *n))
}
pub fn get_configuration(&self, tags: &TagSet) -> &Properties {
for tag in &tags.0 {
if let Some(properties) = self.configuration.tags.get(tag) {
return properties;
}
}
&self.configuration.base
}
pub fn hours_overall(&self) -> f64 {
let mut hours = 0.0;
for (_, job) in &self.jobs {
hours += job.hours(self.get_configuration(&job.tags))
}
hours
}
pub fn pay_overall(&self) -> Option<f64> {
let mut pay_sum = 0.0;
let mut has_payment = false;
for (_, job) in &self.jobs {
let properties = self.get_configuration(&job.tags);
if let Some(rate) = properties.rate {
pay_sum += rate * job.hours(properties);
has_payment = true;
}
}
if has_payment {
Some(pay_sum)
} else {
None
}
}
}