Files
ESE/tjavalidator.py
T

198 lines
8.4 KiB
Python

from pathlib import Path
from bidict import bidict
def strip_comments(code: str) -> str:
result = ''
index = 0
for line in code.splitlines():
comment_index = line.find('//')
if comment_index == -1:
result += line
elif comment_index != 0 and not line[:comment_index].isspace():
result += line[:comment_index]
index += 1
return result
def data_to_notes(data, diff):
note_start = -1
note_end = -1
target_found = False
diffs = {0: "easy", 1: "normal", 2: "hard", 3: "oni", 4: "edit", 5: "tower", 6: "dan"}
diff_name = diffs.get(diff, "").lower()
i = 0
while i < len(data):
line = data[i]
if line.startswith("COURSE:"):
course_value = line[7:].strip().lower()
if (course_value.isdigit() and int(course_value) == diff) or course_value == diff_name:
target_found = True
else:
target_found = False
if target_found:
if line == "#START":
note_start = i + 1
elif line == "#END" and note_start != -1:
note_end = i
break
i += 1
notes = []
bar = []
for i in range(note_start, note_end):
line = data[i]
if line.startswith("#"):
bar.append(line)
else:
if line == ',':
if len(bar) == 0 or all(item.startswith('#') for item in bar):
bar.append('')
notes.append(bar)
bar = []
else:
item = line.strip(',')
bar.append(item)
if item != line:
notes.append(bar)
bar = []
return notes, note_start, note_end
def validate_tja(tja_file: Path, check_watermark=False):
diffs = bidict({0: "easy", 1: "normal", 2: "hard", 3: "oni", 4: "edit", 5: "tower", 6: "dan"})
try:
tja_file.read_text(encoding='utf-8-sig')
except Exception as e:
print(f'Incorrect Encoding: {tja_file}')
lines = tja_file.read_text(encoding='utf-8-sig').splitlines()
if check_watermark and lines[0] != "//TJADB Project":
print(f'Missing Watermark: {tja_file}')
tja_data = [cleaned for line in lines if (cleaned := strip_comments(line).strip())]
current_diff = None
balloon_data = []
for i, line in enumerate(tja_data):
if line.startswith('TITLE'):
if line.split(':')[1] == 'FIXME':
print(f'FIXME name: {tja_file}')
elif line.startswith('SUBTITLE:'):
subtitle_display = line.split(':')[1][0:2]
if subtitle_display != '--' and subtitle_display != '++':
print(f'Subtitle Display Type Missing: {tja_file}, Line {i}')
elif line.startswith('WAVE:'):
wave_path = tja_file.parent / line.split(':')[1]
if not wave_path.exists():
print(f'WAVE Path Invalid: {tja_file}, Line {i}')
elif wave_path.suffix != '.ogg':
print(f'WAVE is not an OGG: {tja_file}, Line {i}')
elif line.startswith('DEMOSTART:'):
if float(line.split(':')[1]) < 0:
print(f'DEMOSTART value is negative: {tja_file}, Line {i}')
elif line.startswith('SONGVOL:'):
if float(line.split(':')[1]) < 0:
print(f'SONGVOL value is negative: {tja_file}, Line {i}')
elif line.startswith('SEVOL:'):
if float(line.split(':')[1]) < 0:
print(f'SEVOL value is negative: {tja_file}, Line {i}')
elif line.startswith('BPM:'):
if float(line.split(':')[1]) < 0:
print(f'BPM value is negative: {tja_file}, Line {i}')
elif float(line.split(':')[1]) == 0:
print(f'BPM value is 0: {tja_file}')
elif line.split(':')[1] == '':
print(f'BPM value is missing: {tja_file}, Line {i}')
elif line.startswith('BGMOVIE:'):
movie_path = tja_file.parent / line.split(':')[1]
if not movie_path.exists():
print(f'BGMOVIE Path Invalid: {tja_file}, Line {i}')
elif line.startswith('COURSE:'):
if line.split(':')[1].isdigit():
if not (0 <= int(line.split(':')[1]) <= 6):
print(f'COURSE Name Invalid: {tja_file}, Line {i}')
elif line.split(':')[1].lower() not in diffs.inverse:
print(f'COURSE Name Invalid: {tja_file}, Line {i}')
else:
if line.split(':')[1].isdigit():
current_diff = int(line.split(':')[1])
else:
current_diff = diffs.inverse[line.split(':')[1].lower()]
elif line.startswith('LEVEL:'):
if current_diff is None:
print(f'LEVEL was specified with no COURSE: {tja_file}, Line {i}')
else:
if current_diff == 0:
if not (1 <= int(line.split(':')[1]) <= 6):
print(f'Invalid LEVEL range for COURSE:{current_diff} : {tja_file}, Line {i}')
if current_diff == 1:
if not (1 <= int(line.split(':')[1]) <= 7):
print(f'Invalid LEVEL range for COURSE:{current_diff} : {tja_file}, Line {i}')
if current_diff == 2:
if not (1 <= int(line.split(':')[1]) <= 8):
print(f'Invalid LEVEL range for COURSE:{current_diff} : {tja_file}, Line {i}')
if current_diff >= 3:
if not (1 <= int(line.split(':')[1]) <= 10):
print(f'Invalid LEVEL range for COURSE:{current_diff} : {tja_file}, Line {i}')
elif line.startswith('BALLOON:'):
if line.split(':')[1] == '':
continue
for balloon in line.split(':')[1].split(','):
if not balloon.isdigit():
print(f'Invalid Balloon: {tja_file}, Line {i}')
else:
balloon_data.append(int(balloon))
elif line.startswith('SCOREINIT:'):
for scoreinit in line.split(':')[1].split(','):
if not scoreinit.isdigit():
print(f'Invalid SCOREINIT Value: {tja_file}, Line {i}')
elif int(scoreinit) <= 0:
print(f'Invalid SCOREINIT Value: {tja_file}, Line {i}')
elif line.startswith('SCOREDIFF:'):
if not line.split(':')[1].isdigit():
print(f'Invalid SCOREDIFF Value: {tja_file}, Line {i}')
elif int(line.split(':')[1]) < 0:
print(f'Invalid SCOREDIFF Value: {tja_file}, Line {i}')
for i in range(6):
notes, note_start, note_end = data_to_notes(tja_data, i)
index = 0
balloon_index = 0
in_hold_note = False
if notes != []:
for bar in notes:
for part in bar:
if part.startswith('#BPMCHANGE'):
bpm = part.split()[1]
if float(bpm) <= 0:
print(f'BPMCHANGE Invalid: {tja_file}, Line {index+note_start}')
elif part.startswith('#MEASURE'):
divisor = part.find('/')
if float(part[divisor+1:]) == 0:
print(f'Time Signature Invalid: {tja_file}, Line {index+note_start}')
elif part.startswith('#'):
continue
else:
for note in part:
if not note.isdigit():
print(f'Invalid Note Type {note}: {tja_file}, Line {index+note_start}')
continue
if note == '7' or note == '9':
balloon_index += 1
if balloon_index > len(balloon_data):
print(f'Balloon Data Missing: {tja_file}, Line {index+note_start}')
if note == '8':
in_hold_note = False
elif 5 <= int(note) <= 9:
if in_hold_note:
print(f'Drumroll/Balloon Tail Missing or Head Repeated: {tja_file}, Line {index+note_start}')
in_hold_note = True
index += 1
for file in (Path.cwd()).rglob('*.tja'):
validate_tja(file, check_watermark=True)
#print(f'{file} is valid')