#![allow(mixed_script_confusables)]
use std::io::{Read, Seek};
use calamine::Reader;
#[derive(Debug)]
pub struct Range {
pub from: (u8, u8, u16),
pub to: (u8, u8, u16),
}
#[derive(Debug)]
pub enum Rate {
F1,
F2,
F3,
}
#[derive(Debug)]
pub struct Rates {
pub validity: Range,
pub pe_single_rate: f32,
pub pe: [(Rate, f32); 3],
pub pd: f32,
pub pcv: f32,
pub disp_bt: f32,
pub ppe: f32,
pub σ1: f32,
pub σ2: f32,
pub σ3: f32,
pub uc3: f32,
pub uc6: [f32; 2],
pub asos: f32,
pub arim: f32,
}
fn load_households_generic_wb<R: Read + Seek>(reader: R, offset: u8) -> Vec<Rates> {
let mut workbook: calamine::Xls<R> = calamine::Xls::new(reader).expect("Could not parse file");
let sheets: Vec<_> = workbook.sheet_names().into_iter().collect();
sheets
.into_iter()
.map(|x| {
load_households_generic_sheet(
workbook.worksheet_range(&x).expect("Sheet not found"),
offset,
)
})
.filter(|x| x.validity.from.2 >= 2018)
.collect()
}
fn value_to_float(v: &calamine::Data) -> f32 {
match v {
calamine::Data::Float(x) => *x as f32,
_ => panic!("Trying to convert {:?} to float...", v),
}
}
fn value_to_string(v: &calamine::Data) -> String {
match v {
calamine::Data::String(x) => x.clone(),
_ => panic!("Trying to convert {:?} to float...", v),
}
}
fn month_to_number(month: &str) -> u8 {
match month {
"gennaio" => 1,
"febbraio" => 2,
"marzo" => 3,
"aprile" => 4,
"maggio" => 5,
"giugno" => 6,
"luglio" => 7,
"agosto" => 8,
"settembre" => 9,
"ottobre" => 10,
"novembre" => 11,
"dicembre" => 12,
_ => 0,
}
}
fn load_households_generic_sheet(sheet: calamine::Range<calamine::Data>, offset: u8) -> Rates {
let row = offset as usize + 18
- if let calamine::Data::Float(_) = sheet.get((offset as usize + 18, 1)).unwrap() {
0
} else {
1
};
let row_offset = if let calamine::Data::Empty = sheet.get((row + 1, 5)).unwrap() {
2
} else {
1
};
let range_string = value_to_string(sheet.get((row - 3, 0)).expect("Failed to extract date"));
let mut splitted = range_string.split(' ');
let starting_day = splitted.next().unwrap().parse::<u8>().unwrap();
let starting_month = splitted.next().map(month_to_number).unwrap();
splitted.next();
let ending_day = splitted.next().unwrap().parse::<u8>().unwrap();
let ending_month = splitted.next().map(month_to_number).unwrap();
let year = splitted.next().unwrap().parse::<u16>().unwrap();
Rates {
validity: Range {
from: (starting_day, starting_month, year),
to: (ending_day, ending_month, year),
},
pe_single_rate: value_to_float(sheet.get((row, 1)).expect("Failed to parse field")),
pe: [
(
Rate::F1,
value_to_float(sheet.get((row, 2)).expect("Failed to parse field")),
),
(
Rate::F2,
value_to_float(sheet.get((row, 3)).expect("Failed to parse field")),
),
(
Rate::F3,
value_to_float(sheet.get((row, 3)).expect("Failed to parse field")),
),
],
pd: value_to_float(sheet.get((row, 4)).expect("Failed to parse field")),
pcv: value_to_float(
sheet
.get((row + row_offset, 5))
.expect("Failed to parse field"),
),
disp_bt: value_to_float(
sheet
.get((row + row_offset, 6))
.expect("Failed to parse field"),
),
ppe: value_to_float(sheet.get((row, 7)).expect("Failed to parse field")),
σ1: value_to_float(
sheet
.get((row + row_offset, 11))
.expect("Failed to parse field"),
),
σ2: value_to_float(
sheet
.get((row + row_offset + 1, 12))
.expect("Failed to parse field"),
),
σ3: value_to_float(sheet.get((row, 13)).expect("Failed to parse field")),
uc3: value_to_float(sheet.get((row, 14)).expect("Failed to parse field")),
uc6: [
value_to_float(sheet.get((row, 15)).expect("Failed to parse field")),
value_to_float(
sheet
.get((row + row_offset + 1, 15))
.expect("Failed to parse field"),
),
],
asos: value_to_float(sheet.get((row, 17)).expect("Failed to parse field")),
arim: value_to_float(sheet.get((row, 18)).expect("Failed to parse field")),
}
}
pub fn load_first_household_rates<R: Read + Seek>(reader: R) -> Vec<Rates> {
load_households_generic_wb(reader, 0)
}
#[cfg(test)]
mod tests {}