import sys import json from datetime import datetime import gradio as gr from dateutil import parser def _get_scene_titles(storydata): scene_titles = {} choice_names = {} for chapter in storydata.get("chapters", []): for scene_id, scene in chapter.get("contents", {}).get("scenes", {}).items(): scene_titles[scene_id] = scene["title"] for comp in scene.get("components", []): if comp["type"] == "choiceComponent": choice_names[comp["id"]] = comp["name"] return scene_titles, choice_names def _print_text_component(comp, output_lines): print(comp["text"]) output_lines.append(comp['text']) print() def _print_dialog_component(comp, config, output_lines): character_key = comp.get("characterAssetId") character_name = config.get("characterMap", {}).get(character_key, {}).get("characterName") dialog = comp["dialog"].replace("\n", " ") if character_name: dialog_line = f"{character_name}: {dialog}" print(dialog_line) output_lines.append(dialog_line) else: print(dialog) output_lines.append(dialog) print() output_lines.append("") def _print_jump_component(comp, scene_titles, output_lines): dest = comp["jumpTransition"]["destination"] if dest == "end-of-chapter": print("JUMP TO END OF CHAPTER") print() output_lines.append("JUMP TO END OF CHAPTER") output_lines.append("") elif dest == "specific-scene": scene_id = comp["jumpTransition"]["targetScene"] scene_title = scene_titles.get(scene_id, "") print(f"JUMP TO SCENE: {scene_title}") print() output_lines.append(f"JUMP TO SCENE: {scene_title}") output_lines.append("") def _print_switch_component(comp, variables, scene_titles, choice_names, config, output_lines, mapping): var_id = comp["variableId"] var_name = [v["name"] for v in variables if v["id"] == var_id][0] print(f"VARIABLE CHECK. DEPENDING ON `{var_name}`, TAKE ONE BRANCH:") print() output_lines.append(f"VARIABLE CHECK. DEPENDING ON `{var_name}`, TAKE ONE BRANCH:") output_lines.append("") for ibranch, branch in enumerate(comp["branches"], start=1): print(f"BRANCH {ibranch}") print() for branch_comp in branch["components"]: _print_component(branch_comp, variables, scene_titles, choice_names, config, output_lines, mapping) print("END VARIABLE CHECK") print() def _print_if_component(comp, variables, scene_titles, choice_names, config, output_lines, mapping): choice_id = comp.get("choiceId") choice_name = choice_names.get(choice_id, "") if choice_name: choice_name = f' "{choice_name}"' print(f'CHOICE CHECK. DEPENDING ON CHOICE{choice_name}, TAKE ONE BRANCH:') print() output_lines.append(f'CHOICE CHECK. DEPENDING ON CHOICE{choice_name}, TAKE ONE BRANCH:') output_lines.append("") for ibranch, branch in enumerate(comp["conditions"], start=1): print(f"BRANCH {ibranch}") print() output_lines.append(f"BRANCH {ibranch}") output_lines.append("") for branch_comp in branch["components"]: _print_component(branch_comp, variables, scene_titles, choice_names, config, output_lines, mapping) print(f'END CHOICE CHECK{choice_name}') print() output_lines.append(f'END CHOICE CHECK{choice_name}') output_lines.append("") def _print_choice_component(comp, variables, scene_titles, choice_names, config, output_lines, mapping): choice_name = comp.get("name", "") if choice_name: choice_name = f' "{choice_name}"' print(f"BEGIN CHOICE BLOCK{choice_name}") print() output_lines.append(f"BEGIN CHOICE BLOCK{choice_name}") output_lines.append("") prompt = comp.get("promptComponent") if prompt is not None: _print_component(prompt, variables, scene_titles, choice_names, config, output_lines, mapping) for iopt, option in enumerate(comp.get("options", []), start=1): choice_text = option.get("displayText") if choice_text is not None: print(f"OPTION {iopt}: {choice_text}") print() output_lines.append(f"OPTION {iopt}: {choice_text}") output_lines.append("") for opt_comp in option.get("components", []): _print_component(opt_comp, variables, scene_titles, choice_names, config, output_lines, mapping) print(f"END CHOICE BLOCK{choice_name}") print() output_lines.append(f"END CHOICE BLOCK{choice_name}") output_lines.append("") def _print_note_component(comp, output_lines): print("---") print() print(f'NOTE: {comp["note"]}') print() print("---") print() output_lines.append("---") output_lines.append("") output_lines.append(f'NOTE: {comp["note"]}') output_lines.append("") output_lines.append("---") output_lines.append("") def _print_background(comp, mapping, output_lines): asset_id = comp.get('backgroundAssetId') output_lines.append(f"Transition: {comp.get('transition')}") output_lines.append("") output_lines.append(f'Background: {mapping.get(asset_id)}') output_lines.append("") print(f'Background: {mapping.get(asset_id)}') print() def _print_component(comp, variables, scene_titles, choice_names, config, output_lines, mapping): component_type = comp.get("type") if component_type == 'backgroundComponent': _print_background(comp, mapping, output_lines) if component_type == "textComponent": _print_text_component(comp, output_lines) elif component_type == "dialogComponent": _print_dialog_component(comp, config, output_lines) elif component_type == "jumpComponent": _print_jump_component(comp, scene_titles, output_lines) elif component_type in ("choiceV2Component", "choiceComponent"): _print_choice_component(comp, variables, scene_titles, choice_names, config, output_lines, mapping) elif component_type == "switchComponent": _print_switch_component(comp, variables, scene_titles, choice_names, config, output_lines, mapping) elif component_type == "ifComponent": _print_if_component(comp, variables, scene_titles, choice_names, config, output_lines, mapping) elif component_type == "noteComponent": _print_note_component(comp, output_lines) def format_story(storydata): output_lines=[] background_map = storydata["configuration"]["backgroundMap"] # Creating a new dictionary with the id's as keys and the names as values background_dic={bg_id: details['name'] for bg_id, details in background_map.items()} # Get the story configuration data, etc. variables = storydata.get("variables", {}) scene_titles, choice_names = _get_scene_titles(storydata) config = storydata.get("configuration", {}) # Story title #with open(output_file, "w", encoding="utf-8") as file: title = storydata.get("name", "Untitled") #_write_to_file(file, f"# {title} #") #_write_to_file(file, "") print(f"# {title} #") print() output_lines.append(title) # Dates of creation and last modification created = storydata.get("createdOn") if created is not None: created = parser.isoparse(created).strftime("%Y/%m/%d") output_lines.append(created) #_write_to_file(file, f"{created}") #_write_to_file(file, "") lastmod = storydata.get("lastModified") if lastmod is not None: lastmod = parser.isoparse(lastmod).strftime("%Y/%m/%d") output_lines.append(lastmod) #_write_to_file(file, f"{lastmod}") #_write_to_file(file, "") print(f"Created {created}") print() print(f"Last modified {lastmod}") print() # Story description description = storydata.get("description") print("### Description ###") print() print(description) print() output_lines.append(description) #_write_to_file(file, f"{description}") #_write_to_file(file, "") # Chapter and scene information chapters = sorted(storydata.get("chapters", []), key=lambda c: c.get("order", 0)) for ichapter, chapter in enumerate(chapters, start=1): # Chapter title chapter_title = chapter.get("title") print(f"## Chapter {ichapter}", end="") print(" ##" if chapter_title is None else f": {chapter_title} ##") print() output_lines.append(f"## Chapter {ichapter}") output_lines.append(" ##" if chapter_title is None else f": {chapter_title} ##") output_lines.append("") if chapter_title is not None: output_lines.append(chapter_title) #_write_to_file(file, f"{description}") #_write_to_file(file, "") else: output_lines.append('##') #_write_to_file(file, "##") #_write_to_file(file, "") # Chapter description chapter_description = chapter.get("description") if chapter_description is not None: print("---") print() print(chapter_description) print() print("---") print() output_lines.append(chapter_description) #_write_to_file(file, f"{chapter_description}") #_write_to_file(file, "") scenes = sorted(chapter.get("contents", {}).get("scenes", {}).values(), key=lambda s: s.get("order", 0)) for scene in scenes: # Scene title scene_title = scene.get("title", "Untitled") print(f"### Scene: {scene_title} ###") print() output_lines.append(scene_title) #_write_to_file(file, f"{scene_title}") #_write_to_file(file, "") # Print the scene components for comp in scene.get("components", []): _print_component(comp, variables, scene_titles, choice_names, config, output_lines, background_dic) return "\n".join(output_lines) def process_story(file): with open(file.name, "r", encoding="utf-8") as f: storydata = json.load(f) output=format_story(storydata) return output iface = gr.Interface( fn=process_story, inputs=gr.File(type='filepath'), outputs="text", title="Story Formatter", description="Upload your JSON file and get the formatted story" ) if __name__ == "__main__": iface.launch(share=True)