UPDATE: Adds ARABIC and ROMAN (#509)
This commit is contained in:
committed by
GitHub
parent
7f57826371
commit
e5854ab3d7
@@ -2,6 +2,7 @@ use crate::cast::NumberOrArray;
|
||||
use crate::constants::{LAST_COLUMN, LAST_ROW};
|
||||
use crate::expressions::parser::ArrayNode;
|
||||
use crate::expressions::types::CellReferenceIndex;
|
||||
use crate::functions::math_util::{from_roman, to_roman_with_form};
|
||||
use crate::number_format::to_precision;
|
||||
use crate::single_number_fn;
|
||||
use crate::{
|
||||
@@ -1376,4 +1377,92 @@ impl Model {
|
||||
}
|
||||
CalcResult::Number((x + random() * (y - x)).floor())
|
||||
}
|
||||
|
||||
pub(crate) fn fn_roman(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
||||
if args.is_empty() || args.len() > 2 {
|
||||
return CalcResult::new_args_number_error(cell);
|
||||
}
|
||||
let number = match self.get_number(&args[0], cell) {
|
||||
Ok(f) => f.floor(),
|
||||
Err(s) => return s,
|
||||
};
|
||||
|
||||
if number == 0.0 {
|
||||
return CalcResult::String(String::new());
|
||||
}
|
||||
if !(0.0..=3999.0).contains(&number) {
|
||||
return CalcResult::Error {
|
||||
error: Error::VALUE,
|
||||
origin: cell,
|
||||
message: "Number must be between 0 and 3999".to_string(),
|
||||
};
|
||||
}
|
||||
let form = if args.len() == 2 {
|
||||
let mut t = match self.get_number(&args[1], cell) {
|
||||
Ok(f) => f as i32,
|
||||
Err(s) => return s,
|
||||
};
|
||||
// If the value is a boolean TRUE/FALSE, convert to 0/4
|
||||
if t == 0 || t == 1 {
|
||||
if let CalcResult::Boolean(b) = self.evaluate_node_in_context(&args[1], cell) {
|
||||
if b {
|
||||
// classic form
|
||||
t = 0;
|
||||
} else {
|
||||
// simplified form
|
||||
t = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
t
|
||||
} else {
|
||||
0
|
||||
};
|
||||
if !(0..=4).contains(&form) {
|
||||
return CalcResult::Error {
|
||||
error: Error::VALUE,
|
||||
origin: cell,
|
||||
message: "Form must be between 0 and 4".to_string(),
|
||||
};
|
||||
}
|
||||
let roman_numeral = match to_roman_with_form(number as u32, form) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
return CalcResult::Error {
|
||||
error: Error::VALUE,
|
||||
origin: cell,
|
||||
message: format!("Could not convert to Roman numeral: {e}"),
|
||||
}
|
||||
}
|
||||
};
|
||||
CalcResult::String(roman_numeral)
|
||||
}
|
||||
|
||||
pub(crate) fn fn_arabic(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
||||
if args.len() != 1 {
|
||||
return CalcResult::new_args_number_error(cell);
|
||||
}
|
||||
let roman_numeral = match self.evaluate_node_in_context(&args[0], cell) {
|
||||
CalcResult::String(s) => s,
|
||||
error @ CalcResult::Error { .. } => return error,
|
||||
_ => {
|
||||
return CalcResult::Error {
|
||||
error: Error::VALUE,
|
||||
origin: cell,
|
||||
message: "Argument must be a text string".to_string(),
|
||||
}
|
||||
}
|
||||
};
|
||||
if roman_numeral.is_empty() {
|
||||
return CalcResult::Number(0.0);
|
||||
}
|
||||
match from_roman(&roman_numeral) {
|
||||
Ok(value) => CalcResult::Number(value as f64),
|
||||
Err(e) => CalcResult::Error {
|
||||
error: Error::VALUE,
|
||||
origin: cell,
|
||||
message: format!("Invalid Roman numeral: {e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user