use crate::evaluator::RuntimeError;
use crate::value::Value;
fn get_number(val: &Value) -> Result<f64, RuntimeError> {
match val {
Value::Number(n) => Ok(*n),
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Number".to_string(),
got: format!("{:?}", val),
}),
}
}
pub fn calc_attendance_rate(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let actual_days = get_number(&args[0])?;
let required_days = get_number(&args[1])?;
if required_days <= 0.0 {
return Err(RuntimeError::InvalidOperation(
"应出勤天数必须大于0".to_string(),
));
}
let rate = (actual_days / required_days).clamp(0.0, 1.0);
Ok(Value::Number(rate))
}
pub fn calc_late_deduction(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let late_count = get_number(&args[0])?;
let deduction_per_time = get_number(&args[1])?;
Ok(Value::Number(late_count * deduction_per_time))
}
pub fn calc_early_leave_deduction(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let early_leave_count = get_number(&args[0])?;
let deduction_per_time = get_number(&args[1])?;
Ok(Value::Number(early_leave_count * deduction_per_time))
}
pub fn calc_absent_deduction(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let absent_days = get_number(&args[0])?;
let daily_pay = get_number(&args[1])?;
Ok(Value::Number(absent_days * daily_pay))
}
pub fn calc_leave_deduction(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let leave_days = get_number(&args[0])?;
let daily_pay = get_number(&args[1])?;
let deduction_ratio = if args.len() > 2 {
get_number(&args[2])?
} else {
1.0 };
Ok(Value::Number(leave_days * daily_pay * deduction_ratio))
}
pub fn calc_sick_leave_pay(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 3 {
return Err(RuntimeError::WrongArity {
expected: 3,
got: args.len(),
});
}
let base_salary = get_number(&args[0])?;
let sick_days = get_number(&args[1])?;
let seniority = get_number(&args[2])?;
let ratio = if seniority < 2.0 {
0.60 } else if seniority < 4.0 {
0.70 } else if seniority < 6.0 {
0.80 } else if seniority < 8.0 {
0.90 } else {
1.00 };
let daily_pay = base_salary / 21.75;
Ok(Value::Number(daily_pay * sick_days * ratio))
}
pub fn calc_unpaid_leave_deduction(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() < 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
let base_salary = get_number(&args[0])?;
let unpaid_days = get_number(&args[1])?;
let daily_pay = base_salary / 21.75;
Ok(Value::Number(daily_pay * unpaid_days))
}