fn parse_zip_election_file(zipfile : File, metadata:ElectionMetadata, reject_vote_type : Option<HashSet<String>>, mayoral: bool) -> anyhow::Result<ElectionData> {
    let mut zipfile = zip::ZipArchive::new(zipfile)?;
    let zip_contents = zipfile.by_index(0)?;
    let mut reader = csv::ReaderBuilder::new().delimiter(b'\t').from_reader(zip_contents);
    let headings = reader.headers()?;
    let find_col = |heading_name:&str|headings.iter().position(|s|s==heading_name).ok_or_else(||anyhow!("Could not find {} column",heading_name));
    let vote_type_column = find_col("VoteType")?;
    let paper_id_column = find_col("VCBallotPaperID")?;
    let preference_number_column = find_col("PreferenceNumber")?; // if formal, the number written
    let candidate_name_column = find_col("CandidateName")?; // if BTL, the candidate name
    let group_column = if mayoral {0} else {find_col("GroupCode")?}; // Not applicable for mayoral.
    let mut helper = PreferencesComingOutOfOrderHelper::default();
    let candidate_name_lookup = metadata.get_candidate_name_lookup();
    let group_id_lookup = metadata.get_party_id_lookup();
    for record in reader.records() {
        let record = record?;
        helper.set_current_paper(&record[paper_id_column]);
        let preference = &record[preference_number_column];
        if !preference.is_empty() { // part of a formal vote
            let vote_type = &record[vote_type_column];
            helper.set_vote_type(vote_type);
            if let Some(restrictions) = reject_vote_type.as_ref() {
                if restrictions.contains(vote_type) { continue }
            }
            let preference : usize = preference.parse()?;
            let candidate_name = &record[candidate_name_column];
            if candidate_name.is_empty() { // ATL vote
                let group_id = &record[group_column];
                let party = *group_id_lookup.get(group_id).ok_or_else(||anyhow!("Unknown group id {}",group_id))?;
                helper.add_atl_pref(preference,party)?;
            } else { // BTL vote
                let candidate = *candidate_name_lookup.get(candidate_name).ok_or_else(||anyhow!("Unknown candidate name {}",candidate_name))?;
                helper.add_btl_pref(preference,candidate)?;
            }
        }
    }
    Ok(helper.done(metadata))
}
/// Parse the zipped election file.
/// The function currently ignores non-formal markings.
/// Optionally, some particular vote types can be suppressed.
Parse the zipped election file.
The function currently ignores non-formal markings.
Optionally, some particular vote types can be suppressed.
Parse the zipped election file . The function currently ignores non - formal markings . Optionally some particular vote types can be suppressed .
fn parse_zip_election_file(zipfile : File, metadata:ElectionMetadata, reject_vote_type : Option<HashSet<String>>, mayoral: bool) -> anyhow::Result<ElectionData> {
    let mut zipfile = zip::ZipArchive::new(zipfile)?;
    let zip_contents = zipfile.by_index(0)?;
    let mut reader = csv::ReaderBuilder::new().delimiter(b'\t').from_reader(zip_contents);
    let headings = reader.headers()?;
    let find_col = |heading_name:&str|headings.iter().position(|s|s==heading_name).ok_or_else(||anyhow!("Could not find {} column",heading_name));
    let vote_type_column = find_col("VoteType")?;
    let paper_id_column = find_col("VCBallotPaperID")?;
    let preference_number_column = find_col("PreferenceNumber")?; // if formal, the number written
    let candidate_name_column = find_col("CandidateName")?; // if BTL, the candidate name
    let group_column = if mayoral {0} else {find_col("GroupCode")?}; // Not applicable for mayoral.
    let mut helper = PreferencesComingOutOfOrderHelper::default();
    let candidate_name_lookup = metadata.get_candidate_name_lookup();
    let group_id_lookup = metadata.get_party_id_lookup();
    for record in reader.records() {
        let record = record?;
        helper.set_current_paper(&record[paper_id_column]);
        let preference = &record[preference_number_column];
        if !preference.is_empty() { // part of a formal vote
            let vote_type = &record[vote_type_column];
            helper.set_vote_type(vote_type);
            if let Some(restrictions) = reject_vote_type.as_ref() {
                if restrictions.contains(vote_type) { continue }
            }
            let preference : usize = preference.parse()?;
            let candidate_name = &record[candidate_name_column];
            if candidate_name.is_empty() { // ATL vote
                let group_id = &record[group_column];
                let party = *group_id_lookup.get(group_id).ok_or_else(||anyhow!("Unknown group id {}",group_id))?;
                helper.add_atl_pref(preference,party)?;
            } else { // BTL vote
                let candidate = *candidate_name_lookup.get(candidate_name).ok_or_else(||anyhow!("Unknown candidate name {}",candidate_name))?;
                helper.add_btl_pref(preference,candidate)?;
            }
        }
    }
    Ok(helper.done(metadata))
}
fn parse_zip_election_file ( zipfile : File , metadata : ElectionMetadata , reject_vote_type : Option < HashSet < String > > , mayoral : bool ) -> anyhow :: Result < ElectionData > { let mut zipfile = zip :: ZipArchive :: new ( zipfile ) ? ; let zip_contents = zipfile . by_index ( 0 ) ? ; let mut reader = csv :: ReaderBuilder :: new ( ) . delimiter ( b'\t' ) . from_reader ( zip_contents ) ; let headings = reader . headers ( ) ? ; let find_col = | heading_name : & str | headings . iter ( ) . position ( | s | s == heading_name ) . ok_or_else ( | | anyhow ! ( " " heading_name ) ) ; let vote_type_column = find_col ( " " ) ? ; let paper_id_column = find_col ( " " ) ? ; let preference_number_column = find_col ( " " ) ? ; // if formal, the number written let candidate_name_column = find_col ( " " ) ? ; // if BTL, the candidate name let group_column = if mayoral { 0 } else { find_col ( " " ) ? } ; // Not applicable for mayoral. let mut helper = PreferencesComingOutOfOrderHelper :: default ( ) ; let candidate_name_lookup = metadata . get_candidate_name_lookup ( ) ; let group_id_lookup = metadata . get_party_id_lookup ( ) ; for record in reader . records ( ) { let record = record ? ; helper . set_current_paper ( & record [ paper_id_column ] ) ; let preference = & record [ preference_number_column ] ; if ! preference . is_empty ( ) { // part of a formal vote let vote_type = & record [ vote_type_column ] ; helper . set_vote_type ( vote_type ) ; if let Some ( restrictions ) = reject_vote_type . as_ref ( ) { if restrictions . contains ( vote_type ) { continue } } let preference : usize = preference . parse ( ) ? ; let candidate_name = & record [ candidate_name_column ] ; if candidate_name . is_empty ( ) { // ATL vote let group_id = & record [ group_column ] ; let party = * group_id_lookup . get ( group_id ) . ok_or_else ( | | anyhow ! ( " " group_id ) ) ? ; helper . add_atl_pref ( preference , party ) ? ; } else { // BTL vote let candidate = * candidate_name_lookup . get ( candidate_name ) . ok_or_else ( | | anyhow ! ( " " candidate_name ) ) ? ; helper . add_btl_pref ( preference , candidate ) ? ; } } } Ok ( helper . done ( metadata ) ) }
Parse the zipped election file.
Parse the zipped election file .
zipfile
File
metadata
ElectionMetadata
reject_vote_type
Option<HashSet<String>>
mayoral
bool
zipfile
File
metadata
ElectionMetadata
reject_vote_type
Option<HashSet<String>>
mayoral
bool