From fbe2fe21cc9d5d4db8099bfd9d41f6ce477aa037 Mon Sep 17 00:00:00 2001 From: Viv Date: Sat, 15 Jul 2023 11:58:33 -0400 Subject: [PATCH] Fix crash for `#SECTION` commands that occur before the first `#BRANCHSTART` (#36) This PR adds `genpe.tja` to the test suite, a song that currently fails due to how `tja2fumen` handles `#SECTION` commands. We fix the problems with branching commands in 8ad2102f0adf29f58f7dafbdb4ef5b2b5ae0c70a. (Making sure that any #SECTION commands that occur before the first #BRANCHSTART are properly handled.) This PR also contains a few refactoring commits to improve the clarity of how the branching logic works, to make further debugging of branching songs easier. Fixes #33. --- src/tja2fumen/converters.py | 34 +- src/tja2fumen/parsers.py | 31 +- testing/data/genpe.tja | 932 ++++++++++++++++++++++++++++++++++++ testing/data/genpe.zip | Bin 0 -> 14505 bytes testing/test_conversion.py | 24 +- 5 files changed, 999 insertions(+), 22 deletions(-) create mode 100644 testing/data/genpe.tja create mode 100644 testing/data/genpe.zip diff --git a/src/tja2fumen/converters.py b/src/tja2fumen/converters.py index 77b2976..38eceab 100644 --- a/src/tja2fumen/converters.py +++ b/src/tja2fumen/converters.py @@ -51,6 +51,12 @@ def processTJACommands(tja): measureTJAProcessed.delay = data.value * 1000 # ms -> s elif data.name == 'branchStart': measureTJAProcessed.branchStart = data.value + # If the measure immediately preceding a #BRANCHSTART has a #SECTION command, then remove it. + # From TJA spec: "Placing [a #SECTION command] near #BRANCHSTART or a measure before does not reset + # the accuracy for that branch. The value is calculated before it and a measure + # has not started yet at that point." + if tjaBranchesProcessed[branchName][-1].branchStart == ["#SECTION", -1, -1]: + tjaBranchesProcessed[branchName][-1].branchStart = None elif data.name == 'barline': currentBarline = bool(int(data.value)) measureTJAProcessed.barline = currentBarline @@ -194,11 +200,25 @@ def convertTJAToFumen(tja): if measureTJAProcessed.branchStart: # Determine which values to assign based on the type of branching condition if measureTJAProcessed.branchStart[0] == 'p': - vals = [int(total_notes_branch * v * 20) if 0 <= v <= 1 # Ensure value is actually a percentage - else int(v * 100) # If it's not, pass the value as-is - for v in measureTJAProcessed.branchStart[1:]] + vals = [] + for percent in measureTJAProcessed.branchStart[1:]: + # Ensure percentage is actually a percentage value + if 0 <= percent <= 1: + val = total_notes_branch * percent * 20 + # If the result is very close, then round to account for lack of precision in percentage + if abs(val - round(val)) < 0.1: + val = round(val) + vals.append(int(val)) + # If it isn't a percentage value, then pass it back as-is + else: + vals.append(int(percent * 100)) + # If it's a drumroll then use the branch condition values as-is elif measureTJAProcessed.branchStart[0] == 'r': vals = measureTJAProcessed.branchStart[1:] + # If it's a #SECTION command, use the branch condition values as-is AND reset the accuracy + elif measureTJAProcessed.branchStart[0] == '#SECTION': + vals = measureTJAProcessed.branchStart[1:] + note_counter_branch = 0 # Determine which bytes to assign the values to if currentBranch == 'normal': idx_b1, idx_b2 = 0, 1 @@ -209,8 +229,14 @@ def convertTJAToFumen(tja): # Assign the values to their intended bytes measureFumen.branchInfo[idx_b1] = vals[0] measureFumen.branchInfo[idx_b2] = vals[1] - # Reset the note counter corresponding to this branch + # Reset the note counter corresponding to this branch (i.e. reset the accuracy) total_notes_branch = 0 + + # NB: We update the branch condition note counter *after* we check the current measure's branch condition. + # This is because the TJA spec says: + # "The requirement is calculated one measure before #BRANCHSTART, changing the branch visually when it + # is calculated and changing the notes after #BRANCHSTART." + # So, by delaying the summation by one measure, we perform the calculation with notes "one measure before". total_notes_branch += note_counter_branch # Create notes based on TJA measure data diff --git a/src/tja2fumen/parsers.py b/src/tja2fumen/parsers.py index 86355ab..b186d88 100644 --- a/src/tja2fumen/parsers.py +++ b/src/tja2fumen/parsers.py @@ -111,6 +111,7 @@ def parseCourseMeasures(course): # Check if the course has branches or not hasBranches = True if [l for l in course.data if l.name == 'BRANCHSTART'] else False currentBranch = 'all' if hasBranches else 'normal' + branch_condition = None flagLevelhold = False # Process course lines @@ -133,7 +134,7 @@ def parseCourseMeasures(course): # 2. Parse measure commands that produce an "event" elif line.name in ['GOGOSTART', 'GOGOEND', 'BARLINEON', 'BARLINEOFF', 'DELAY', - 'SCROLL', 'BPMCHANGE', 'MEASURE', 'BRANCHSTART']: + 'SCROLL', 'BPMCHANGE', 'MEASURE', 'SECTION', 'BRANCHSTART']: # Get position of the event for branch in course.branches.keys() if currentBranch == 'all' else [currentBranch]: pos = len(course.branches[branch][idx_m].notes) @@ -155,27 +156,31 @@ def parseCourseMeasures(course): currentEvent = TJAData('bpm', float(line.value), pos) elif line.name == 'MEASURE': currentEvent = TJAData('measure', line.value, pos) + elif line.name == 'SECTION': + # If #SECTION occurs before the first #BRANCHSTART condition, then we have no percentage/drumroll values + # to use for the branchInfo bytes when writing to the fumen. So, we just use default values (-1, -1). + if branch_condition is None: + branch_condition = ['#SECTION', -1, -1] + # Otherwise, if #SECTION occurs after a #BRANCHSTART condition, then we just repeat the previous + # condition (to set the correct branchInfo bytes for this measure.) + currentEvent = TJAData('branchStart', branch_condition, pos) elif line.name == 'BRANCHSTART': if flagLevelhold: continue currentBranch = 'all' # Ensure that the #BRANCHSTART command is present for all branches - values = line.value.split(',') - if values[0] == 'r': # r = drumRoll - values[1] = int(values[1]) # # of drumrolls - values[2] = int(values[2]) # # of drumrolls - elif values[0] == 'p': # p = Percentage - values[1] = float(values[1]) / 100 # % - values[2] = float(values[2]) / 100 # % - currentEvent = TJAData('branchStart', values, pos) + branch_condition = line.value.split(',') + if branch_condition[0] == 'r': # r = drumRoll + branch_condition[1] = int(branch_condition[1]) # # of drumrolls + branch_condition[2] = int(branch_condition[2]) # # of drumrolls + elif branch_condition[0] == 'p': # p = Percentage + branch_condition[1] = float(branch_condition[1]) / 100 # % + branch_condition[2] = float(branch_condition[2]) / 100 # % + currentEvent = TJAData('branchStart', branch_condition, pos) idx_m_branchstart = idx_m # Preserve the index of the BRANCHSTART command to re-use for each branch # Append event to the current measure's events for branch in course.branches.keys() if currentBranch == 'all' else [currentBranch]: course.branches[branch][idx_m].events.append(currentEvent) - elif line.name == 'SECTION': - # Simply repeat the same #BRANCHSTART condition that happened previously - # The purpose of #SECTION is to "Reset accuracy values for notes and drumrolls on the next measure." - course.branches[branch][idx_m].events.append(TJAData('branchStart', values, pos)) # 3. Parse commands that don't create an event (e.g. simply changing the current branch) else: diff --git a/testing/data/genpe.tja b/testing/data/genpe.tja new file mode 100644 index 0000000..6121310 --- /dev/null +++ b/testing/data/genpe.tja @@ -0,0 +1,932 @@ +BPM:130.809005737305 +OFFSET:-2.185 + +COURSE:Edit +LEVEL:10 +STYLE:Single +BALLOON: +SCOREINIT:380 +SCOREDIFF:90 + +#START +300000200200101010100000300000200200101010100000, +#BPMCHANGE 126.651481628418 +100020002000100020002000500000000000000000000000, +#BPMCHANGE 133.79866027832 +000000000000000000000000000000000000000000000000, +#BPMCHANGE 134.100387573242 +008000000000000000000000000000000000000000000000, +#BPMCHANGE 125.664978027344 +#SCROLL 1.05999994277954 +100000000000200000200000100000200200200000100000, +#BPMCHANGE 127.921951293945 +#SCROLL 1.03999996185303 +100000000000000000200000200000000000000000200200, +#BPMCHANGE 130.834686279297 +#SCROLL 1 +100000000000200000200000100000200200200000100000, +#BPMCHANGE 131.710662841797 +#MEASURE 2/4 +100000000000200000200000, +#BPMCHANGE 130.000137329102 +#MEASURE 4/4 +#BARLINEOFF +100000100100200010102000100200100100200010102000, +#BARLINEON +100100100200200100200100200100200200100200000000, +#GOGOSTART +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200100100100200000, +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200100100100200000, +#MEASURE 2/4 +100200100100200200100200, +#GOGOEND +#MEASURE 4/4 +#BARLINEOFF +100100101010200100100100100100101010200100100100, +#BARLINEON +100100101010200100100100200100200100200100200100, +100100101010200100100100100100101010200100100100, +100100101010200100100100200100200100200100200100, +#MEASURE 2/4 +100200100100200200100200, +#MEASURE 4/4 +#BARLINEOFF +100000001010200100200200100200200100200200100000, +#BARLINEON +101010000000202020000000101010000000200200100000, +100000001010200100200200100200200100200200100000, +101010000000202020000000101010000000300000000000, +#GOGOSTART +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200100100100200000, +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200100100100200000, +#GOGOEND +#MEASURE 2/4 +100200100100200200100200, +#MEASURE 4/4 +#BARLINEOFF +100000200100100200000100100200200100100000200100, +#BARLINEON +100000200100100200000100100200200100200100100200, +100000200100100200000100100200200100100000200100, +100000200100100200000100100200200100200100100200, +100000200100100200000100100200200100100000200100, +100000200100100200000100100200200100200100100200, +100000200100100200000100100200200100100000100200, +200100100200100200200100100200100200200100100200, +100000200000100100200000100010200010100100200000, +100000200000100100200000100010200010100100200000, +100000200000100100200000100010200010100100200000, +100000200000100100200000100010200010100010200000, +100000200000100100200000100010200010100100200000, +100000200000100100200000100010200010100100200000, +100000200000100100200000100010200010100100200000, +100000200000100100200000100010200010100010200010, +100000000000000000000000100000000000100000100000, +100100100100200100100200100100100100200100100200, +100100100100200100100200100200100100201010100000, +#MEASURE 2/4 +300000300000200200200200, +#GOGOSTART +#MEASURE 4/4 +#BARLINEOFF +100000101010200100000100100000101010200100000100, +#BARLINEON +100000101010200100000100100100200200100100200000, +100000101010200100000100100000101010200100000100, +100000101010200100000100100100200200100100200000, +#GOGOEND +#MEASURE 2/4 +100200100100200200100200, +#MEASURE 4/4 +#BARLINEOFF +100100101010200100100100100100101010200100100100, +#BARLINEON +100100101010200100100100200100200100200100200100, +100100101010200200100100100100101010200200100100, +100100101010200200100100200100200100200100200100, +#MEASURE 2/4 +100200100100200200100200, +#MEASURE 4/4 +#BARLINEOFF +100000200100100200000100100200000200100100200100, +#BARLINEON +100000200100100200000100100200000100100200200100, +100000200100100200000100100200000200100100200100, +100000200100100200000100100200000100100200200100, +100000200100100200000100100200100100200000200100, +100000200100100200000100100200100100200000200100, +200000200100100200000200000200100100200000200000, +100200000200200200000200200200000200000300000000, +100000200100100200000100100200200100100000200100, +100000200100100200000200200100100200200000200100, +100000200100100200000100100200200100100000200100, +100000200100100200000200200100100200200000200100, +100000200100100200000100100200100200200100200100, +100000200100100200000100100200100200200100200100, +100000200200100100000000200200100100000000200000, +100100000000200000100100000200000100000300000000, +#GOGOSTART +100000101010200100000100100000101010200100000100, +100000101010200100100200100100200100200000000000, +100000101010200100000100100000101010200100000100, +100000101010200100100200100100200100200000000100, +#SECTION +#BRANCHSTART p, 52.85412, 73.99577 +#N +100000201010200100000100200000000000300000000100, +100000201010200100000100200000000000300000000100, +100000201010200100000100200000000000300000000100, +100000201010200100000100508000000000000000000000, +#GOGOEND +000000000000000000000000000000000000000000000000, +000000000000000000000000000000000000000000000000, +#E +100000201010200100000100200000000000300000000100, +100000201010200100000100200000000000300000000100, +100000201010200100000100200000000000300000000100, +100000201010200100100100508000000000000000000000, +#GOGOEND +000000000000000000000000000000000000000000000000, +000000000000000000000000000000000000000000000000, +#M +100000201010200100000100200000000000300000000100, +100000201010200100000100200000000000300000000100, +100000201010200100000100200000000000300000000100, +100000201010200100100100100000000000000000000000, +#GOGOEND +000000000000000000000000000000000000000000000000, +000000000000000000000000000000000000000000000000, +#BRANCHEND +#END + +// NB: I currently do not have an official fumen +// that has the correct 2P charts, so I've +// commented them out for now. +//STYLE:Double +//BALLOON:8 +//SCOREINIT:380 +//SCOREDIFF:90 +// +//#START P1 +//300000000000000000000000600000000008000000000000, +//#BPMCHANGE 126.651481628418 +//100000000000300000000000500000000000000000000000, +//#BPMCHANGE 133.79866027832 +//000000000000000000000000000000000000000000000000, +//#BPMCHANGE 134.100387573242 +//008000000000000000000000000000000000000000000000, +//#BPMCHANGE 125.664978027344 +//#SCROLL 1.01999998092651 +//000000000000000000000000100000100000100000100000, +//#BPMCHANGE 127.921951293945 +//#SCROLL 1 +//200000000000000000200000200000000000000000000000, +//#BPMCHANGE 130.834686279297 +//#SCROLL 0.980000019073486 +//000000000000000000000000000000000000000000000000, +//#BPMCHANGE 131.710662841797 +//#SCROLL 1 +//#MEASURE 2/4 +//000000000000000000000000, +//#BPMCHANGE 130.000137329102 +//#MEASURE 4/4 +//100000000000200000000000100000100100200000000000, +//700000000000000000000000008000000000100200000000, +//#GOGOSTART +//100000100100200000000000100000100100200000000000, +//100000100100200000000000000000200000000000200000, +//100000000000200000100100100000000000200000100100, +//100000000000200000100000100100100000100100100000, +//#MEASURE 2/4 +//300000000000000000000000, +//#GOGOEND +//#MEASURE 4/4 +//000000100100200000100100000000100100200000100100, +//000000100100200000100100100000100000100000100000, +//100000200000100100000000100000200000100100000000, +//100000200000100100000000100000100000100000100000, +//#MEASURE 2/4 +//100100100000100100100000, +//#MEASURE 4/4 +//100000000100100000200000100000000000000000000000, +//100100000000200200000000100100000000200200200000, +//100000000000200000000000100100200000000000000000, +//100100000000200200000000100100000000300000000000, +//#GOGOSTART +//100000000000200000100100100000000000200000100100, +//100000000000200000100000100100100000100100100000, +//100000100100200000000000100000100100200000000000, +//100000100100200000100000000000200000000000200000, +//#GOGOEND +//#MEASURE 2/4 +//300000000000000000000000, +//#MEASURE 4/4 +//100000000100100000000100100000000100100000200000, +//100000000100100000000100100000000100100000200000, +//100000000100100000000100100000000100100000200000, +//100000000100100000000000100000000100000000200000, +//100000000000200000000000100200100000200000000000, +//100000000000200000000000100200100000200000000000, +//000000000000000000000000200200200200200000000000, +//000000000000200200200200100000000000000000000000, +//100000200000100100100000100000200000100100100000, +//100000200000000000200000100000200000000000200000, +//100000200000100100100000100000200000100100100000, +//100000200000000000200000100000200000000000200000, +//100000200000100100100000100000200000100100100000, +//100000200000000000200000100000200000000000200000, +//100000200000100100100000100000200000100100100000, +//000000000000100100100000000000000000100100100100, +//100000000000000000000000100000000000100000000000, +//100100100100000000000000100100100100000000000000, +//200200200200000000000000200200200200000000000000, +//#MEASURE 2/4 +//300000000000000000000000, +//#GOGOSTART +//#MEASURE 4/4 +//100000100100200000000000100000100100200000000000, +//100000100100200000000000000000200000000000200000, +//100000000000200000100100100000000000200000100100, +//100000000000200000100000100100100000100100100000, +//#GOGOEND +//#MEASURE 2/4 +//300000000000000000000000, +//#MEASURE 4/4 +//000000100100200200100100000000100100200200100100, +//000000100100200200100100100000100000100000100000, +//100000200000100100000000100000200000100100000000, +//100000200000100100000000100000100000100000100000, +//#MEASURE 2/4 +//100100100000100100100000, +//#MEASURE 4/4 +//100000200100100000000100100000000100100000200000, +//100000200100100000000100100000000100100000200000, +//100000000000200000000000100200100000200000000000, +//100000000000200000000000100200100000200000000000, +//100000200100100000000100100000000100100000200000, +//100000200100100000000100100000000100100000200000, +//000000000000000000000000000000000000200000200000, +//100000000000100000000000100000100000000300000000, +//100000000100200000000000100200100000200000000000, +//100000000100200000000000100200100000200000000000, +//100000200100100000000100100000000100100000200000, +//100000200100100000000100100000000200200000200000, +//100000000100200000000000100200100000200000000000, +//100000000100200000000000100200100000100000000000, +//000000100000100100000000000000000000000000100000, +//100100000000000000000000000000100000000300000000, +//#GOGOSTART +//100000100100200000000000100000100100200000000000, +//100000100100200000000000100000000000300000000000, +//100000000000200000100100100000000000200000100100, +//100000000000200000100100100000000000000000000000, +//100000100100100100000100100000000000300000000000, +//100000000000200000100000100000000000300000000000, +//100000100100100100000100100000000000300000000000, +//100000100100200200000200100000000000000000000000, +//#GOGOEND +//000000000000000000000000000000000000000000000000, +//000000000000000000000000000000000000000000000000, +//#END +// +//BALLOON:8 +//SCOREINIT:690 +//SCOREDIFF:90 +// +//#START P2 +//600000000008000000000000300000000000000000000000, +//#BPMCHANGE 126.651481628418 +//100000000000300000000000500000000000000000000000, +//#BPMCHANGE 133.79866027832 +//000000000000000000000000000000000000000000000000, +//#BPMCHANGE 134.100387573242 +//008000000000000000000000000000000000000000000000, +//#BPMCHANGE 125.664978027344 +//#SCROLL 1.01999998092651 +//000000000000000000000000000000000000000000000000, +//#BPMCHANGE 127.921951293945 +//#SCROLL 1 +//000000000000000000000000000000000000000000000000, +//#BPMCHANGE 130.834686279297 +//#SCROLL 0.980000019073486 +//100000000000000000000000100000100000100000100000, +//#BPMCHANGE 131.710662841797 +//#SCROLL 1 +//#MEASURE 2/4 +//200000000000200000200000, +//#BPMCHANGE 130.000137329102 +//#MEASURE 4/4 +//100000000000200000000000100000100100200000000000, +//700000000000000000000000008000000000100200000000, +//#GOGOSTART +//100000000000200000100100100000000000200000100100, +//100000000000200000100000100100100000100100100000, +//100000100100200000000000100000100100200000000000, +//100000100100200000000000000000200000000000200000, +//#MEASURE 2/4 +//300000000000000000000000, +//#GOGOEND +//#MEASURE 4/4 +//100000200000100100000000100000200000100100000000, +//100000200000100100000000100000100000100000100000, +//000000100100200000100100000000100100200000100100, +//000000100100200000100100100000100000100000100000, +//#MEASURE 2/4 +//100100100000100100100000, +//#MEASURE 4/4 +//100000000000200000000000100100200000000000000000, +//100100000000200200000000100100000000200200200000, +//100000000100100000200000100000000000000000000000, +//100100000000200200000000100100000000300000000000, +//#GOGOSTART +//100000100100200000000000100000100100200000000000, +//100000100100200000000000000000200000000000200000, +//100000000000200000100000100000000000200000100000, +//100000000000200000100000100100100000100100100000, +//#GOGOEND +//#MEASURE 2/4 +//300000000000000000000000, +//#MEASURE 4/4 +//100000000000200000000000100200100000200000000000, +//100000000000200000000000100200100000200000000000, +//100000000000200000000000100200100000200000000000, +//100000000000200000000000100000000100000000200000, +//100000000100100000000100100000000100100000200000, +//100000000100100000000100100000000100100000200000, +//100100100100100000000000000000000000000000100100, +//100100100000000000000000000000000000000000000000, +//100000200000000000200000100000200000000000200000, +//100000200000100100100000100000200000100100100000, +//100000200000000000200000100000200000000000200000, +//100000200000100100100000100100100000100100100000, +//100000200000000000200000100000200000000000200000, +//100000200000100100100000100000200000100100100000, +//100000200000000000200000100000200000000000200000, +//100100100000000000000000100100100100000000000000, +//100000000000000000000000100000000000100000000000, +//000000000000200200200200000000000000200200200200, +//000000000000100100100100000000000000100100100000, +//#MEASURE 2/4 +//300000000000000000000000, +//#GOGOSTART +//#MEASURE 4/4 +//100000000000200000100100100000000000200000100100, +//100000000000200000100000100100100000100100100000, +//100000100100200000000000100000100100200000000000, +//100000100100200000100000100100100000100100100000, +//#GOGOEND +//#MEASURE 2/4 +//300000000000000000000000, +//#MEASURE 4/4 +//100000200000100100000000100000200000100100000000, +//100000200000100100000000100000100000100000100000, +//000000100100200200100100000000100100200200100100, +//000000100100200200100100100000100000100000100000, +//#MEASURE 2/4 +//100100100000100100100000, +//#MEASURE 4/4 +//100000000000200000000000100200100000200000000000, +//100000000000200000000000100200100000200000000000, +//100000200100100000000100100000000100100000200000, +//100000200100100000000100100000000200200000200000, +//100000000000200000000000100200100000200000000000, +//100000000000200000000000100200100000200000000000, +//000000000000000000000000000000000000200000200000, +//100000000000100000000000100000100000000300000000, +//100000200100100000000100100000000100100000200000, +//100000200100100000000100100000000100100000200000, +//100000000100200000000000100200100000200000000000, +//100000000100200000000000100200100000200000000000, +//100000200100100000000100100000000100100000200000, +//100000200100100000000100100000000100100000200000, +//000000000000000000000000100000100100000000000000, +//000000000000100000100100000000100000000300000000, +//#GOGOSTART +//100000000000200000100100100000000000200000100100, +//100000000000200000100100100000000000000000000000, +//100000100100200000000000100000100100200000000000, +//100000100100200000000000100000000000300000000000, +//100000000000200000100000100000000000300000000000, +//100000100100100100000100100000000000300000000000, +//100000000000200000100000100000000000300000000000, +//100000100100200200000200100000000000000000000000, +//#GOGOEND +//000000000000000000000000000000000000000000000000, +//000000000000000000000000000000000000000000000000, +//#END + +COURSE:Oni +LEVEL:8 +BALLOON: +SCOREINIT:410 +SCOREDIFF:107 + +#START +100000000000000000000000100000000000000000000000, +#BPMCHANGE 126.651481628418 +100000000000100000000000500000000000000000000000, +#BPMCHANGE 133.79866027832 +000000000000000000000000000000000000000000000000, +#BPMCHANGE 134.100387573242 +008000000000000000000000000000000000000000000000, +#BPMCHANGE 125.664978027344 +#SCROLL 1.01999998092651 +000000000000000000000000100000100000100000100000, +#BPMCHANGE 127.921951293945 +#SCROLL 1 +200000000000000000200000200000000000000000000000, +#BPMCHANGE 130.834686279297 +#SCROLL 0.980000019073486 +000000000000000000000000100000100000100000100000, +#BPMCHANGE 131.710662841797 +#SCROLL 1 +#MEASURE 2/4 +200000000000200000200000, +#BPMCHANGE 130.000137329102 +#MEASURE 4/4 +100000100100200000000000100200100100200000000000, +100100100200000100000100000100000100100200000000, +#GOGOSTART +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200000100100200000, +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200000100100200000, +#MEASURE 2/4 +100000100100100100100100, +#GOGOEND +#MEASURE 4/4 +000000100100200000100100000000100100200000100100, +000000100100200000100100100000100000100000100000, +000000100100200000100100000000100100200000100100, +000000100100200000100100100000100000100000100000, +#MEASURE 2/4 +100000100000200200100100, +#MEASURE 4/4 +100000000100100100200200100000000000000000000000, +100100000000200200000000100100000000200200100000, +100000000100100100200200100000000000000000000000, +100100000000200200000000100100100000300000000000, +#GOGOSTART +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200000100100200000, +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200000100100200000, +#GOGOEND +#MEASURE 2/4 +100000200200200200200200, +#MEASURE 4/4 +100000000100100000000100100000000100100000200000, +100000000100100000000100100000000100100200200100, +100000000100100000000100100000000100100000200000, +100000000100100000000100100200200100100200200100, +100000000100100000000100100000000100100000200000, +100000000100100000000100100000000100100200200100, +100000000100100000000100100200200100100000100200, +200100100000100200200100100000000000000000000000, +100000200000100100200000100000200000100100200000, +100000200000100100200000100000200000100100200000, +100000200000100100200000100000200000100100200000, +100000200000100100200000100100200100100100200100, +100000200000100100200000100000200000100100200000, +100000200000100100200000100000200000100100200000, +100000200000100100200000100000200000100100200000, +100100200100100100200100100100100100100100100100, +100000000000000000000000100000000000100000000000, +100000100000200000100200100000100000200000100200, +100000100000200000100200100200100000100100100000, +#MEASURE 2/4 +300000000000000000000000, +#GOGOSTART +#MEASURE 4/4 +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200000100100200000, +100000100100200100000100100000100100200100000100, +100000100100200100000100100100200000100100200000, +#GOGOEND +#MEASURE 2/4 +100000100100100100100100, +#MEASURE 4/4 +100000100100200000100100100000100100200000100100, +100000100100200000100100100000100000100000100000, +100000100100200200100100100000100100200200100100, +100000100100200200100100100000100000100000100000, +#MEASURE 2/4 +100000100000100100100100, +#MEASURE 4/4 +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000200200000200200, +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000100100000200100, +200000200000000200000200000200000000200000200000, +100200000200200200000200200200000200000300000000, +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000200000200100100, +100000200100100200000100100200000100100000200100, +100000200100100200000100100200000100100000200100, +000000200000100100000000200000100100000000200000, +100100000000200000100100000000100000000300000000, +#GOGOSTART +100000100100200100000100100000100100200100000100, +100000100100200100000100100000000000300000000000, +100000100100200100000100100000100100200100000100, +100000100100200100000100100000000000300000000000, +100000100100200100000100100000000000300000000000, +100000100100200100000100100000000000300000000000, +100000100100200100000100100000000000300000000000, +100000100100100100000100100000000000000000000000, +#GOGOEND +000000000000000000000000000000000000000000000000, +000000000000000000000000000000000000000000000000, +#END + +COURSE:Hard +LEVEL:7 +BALLOON:8 +SCOREINIT:430 +SCOREDIFF:105 + +#START +100000000000000000000000100000000000000000000000, +#BPMCHANGE 126.651481628418 +100000000000100000000000500000000000000000000000, +#BPMCHANGE 133.79866027832 +000000000000000000000000000000000000000000000000, +#BPMCHANGE 134.100387573242 +008000000000000000000000000000000000000000000000, +#BPMCHANGE 125.664978027344 +#SCROLL 1.01999998092651 +000000000000000000000000100000100000100000100000, +#BPMCHANGE 127.921951293945 +#SCROLL 1 +200000000000000000200000200000000000000000000000, +#BPMCHANGE 130.834686279297 +#SCROLL 0.980000019073486 +100000000000000000000000100000100000100000100000, +#BPMCHANGE 131.710662841797 +#SCROLL 1 +#MEASURE 2/4 +200000000000200000200000, +#BPMCHANGE 130.000137329102 +#MEASURE 4/4 +100000000000200000000000100000100100200000000000, +700000000000000000000000008000000000100200000000, +#GOGOSTART +100000100100200000000000100000100100200000000000, +100000100100200000000000100100100000100100100000, +100000100100200000000000100000100100200000000000, +100000100100200000000000100100100000100100100000, +#MEASURE 2/4 +300000000000000000000000, +#GOGOEND +#MEASURE 4/4 +000000100100200000100100000000100100200000100100, +000000100100200000100100100000100000100000100000, +000000100100200000100100000000100100200000100100, +000000100100200000100100100000100000100000100000, +#MEASURE 2/4 +100000100000100100100000, +#MEASURE 4/4 +100000000100100000200000100000000000000000000000, +100100000000200200000000100100000000200200200000, +100000000100100000200000100000000000000000000000, +100100000000200200000000100100100000300000000000, +#GOGOSTART +100000100100200000000000100000100100200000000000, +100000100100200000000000100100100000100100100000, +100000100100200000000000100000100100200000000000, +100000100100200000000000100100100000100100100000, +#GOGOEND +#MEASURE 2/4 +300000000000000000000000, +#MEASURE 4/4 +100000000100100000000100100000000100100000200000, +100000000100100000000100100000000100100000200000, +100000000100100000000100100000000100100000200000, +100000000100100000000000200000000200000000200000, +100000000100100000000100100000000100100000200000, +100000000100100000000100100000000100100000200000, +100100100100100000000000200200200200200000100100, +100100100000200200200200100000000000000000000000, +100000200000100100100000100000200000100100100000, +100000200000100100100000100000200000100100100000, +100000200000100100100000100000200000100100100000, +100000200000100100100000100100100000100100100000, +100000200000100100100000100000200000100100100000, +100000200000100100100000100000200000100100100000, +100000200000100100100000100000200000100100100000, +100100100000100100100000100100100100100100100100, +100000000000000000000000100000000000100000000000, +100000100000200000000200100000100000200000000200, +100000100000200000000200100100100000100100100000, +#MEASURE 2/4 +300000000000000000000000, +#GOGOSTART +#MEASURE 4/4 +100000100100200000000000100000100100200000000000, +100000100100200000000000100100100000100100100000, +100000100100200000000000100000100100200000000000, +100000100100200000000000100100100000100100100000, +#GOGOEND +#MEASURE 2/4 +300000000000000000000000, +#MEASURE 4/4 +000000100100200000100100000000100100200000100100, +000000100100200000100100100000100000100000100000, +000000100100200200100100000000100100200200100100, +000000100100200200100100100000100000100000100000, +#MEASURE 2/4 +300000000000000000000000, +#MEASURE 4/4 +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000200200000200000, +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000100100000200000, +200000200000000200000200000200000000200000200000, +100000000000100000000000100000100000000300000000, +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000200200000200000, +100000200100100000000100100000000100100000200000, +100000200100100000000100100000000100100000200000, +000000100000100100000000100000100100000000100000, +100100000000100000100100000000100000000300000000, +#GOGOSTART +100000100100200000000000100000100100200000000000, +100000100100200000000000100000000000300000000000, +100000100100200000000000100000100100200000000000, +100000100100200000000000100000000000300000000000, +100000100100100100000100100000000000300000000000, +100000100100200200000200200000000000300000000000, +100000100100100100000100100000000000300000000000, +100000100100200200000200100000000000000000000000, +#GOGOEND +000000000000000000000000000000000000000000000000, +000000000000000000000000000000000000000000000000, +#END + +COURSE:Normal +LEVEL:5 +BALLOON: +SCOREINIT:720 +SCOREDIFF:235 + +#START +300000000000000000000000300000000000000000000000, +#BPMCHANGE 126.651481628418 +100000000000100000000000500000000000000000000000, +#BPMCHANGE 133.79866027832 +000000000000000000000000000000000000000000000000, +#BPMCHANGE 134.100387573242 +008000000000000000000000000000000000000000000000, +#BPMCHANGE 125.664978027344 +#SCROLL 1.01999998092651 +100000000000000000000000200000000000000000000000, +#BPMCHANGE 127.921951293945 +#SCROLL 1 +100000100000000000000000200000000000000000000000, +#BPMCHANGE 130.834686279297 +#SCROLL 0.980000019073486 +100000000000000000000000200000000000000000000000, +#BPMCHANGE 131.710662841797 +#SCROLL 1 +#MEASURE 2/4 +100000100000000000000000, +#BPMCHANGE 130.000137329102 +#MEASURE 4/4 +500000000000000000000000000000000000000000000008, +000000000000000000000000000000000000000000000000, +#GOGOSTART +100000100000100000000000100000000000100000000000, +100000000000100000100000100000000000000000000000, +100000100000100000000000100000000000100000000000, +100000000000100000100000100000000000000000000000, +#GOGOEND +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +000000000000100100000000000000000000100100000000, +000000000000000000000000100000100000100000100000, +000000000000200200000000000000000000200200000000, +000000000000000000000000100000100000100000100000, +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +100000000000000000000000200000000000000000000000, +100100000000000000000000200200000000000000000000, +100000000000000000000000200000000000000000000000, +100100000000000000000000200200000000000000000000, +#GOGOSTART +100000100000100000000000100000000000100000000000, +100000000000100000100000100000000000000000000000, +100000100000100000000000100000000000100000000000, +100000000000100000100000100000000000000000000000, +#GOGOEND +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +100000000000000000000000100100000000000000000000, +100000000000000000000000100100000000000000000000, +100000000000000000000000200200000000000000100100, +100000000100000000000000000000000000000000000000, +100000000000000000000000100100000000000000000000, +100000000000000000000000100100000000000000000000, +100000000000000000000000100000100000100000000000, +000000000000000000000000000000000000000000000000, +100000100000000000200000000000000000000000000000, +100000000000200000000000000000000000000000000000, +100000100000000000000000100000100000000000000000, +100000100000000000000000000000000000000000000000, +100000100000000000200000000000000000000000000000, +100000000000200000000000000000000000000000000000, +100000100000000000000000100000100000000000000000, +500000000000000000000000000000000000000000000008, +000000000000000000000000300000000000300000000000, +100000000000200000000000000000000000000000000000, +100000000000200000000000100000000000000000000000, +#MEASURE 2/4 +000000000000000000000000, +#GOGOSTART +#MEASURE 4/4 +100000100000100000000000100000100000100000000000, +100000000000100000100000100000000000000000000000, +100000100000100000000000100000100000100000000000, +100000000000100000100000100000000000000000000000, +#GOGOEND +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +000000000000100100000000000000000000100100000000, +000000000000000000000000100000100000100000100000, +000000000000100100000000000000000000100100000000, +000000000000000000000000100000100000100000100000, +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +100000000000000000000000100000000000000000000000, +100000100000000000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +100000100000000000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +200000000000200000000000200000000000000000000000, +000000000000000000000000000000000000000000000000, +100000000000100000000000100000100000000000000000, +100000000000000000000000100000000000000000000000, +100000100000000000000000200000000000000000000000, +100000000000000000000000100000000000000000000000, +100000100000000000000000200000000000000000000000, +100000000000200000000000100000000000200000000000, +100000000000200000000000100000000000200000000000, +100000000000000000000000100000000100000000100000, +000100000000100000000000000000000000000000000000, +#GOGOSTART +100000100000100000000000100000100000100000000000, +100000000000100000100000100000000000000000000000, +100000100000100000000000100000100000100000000000, +100000000000100000100000100000000000000000000000, +100000100000100000000000100000000000300000000000, +100000100000100000000000100000000000300000000000, +100000100000100000000000100000000000300000000000, +100000100000100000000000300000000000000000000000, +#GOGOEND +000000000000000000000000000000000000000000000000, +000000000000000000000000000000000000000000000000, +#END + +COURSE:Easy +LEVEL:4 +BALLOON:10 +SCOREINIT:650 +SCOREDIFF:245 + +#START +300000000000000000000000300000000000000000000000, +#BPMCHANGE 126.651481628418 +100000000000100000000000500000000000000000000000, +#BPMCHANGE 133.79866027832 +000000000000000000000000000000000000000000000000, +#BPMCHANGE 134.100387573242 +008000000000000000000000000000000000000000000000, +#BPMCHANGE 125.664978027344 +#SCROLL 1.01999998092651 +100000000000000000000000200000000000000000000000, +#BPMCHANGE 127.921951293945 +#SCROLL 1 +100000000000000000000000100000000000000000000000, +#BPMCHANGE 130.834686279297 +#SCROLL 0.980000019073486 +100000000000000000000000200000000000000000000000, +#BPMCHANGE 131.710662841797 +#SCROLL 1 +#MEASURE 2/4 +100000000000000000000000, +#BPMCHANGE 130.000137329102 +#MEASURE 4/4 +500000000000000000000000000000000000000000000008, +000000000000000000000000000000000000000000000000, +#GOGOSTART +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +#MEASURE 2/4 +000000000000000000000000, +#GOGOEND +#MEASURE 4/4 +100000000000000000000000100000000000000000000000, +100000000000000000000000300000000000000000000000, +100000000000000000000000100000000000000000000000, +100000000000000000000000300000000000000000000000, +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +100000000000000000000000200000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000000000000000200000000000000000000000, +100000000000100000000000100000000000000000000000, +#GOGOSTART +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +#GOGOEND +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +100000000000000000000000100100000000000000000000, +100000000000000000000000100100000000000000000000, +100000000000000000000000100100000000000000000000, +100000000000000000000000000000000000000000000000, +100000000000000000000000100100000000000000000000, +100000000000000000000000100100000000000000000000, +100000000000000000000000700000000000000000000000, +000000000000000000000000000080000000000000000000, +100000000000000000000000100000100000000000000000, +100000000000100000000000000000000000000000000000, +100000000000000000000000100000100000000000000000, +100000000000100000000000000000000000000000000000, +100000000000000000000000100000100000000000000000, +100000000000100000000000000000000000000000000000, +100000100000000000000000100000100000000000000000, +500000000000000000000000000000000000000000000008, +000000000000000000000000000000000000000000000000, +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000100000000000, +#MEASURE 2/4 +000000000000000000000000, +#GOGOSTART +#MEASURE 4/4 +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +#GOGOEND +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +100000000000000000000000100000000000000000000000, +100000000000000000000000300000000000000000000000, +100000000000000000000000100000000000000000000000, +100000000000000000000000300000000000000000000000, +#MEASURE 2/4 +000000000000000000000000, +#MEASURE 4/4 +100000000000000000000000100000000000000000000000, +100000100000000000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +100000100000000000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +200000000000200000000000200000000000000000000000, +000000000000000000000000000000000000000000000000, +100000000000100000000000100000100000000000000000, +100000000000000000000000000000000000000000000000, +100000100000000000000000200000000000000000000000, +100000000000000000000000000000000000000000000000, +100000100000000000000000200000000000000000000000, +100000000000200000000000100000000000000000000000, +100000000000200000000000100000000000000000000000, +100000000000000000000000500000000000000000000000, +000000000000000000000000000008000000000000000000, +#GOGOSTART +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000000000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000100000000000100000000000000000000000, +100000000000100000000000300000000000000000000000, +#GOGOEND +000000000000000000000000000000000000000000000000, +000000000000000000000000000000000000000000000000, +#END diff --git a/testing/data/genpe.zip b/testing/data/genpe.zip new file mode 100644 index 0000000000000000000000000000000000000000..9ecbcb72ea7344de8d9f5462fea6a11d777ae01f GIT binary patch literal 14505 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