fn build_chunk(
    chunk_range: &ChunkRange,
    distance: usize,
    num_parts: Rotation,
    start_stroke: Stroke,
    part_heads: &[RowBuf],
    query: &Query,
    link_set: &mut LinkSet,
) -> Chunk {
    // Add up music from each part
    let mut music = Breakdown::zero(query.music_types.len());
    for ph in part_heads {
        if let Some(source_ch) = chunk_range.chunk_id.course_head() {
            let ch = ph * source_ch;
            // Count weight from this part
            music += &Breakdown::from_rows(
                chunk_range.untransposed_rows(&query.layout),
                &ch,
                &query.music_types,
                start_stroke,
            );
            // Count weight from CH masks
            for (mask, weight) in &query.ch_weights {
                if mask.matches(&ch) {
                    // Weight applies to each row
                    music.score += *weight * chunk_range.per_part_length.0 as f32;
                }
            }
        }
    }

    // Determine if this chunk is (not) a duffer.  A chunk is a duffer it doesn't include any music
    // of types considered 'non-duffer'.
    //
    // TODO: Determine how close to the ends of this chunk the music is generated?
    let non_duffer = query
        .music_types
        .iter()
        .zip_eq(music.counts.as_slice())
        .any(|(music_type, count)| music_type.non_duffer() && *count > 0);

    let successors = chunk_range
        .links()
        .iter()
        .cloned()
        .map(|(source_idx, to, rotation)| {
            assert!(rotation < num_parts);
            link_set.add(Link {
                from: chunk_range.chunk_id.clone(),
                to,
                source_idx,
                rotation,
                rotation_back: num_parts - rotation,
            })
        })
        .collect_vec();

    Chunk {
        per_part_length: chunk_range.per_part_length,
        total_length: chunk_range.total_length,

        is_start: chunk_range.chunk_id.is_start(),
        end: chunk_range.end(),
        label: chunk_range.label.clone(),

        method_counts: chunk_range.method_counts.clone(),
        music,

        duffer: !non_duffer,
        // Distances will be computed during optimisation passes
        lb_distance_from_non_duffer: 0,
        lb_distance_to_non_duffer: 0,

        required: false,
        lb_distance_from_rounds: distance,
        // Distances to rounds are computed later, but the distance is an lower bound,
        // so we can set it to 0 without breaking any invariants.
        lb_distance_to_rounds: 0,

        successors,

        // These are populated in separate passes once all the `Chunk`s have been created
        false_chunks: Vec::new(),
        predecessors: Vec::new(),
    }
}
/// Construct a [`Chunk`] from the data returned by the `RangeFactory`.  This is mostly
/// unpacking/repacking data, but also involves computing music and 'dufferness'.
Construct a [`Chunk`] from the data returned by the `RangeFactory`.  This is mostly
unpacking/repacking data, but also involves computing music and 'dufferness'.
Construct a [ ` Chunk ` ] from the data returned by the ` RangeFactory ` . This is mostly unpacking / repacking data but also involves computing music and ' dufferness ' .
fn build_chunk(
    chunk_range: &ChunkRange,
    distance: usize,
    num_parts: Rotation,
    start_stroke: Stroke,
    part_heads: &[RowBuf],
    query: &Query,
    link_set: &mut LinkSet,
) -> Chunk {
    // Add up music from each part
    let mut music = Breakdown::zero(query.music_types.len());
    for ph in part_heads {
        if let Some(source_ch) = chunk_range.chunk_id.course_head() {
            let ch = ph * source_ch;
            // Count weight from this part
            music += &Breakdown::from_rows(
                chunk_range.untransposed_rows(&query.layout),
                &ch,
                &query.music_types,
                start_stroke,
            );
            // Count weight from CH masks
            for (mask, weight) in &query.ch_weights {
                if mask.matches(&ch) {
                    // Weight applies to each row
                    music.score += *weight * chunk_range.per_part_length.0 as f32;
                }
            }
        }
    }
    // Determine if this chunk is (not) a duffer.  A chunk is a duffer it doesn't include any music
    // of types considered 'non-duffer'.
    //
    // TODO: Determine how close to the ends of this chunk the music is generated?
    let non_duffer = query
        .music_types
        .iter()
        .zip_eq(music.counts.as_slice())
        .any(|(music_type, count)| music_type.non_duffer() && *count > 0);
    let successors = chunk_range
        .links()
        .iter()
        .cloned()
        .map(|(source_idx, to, rotation)| {
            assert!(rotation < num_parts);
            link_set.add(Link {
                from: chunk_range.chunk_id.clone(),
                to,
                source_idx,
                rotation,
                rotation_back: num_parts - rotation,
            })
        })
        .collect_vec();
    Chunk {
        per_part_length: chunk_range.per_part_length,
        total_length: chunk_range.total_length,
        is_start: chunk_range.chunk_id.is_start(),
        end: chunk_range.end(),
        label: chunk_range.label.clone(),
        method_counts: chunk_range.method_counts.clone(),
        music,
        duffer: !non_duffer,
        // Distances will be computed during optimisation passes
        lb_distance_from_non_duffer: 0,
        lb_distance_to_non_duffer: 0,
        required: false,
        lb_distance_from_rounds: distance,
        // Distances to rounds are computed later, but the distance is an lower bound,
        // so we can set it to 0 without breaking any invariants.
        lb_distance_to_rounds: 0,
        successors,
        // These are populated in separate passes once all the `Chunk`s have been created
        false_chunks: Vec::new(),
        predecessors: Vec::new(),
    }
}
fn build_chunk ( chunk_range : & ChunkRange , distance : usize , num_parts : Rotation , start_stroke : Stroke , part_heads : & [ RowBuf ] , query : & Query , link_set : & mut LinkSet , ) -> Chunk { // Add up music from each part let mut music = Breakdown :: zero ( query . music_types . len ( ) ) ; for ph in part_heads { if let Some ( source_ch ) = chunk_range . chunk_id . course_head ( ) { let ch = ph * source_ch ; // Count weight from this part music += & Breakdown :: from_rows ( chunk_range . untransposed_rows ( & query . layout ) , & ch , & query . music_types , start_stroke , ) ; // Count weight from CH masks for ( mask , weight ) in & query . ch_weights { if mask . matches ( & ch ) { // Weight applies to each row music . score += * weight * chunk_range . per_part_length . 0 as f32 ; } } } } // Determine if this chunk is (not) a duffer.  A chunk is a duffer it doesn't include any music // of types considered 'non-duffer'. // // TODO: Determine how close to the ends of this chunk the music is generated? let non_duffer = query . music_types . iter ( ) . zip_eq ( music . counts . as_slice ( ) ) . any ( | ( music_type , count ) | music_type . non_duffer ( ) && * count > 0 ) ; let successors = chunk_range . links ( ) . iter ( ) . cloned ( ) . map ( | ( source_idx , to , rotation ) | { assert ! ( rotation num_parts ) ; link_set . add ( Link { from : chunk_range . chunk_id . clone ( ) , to , source_idx , rotation , rotation_back : num_parts - rotation , } ) } ) . collect_vec ( ) ; Chunk { per_part_length : chunk_range . per_part_length , total_length : chunk_range . total_length , is_start : chunk_range . chunk_id . is_start ( ) , end : chunk_range . end ( ) , label : chunk_range . label . clone ( ) , method_counts : chunk_range . method_counts . clone ( ) , music , duffer : ! non_duffer , // Distances will be computed during optimisation passes lb_distance_from_non_duffer : 0 , lb_distance_to_non_duffer : 0 , required : false , lb_distance_from_rounds : distance , // Distances to rounds are computed later, but the distance is an lower bound, // so we can set it to 0 without breaking any invariants. lb_distance_to_rounds : 0 , successors , // These are populated in separate passes once all the `Chunk`s have been created false_chunks : Vec :: new ( ) , predecessors : Vec :: new ( ) , } }
Construct a [`Chunk`] from the data returned by the `RangeFactory`.
Construct a [ ` Chunk ` ] from the data returned by the ` RangeFactory ` .
chunk_range
&ChunkRange
distance
usize
num_parts
Rotation
start_stroke
Stroke
part_heads
&[RowBuf]
query
&Query
link_set
&mut LinkSet
chunk_range
&ChunkRange
distance
usize
num_parts
Rotation
start_stroke
Stroke
part_heads
&[RowBuf]
query
&Query
link_set
&mut LinkSet