1use std::{ops::Range, fmt::Display};
2use error_stack::{Report, IntoReport};
3use gcollections::ops::{Intersection, Union, Bounded};
4use interval::{IntervalSet, interval_set::ToIntervalSet};
5use klavier_helper::store::Store;
6use crate::{bar::{Bar, VarIndex, Repeat}, rhythm::Rhythm, have_start_tick::HaveBaseStartTick, global_repeat::{GlobalRepeat, RenderRegionWarning, GlobalRepeatBuilder}};
7
8pub type AccumTick = u32;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct Chunk {
13 start_tick: u32,
14 end_tick: u32,
15}
16
17impl Chunk {
18 pub fn new(start_tick: u32, end_tick: u32) -> Self {
19 Self {
20 start_tick, end_tick
21 }
22 }
23
24 pub fn start_tick(self) -> u32 {
25 self.start_tick
26 }
27
28 pub fn end_tick(self) -> u32 {
29 self.end_tick
30 }
31
32 pub fn optimize(chunks: &[Chunk]) -> Vec<Chunk> {
33 let mut ret: Vec<Chunk> = vec![];
34 let mut z = chunks.iter();
35 let mut cur = match z.next() {
36 None => return ret,
37 Some(c) => *c,
38 };
39
40 for next in z {
41 if cur.end_tick == next.start_tick {
42 cur.end_tick = next.end_tick;
43 } else {
44 ret.push(cur);
45 cur = *next;
46 }
47 }
48
49 ret.push(cur);
50 ret
51 }
52
53 pub fn contains(self, tick: u32) -> bool {
54 self.start_tick <= tick && tick < self.end_tick
55 }
56
57 pub fn len(self) -> u32 {
58 self.end_tick - self.start_tick()
59 }
60
61 pub fn is_empty(self) -> bool {
62 self.start_tick == self.end_tick
63 }
64
65 pub fn by_accum_tick(chunks: &[Chunk]) -> Store<AccumTick, Chunk, ()> {
66 let mut offset: u32 = 0;
67 let mut buf: Store<AccumTick, Chunk, ()> = Store::new(false);
68
69 for c in chunks {
70 buf.add(offset, *c, ());
71 if c.end_tick() != u32::MAX {
72 offset += c.len();
73 }
74 }
75
76 buf
77 }
78}
79
80pub trait Region: std::fmt::Debug {
81 fn to_chunks(&self) -> Vec<Chunk>;
82}
83
84#[derive(Debug, Clone, PartialEq)]
85enum RenderPhase {
86 NonDcDs,
87 DcDsIter0 { dc_ds_tick: u32 },
88 DcDsIter1 { global_repeat: GlobalRepeat },
89}
90
91trait SimpleRegion: Region {
93 fn render_chunks(&self, phase: &RenderPhase) -> Vec<Chunk>;
94 fn to_iter1_chunks(&self, global_repeat: &GlobalRepeat) -> Vec<Chunk>;
95}
96
97#[derive(Debug, PartialEq, Eq)]
98pub struct SequenceRegion {
99 tick_range: Range<u32>,
100}
101
102impl SequenceRegion {
103 #[inline]
104 #[allow(dead_code)]
105 fn tick_len(&self) -> u32 {
106 self.tick_range.len() as u32
107 }
108
109 #[inline]
110 fn start_tick(&self) -> u32 {
111 self.tick_range.start
112 }
113
114 #[inline]
116 fn end_tick(&self) -> u32 {
117 self.tick_range.end
118 }
119
120 fn to_iter1_interval_set(&self) -> IntervalSet<u32> {
121 (self.tick_range.start, self.tick_range.end - 1).to_interval_set()
122 }
123}
124
125impl Region for SequenceRegion {
126 fn to_chunks(&self) -> Vec<Chunk> {
127 self.render_chunks(&RenderPhase::NonDcDs)
128 }
129}
130
131impl SimpleRegion for SequenceRegion {
132 fn render_chunks(&self, phase: &RenderPhase) -> Vec<Chunk> {
133 match phase {
134 RenderPhase::NonDcDs => vec![Chunk { start_tick: self.start_tick(), end_tick: self.end_tick() }],
135 RenderPhase::DcDsIter0 { dc_ds_tick } => {
136 if self.end_tick() <= *dc_ds_tick {
137 vec![Chunk::new(self.start_tick(), self.end_tick())]
138 } else if self.start_tick() < *dc_ds_tick && *dc_ds_tick < self.end_tick() {
139 vec![Chunk::new(self.start_tick(), *dc_ds_tick)]
140 } else {
141 vec![]
142 }
143 }
144 RenderPhase::DcDsIter1 { global_repeat } => {
145 self.to_iter1_chunks(global_repeat)
146 }
147 }
148 }
149
150 fn to_iter1_chunks(&self, global_repeat: &GlobalRepeat) -> Vec<Chunk> {
151 let sections: IntervalSet<u32> = global_repeat.iter1_interval_set().clone().intersection(
152 &self.to_iter1_interval_set()
153 );
154
155 sections.into_iter().map(|sec| {
156 Chunk::new(sec.lower(), sec.upper() + 1)
157 }).collect()
158 }
159}
160
161#[derive(Debug, PartialEq, Eq)]
162pub struct RepeatRegion {
163 region: SequenceRegion,
164}
165
166impl RepeatRegion {
167 fn to_iter1_interval_set(&self) -> IntervalSet<u32> {
168 (self.region.start_tick(), self.region.end_tick() - 1).to_interval_set()
169 }
170}
171
172impl Region for RepeatRegion {
173 fn to_chunks(&self) -> Vec<Chunk> {
174 self.render_chunks(&RenderPhase::NonDcDs)
175 }
176}
177
178impl SimpleRegion for RepeatRegion {
179 fn render_chunks(&self, phase: &RenderPhase) -> Vec<Chunk> {
180 fn full(sr: &RepeatRegion) -> Vec<Chunk> {
181 let mut chunks = Vec::with_capacity(2);
182 chunks.extend(sr.region.to_chunks());
183 chunks.extend(sr.region.to_chunks());
184 chunks
185 }
186
187 match phase {
188 RenderPhase::NonDcDs => full(self),
189 RenderPhase::DcDsIter0 { dc_ds_tick } => {
190 if self.region.end_tick() <= *dc_ds_tick {
191 full(self)
192 } else if self.region.end_tick() < *dc_ds_tick && *dc_ds_tick < self.region.end_tick() {
193 panic!("Logic error.");
195 } else {
196 vec![]
197 }
198 },
199 RenderPhase::DcDsIter1 { global_repeat } => {
200 self.to_iter1_chunks(global_repeat)
201 }
202 }
203 }
204
205 fn to_iter1_chunks(&self, global_repeat: &GlobalRepeat) -> Vec<Chunk> {
206 let sections: IntervalSet<u32> = global_repeat.iter1_interval_set().clone().intersection(
207 &self.to_iter1_interval_set()
208 );
209
210 sections.into_iter().map(|sec| {
211 Chunk::new(sec.lower(), sec.upper() + 1)
212 }).collect()
213 }
214}
215
216#[derive(Debug)]
217pub struct VariationRegion {
218 common: SequenceRegion,
219 variations: Vec<SequenceRegion>,
220}
221
222impl VariationRegion {
223 fn end_tick(&self) -> u32 {
224 self.variations.last().unwrap().end_tick()
225 }
226}
227
228impl VariationRegion {
229 fn last_variation(&self) -> &SequenceRegion {
230 &self.variations[self.variations.len() - 1]
231 }
232
233 fn to_iter1_interval_set(&self) -> IntervalSet<u32> {
234 self.common.to_iter1_interval_set().union(
235 &self.last_variation().to_iter1_interval_set()
236 )
237 }
238}
239
240impl Region for VariationRegion {
241 fn to_chunks(&self) -> Vec<Chunk> {
242 self.render_chunks(&RenderPhase::NonDcDs)
243 }
244}
245
246impl SimpleRegion for VariationRegion {
247 fn render_chunks(&self, phase: &RenderPhase) -> Vec<Chunk> {
248 fn full(vr: &VariationRegion) -> Vec<Chunk> {
249 let mut chunks = vec![];
250 let common = vr.common.to_chunks();
251 for v in vr.variations.iter() {
252 chunks.extend(common.clone());
253 chunks.extend(v.to_chunks());
254 }
255
256 chunks
257 }
258
259 match phase {
260 RenderPhase::NonDcDs => full(self),
261 RenderPhase::DcDsIter0 { dc_ds_tick } => {
262 if *dc_ds_tick <= self.common.start_tick() {
263 vec![]
264 } else if *dc_ds_tick < self.end_tick() {
265 panic!("Logic error");
267 } else {
268 full(self)
269 }
270 },
271 RenderPhase::DcDsIter1 { global_repeat } => {
272 self.to_iter1_chunks(global_repeat)
273 }
274 }
275 }
276
277 fn to_iter1_chunks(&self, global_repeat: &GlobalRepeat) -> Vec<Chunk> {
278 let sections: IntervalSet<u32> = global_repeat.iter1_interval_set().clone().intersection(
279 &self.to_iter1_interval_set()
280 );
281
282 sections.into_iter().map(|sec| {
283 Chunk::new(sec.lower(), sec.upper() + 1)
284 }).collect()
285 }
286}
287
288#[derive(Debug)]
289pub struct CompoundRegion {
290 global_repeat: Option<GlobalRepeat>,
291 regions: Vec<Box<dyn SimpleRegion>>,
292}
293
294impl Region for CompoundRegion {
295 fn to_chunks(&self) -> Vec<Chunk> {
296 match self.global_repeat.as_ref() {
297 Some(gr) => {
298 let mut chunks = vec![];
299 for r in self.regions.iter() {
300 chunks.extend(r.render_chunks(&RenderPhase::DcDsIter0 { dc_ds_tick: gr.ds_dc().tick() }));
301 }
302 for r in self.regions.iter() {
303 chunks.extend(r.render_chunks(&RenderPhase::DcDsIter1 { global_repeat: gr.clone() } ));
304 }
305
306 chunks
307 }
308 None => {
309 let mut chunks = vec![];
310 for r in self.regions.iter() {
311 chunks.extend(r.render_chunks(&RenderPhase::NonDcDs));
312 }
313
314 chunks
315 }
316 }
317 }
318}
319
320#[derive(Debug)]
321enum RenderRegionState {
322 Idle,
323 Seq { start_tick: u32 },
324 RepeatStart { start_tick: u32 },
325 Variation {
326 start_tick: u32,
327 region_start_ticks: Vec<u32>,
328 },
329}
330
331#[derive(Debug, PartialEq, Eq, Clone)]
332pub enum RenderRegionError {
333 DuplicatedRepeatStart { tick: u32 },
334 DuplicatedSegno { tick: [u32; 2] },
335 DuplicatedDsDc { tick: [u32; 2] },
336 DuplicatedFine { tick: [u32; 2] },
337 OrphanRepeatEnd { tick: u32 },
338 FineWithoutDsDc { tick: u32 },
339 SegnoWithoutDs { tick: u32 },
340 CodaWithoutDsDc { tick: [u32; 2]},
341 NoRepeatEnd { tick: u32 },
342 InvalidRegionIndex { tick: u32, actual: VarIndex, expected: VarIndex },
343 RepeatInVariation { tick: u32 },
344 VariationNotClosed { tick: u32 },
345 RepeatOrVariationOnDc { tick: u32 },
346 RepeatOrVariationOnDs { tick: u32 },
347 FineNotAfterSegno { segno_tick: u32, fine_tick: u32 },
348 NoSegnoForDs { ds_tick: u32 },
349 MoreThanTwoCodas { tick: [u32; 3] },
350 OnlyOneCoda { tick: u32 },
351 DcDsWhileRepeat { tick: u32 },
352 DcDsWhileVariation { tick: u32 },
353 SegnoWhildVariation { tick: u32 },
354 CodaAfterFine { coda_from: u32, coda_to: u32, fine: u32 },
355}
356
357impl core::error::Error for RenderRegionError {}
358
359impl Display for RenderRegionError {
360 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
361 write!(f, "{:?}", self)
362 }
363}
364
365type RenderRegionResult = Result<(Box<dyn Region>, Vec<RenderRegionWarning>), Report<RenderRegionError>>;
366
367pub fn render_region<'a>(
368 tune_rhythm: Rhythm, bars: impl Iterator<Item = &'a Bar>
369) -> RenderRegionResult {
370 fn create_variation(start_tick: u32, region_start_ticks: Vec<u32>, end_tick: u32) -> Box<dyn SimpleRegion> {
371 let mut variations: Vec<SequenceRegion> = vec![];
372 let mut iter = region_start_ticks.iter();
373 let mut tick = *iter.next().unwrap();
374 for t in iter {
375 variations.push(SequenceRegion { tick_range: tick..*t });
376 tick = *t;
377 }
378
379 variations.push(SequenceRegion { tick_range: tick..end_tick });
380
381 Box::new(VariationRegion {
382 common: SequenceRegion { tick_range: start_tick..region_start_ticks[0] }, variations
383 })
384 }
385
386 let mut regions: Vec<Box<dyn SimpleRegion>> = vec![];
387 let mut state = RenderRegionState::Idle;
388 let mut is_auftakt: Option<bool> = None;
389 let mut global_repeat: GlobalRepeatBuilder = GlobalRepeatBuilder::new(tune_rhythm);
390
391 for bar in bars {
392 global_repeat = global_repeat.on_bar(bar)?;
393 if is_auftakt.is_none() && bar.base_start_tick() != 0 {
394 is_auftakt = Some(bar.base_start_tick() < tune_rhythm.tick_len());
395 }
396
397 state = match &state {
398 RenderRegionState::Idle => {
399 if bar.repeats.contains(Repeat::Start) && bar.repeats.contains(Repeat::End) {
400 regions.push(Box::new(RepeatRegion { region: SequenceRegion { tick_range: 0..bar.base_start_tick() }}));
401 RenderRegionState::RepeatStart { start_tick: bar.base_start_tick() }
402 } else if bar.repeats.contains(Repeat::End) {
403 regions.push(Box::new(RepeatRegion { region: SequenceRegion { tick_range: 0..bar.base_start_tick() }}));
404 RenderRegionState::Seq { start_tick: bar.base_start_tick() }
405 } else if bar.repeats.contains(Repeat::Start) {
406 regions.push(Box::new(SequenceRegion { tick_range: 0..bar.base_start_tick() }));
407 RenderRegionState::RepeatStart { start_tick: bar.base_start_tick() }
408 } else if let Some(idx) = bar.repeats.region_index() {
409 if idx != VarIndex::VI1 {
410 return Err(IntoReport::into_report(RenderRegionError::InvalidRegionIndex { tick: bar.base_start_tick(), actual: idx, expected: VarIndex::VI1 }));
411 }
412 RenderRegionState::Variation { start_tick: 0, region_start_ticks: vec![bar.base_start_tick()] }
413 } else {
414 state
415 }
416 },
417 RenderRegionState::Seq { start_tick } => {
418 if bar.repeats.contains(Repeat::End) {
419 return Err(IntoReport::into_report(RenderRegionError::OrphanRepeatEnd{ tick: bar.base_start_tick() }));
420 } else if bar.repeats.contains(Repeat::Start) {
421 regions.push(Box::new(SequenceRegion { tick_range: *start_tick..bar.base_start_tick() }));
422 RenderRegionState::RepeatStart { start_tick: bar.base_start_tick() }
423 } else {
424 state
425 }
426 },
427 RenderRegionState::RepeatStart { start_tick } => {
428 if bar.repeats.contains(Repeat::Start) && bar.repeats.contains(Repeat::End) {
429 regions.push(Box::new(RepeatRegion { region: SequenceRegion { tick_range: *start_tick..bar.base_start_tick() }}));
430 RenderRegionState::RepeatStart { start_tick: bar.base_start_tick() }
431 } else if bar.repeats.contains(Repeat::End) {
432 regions.push(Box::new(RepeatRegion { region: SequenceRegion { tick_range: *start_tick..bar.base_start_tick() }}));
433 RenderRegionState::Seq { start_tick: bar.base_start_tick() }
434 } else if bar.repeats.contains(Repeat::Start) {
435 return Err(IntoReport::into_report(RenderRegionError::DuplicatedRepeatStart { tick: bar.base_start_tick() }));
436 } else if bar.repeats.contains(Repeat::Dc) || bar.repeats.contains(Repeat::Ds) {
437 return Err(IntoReport::into_report(RenderRegionError::DcDsWhileRepeat { tick: bar.base_start_tick() }));
438 } else if let Some(idx) = bar.repeats.region_index() {
439 if idx != VarIndex::VI1 {
440 return Err(IntoReport::into_report(RenderRegionError::InvalidRegionIndex { tick: bar.base_start_tick(), actual: idx, expected: VarIndex::VI1 }));
441 }
442 RenderRegionState::Variation { start_tick: *start_tick, region_start_ticks: vec![bar.base_start_tick()] }
443 } else {
444 state
445 }
446 },
447 RenderRegionState::Variation { start_tick, region_start_ticks } => {
448 if bar.repeats.contains(Repeat::End) {
449 return Err(IntoReport::into_report(RenderRegionError::RepeatInVariation { tick: bar.base_start_tick() }))
450 } else if let Some(ri) = bar.repeats.region_index() {
451 if bar.repeats.contains(Repeat::Dc) || bar.repeats.contains(Repeat::Ds) {
452 return Err(IntoReport::into_report(RenderRegionError::DcDsWhileVariation { tick: bar.base_start_tick() }));
453 }
454 let current_idx = region_start_ticks.len() as u8;
455 let idx = ri.value();
456 if idx == current_idx {
457 state
458 } else if idx == current_idx + 1 {
459 let mut rst = region_start_ticks.clone();
460 rst.push(bar.base_start_tick());
461 RenderRegionState::Variation { start_tick: *start_tick, region_start_ticks: rst }
462 } else {
463 return Err(IntoReport::into_report(RenderRegionError::InvalidRegionIndex {
464 tick: bar.base_start_tick(), actual: ri, expected: VarIndex::from_value(current_idx + 1).unwrap()
465 }));
466 }
467 } else {
468 if let Some(segno) = global_repeat.segno {
469 if region_start_ticks[0] <= segno && segno < *region_start_ticks.last().unwrap() {
470 return Err(IntoReport::into_report(RenderRegionError::SegnoWhildVariation { tick: bar.base_start_tick() }));
471 }
472 }
473 regions.push(create_variation(*start_tick, region_start_ticks.clone(), bar.base_start_tick()));
474
475 if bar.repeats.contains(Repeat::Start) {
476 RenderRegionState::RepeatStart { start_tick: bar.base_start_tick() }
477 } else {
478 RenderRegionState::Seq { start_tick: bar.base_start_tick() }
479 }
480 }
481 }
482 }
483 }
484
485 match state {
486 RenderRegionState::Idle => {
487 regions.push(Box::new(SequenceRegion { tick_range: 0..u32::MAX }));
488 let (gr, w) = global_repeat.build()?;
489 Ok((Box::new(CompoundRegion { regions, global_repeat: gr }), w))
490 },
491 RenderRegionState::Seq { start_tick } => {
492 regions.push(Box::new(SequenceRegion { tick_range: start_tick..u32::MAX }));
493 let (gr, w) = global_repeat.build()?;
494 Ok((Box::new(CompoundRegion { regions, global_repeat: gr }), w))
495 }
496 RenderRegionState::RepeatStart { start_tick } => Err(IntoReport::into_report(RenderRegionError::NoRepeatEnd { tick: start_tick })),
497 RenderRegionState::Variation { start_tick: _, region_start_ticks } => {
498 Err(IntoReport::into_report(RenderRegionError::VariationNotClosed { tick: *region_start_ticks.last().unwrap() }))
499 }
500 }
501}
502
503#[cfg(test)]
504mod tests {
505 use error_stack::Report;
506
507use crate::{bar::{Bar, Repeat}, play_iter::PlayIter, play_start_tick::{PlayStartTick, ToAccumTickError}, repeat::{render_region, Chunk, GlobalRepeatBuilder, RenderRegionError, SimpleRegion}, rhythm::Rhythm};
508 use crate::repeat_set;
509 use super::{AccumTick, RenderPhase, SequenceRegion};
510 use crate::bar::RepeatSet;
511
512 fn to_accum_tick(tick: u32, iter: u8, chunks: &[(AccumTick, Chunk)]) -> std::result::Result<AccumTick, ToAccumTickError> {
513 PlayStartTick::new(tick, iter).to_accum_tick(chunks)
514 }
515
516 #[test]
517 fn empty() {
518 let bars: Vec<Bar> = vec![];
519 let (region, _warnings) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
520 let chunks = region.to_chunks();
521 assert_eq!(chunks.len(), 1);
522 assert_eq!(chunks[0], Chunk::new(0, u32::MAX));
523
524 let by_accum_tick = Chunk::by_accum_tick(&chunks);
525 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
526 assert_eq!(to_accum_tick(100, 1, &by_accum_tick).unwrap(), 100);
527 assert_eq!(to_accum_tick(100, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
528 }
529
530 #[test]
533 fn single_bar() {
534 let bar = Bar::new(100, None, None, crate::repeat_set!());
535 let bars = [bar];
536 let (region, _warnings) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
537 let chunks = region.to_chunks();
538 assert_eq!(chunks.len(), 1);
539 assert_eq!(chunks[0], Chunk::new(0, u32::MAX));
540
541 let by_accum_tick = Chunk::by_accum_tick(&chunks);
542 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
543 assert_eq!(to_accum_tick(100, 1, &by_accum_tick).unwrap(), 100);
544 assert_eq!(to_accum_tick(100, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
545 }
546
547 #[test]
553 fn default_start_repeat() {
554 let bars = [
555 Bar::new(100, None, None, repeat_set!(Repeat::End))
556 ];
557 let (region, _warnings) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
558 let chunks = region.to_chunks();
559 assert_eq!(chunks.len(), 3);
560 assert_eq!(chunks[0], Chunk::new(0, 100));
561 assert_eq!(chunks[1], Chunk::new(0, 100));
562 assert_eq!(chunks[2], Chunk::new(100, u32::MAX));
563
564 let chunks = Chunk::optimize(&chunks);
565 assert_eq!(chunks.len(), 2);
566 assert_eq!(chunks[0], Chunk::new(0, 100));
567 assert_eq!(chunks[1], Chunk::new(0, u32::MAX));
568
569 let by_accum_tick = Chunk::by_accum_tick(&chunks);
570 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
571 assert_eq!(to_accum_tick(50, 1, &by_accum_tick).unwrap(), 50);
572 assert_eq!(to_accum_tick(0, 2, &by_accum_tick).unwrap(), 100);
573 assert_eq!(to_accum_tick(50, 2, &by_accum_tick).unwrap(), 150);
574 assert_eq!(to_accum_tick(100, 1, &by_accum_tick).unwrap(), 200);
575 assert_eq!(to_accum_tick(150, 1, &by_accum_tick).unwrap(), 250);
576 assert_eq!(to_accum_tick(100, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
577 }
578
579 #[test]
584 fn invalid_repeat_end() {
585 let bars = [
586 Bar::new(100, None, None, repeat_set!(Repeat::End)),
587 Bar::new(200, None, None, repeat_set!(Repeat::End)),
588 ];
589
590 let e = render_region(Rhythm::new(4, 4), bars.iter()).unwrap_err();
591 let err: &RenderRegionError = e.current_context();
592 assert_eq!(*err, RenderRegionError::OrphanRepeatEnd { tick: 200 });
593 }
594
595 #[test]
601 fn single_repeat() {
602 let bars = [
603 Bar::new(100, None, None, repeat_set!(Repeat::Start)),
604 Bar::new(200, None, None, repeat_set!(Repeat::End)),
605 ];
606
607 let (region, _warnings) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
608 let chunks = region.to_chunks();
609 assert_eq!(chunks.len(), 4);
610 assert_eq!(chunks[0], Chunk::new(0, 100));
611 assert_eq!(chunks[1], Chunk::new(100, 200));
612 assert_eq!(chunks[2], Chunk::new(100, 200));
613 assert_eq!(chunks[3], Chunk::new(200, u32::MAX));
614
615 let chunks = Chunk::optimize(&chunks);
616 assert_eq!(chunks.len(), 2);
617 assert_eq!(chunks[0], Chunk::new(0, 200));
618 assert_eq!(chunks[1], Chunk::new(100, u32::MAX));
619
620 let by_accum_tick = Chunk::by_accum_tick(&chunks);
621 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
622 assert_eq!(to_accum_tick(0, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
623 assert_eq!(to_accum_tick(50, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
624 assert_eq!(to_accum_tick(100, 1, &by_accum_tick).unwrap(), 100);
625 assert_eq!(to_accum_tick(150, 1, &by_accum_tick).unwrap(), 150);
626 assert_eq!(to_accum_tick(100, 2, &by_accum_tick).unwrap(), 200);
627 assert_eq!(to_accum_tick(150, 2, &by_accum_tick).unwrap(), 250);
628 assert_eq!(to_accum_tick(200, 1, &by_accum_tick).unwrap(), 300);
629 assert_eq!(to_accum_tick(250, 1, &by_accum_tick).unwrap(), 350);
630 assert_eq!(to_accum_tick(200, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
631 assert_eq!(to_accum_tick(250, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
632 }
633
634 #[test]
640 fn single_repeat2() {
641 let bars = [
642 Bar::new(50, None, None, repeat_set!(Repeat::Start)),
643 Bar::new(200, None, None, repeat_set!(Repeat::End)),
644 ];
645
646 let (region, _warnings) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
647 let chunks = region.to_chunks();
648 assert_eq!(chunks.len(), 4);
649 assert_eq!(chunks[0], Chunk::new(0, 50));
650 assert_eq!(chunks[1], Chunk::new(50, 200));
651 assert_eq!(chunks[2], Chunk::new(50, 200));
652 assert_eq!(chunks[3], Chunk::new(200, u32::MAX));
653
654 let chunks = Chunk::optimize(&chunks);
655 assert_eq!(chunks.len(), 2);
656 assert_eq!(chunks[0], Chunk::new(0, 200));
657 assert_eq!(chunks[1], Chunk::new(50, u32::MAX));
658
659 let by_accum_tick = Chunk::by_accum_tick(&chunks);
660 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
661 assert_eq!(to_accum_tick(50, 1, &by_accum_tick).unwrap(), 50);
662 assert_eq!(to_accum_tick(50, 2, &by_accum_tick).unwrap(), 200);
663 assert_eq!(to_accum_tick(199, 2, &by_accum_tick).unwrap(), 349);
664 assert_eq!(to_accum_tick(200, 1, &by_accum_tick).unwrap(), 350);
665 assert_eq!(to_accum_tick(200, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
666 }
667
668 #[test]
674 fn simple_variation() {
675 let bars = [
676 Bar::new(50, None, None, repeat_set!(Repeat::Var1)),
677 Bar::new(100, None, None, repeat_set!(Repeat::Var2)),
678 Bar::new(150, None, None, repeat_set!()),
679 ];
680
681 let (region, _warnings) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
682 let chunks = region.to_chunks();
683 assert_eq!(chunks.len(), 5);
684 assert_eq!(chunks[0], Chunk::new(0, 50));
685 assert_eq!(chunks[1], Chunk::new(50, 100));
686 assert_eq!(chunks[2], Chunk::new(0, 50));
687 assert_eq!(chunks[3], Chunk::new(100, 150));
688 assert_eq!(chunks[4], Chunk::new(150, u32::MAX));
689
690 let chunks = Chunk::optimize(&chunks);
691 assert_eq!(chunks.len(), 3);
692 assert_eq!(chunks[0], Chunk::new(0, 100));
693 assert_eq!(chunks[1], Chunk::new(0, 50));
694 assert_eq!(chunks[2], Chunk::new(100, u32::MAX));
695
696 let by_accum_tick = Chunk::by_accum_tick(&chunks);
697 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
698 assert_eq!(to_accum_tick(0, 2, &by_accum_tick).unwrap(), 100);
699 assert_eq!(to_accum_tick(20, 2, &by_accum_tick).unwrap(), 120);
700 assert_eq!(to_accum_tick(100, 1, &by_accum_tick).unwrap(), 150);
701 assert_eq!(to_accum_tick(100, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
702 }
703
704 #[test]
710 fn simple_variation2() {
711 let bars = [
712 Bar::new(100, None, None, repeat_set!(Repeat::Var1)),
713 Bar::new(200, None, None, repeat_set!(Repeat::Var1)),
714 Bar::new(350, None, None, repeat_set!(Repeat::Var2)),
715 Bar::new(500, None, None, repeat_set!(Repeat::Var2)),
716 Bar::new(650, None, None, repeat_set!()),
717 ];
718
719 let (region, _warnings) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
720 let chunks = region.to_chunks();
721 assert_eq!(chunks.len(), 5);
722 assert_eq!(chunks[0], Chunk::new(0, 100));
723 assert_eq!(chunks[1], Chunk::new(100, 350));
724 assert_eq!(chunks[2], Chunk::new(0, 100));
725 assert_eq!(chunks[3], Chunk::new(350, 650));
726 assert_eq!(chunks[4], Chunk::new(650, u32::MAX));
727
728 let chunks = Chunk::optimize(&chunks);
729 assert_eq!(chunks.len(), 3);
730 assert_eq!(chunks[0], Chunk::new(0, 350));
731 assert_eq!(chunks[1], Chunk::new(0, 100));
732 assert_eq!(chunks[2], Chunk::new(350, u32::MAX));
733
734 let by_accum_tick = Chunk::by_accum_tick(&chunks);
735 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
736 assert_eq!(to_accum_tick(200, 1, &by_accum_tick).unwrap(), 200);
737 assert_eq!(to_accum_tick(0, 2, &by_accum_tick).unwrap(), 350);
738 assert_eq!(to_accum_tick(350, 1, &by_accum_tick).unwrap(), 450);
739 assert_eq!(to_accum_tick(650, 1, &by_accum_tick).unwrap(), 750);
740 assert_eq!(to_accum_tick(650, 2, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(2), max_iter: 1 }));
741 assert_eq!(to_accum_tick(0, 3, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(3), max_iter: 2 }));
742 }
743
744 #[test]
751 fn simple_dc() {
752 let bars = [
753 Bar::new(480, None, None, repeat_set!(Repeat::Fine)),
754 Bar::new(960, None, None, repeat_set!()),
755 Bar::new(1440, None, None, repeat_set!(Repeat::Dc)),
756 ];
757
758 let (region, _warnings) = render_region(Rhythm::new(2, 4), bars.iter()).unwrap();
759 let chunks = region.to_chunks();
760 assert_eq!(chunks.len(), 2);
761 assert_eq!(chunks[0], Chunk::new(0, 1440));
762 assert_eq!(chunks[1], Chunk::new(0, 480));
763
764 let chunks = Chunk::optimize(&chunks);
765 assert_eq!(chunks.len(), 2);
766 assert_eq!(chunks[0], Chunk::new(0, 1440));
767 assert_eq!(chunks[1], Chunk::new(0, 480));
768
769 let by_accum_tick = Chunk::by_accum_tick(&chunks);
770 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
771 assert_eq!(to_accum_tick(0, 2, &by_accum_tick).unwrap(), 1440);
772 assert_eq!(to_accum_tick(0, 3, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(3), max_iter: 2 }));
773 }
774
775 #[test]
781 fn simple_var_dc() {
782 let bars = [
783 Bar::new(480, None, None, repeat_set!(Repeat::Var1)),
784 Bar::new(580, None, None, repeat_set!(Repeat::Var1)),
785 Bar::new(730, None, None, repeat_set!(Repeat::Var2)),
786 Bar::new(880, None, None, repeat_set!(Repeat::Var2)),
787 Bar::new(1030, None, None, repeat_set!(Repeat::Fine)),
788 Bar::new(1180, None, None, repeat_set!()),
789 Bar::new(1280, None, None, repeat_set!(Repeat::Dc)),
790 ];
791
792 let (region, _) = render_region(Rhythm::new(2, 4), bars.iter()).unwrap();
793 let chunks = region.to_chunks();
794 assert_eq!(chunks.len(), 6);
795 assert_eq!(chunks[0], Chunk::new(0, 480));
796 assert_eq!(chunks[1], Chunk::new(480, 730));
797 assert_eq!(chunks[2], Chunk::new(0, 480));
798 assert_eq!(chunks[3], Chunk::new(730, 1030));
799 assert_eq!(chunks[4], Chunk::new(1030, 1280));
800 assert_eq!(chunks[5], Chunk::new(730, 1030));
801
802 let chunks = Chunk::optimize(&chunks);
803 assert_eq!(chunks.len(), 4);
804 assert_eq!(chunks[0], Chunk::new(0, 730));
805 assert_eq!(chunks[1], Chunk::new(0, 480));
806 assert_eq!(chunks[2], Chunk::new(730, 1280));
807 assert_eq!(chunks[3], Chunk::new(730, 1030));
808
809 let by_accum_tick = Chunk::by_accum_tick(&chunks);
810 assert_eq!(to_accum_tick(0, 1, &by_accum_tick).unwrap(), 0);
811 assert_eq!(to_accum_tick(480, 1, &by_accum_tick).unwrap(), 480);
812 assert_eq!(to_accum_tick(400, 2, &by_accum_tick).unwrap(), 730 + 400);
813 assert_eq!(to_accum_tick(800, 1, &by_accum_tick).unwrap(), 730 + 480 + (800 - 730));
814 assert_eq!(to_accum_tick(1180, 1, &by_accum_tick).unwrap(), 730 + 480 + (1180 - 730));
815 assert_eq!(to_accum_tick(730, 2, &by_accum_tick).unwrap(), 730 + 480 + (1280 - 730));
816 assert_eq!(to_accum_tick(730, 3, &by_accum_tick), Err(ToAccumTickError::CannotFind { specified_iter: PlayIter::new(3), max_iter: 2 }));
817 }
818
819 #[test]
824 fn dc_and_repeat_end() {
825 let bars = [
826 Bar::new(480, None, None, repeat_set!(Repeat::Start)),
827 Bar::new(530, None, None, repeat_set!(Repeat::Start, Repeat::End, Repeat::Fine)),
828 Bar::new(600, None, None, repeat_set!(Repeat::Start, Repeat::End)),
829 Bar::new(1080, None, None, repeat_set!(Repeat::Dc, Repeat::End)),
830 ];
831
832 let (region, _warnings) = render_region(Rhythm::new(2, 4), bars.iter()).unwrap();
833 let chunks = region.to_chunks();
834
835 assert_eq!(chunks.len(), 9);
836 assert_eq!(chunks[0], Chunk::new(0, 480));
837 assert_eq!(chunks[1], Chunk::new(480, 530));
838 assert_eq!(chunks[2], Chunk::new(480, 530));
839 assert_eq!(chunks[3], Chunk::new(530, 600));
840 assert_eq!(chunks[4], Chunk::new(530, 600));
841 assert_eq!(chunks[5], Chunk::new(600, 1080));
842 assert_eq!(chunks[6], Chunk::new(600, 1080));
843 assert_eq!(chunks[7], Chunk::new(0, 480));
844 assert_eq!(chunks[8], Chunk::new(480, 530));
845
846 let chunks = Chunk::optimize(&chunks);
847 assert_eq!(chunks.len(), 5);
848 assert_eq!(chunks[0], Chunk::new(0, 530));
849 assert_eq!(chunks[1], Chunk::new(480, 600));
850 assert_eq!(chunks[2], Chunk::new(530, 1080));
851 assert_eq!(chunks[3], Chunk::new(600, 1080));
852 assert_eq!(chunks[4], Chunk::new(0, 530));
853 }
854
855 #[test]
861 fn two_vars() {
862 let bars = [
863 Bar::new(50, None, None, repeat_set!(Repeat::Start)),
864 Bar::new(100, None, None, repeat_set!()),
865 Bar::new(150, None, None, repeat_set!(Repeat::Var1)),
866 Bar::new(200, None, None, repeat_set!(Repeat::Var2)),
867 Bar::new(250, None, None, repeat_set!(Repeat::Start)),
868 Bar::new(300, None, None, repeat_set!()),
869 Bar::new(350, None, None, repeat_set!(Repeat::Var1)),
870 Bar::new(400, None, None, repeat_set!(Repeat::Var2)),
871 Bar::new(450, None, None, repeat_set!()),
872 ];
873
874 let (region, _warnings) = render_region(Rhythm::new(2, 4), bars.iter()).unwrap();
875 let chunks = region.to_chunks();
876
877 assert_eq!(chunks.len(), 10);
878 assert_eq!(chunks[0], Chunk::new(0, 50));
879 assert_eq!(chunks[1], Chunk::new(50, 150));
880 assert_eq!(chunks[2], Chunk::new(150, 200));
881 assert_eq!(chunks[3], Chunk::new(50, 150));
882 assert_eq!(chunks[4], Chunk::new(200, 250));
883 assert_eq!(chunks[5], Chunk::new(250, 350));
884 assert_eq!(chunks[6], Chunk::new(350, 400));
885 assert_eq!(chunks[7], Chunk::new(250, 350));
886 assert_eq!(chunks[8], Chunk::new(400, 450));
887 assert_eq!(chunks[9], Chunk::new(450, u32::MAX));
888
889 let chunks = Chunk::optimize(&chunks);
890 assert_eq!(chunks.len(), 5);
891 assert_eq!(chunks[0], Chunk::new(0, 200));
892 assert_eq!(chunks[1], Chunk::new(50, 150));
893 assert_eq!(chunks[2], Chunk::new(200, 400));
894 assert_eq!(chunks[3], Chunk::new(250, 350));
895 assert_eq!(chunks[4], Chunk::new(400, u32::MAX));
896 }
897
898 #[test]
904 fn two_vars_with_end_bar() {
905 let bars = [
906 Bar::new(50, None, None, repeat_set!(Repeat::Start)),
907 Bar::new(100, None, None, repeat_set!()),
908 Bar::new(150, None, None, repeat_set!(Repeat::Var1)),
909 Bar::new(200, None, None, repeat_set!(Repeat::Var2)),
910 Bar::new(250, None, None, repeat_set!()),
911 Bar::new(300, None, None, repeat_set!(Repeat::Start)),
912 Bar::new(350, None, None, repeat_set!()),
913 Bar::new(400, None, None, repeat_set!(Repeat::Var1)),
914 Bar::new(450, None, None, repeat_set!(Repeat::Var1)),
915 Bar::new(500, None, None, repeat_set!(Repeat::Var2)),
916 Bar::new(550, None, None, repeat_set!()),
917 Bar::new(600, None, None, repeat_set!()),
918 ];
919
920 let (region, _warnings) = render_region(Rhythm::new(2, 4), bars.iter()).unwrap();
921 let chunks = region.to_chunks();
922
923 assert_eq!(chunks.len(), 11);
924 assert_eq!(chunks[0], Chunk::new(0, 50));
925 assert_eq!(chunks[1], Chunk::new(50, 150));
926 assert_eq!(chunks[2], Chunk::new(150, 200));
927 assert_eq!(chunks[3], Chunk::new(50, 150));
928 assert_eq!(chunks[4], Chunk::new(200, 250));
929 assert_eq!(chunks[5], Chunk::new(250, 300));
930 assert_eq!(chunks[6], Chunk::new(300, 400));
931 assert_eq!(chunks[7], Chunk::new(400, 500));
932 assert_eq!(chunks[8], Chunk::new(300, 400));
933 assert_eq!(chunks[9], Chunk::new(500, 550));
934 assert_eq!(chunks[10], Chunk::new(550, u32::MAX));
935
936 let chunks = Chunk::optimize(&chunks);
937 assert_eq!(chunks.len(), 5);
938 assert_eq!(chunks[0], Chunk::new(0, 200));
939 assert_eq!(chunks[1], Chunk::new(50, 150));
940 assert_eq!(chunks[2], Chunk::new(200, 500));
941 assert_eq!(chunks[3], Chunk::new(300, 400));
942 assert_eq!(chunks[4], Chunk::new(500, u32::MAX));
943
944 }
945
946 #[test]
952 fn repeat_and_dc() {
953 let bars = [
954 Bar::new(240, None, None, repeat_set!(Repeat::Start)),
955 Bar::new(320, None, None, repeat_set!()),
956 Bar::new(370, None, None, repeat_set!(Repeat::Var1)),
957 Bar::new(420, None, None, repeat_set!(Repeat::Var2)),
958 Bar::new(470, None, None, repeat_set!()),
959 Bar::new(520, None, None, repeat_set!(Repeat::Start)),
960 Bar::new(570, None, None, repeat_set!()),
961 Bar::new(620, None, None, repeat_set!(Repeat::Var1)),
962 Bar::new(670, None, None, repeat_set!(Repeat::Var2)),
963 Bar::new(720, None, None, repeat_set!(Repeat::Fine)),
964 Bar::new(770, None, None, repeat_set!(Repeat::Start)),
965 Bar::new(820, None, None, repeat_set!()),
966 Bar::new(870, None, None, repeat_set!()),
967 Bar::new(920, None, None, repeat_set!(Repeat::End)),
968 Bar::new(970, None, None, repeat_set!(Repeat::Dc)),
969 ];
970
971 let (region, _warnings) = render_region(Rhythm::new(2, 4), bars.iter()).unwrap();
972 let chunks = region.to_chunks();
973
974 assert_eq!(chunks.len(), 19);
975 let mut z = chunks.iter();
976 assert_eq!(*z.next().unwrap(), Chunk::new(0, 240));
977 assert_eq!(*z.next().unwrap(), Chunk::new(240, 370));
978 assert_eq!(*z.next().unwrap(), Chunk::new(370, 420));
979 assert_eq!(*z.next().unwrap(), Chunk::new(240, 370));
980 assert_eq!(*z.next().unwrap(), Chunk::new(420, 470));
981
982 assert_eq!(*z.next().unwrap(), Chunk::new(470, 520));
983 assert_eq!(*z.next().unwrap(), Chunk::new(520, 620));
984 assert_eq!(*z.next().unwrap(), Chunk::new(620, 670));
985 assert_eq!(*z.next().unwrap(), Chunk::new(520, 620));
986 assert_eq!(*z.next().unwrap(), Chunk::new(670, 720));
987
988 assert_eq!(*z.next().unwrap(), Chunk::new(720, 770));
989 assert_eq!(*z.next().unwrap(), Chunk::new(770, 920));
990 assert_eq!(*z.next().unwrap(), Chunk::new(770, 920));
991 assert_eq!(*z.next().unwrap(), Chunk::new(920, 970));
992
993 assert_eq!(*z.next().unwrap(), Chunk::new(240, 370));
994 assert_eq!(*z.next().unwrap(), Chunk::new(420, 470));
995 assert_eq!(*z.next().unwrap(), Chunk::new(470, 520));
996 assert_eq!(*z.next().unwrap(), Chunk::new(520, 620));
997 assert_eq!(*z.next().unwrap(), Chunk::new(670, 720));
998 assert_eq!(z.next(), None);
999
1000 let chunks = Chunk::optimize(&chunks);
1001 assert_eq!(chunks.len(), 9);
1002 let mut z = chunks.iter();
1003 assert_eq!(*z.next().unwrap(), Chunk::new(0, 420));
1004 assert_eq!(*z.next().unwrap(), Chunk::new(240, 370));
1005 assert_eq!(*z.next().unwrap(), Chunk::new(420, 670));
1006 assert_eq!(*z.next().unwrap(), Chunk::new(520, 620));
1007 assert_eq!(*z.next().unwrap(), Chunk::new(670, 920));
1008 assert_eq!(*z.next().unwrap(), Chunk::new(770, 970));
1009 assert_eq!(*z.next().unwrap(), Chunk::new(240, 370));
1010 assert_eq!(*z.next().unwrap(), Chunk::new(420, 620));
1011 assert_eq!(*z.next().unwrap(), Chunk::new(670, 720));
1012 assert_eq!(z.next(), None);
1013 }
1014
1015 #[test]
1021 fn consecutive_repeat() {
1022 let bars = [
1023 Bar::new(50, None, None, repeat_set!()),
1024 Bar::new(200, None, None, repeat_set!(Repeat::Start, Repeat::End)),
1025 Bar::new(300, None, None, repeat_set!(Repeat::End)),
1026 ];
1027
1028 let (region, _warnings) = render_region(Rhythm::new(2, 4), bars.iter()).unwrap();
1029 let chunks = region.to_chunks();
1030 assert_eq!(chunks.len(), 5);
1031
1032 let mut z = chunks.iter();
1033 assert_eq!(*z.next().unwrap(), Chunk::new(0, 200));
1034 assert_eq!(*z.next().unwrap(), Chunk::new(0, 200));
1035 assert_eq!(*z.next().unwrap(), Chunk::new(200, 300));
1036 assert_eq!(*z.next().unwrap(), Chunk::new(200, 300));
1037 assert_eq!(*z.next().unwrap(), Chunk::new(300, u32::MAX));
1038 assert_eq!(z.next(), None);
1039
1040 let chunks = Chunk::optimize(&chunks);
1041 let mut z = chunks.iter();
1042 assert_eq!(*z.next().unwrap(), Chunk::new(0, 200));
1043 assert_eq!(*z.next().unwrap(), Chunk::new(0, 300));
1044 assert_eq!(*z.next().unwrap(), Chunk::new(200, u32::MAX));
1045 assert_eq!(z.next(), None);
1046 }
1047
1048 #[test]
1053 fn fine_and_repeat() {
1054 let bars = [
1055 Bar::new(120, None, None, repeat_set!()),
1056 Bar::new(270, None, None, repeat_set!(Repeat::Start, Repeat::End, Repeat::Fine)),
1057 Bar::new(370, None, None, repeat_set!(Repeat::Dc, Repeat::End)),
1058 ];
1059
1060 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1061 let chunks = region.to_chunks();
1062 assert_eq!(chunks.len(), 5);
1063
1064 let mut z = chunks.iter();
1065 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1066 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1067 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1068 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1069 assert_eq!(*z.next().unwrap(), Chunk::new(120, 270));
1070 assert_eq!(z.next(), None);
1071
1072 let chunks = Chunk::optimize(&chunks);
1073 let mut z = chunks.iter();
1074 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1075 assert_eq!(*z.next().unwrap(), Chunk::new(0, 370));
1076 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1077 assert_eq!(*z.next().unwrap(), Chunk::new(120, 270));
1078 assert_eq!(z.next(), None);
1079 }
1080
1081 #[test]
1087 fn dc_and_repeat() {
1088 let bars = [
1089 Bar::new(120, None, None, repeat_set!(Repeat::Start)),
1090 Bar::new(170, None, None, repeat_set!(Repeat::Start, Repeat::End, Repeat::Fine)),
1091 Bar::new(270, None, None, repeat_set!(Repeat::Start, Repeat::End)),
1092 Bar::new(370, None, None, repeat_set!(Repeat::Dc, Repeat::End)),
1093 ];
1094
1095 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1096 let chunks = region.to_chunks();
1097 assert_eq!(chunks.len(), 8);
1098
1099 let mut z = chunks.iter();
1100 assert_eq!(*z.next().unwrap(), Chunk::new(0, 120));
1101 assert_eq!(*z.next().unwrap(), Chunk::new(120, 170));
1102 assert_eq!(*z.next().unwrap(), Chunk::new(120, 170));
1103 assert_eq!(*z.next().unwrap(), Chunk::new(170, 270));
1104 assert_eq!(*z.next().unwrap(), Chunk::new(170, 270));
1105 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1106 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1107 assert_eq!(*z.next().unwrap(), Chunk::new(120, 170));
1108 assert_eq!(z.next(), None);
1109
1110 let chunks = Chunk::optimize(&chunks);
1111 let mut z = chunks.iter();
1112 assert_eq!(*z.next().unwrap(), Chunk::new(0, 170));
1113 assert_eq!(*z.next().unwrap(), Chunk::new(120, 270));
1114 assert_eq!(*z.next().unwrap(), Chunk::new(170, 370));
1115 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1116 assert_eq!(*z.next().unwrap(), Chunk::new(120, 170));
1117 assert_eq!(z.next(), None);
1118 }
1119
1120 #[test]
1125 fn dc_without_fine() {
1126 let bars = [
1127 Bar::new(120, None, None, repeat_set!()),
1128 Bar::new(170, None, None, repeat_set!(Repeat::Start)),
1129 Bar::new(270, None, None, repeat_set!()),
1130 Bar::new(370, None, None, repeat_set!(Repeat::Dc, Repeat::End)),
1131 Bar::new(470, None, None, repeat_set!()),
1132 ];
1133
1134 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1135 let chunks = region.to_chunks();
1136 assert_eq!(chunks.len(), 6);
1137
1138 let mut z = chunks.iter();
1139 assert_eq!(*z.next().unwrap(), Chunk::new(0, 170));
1140 assert_eq!(*z.next().unwrap(), Chunk::new(170, 370));
1141 assert_eq!(*z.next().unwrap(), Chunk::new(170, 370));
1142 assert_eq!(*z.next().unwrap(), Chunk::new(120, 170));
1143 assert_eq!(*z.next().unwrap(), Chunk::new(170, 370));
1144 assert_eq!(*z.next().unwrap(), Chunk::new(370, u32::MAX));
1145 assert_eq!(z.next(), None);
1146
1147 let chunks = Chunk::optimize(&chunks);
1148 let mut z = chunks.iter();
1149 assert_eq!(*z.next().unwrap(), Chunk::new(0, 370));
1150 assert_eq!(*z.next().unwrap(), Chunk::new(170, 370));
1151 assert_eq!(*z.next().unwrap(), Chunk::new(120, u32::MAX));
1152 assert_eq!(z.next(), None);
1153 }
1154
1155 #[test]
1160 fn simple_ds() {
1161 let bars = [
1162 Bar::new(120, None, None, repeat_set!()),
1163 Bar::new(200, None, None, repeat_set!(Repeat::Segno)),
1164 Bar::new(270, None, None, repeat_set!(Repeat::Start, Repeat::End, Repeat::Fine)),
1165 Bar::new(370, None, None, repeat_set!(Repeat::Ds, Repeat::End)),
1166 ];
1167
1168 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1169 let chunks = region.to_chunks();
1170 assert_eq!(chunks.len(), 5);
1171
1172 let mut z = chunks.iter();
1173 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1174 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1175 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1176 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1177 assert_eq!(*z.next().unwrap(), Chunk::new(200, 270));
1178 assert_eq!(z.next(), None);
1179
1180 let chunks = Chunk::optimize(&chunks);
1181 let mut z = chunks.iter();
1182 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1183 assert_eq!(*z.next().unwrap(), Chunk::new(0, 370));
1184 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1185 assert_eq!(*z.next().unwrap(), Chunk::new(200, 270));
1186 assert_eq!(z.next(), None);
1187 }
1188
1189 #[test]
1194 fn var_and_ds() {
1195 let bars = [
1196 Bar::new(120, None, None, repeat_set!()),
1197 Bar::new(200, None, None, repeat_set!(Repeat::Segno)),
1198 Bar::new(270, None, None, repeat_set!(Repeat::Start, Repeat::End, Repeat::Fine)),
1199 Bar::new(370, None, None, repeat_set!(Repeat::Var1)),
1200 Bar::new(470, None, None, repeat_set!(Repeat::Var2)),
1201 Bar::new(570, None, None, repeat_set!(Repeat::Ds)),
1202 ];
1203
1204 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1205 let chunks = region.to_chunks();
1206 assert_eq!(chunks.len(), 7);
1207
1208 let mut z = chunks.iter();
1209 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1210 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1211 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1212 assert_eq!(*z.next().unwrap(), Chunk::new(370, 470));
1213 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1214 assert_eq!(*z.next().unwrap(), Chunk::new(470, 570));
1215 assert_eq!(*z.next().unwrap(), Chunk::new(200, 270));
1216 assert_eq!(z.next(), None);
1217
1218 let chunks = Chunk::optimize(&chunks);
1219 let mut z = chunks.iter();
1220 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1221 assert_eq!(*z.next().unwrap(), Chunk::new(0, 470));
1222 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1223 assert_eq!(*z.next().unwrap(), Chunk::new(470, 570));
1224 assert_eq!(*z.next().unwrap(), Chunk::new(200, 270));
1225 assert_eq!(z.next(), None);
1226 }
1227
1228 #[test]
1233 fn ds_and_coda() {
1234 let bars = [
1235 Bar::new(120, None, None, repeat_set!()),
1236 Bar::new(200, None, None, repeat_set!(Repeat::Segno)),
1237 Bar::new(270, None, None, repeat_set!(Repeat::End)),
1238 Bar::new(370, None, None, repeat_set!(Repeat::Coda)),
1239 Bar::new(470, None, None, repeat_set!()),
1240 Bar::new(570, None, None, repeat_set!(Repeat::Coda)),
1241 Bar::new(670, None, None, repeat_set!(Repeat::Ds)),
1242 ];
1243
1244 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1245 let chunks = region.to_chunks();
1246 assert_eq!(chunks.len(), 6);
1247
1248 let mut z = chunks.iter();
1249 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1250 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1251 assert_eq!(*z.next().unwrap(), Chunk::new(270, 670));
1252 assert_eq!(*z.next().unwrap(), Chunk::new(200, 270));
1253 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1254 assert_eq!(*z.next().unwrap(), Chunk::new(570, u32::MAX));
1255 assert_eq!(z.next(), None);
1256
1257 let chunks = Chunk::optimize(&chunks);
1258 let mut z = chunks.iter();
1259 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1260 assert_eq!(*z.next().unwrap(), Chunk::new(0, 670));
1261 assert_eq!(*z.next().unwrap(), Chunk::new(200, 370));
1262 assert_eq!(*z.next().unwrap(), Chunk::new(570, u32::MAX));
1263 assert_eq!(z.next(), None);
1264 }
1265
1266 #[test]
1271 fn ds_and_coda_fine() {
1272 let bars = [
1273 Bar::new(120, None, None, repeat_set!()),
1274 Bar::new(200, None, None, repeat_set!(Repeat::Segno)),
1275 Bar::new(270, None, None, repeat_set!(Repeat::End)),
1276 Bar::new(370, None, None, repeat_set!(Repeat::Coda)),
1277 Bar::new(470, None, None, repeat_set!()),
1278 Bar::new(570, None, None, repeat_set!(Repeat::Coda)),
1279 Bar::new(670, None, None, repeat_set!(Repeat::Fine)),
1280 Bar::new(770, None, None, repeat_set!(Repeat::Ds)),
1281 ];
1282
1283 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1284 let chunks = region.to_chunks();
1285 assert_eq!(chunks.len(), 6);
1286
1287 let mut z = chunks.iter();
1288 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1289 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1290 assert_eq!(*z.next().unwrap(), Chunk::new(270, 770));
1291 assert_eq!(*z.next().unwrap(), Chunk::new(200, 270));
1292 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1293 assert_eq!(*z.next().unwrap(), Chunk::new(570, 670));
1294 assert_eq!(z.next(), None);
1295
1296 let chunks = Chunk::optimize(&chunks);
1297 let mut z = chunks.iter();
1298 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1299 assert_eq!(*z.next().unwrap(), Chunk::new(0, 770));
1300 assert_eq!(*z.next().unwrap(), Chunk::new(200, 370));
1301 assert_eq!(*z.next().unwrap(), Chunk::new(570, 670));
1302 assert_eq!(z.next(), None);
1303 }
1304
1305 #[test]
1310 fn ds_and_coda_skip_ds() {
1311 let bars = [
1312 Bar::new(120, None, None, repeat_set!()),
1313 Bar::new(200, None, None, repeat_set!(Repeat::Segno)),
1314 Bar::new(270, None, None, repeat_set!(Repeat::End)),
1315 Bar::new(370, None, None, repeat_set!(Repeat::Coda)),
1316 Bar::new(470, None, None, repeat_set!()),
1317 Bar::new(570, None, None, repeat_set!(Repeat::Ds)),
1318 Bar::new(670, None, None, repeat_set!(Repeat::Coda)),
1319 ];
1320
1321 let (region, _warnings) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1322 let chunks = region.to_chunks();
1323 assert_eq!(chunks.len(), 6);
1324
1325 let mut z = chunks.iter();
1326 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1327 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1328 assert_eq!(*z.next().unwrap(), Chunk::new(270, 570));
1329 assert_eq!(*z.next().unwrap(), Chunk::new(200, 270));
1330 assert_eq!(*z.next().unwrap(), Chunk::new(270, 370));
1331 assert_eq!(*z.next().unwrap(), Chunk::new(670, u32::MAX));
1332 assert_eq!(z.next(), None);
1333
1334 let chunks = Chunk::optimize(&chunks);
1335 let mut z = chunks.iter();
1336 assert_eq!(*z.next().unwrap(), Chunk::new(0, 270));
1337 assert_eq!(*z.next().unwrap(), Chunk::new(0, 570));
1338 assert_eq!(*z.next().unwrap(), Chunk::new(200, 370));
1339 assert_eq!(*z.next().unwrap(), Chunk::new(670, u32::MAX));
1340 assert_eq!(z.next(), None);
1341 }
1342
1343 #[test]
1344 fn render_sequence_region_when_non_dcds() {
1345 let seq_region = SequenceRegion {
1346 tick_range: 100..200
1347 };
1348 let chunks: Vec<Chunk> = seq_region.render_chunks(&RenderPhase::NonDcDs);
1349 assert_eq!(chunks.len(), 1);
1350 assert_eq!(chunks[0], Chunk { start_tick: 100, end_tick: 200 });
1351 }
1352
1353 #[test]
1354 fn render_sequence_region_when_dcds_iter0() {
1355 let seq_region = SequenceRegion {
1356 tick_range: 100..200
1357 };
1358 let chunks: Vec<Chunk> = seq_region.render_chunks(&RenderPhase::DcDsIter0 { dc_ds_tick: 99 });
1359 assert_eq!(chunks.len(), 0);
1360
1361 let chunks: Vec<Chunk> = seq_region.render_chunks(&RenderPhase::DcDsIter0 { dc_ds_tick: 100 });
1362 assert_eq!(chunks.len(), 0);
1363
1364 let chunks: Vec<Chunk> = seq_region.render_chunks(&RenderPhase::DcDsIter0 { dc_ds_tick: 101 });
1365 assert_eq!(chunks.len(), 1);
1366 assert_eq!(chunks[0], Chunk { start_tick: 100, end_tick: 101 });
1367
1368 let chunks: Vec<Chunk> = seq_region.render_chunks(&RenderPhase::DcDsIter0 { dc_ds_tick: 199 });
1369 assert_eq!(chunks.len(), 1);
1370 assert_eq!(chunks[0], Chunk { start_tick: 100, end_tick: 199 });
1371
1372 let chunks: Vec<Chunk> = seq_region.render_chunks(&RenderPhase::DcDsIter0 { dc_ds_tick: 200 });
1373 assert_eq!(chunks.len(), 1);
1374 assert_eq!(chunks[0], Chunk { start_tick: 100, end_tick: 200 });
1375
1376 let chunks: Vec<Chunk> = seq_region.render_chunks(&RenderPhase::DcDsIter0 { dc_ds_tick: 201 });
1377 assert_eq!(chunks.len(), 1);
1378 assert_eq!(chunks[0], Chunk { start_tick: 100, end_tick: 200 });
1379 }
1380
1381 #[test]
1382 fn render_sequence_region_when_dcds_iter1() -> Result<(), Report<RenderRegionError>> {
1383 let seq_region = SequenceRegion {
1384 tick_range: 100..200
1385 };
1386 let (global_repeat, _warn) = GlobalRepeatBuilder::new(Rhythm::new(4, 4))
1387 .adding_segno(99)?
1388 .adding_dc(400, 100)?
1389 .adding_first_bar_len(30)?
1390 .build()?;
1391
1392 let gr: crate::global_repeat::GlobalRepeat = global_repeat.unwrap();
1393 let rp = RenderPhase::DcDsIter1 { global_repeat: gr };
1394 let chunks = seq_region.render_chunks(&rp);
1395
1396 assert_eq!(chunks.len(), 1);
1397 assert_eq!(chunks[0], Chunk { start_tick: 100, end_tick: 200 });
1398 Ok(())
1399 }
1400
1401 #[test]
1406 fn dc_goes_to_fine() {
1407 let bars = [
1408 Bar::new(200, None, None, repeat_set!(Repeat::Fine)),
1409 Bar::new(400, None, None, repeat_set!(Repeat::Dc)),
1410 ];
1411
1412 let (region, _) = render_region(Rhythm::new(1, 4), bars.iter()).unwrap();
1413 let chunks = region.to_chunks();
1414 assert_eq!(chunks.len(), 1);
1415 }
1416
1417 #[test]
1422 fn dc_and_auftakt() {
1423 let bars = [
1424 Bar::new(240, None, None, repeat_set!()),
1425 Bar::new(1200, None, None, repeat_set!(Repeat::Fine)),
1426 Bar::new(1920, None, None, repeat_set!(Repeat::Dc)),
1427 ];
1428
1429 let (region, _) = render_region(Rhythm::new(4, 4), bars.iter()).unwrap();
1430 let chunks = region.to_chunks();
1431 assert_eq!(chunks.len(), 2);
1432
1433 let mut z = chunks.iter();
1434 assert_eq!(*z.next().unwrap(), Chunk::new(0, 1920));
1435 assert_eq!(*z.next().unwrap(), Chunk::new(0, 1200));
1436 }
1437}