1
0
mirror of synced 2024-11-23 21:20:56 +01:00

parsers.py: Add function to equalize branches

Fixes https://github.com/vivaria/tja2fumen/issues/67.
This commit is contained in:
Viv 2024-02-10 19:21:35 -05:00
parent b5e4f9dc7c
commit f018c54089

View File

@ -230,6 +230,8 @@ def parse_tja_course_data(data: List[str]) -> Dict[str, List[TJAMeasure]]:
if note_data.endswith(','):
for branch_name in (BRANCH_NAMES if current_branch == 'all'
else [current_branch]):
check_branch_length(parsed_branches, branch_name,
expected_len=idx_m+1)
parsed_branches[branch_name][idx_m].notes += note_data[:-1]
parsed_branches[branch_name].append(TJAMeasure())
idx_m += 1
@ -247,6 +249,8 @@ def parse_tja_course_data(data: List[str]) -> Dict[str, List[TJAMeasure]]:
pos = 0
for branch_name in (BRANCH_NAMES if current_branch == 'all'
else [current_branch]):
check_branch_length(parsed_branches, branch_name,
expected_len=idx_m+1)
pos = len(parsed_branches[branch_name][idx_m].notes)
# Parse event type
@ -288,12 +292,18 @@ def parse_tja_course_data(data: List[str]) -> Dict[str, List[TJAMeasure]]:
current_branch = 'all'
name = 'branch_start'
branch_condition = value
# If a branch was intentionally excluded by the charter,
# make sure to copy measures from the longest branch.
for branch_name in BRANCH_NAMES:
check_branch_length(parsed_branches, branch_name)
# Preserve the index of the BRANCHSTART command to re-use
idx_m_branchstart = idx_m
# Append event to the current measure's events
for branch_name in (BRANCH_NAMES if current_branch == 'all'
else [current_branch]):
check_branch_length(parsed_branches, branch_name,
expected_len=idx_m+1)
parsed_branches[branch_name][idx_m].events.append(
TJAData(name=name, value=value, pos=pos)
)
@ -320,9 +330,18 @@ def parse_tja_course_data(data: List[str]) -> Dict[str, List[TJAMeasure]]:
# Delete the last measure in the branch if no notes or events
# were added to it (due to preallocating empty measures)
deleted_branches = False
for branch in parsed_branches.values():
if not branch[-1].notes and not branch[-1].events:
del branch[-1]
deleted_branches = True
if deleted_branches:
idx_m -= 1
# Equalize branch lengths to account for missing branches
for branch_name, branch in parsed_branches.items():
if branch:
check_branch_length(parsed_branches, branch_name)
# Merge measure data and measure events in chronological order
for branch_name, branch in parsed_branches.items():
@ -354,6 +373,7 @@ def parse_tja_course_data(data: List[str]) -> Dict[str, List[TJAMeasure]]:
# Ensure all branches have the same number of measures
if has_branches:
if len({len(b) for b in parsed_branches.values()}) != 1:
# If `check_branch_length` works, this should never be reached
raise ValueError(
"Branches do not have the same number of measures. (This "
"check was performed prior to splitting up the measures due "
@ -364,6 +384,47 @@ def parse_tja_course_data(data: List[str]) -> Dict[str, List[TJAMeasure]]:
return parsed_branches
def check_branch_length(parsed_branches: Dict[str, List[TJAMeasure]],
branch_name: str, expected_len: int = 0) -> None:
"""
Ensure that a given branch ('branch_name') matches either an expected
integer length, or the max length of all branches if length not given.
Note: Modifies branch in-place.
"""
branch_len = len(parsed_branches[branch_name])
# If no length is provided, then we assume we're comparing branches,
# then copying any missing measures from the largest branch.
if expected_len == 0:
max_branch_name = branch_name
expected_len = branch_len
for name, branch in parsed_branches.items():
if len(branch) > expected_len:
expected_len = len(branch)
max_branch_name = name
warning_msg = (f"To fix this, measures will be copied from the "
f"'{max_branch_name}' branch to equalize branch "
f"lengths.")
for idx_m in range(branch_len, expected_len):
parsed_branches[branch_name].append(
parsed_branches[max_branch_name][idx_m]
)
# Otherwise, if length was provided, then simply pad with empty measures
else:
warning_msg = ("To fix this, empty measures will be added to "
"equalize branch lengths.")
for idx_m in range(branch_len, expected_len):
parsed_branches[branch_name].append(TJAMeasure())
if branch_len < expected_len:
warnings.warn(
f"While parsing the TJA's branches, tja2fumen expected "
f"{expected_len} measure(s) from the '{branch_name}' branch, but "
f"it only had {branch_len} measure(s). {warning_msg} (Hint: Do "
f"#N, #E, and #M all have the same number of measures?)"
)
###############################################################################
# Fumen-parsing functions #
###############################################################################