use kcode_audio_history_handoff::RecordingProjection;
use kcode_audio_ingress::{
LegacyReviewDisposition, RecordingState, RecordingStatus, legacy_review_disposition,
};
use uuid::Uuid;
use crate::{Coordinator, Error, audio_error, handoff_error, recording_belongs_to};
impl Coordinator {
pub(crate) fn owned_recordings(&self) -> Result<Vec<RecordingStatus>, Error> {
Ok(self
.audio
.status()
.map_err(audio_error)?
.recordings
.into_iter()
.filter(|recording| recording_belongs_to(recording, &self.user_id))
.collect())
}
pub(crate) async fn project_recordings(
&self,
recordings: &[RecordingStatus],
) -> Result<Vec<RecordingProjection>, Error> {
let projections = self
.handoff
.project(recordings)
.await
.map_err(handoff_error)?;
if recordings.len() != projections.len() {
return Err(Error::internal("handoff returned incomplete projections"));
}
Ok(projections)
}
pub(crate) async fn resolve_legacy_reviews(
&self,
recordings: &[RecordingStatus],
projections: &[RecordingProjection],
) -> Result<bool, Error> {
let decisions = decisions(recordings, projections);
for (recording_id, disposition) in &decisions {
self.audio
.resolve_legacy_review(*recording_id, *disposition)
.map_err(audio_error)?;
}
Ok(!decisions.is_empty())
}
pub(crate) async fn prepared_recordings(
&self,
) -> Result<(Vec<RecordingStatus>, Vec<RecordingProjection>), Error> {
let mut recordings = self.owned_recordings()?;
let mut projections = self.project_recordings(&recordings).await?;
if self
.resolve_legacy_reviews(&recordings, &projections)
.await?
{
recordings = self.owned_recordings()?;
projections = self.project_recordings(&recordings).await?;
}
Ok((recordings, projections))
}
}
pub(crate) fn decisions(
recordings: &[RecordingStatus],
projections: &[RecordingProjection],
) -> Vec<(Uuid, LegacyReviewDisposition)> {
recordings
.iter()
.zip(projections)
.filter_map(|(recording, projection)| {
debug_assert_eq!(recording.id, projection.recording_id);
disposition(recording, !projection.pieces.is_empty())
.map(|disposition| (recording.id, disposition))
})
.collect()
}
pub(crate) fn has_candidates(recordings: &[RecordingStatus]) -> bool {
recordings
.iter()
.any(|recording| disposition(recording, false).is_some())
}
fn disposition(recording: &RecordingStatus, has_ingress: bool) -> Option<LegacyReviewDisposition> {
legacy_review_disposition(
matches!(&recording.state, RecordingState::Complete { .. }),
recording
.correction_packet
.as_ref()
.map(|packet| packet.confirmation_state),
has_ingress,
)
}