use super::quote_if_needed;
use crate::analyses::code_health::CodeHealthRow;
use crate::analyses::hotspots::HotspotRow;
use crate::{CodeLoreError, Result};
use std::io::Write;
pub fn write_hotspot_velocity_csv<W: Write>(
rows: &[crate::analyses::hotspot_velocity::HotspotVelocityRow],
w: &mut W,
) -> Result<()> {
writeln!(
w,
"entity,revs-recent,revs-baseline,recent-per-week,baseline-per-week,acceleration"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
writeln!(
w,
"{},{},{},{:.2},{:.2},{:.2}",
quote_if_needed(&row.path),
row.revs_recent,
row.revs_baseline,
row.recent_per_week,
row.baseline_per_week,
row.acceleration,
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_hotspots_csv<W: Write>(rows: &[HotspotRow], w: &mut W) -> Result<()> {
writeln!(
w,
"entity,revisions,cognitive,cognitive-health,hotspot-score,mi,mi-rank,mi-band,ai-pct,hotspot-score-anchored"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
let mi_cell = match row.mi {
Some(v) => format!("{v:.2}"),
None => String::new(),
};
let (rank_cell, band_cell) = match row.mi_rank {
Some(rank) if rank.is_finite() => (
format!("{rank:.4}"),
crate::analyses::mi::MiBand::from_rank(rank)
.as_str()
.to_owned(),
),
_ => (String::new(), String::new()),
};
let ai_cell = match row.ai_pct {
Some(v) if v.is_finite() => format!("{v:.2}"),
_ => String::new(),
};
let anchored_cell = row
.hotspot_score_anchored
.map_or_else(String::new, |v| format!("{v:.4}"));
writeln!(
w,
"{},{},{:.2},{:.2},{:.4},{},{},{},{},{}",
quote_if_needed(&row.path),
row.revisions,
row.cognitive,
row.cognitive_health,
row.hotspot_score,
mi_cell,
rank_cell,
band_cell,
ai_cell,
anchored_cell
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_code_health_csv<W: Write>(rows: &[CodeHealthRow], w: &mut W) -> Result<()> {
writeln!(
w,
"entity,cognitive,score,structural_risk,percentile,band,corpus-pct,corpus-pct-ci-low,corpus-pct-ci-high"
)
.map_err(CodeLoreError::Io)?;
let cell = |v: Option<f64>| v.map_or_else(String::new, |v| format!("{v:.2}"));
for row in rows {
writeln!(
w,
"{},{:.2},{:.2},{:.4},{:.4},{},{},{},{}",
quote_if_needed(&row.path),
row.cognitive,
row.score,
row.structural_risk,
row.percentile,
row.band,
cell(row.corpus_percentile),
cell(row.corpus_percentile_ci_low),
cell(row.corpus_percentile_ci_high),
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_health_trend_csv<W: Write>(
rows: &[crate::analyses::health_trend::HealthTrendRow],
w: &mut W,
) -> Result<()> {
writeln!(
w,
"date,rev,files,arch-health,code-health,combined-health,arch-band,code-band,combined-band"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
writeln!(
w,
"{},{},{},{:.2},{:.2},{:.2},{},{},{}",
quote_if_needed(&row.date),
quote_if_needed(&row.rev),
row.files,
row.arch_health,
row.code_health,
row.combined_health,
row.arch_band,
row.code_band,
row.combined_band,
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_effort_exposure_csv<W: Write>(
rows: &[crate::analyses::effort_exposure::EffortExposureRow],
w: &mut W,
) -> Result<()> {
writeln!(
w,
"band,files,loc-share-pct,commit-share-pct,churn-share-pct,commit-share-ci-low,commit-share-ci-high,churn-share-improving-pct,churn-share-degrading-pct"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
let improving = row
.churn_share_improving_pct
.map_or_else(String::new, |v| format!("{v:.2}"));
let degrading = row
.churn_share_degrading_pct
.map_or_else(String::new, |v| format!("{v:.2}"));
writeln!(
w,
"{},{},{:.2},{:.2},{:.2},{:.4},{:.4},{},{}",
quote_if_needed(&row.band),
row.files,
row.loc_share_pct,
row.commit_share_pct,
row.churn_share_pct,
row.commit_share_ci_low,
row.commit_share_ci_high,
improving,
degrading,
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_defect_validation_csv<W: Write>(
rows: &[crate::analyses::defect_validation::DefectValidationRow],
w: &mut W,
) -> Result<()> {
writeln!(w, "metric,value").map_err(CodeLoreError::Io)?;
for row in rows {
writeln!(
w,
"{},{}",
quote_if_needed(&row.metric),
quote_if_needed(&row.value),
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_refactoring_targets_csv<W: Write>(
rows: &[crate::analyses::refactoring_targets::RefactoringTargetRow],
w: &mut W,
) -> Result<()> {
writeln!(
w,
"entity,priority,combined_risk,structural_risk,hotspot_score,revisions,loc,dominant_type,band,manual_up_rank"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
writeln!(
w,
"{},{:.6},{:.6},{:.4},{:.4},{},{},{},{},{}",
quote_if_needed(&row.path),
row.priority,
row.combined_risk,
row.structural_risk,
row.hotspot_score,
row.revisions,
row.loc,
quote_if_needed(&row.dominant_type),
row.band,
row.manual_up_rank,
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_function_xray_csv<W: Write>(
rows: &[crate::analyses::function_xray::FunctionXrayRow],
w: &mut W,
) -> Result<()> {
writeln!(
w,
"function,change-freq,loc,cyclomatic,cognitive,last-changed"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
writeln!(
w,
"{},{},{},{},{},{}",
quote_if_needed(&row.function),
row.change_freq,
row.loc,
row.cyclomatic.map_or_else(String::new, |v| v.to_string()),
row.cognitive.map_or_else(String::new, |v| v.to_string()),
quote_if_needed(&row.last_changed),
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_function_hotspots_csv<W: Write>(
rows: &[crate::analyses::function_hotspots::FunctionHotspotRow],
w: &mut W,
) -> Result<()> {
writeln!(
w,
"path,function,revs,cognitive,cognitive-health,function-hotspot-score"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
writeln!(
w,
"{},{},{},{:.2},{:.2},{:.4}",
quote_if_needed(&row.path),
quote_if_needed(&row.function),
row.revs,
row.cognitive,
row.cognitive_health,
row.function_hotspot_score,
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}
pub fn write_finding_hotspot_overlap_csv<W: Write>(
rows: &[crate::analyses::finding_hotspot_overlap::FindingHotspotOverlapRow],
w: &mut W,
) -> Result<()> {
writeln!(
w,
"path,findings,engines,worst-level,hotspot-score,revs-percentile,health-band,priority"
)
.map_err(CodeLoreError::Io)?;
for row in rows {
writeln!(
w,
"{},{},{},{},{:.4},{:.4},{},{}",
quote_if_needed(&row.path),
row.findings,
quote_if_needed(&row.engines),
quote_if_needed(&row.worst_level),
row.hotspot_score,
row.revs_percentile,
quote_if_needed(&row.health_band),
quote_if_needed(&row.priority),
)
.map_err(CodeLoreError::Io)?;
}
Ok(())
}