def check_dialogue(chara_name, dialogue, line_num): for c in dialogue: if is_special_char(c): print( f'Line {line_num}: special character U+{ord(c):04X} in dialogue' ) match = re.compile('(TODO:(.*?):.*?)').search(dialogue) if match: print(f'Line {line_num}: TODO: {match.group(1)} in dialogue') elif 'TODO' in dialogue: print(f'Line {line_num}: TODO in dialogue') dialogue = normalize_dialogue(dialogue) if chara_name: if not dialogue.startswith('“'): print(f'Line {line_num}: dialogue not start with quotation mark') if not dialogue.endswith('”'): print(f'Line {line_num}: dialogue not end with quotation mark') else: match = re.compile('.*?:“.*?”').fullmatch(dialogue) if match: print(f'Line {line_num}: quote with single colon') # if len(dialogue) > 54: # print(f'Line {line_num}: dialogue longer than 54 chars') if any(x in dialogue for x in ',.?!;:\'"()'): print(f'Line {line_num}: half width punctuation in dialogue')
def main(): with open(in_filename, 'r', encoding='utf-8') as f: chapters = parse_chapters(f) doc = Document() style = doc.styles['Normal'] style.font.name = 'Microsoft YaHei' style._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') style = doc.styles['Heading 1'] style.font.name = 'Microsoft YaHei' style._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') style = doc.styles.add_style('Character Name', WD_STYLE_TYPE.CHARACTER) style.font.name = 'Microsoft YaHei' style._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') style.font.color.rgb = RGBColor(210, 210, 210) style = doc.styles.add_style('BG', WD_STYLE_TYPE.CHARACTER) style.font.name = 'Microsoft YaHei' style._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') style.font.color.rgb = RGBColor(255, 128, 0) style = doc.styles.add_style('BGM', WD_STYLE_TYPE.CHARACTER) style.font.name = 'Microsoft YaHei' style._element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') style.font.color.rgb = RGBColor(0, 0, 255) for chapter_name, entries, _, _ in chapters: print(chapter_name) doc.add_heading(chapter_name) for code, chara_name, dialogue in entries: bg_name, bgm_name = parse_code(code, f) if bg_name: para = doc.add_paragraph() para.add_run('场景:' + translate(bg_name), 'BG') if bgm_name: para = doc.add_paragraph() para.add_run('音乐:' + translate(bgm_name), 'BGM') dialogue = normalize_dialogue(dialogue, keep_todo=['配音']) if dialogue: if chara_name: para = doc.add_paragraph() para.add_run(chara_name, 'Character Name') para.add_run(dialogue) else: doc.add_paragraph(dialogue) doc.add_page_break() doc.save(out_filename)
def main(): with open(in_filename, 'r', encoding='utf-8') as f: chapters = parse_chapters(f) with open(out_filename, 'w', encoding='utf-8', newline='\n') as f: f.write(r"""\documentclass{article} \usepackage[a4paper,left=1in,right=1in,top=1in,bottom=1in]{geometry} \usepackage[hidelinks]{hyperref} \usepackage{xcolor} \usepackage{xeCJK} \setlength{\parindent}{0pt} \setlength{\parskip}{1ex} """) f.write('\\begin{document}\n\n') for chapter_name, entries, _, _ in chapters: print(chapter_name) chapter_name = normalize_tex(chapter_name) f.write(f'\\section{{{chapter_name}}}\n\n') for code, chara_name, dialogue in entries: bg_name, bgm_name = parse_code(code, f) if bg_name: bg_name = normalize_tex(translate(bg_name)) f.write(f'{{\\color{{orange}} 场景:{bg_name}}}\n\n') if bgm_name: bgm_name = normalize_tex(translate(bgm_name)) f.write(f'{{\\color{{blue}} 音乐:{bgm_name}}}\n\n') dialogue = normalize_dialogue(dialogue, keep_todo=['配音']) if dialogue: dialogue = normalize_tex(dialogue) if chara_name: chara_name = normalize_tex(chara_name) f.write( f'{{\\color{{lightgray}} {chara_name}}}{dialogue}\n\n' ) else: f.write(dialogue + '\n\n') f.write('\\newpage\n\n') f.write('\\end{document}\n')
#!/usr/bin/env python3 from collections import Counter from nova_script_parser import normalize_dialogue, parse_chapters in_filename = 'scenario.txt' with open(in_filename, 'r', encoding='utf-8') as f: chapters = parse_chapters(f) counter = Counter() for chapter_name, entries, _, _ in chapters: print(chapter_name) for _, _, dialogue in entries: dialogue = normalize_dialogue(dialogue) if dialogue: counter[len(dialogue)] += 1 for k, v in sorted(counter.items()): print(k, v)
def lint_file(in_filename): with open(in_filename, 'r', encoding='utf-8') as f: chapters = parse_chapters(f, keep_line_num=True) for chapter_name, entries, _, _ in chapters: print(chapter_name) anim_persist_tracked = True for code, chara_name, dialogue, line_num in entries: if code and not dialogue: print(f'Line {line_num}: code block with empty dialogue') if code: for line in code.splitlines(): if not line: print(f'Line {line_num}: empty line in code block') check_show = False check_trans = False check_anim_persist_override = False try: for func_name, args, env in walk_functions(code): if func_name == 'anim': if env: print( f'Line {line_num}: anim in anon function') elif func_name == 'anim_persist_begin': anim_persist_tracked = True if env: check_anim_persist_override = True elif func_name == 'anim_persist_end': if anim_persist_tracked: anim_persist_tracked = False else: print( f'Line {line_num}: anim_persist_end() not match' ) if env: check_anim_persist_override = True elif func_name == 'anim_persist': if 'anim_persist' in env: print( f'Line {line_num}: anim_persist in anim_persist' ) if not anim_persist_tracked: print( f'Line {line_num}: anim_persist not tracked' ) if check_anim_persist_override and not env: print( f'Line {line_num}: anim_persist overridden by anim_persist_begin() or anim_persist_end()' ) if func_name == 'show': if (not env and args and get_node_name(args[0]) != 'extra_text'): check_show = True elif 'trans' in func_name: if (len(args) >= 2 and get_node_name(args[0]) == 'cam' and not isinstance(args[1], astnodes.Nil)): check_trans = True except Exception as e: print(f'Line {line_num}: error when parsing code: {e}') if check_show and check_trans: print(f'Line {line_num}: show() outside of trans()') if dialogue: normal_dialogue = normalize_dialogue(dialogue) if chara_name: if not normal_dialogue.startswith('“'): print( f'Line {line_num}: dialogue not start with quotation mark' ) if not normal_dialogue.endswith('”'): print( f'Line {line_num}: dialogue not end with quotation mark' ) else: match = re.compile('.*?:“.*?”').fullmatch(normal_dialogue) if match: print(f'Line {line_num}: quote with single colon') # if len(normal_dialogue) > 54: # print( # f'Line {line_num}: normal_dialogue longer than 54 chars' # ) if any(x in normal_dialogue for x in ',.?!;:\'"()'): print(f'Line {line_num}: half width punctuation') match = re.compile('(TODO:(.*?):.*?)').search(normal_dialogue) if match: print(f'Line {line_num}: TODO: {match.group(1)} found') elif 'TODO' in normal_dialogue: print(f'Line {line_num}: TODO found')
#!/usr/bin/env python3 from nova_script_parser import normalize_dialogue, parse_chapters from openpyxl import Workbook in_filename = 'scenario.txt' out_filename = 'scenario_no_code.xlsx' with open(in_filename, 'r', encoding='utf-8') as f: chapters = parse_chapters(f) wb = Workbook() for chapter_name, entries, _, _ in chapters: print(chapter_name) ws = wb.create_sheet(chapter_name) for _, chara_name, dialogue in entries: dialogue = normalize_dialogue(dialogue, remove_rich=False, remove_todo=False) if dialogue: if chara_name: ws.append([f'{chara_name}:{dialogue}']) else: ws.append([dialogue]) wb.save(out_filename)