Use Option instead of Result where applicable

This commit is contained in:
Simon Bruder 2020-06-25 13:25:47 +02:00
parent 5d3138ed2d
commit 8c8f954bbe
No known key found for this signature in database
GPG key ID: 6F03E0000CC5B62F
2 changed files with 113 additions and 86 deletions

View file

@ -3,7 +3,7 @@ use std::str::FromStr;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use clap::Clap; use clap::Clap;
use log::{debug, info, trace}; use log::{debug, info, trace, warn};
use crate::ddr::ssq; use crate::ddr::ssq;
use crate::osu::beatmap; use crate::osu::beatmap;
@ -142,25 +142,25 @@ impl ShockStepGenerator {
} }
} }
fn get_time_from_beats(beats: f32, tempo_changes: &[ssq::TempoChange]) -> Result<i32> { fn get_time_from_beats(beats: f32, tempo_changes: &[ssq::TempoChange]) -> Option<i32> {
for tempo_change in tempo_changes { for tempo_change in tempo_changes {
// For TempoChanges that are infinitely short but exactly cover that beat, use the start // For TempoChanges that are infinitely short but exactly cover that beat, use the start
// time of that TempoChange // time of that TempoChange
if (beats - tempo_change.start_beats).abs() < 0.001 if (beats - tempo_change.start_beats).abs() < 0.001
&& (beats - tempo_change.end_beats).abs() < 0.001 && (beats - tempo_change.end_beats).abs() < 0.001
{ {
return Ok(tempo_change.start_ms); return Some(tempo_change.start_ms);
} }
if beats < tempo_change.end_beats { if beats < tempo_change.end_beats {
return Ok(tempo_change.start_ms return Some(
+ ((beats - tempo_change.start_beats) * tempo_change.beat_length) as i32); tempo_change.start_ms
+ ((beats - tempo_change.start_beats) * tempo_change.beat_length) as i32,
);
} }
} }
Err(anyhow!( None
"Conversion of Step to HitObject failed: Beat lies outside of TimingPoints range"
))
} }
impl From<ssq::TempoChange> for beatmap::TimingPoint { impl From<ssq::TempoChange> for beatmap::TimingPoint {
@ -191,69 +191,93 @@ impl ssq::Step {
num_columns: u8, num_columns: u8,
tempo_changes: &ssq::TempoChanges, tempo_changes: &ssq::TempoChanges,
shock_step_generator: &mut ShockStepGenerator, shock_step_generator: &mut ShockStepGenerator,
) -> Result<Vec<beatmap::HitObject>> { ) -> Option<Vec<beatmap::HitObject>> {
let mut hit_objects = Vec::new(); let mut hit_objects = Vec::new();
match self { match self {
ssq::Step::Step { beats, row } => { ssq::Step::Step { beats, row } => {
let time = get_time_from_beats(*beats, &tempo_changes.0)?; let time = get_time_from_beats(*beats, &tempo_changes.0);
let columns: Vec<bool> = row.clone().into(); match time {
Some(time) => {
let columns: Vec<bool> = row.clone().into();
for (column, active) in columns.iter().enumerate() { for (column, active) in columns.iter().enumerate() {
if *active { if *active {
hit_objects.push(beatmap::HitObject::HitCircle { hit_objects.push(beatmap::HitObject::HitCircle {
x: beatmap::column_to_x(column as u8, num_columns), x: beatmap::column_to_x(column as u8, num_columns),
y: 192, y: 192,
time, time,
hit_sound: beatmap::HitSound { hit_sound: beatmap::HitSound {
normal: true, normal: true,
whistle: false, whistle: false,
finish: false, finish: false,
clap: false, clap: false,
}, },
new_combo: false, new_combo: false,
skip_combo_colours: 0, skip_combo_colours: 0,
hit_sample: beatmap::HitSample { hit_sample: beatmap::HitSample {
normal_set: 0, normal_set: 0,
addition_set: 0, addition_set: 0,
index: 0, index: 0,
volume: 0, volume: 0,
filename: "".to_string(), filename: "".to_string(),
}, },
}) })
}
}
}
None => {
warn!("Could not get start time of step, skipping");
return None;
} }
} }
} }
ssq::Step::Freeze { start, end, row } => { ssq::Step::Freeze { start, end, row } => {
let time = get_time_from_beats(*start, &tempo_changes.0)?; let time = get_time_from_beats(*start, &tempo_changes.0);
let end_time = get_time_from_beats(*end, &tempo_changes.0)?; let end_time = get_time_from_beats(*end, &tempo_changes.0);
let columns: Vec<bool> = row.clone().into(); match (time, end_time) {
(Some(time), Some(end_time)) => {
let columns: Vec<bool> = row.clone().into();
for (column, active) in columns.iter().enumerate() { for (column, active) in columns.iter().enumerate() {
if *active { if *active {
hit_objects.push(beatmap::HitObject::Hold { hit_objects.push(beatmap::HitObject::Hold {
column: column as u8, column: column as u8,
columns: num_columns, columns: num_columns,
time, time,
end_time, end_time,
hit_sound: beatmap::HitSound { hit_sound: beatmap::HitSound {
normal: true, normal: true,
whistle: false, whistle: false,
finish: true, finish: true,
clap: false, clap: false,
}, },
new_combo: false, new_combo: false,
skip_combo_colours: 0, skip_combo_colours: 0,
hit_sample: beatmap::HitSample { hit_sample: beatmap::HitSample {
normal_set: 0, normal_set: 0,
addition_set: 0, addition_set: 0,
index: 0, index: 0,
volume: 0, volume: 0,
filename: "".to_string(), filename: "".to_string(),
}, },
}) })
}
}
}
(None, Some(_)) => {
warn!("Could not get start time of freeze, skipping");
return None;
}
(Some(_), None) => {
warn!("Could not get end time of freeze, skipping");
return None;
}
(None, None) => {
warn!("Could not get start and end time of freeze, skipping");
return None;
} }
} }
} }
@ -288,7 +312,7 @@ impl ssq::Step {
} }
} }
Ok(hit_objects) Some(hit_objects)
} }
} }
@ -363,12 +387,13 @@ impl ssq::SSQ {
ShockStepGenerator::new(chart.difficulty.players * 4, config.shock_action.clone()); ShockStepGenerator::new(chart.difficulty.players * 4, config.shock_action.clone());
for step in &chart.steps.0 { for step in &chart.steps.0 {
trace!("Converting {:?} to hit object", step); trace!("Converting {:?} to hit object", step);
let mut step_hit_objects = step.to_hit_objects( if let Some(mut step_hit_objects) = step.to_hit_objects(
chart.difficulty.players * 4, chart.difficulty.players * 4,
&self.tempo_changes, &self.tempo_changes,
&mut shock_step_generator, &mut shock_step_generator,
)?; ) {
hit_objects.0.append(&mut step_hit_objects); hit_objects.0.append(&mut step_hit_objects);
}
} }
let converted_chart = ConvertedChart { let converted_chart = ConvertedChart {

View file

@ -1,7 +1,7 @@
use std::convert::From; use std::convert::From;
use std::fmt; use std::fmt;
use anyhow::{anyhow, Result}; use anyhow::Result;
use log::{debug, info, trace, warn}; use log::{debug, info, trace, warn};
use nom::bytes::complete::take; use nom::bytes::complete::take;
use nom::multi::many0; use nom::multi::many0;
@ -126,27 +126,29 @@ impl Steps {
continue; continue;
} }
let last_step = match Self::find_last(Self(parsed_steps.clone()), &row) {
Ok(last_step) => last_step,
Err(err) => {
warn!("Could not add freeze arrow: {}; adding normal step", err);
parsed_steps.push(Step::Step { beats, row });
continue;
}
};
if FREEZE { if FREEZE {
parsed_steps.push(Step::Freeze { match Self::find_last(Self(parsed_steps.clone()), &row) {
start: if let Step::Step { beats, .. } = parsed_steps[last_step] { Some(last_step) => {
beats parsed_steps.push(Step::Freeze {
} else { start: if let Step::Step { beats, .. } = parsed_steps[last_step]
unreachable!() {
}, beats
end: beats, } else {
row, unreachable!()
}); },
end: beats,
row,
});
parsed_steps.remove(last_step); parsed_steps.remove(last_step);
}
None => {
warn!(
"Could not find previous step for freeze, adding normal step"
);
parsed_steps.push(Step::Step { beats, row });
}
}
} else { } else {
trace!("Freeze disabled, adding normal step"); trace!("Freeze disabled, adding normal step");
parsed_steps.push(Step::Step { beats, row }); parsed_steps.push(Step::Step { beats, row });
@ -173,16 +175,16 @@ impl Steps {
Ok((input, Self(parsed_steps))) Ok((input, Self(parsed_steps)))
} }
fn find_last(steps: Self, row: &Row) -> Result<usize> { fn find_last(steps: Self, row: &Row) -> Option<usize> {
for i in (0..steps.0.len()).rev() { for i in (0..steps.0.len()).rev() {
if let Step::Step { row: step_row, .. } = &steps.0[i] { if let Step::Step { row: step_row, .. } = &steps.0[i] {
if step_row.clone().intersects(row.clone()) { if step_row.clone().intersects(row.clone()) {
return Ok(i); return Some(i);
} }
} }
} }
Err(anyhow!("No previous step found on that column")) None
} }
} }