def _output(self, src: list, config: StoryConfig) -> ResultData: LOG.info('RUN: OUTPUT: start') assertion.is_instance(config, StoryConfig) result = ResultData(src, True, None) prefixs = assertion.is_valid_length( ['', '_p', '', '_data', '_sc', '_ad'], len(CompileMode.get_all())) extentions = assertion.is_valid_length( ['md', 'md', 'txt', 'md', 'md', 'md'], len(CompileMode.get_all())) fmt_idx = 0 outputter = Outputter() for fmt_data in assertion.is_listlike(src): if fmt_data: LOG.info(f'RUN: START: Outputter [{fmt_idx}]') result = assertion.is_instance( outputter.execute(fmt_data, config.output_mode, config.filename, prefixs[fmt_idx], extentions[fmt_idx], config.builddir), ResultData) if not result.is_succeeded: LOG.error(f'Failure in Outputter [{fmt_idx}]!!') return result LOG.info(f'... SUCCESS: Outputter [{fmt_idx}]') fmt_idx += 1 return result
def times_in_scene(self, src: Scene) -> list: tmp = [] for child in assertion.is_instance(src, Scene).children: if isinstance(child, SCode): if child.cmd is SCmd.CHANGE_TIME: tmp.append(assertion.is_instance(child.src, Time)) return tmp
def execute(self, src: RawData, mode: FormatMode) -> ResultData: LOG.info(f'FORMATTER: start exec on [{mode}] mode') LOG.debug(f'-- src: {src}') is_succeeded = True tmp = [] error = None if mode is FormatMode.DEFAULT: tmp = assertion.is_instance(self._to_default(src), TextList) elif mode is FormatMode.PLAIN: tmp = src elif mode is FormatMode.WEB: tmp = assertion.is_instance(self._to_web(src), TextList) elif mode is FormatMode.SMARTPHONE: tmp = src else: msg = f'Invalid format-mode! {mode}' LOG.critical(msg) is_succeeded = False error = FormatModeError(msg) return ResultData( tmp, is_succeeded, error)
def cameras_in_scene(self, src: Scene) -> list: tmp = [] for child in assertion.is_instance(src, Scene).children: if isinstance(child, SCode): if child.cmd is SCmd.CHANGE_CAMEARA: tmp.append(assertion.is_instance(child.src, Person)) return tmp
def _dialogue_percents(self, src: TextList) -> list: assertion.is_instance(src, TextList) tmp = [] def _is_desc(val): return val.startswith(' ') def _is_dialogue(val): return val.startswith(('「', '『')) totals = len([line for line in src.data]) total_chars = sum([len(self._rid_topspace(line)) for line in src.data]) descriptions = len([line for line in src.data if _is_desc(line)]) desc_chars = sum([ len(self._rid_topspace(line)) for line in src.data if _is_desc(line) ]) dialogues = len([line for line in src.data if _is_dialogue(line)]) dial_chars = sum( [len(line) for line in src.data if _is_dialogue(line)]) desc_per = safe_divided(desc_chars, total_chars) * 100 dial_per = safe_divided(dial_chars, total_chars) * 100 tmp.append('## 台詞\n') tmp.append(f'- Total : {total_chars}c / {totals}line') tmp.append( f'- Description: {desc_per:.2f}% [{desc_chars}c / {descriptions}line]' ) tmp.append( f'- Dialogue : {dial_per:.2f}% [{dial_chars}c / {dialogues}line]' ) return tmp
def _update_container_info( self, src: (Chapter, Episode, Scene, Material), columns: int, rows: int) -> (Chapter, Episode, Scene, Material): LOG.info('HEAD_UPDATER: update_container_info') LOG.debug(f'-- src: {src}') LOG.debug(f'-- columns/rows: {columns}/{rows}') assertion.is_instance(src, (Chapter, Episode, Scene, Material)) tmp = [] tmp.append(self._containerhead_of(src)) tmp.append(self._collect_header_info(src, columns, rows)) tmp.append(self._title_of(src)) if isinstance(src, Scene): tmp.append(self._collect_scene_info(src)) if src.outline: tmp.append(self._outline_of(src)) for child in src.children: if isinstance(child, (Chapter, Episode, Scene)): tmp.append(self._update_container_info(child, columns, rows)) elif isinstance(child, SCode): if Checker().has_then(child): tmp.append(SCode(None, SCmd.THEN, (), '')) tmp.append(child) elif isinstance(child, Material): tmp.append(self._update_container_info(child, columns, rows)) else: LOG.error(f'Invalid child value!: {type(child)} | {child}') tmp.append(self._end_of(src)) return src.inherited(*tmp)
def _exec_internal( self, src: Story) -> Tuple[Story, bool, (SceneUpdaterError, None)]: assertion.is_instance(src, Story) tmp = [] is_succeeded = True error = None camera = None stage = None day = None time = None for child in src.children: if isinstance(child, (Chapter, Episode, Scene)): LOG.debug( f'>> {camera.name if camera else camera}/{stage.name if stage else stage}/{day.name if day else day}/{time.name if time else time}' ) ret, camera, stage, day, time = self._updated_scene_info( child, camera, stage, day, time) tmp.append(ret) elif isinstance(child, SCode): tmp.append(child) elif isinstance(child, Material): tmp.append(child) else: msg = f'Invalid a child value in scene_update_exec!: {type(child)}: {child}' LOG.error(msg) error = SceneUpdaterError(msg) return src.inherited(*tmp), is_succeeded, error
def _add_rubi_on_novel(self, src: RawData, rubis: dict) -> RawData: LOG.info('COMP: add_rubi_on_novel start') tmp = [] discards = [] checker = Checker() conv = Converter() for line in assertion.is_instance(src, RawData).data: if isinstance(line, FormatTag) \ or checker.has_tag_top(assertion.is_str(line)) \ or checker.is_breakline(line) \ or checker.has_tag_comment(line): tmp.append(line) else: for key, rubi in rubis.items(): if key in discards: continue elif checker.has_rubi_key(line, key): if checker.has_rubi_exclusions( line, assertion.is_instance(rubi, Rubi).exclusions): continue line = conv.add_rubi(line, key, rubi.rubi) if not rubi.is_always: discards.append(key) tmp.append(line) return RawData(*tmp)
def _updated_plot_info(self, src: Story, title: str) -> list: assertion.is_instance(src, Story) tmp = [] for child in src.children: ret = self._updated_plot_info_internal(child, title) if ret: tmp.extend(ret) return tmp
def _get_sceneinfo(self, code: SCode) -> str: data = assertion.is_instance( assertion.is_instance(code, SCode).script[0], SceneInfo) camera = data.camera.name if data.camera else "第三者" stage = data.stage.name if data.stage else "どこか" day = data.day.daystring if data.day else "某月某日/某年" time = data.time.name if data.time else "不詳" return f"○{stage}({time}) - {day}【{camera}】\n"
def execute(self, src: (str, list, TextList), person_names: list, is_debug: bool=False) -> ResultData: # pragma: no cover LOG.info('ANALYZER: start exec') is_succeeded = True error = None basesrc = None result = ResultData([], is_succeeded, error) if isinstance(src, str): basesrc = TextList(*get_content_from_text_file(src)) elif isinstance(src, TextList): basesrc = src elif isinstance(src, (list, tuple)): basesrc = TextList(*src) else: msg = f'Invalid analyze source!: {src}' LOG.critical(msg) return ResultData(result, False, AnalyzerError(msg)) tmp = self._rid_tag(basesrc) LOG.info('TOKENIZER: call') result = assertion.is_instance(Tokenizer().execute(tmp, person_names), ResultData) if not result.is_succeeded: return result tokens = assertion.is_instance(result.data, TokenList) LOG.info('WORD_ANALYZER: call') result = assertion.is_instance(WordAnalyzer().execute(tokens), ResultData) if not result.is_succeeded: return result word_data = assertion.is_listlike(result.data) LOG.info('PERCENT_ANALYZER: call') result = assertion.is_instance(PercentAnalyzer().execute(tmp), ResultData) if not result.is_succeeded: return result percent_data = assertion.is_listlike(result.data) LOG.info('FREQUENCY_ANALYZER: call') result = assertion.is_instance(FrequencyAnalyzer().execute(tokens), ResultData) if not result.is_succeeded: return result freq_data = assertion.is_listlike(result.data) LOG.info('Analyzer result output') result_data = percent_data + ['\n---\n'] \ + word_data + ['\n---\n'] \ + freq_data fname = 'result' suffix = '' extention = 'md' builddir = 'build/results' mode = OutputMode.CONSOLE if is_debug else OutputMode.FILE data = TextList(*[f'{line}\n' for line in result_data]) Outputter().execute(data, mode, fname, suffix, extention, builddir) return result
def _config_data_replaced(self, config: StoryConfig, tags: dict) -> bool: assertion.is_instance(config, StoryConfig) is_succeeded = True config.set_title(string_replaced_by_tag(config.title, tags)) config.set_copy(string_replaced_by_tag(config.copy, tags)) config.set_oneline(string_replaced_by_tag(config.oneline, tags)) config.set_outline(string_replaced_by_tag(config.outline, tags)) return is_succeeded
def __init__( self, camera: Person, stage: Stage, day: Day, time: Time, ): self._camera = assertion.is_instance(camera, Person) if camera else None self._stage = assertion.is_instance(stage, Stage) if stage else None self._day = assertion.is_instance(day, Day) if day else None self._time = assertion.is_instance(time, Time) if time else None
def __init__( self, src: SObject, cmd: SCmd, script: tuple, option: (int, str) = '', ): super().__init__('__scode__') self._src = assertion.is_instance(src, SObject) if src else None self._cmd = assertion.is_instance(cmd, SCmd) self._script = assertion.is_tuple(script) self._option = assertion.is_int_or_str(option)
def execute( self, src: Story, config: StoryConfig, db: Database, ) -> ResultData: # pragma: no cover ''' Exec story building, compiling and outputting. NOTE: Compile option 1. normal: output `story.md` 2. plot: output `plot.md` 3. text: output `story.txt` 4. scenario: output `sc_story.md` ''' LOG.info('RUN: == START EXEC ==') LOG.info('RUN: START-PHASE: Preparation') tmp = assertion.is_instance(src, Story) is_succeeded = True result = None error = None is_succeeded = self._build_options(config) if not is_succeeded: msg = 'Cannot build option arguments!!' error = RunnerError(msg) LOG.error(msg) return ResultData([], is_succeeded, error) LOG.info('... SUCCESS: Preparation') LOG.info('RUN: START-PHASE: Pre-Compile') result = self._pre_compile(src, config, db) if not result.is_succeeded: return result tmp = assertion.is_instance(result.data, Story) LOG.info('... SUCCESS: Finish: Pre-Compile') LOG.info('RUN: START-PHASE: Compile and Output') result = assertion.is_instance(self._compile(tmp, config, db), ResultData) LOG.info('... SUCCESS: Finish: Compile and Output') self._output_storyinfo(config) LOG.info('RUN: analyzer check') if self._is_analyzed: result = assertion.is_instance( self._analyze_and_output(tmp, db.get_person_names(), self._is_debug), ResultData) LOG.info('RUN: == ALL SUCCEEDED ==') return result
def _wordclass_counts(self, src: TokenList) -> list: assertion.is_instance(src, TokenList) tmp = [] counter = WordCounter() # 品詞数 total = len(src.data) each_nums = [(wcls, counter.word_classes_of(src, wcls)) for wcls in WordClass.get_all()] tmp.append('# 品詞分析\n') tmp.append(f'- Total: {total}') for val in each_nums: tmp.append(f'- {val[0].conv_str()}: {val[1]}') return tmp
def _inserted_after_storyinfo(self, src: Story, infos: list) -> Story: assertion.is_instance(src, Story) LOG.debug(f'- info in inserted_after_storyinfo:{infos}') tmp = [] for child in src.children: if isinstance(child, SCode) and child.cmd is SCmd.INFO_STORY: tmp.append(child) for info in infos: tmp.append(SCode(None, SCmd.INFO_DATA, (info,), "")) else: tmp.append(child) return src.inherited(*tmp)
def _analyze_and_output(self, src: Story, person_names: list, is_debug: bool) -> ResultData: # serialize and compile as text mode = CompileMode.NOVEL_TEXT fmode = FormatMode.DEFAULT LOG.info('Serialize for Analyzer') result = assertion.is_instance(Serializer().execute(src, mode), ResultData) if not result.is_succeeded: return result tmp = assertion.is_instance(result.data, CodeList) LOG.info('Validate for Analyzer') result = assertion.is_instance(Validater().execute(tmp), ResultData) if not result.is_succeeded: return result tmp = assertion.is_instance(result.data, CodeList) LOG.info('Compile for Analyzer') result = assertion.is_instance( Compiler().execute(tmp, mode, {}, False, False), ResultData) if not result.is_succeeded: return result tmp = assertion.is_instance(result.data, RawData) LOG.info('Format for Analyzer') result = assertion.is_instance(Formatter().execute(tmp, fmode), ResultData) if not result.is_succeeded: return result tmp = assertion.is_instance(result.data, TextList) LOG.info('RUN: call Analyzer') result = Analyzer().execute(tmp, person_names, is_debug) return ResultData([], True, None)
def execute(self, src: Story, config: StoryConfig) -> ResultData: LOG.info('REDUCER: start exec') is_succeeded = True error = None tmp = assertion.is_instance( self._exec_internal(src, config.start, config.end), Story) return ResultData(tmp, is_succeeded, error)
def _to_web(self, src: RawData) -> TextList: LOG.info('FORMAT: to_web') tmp = [] in_dialogue = False for line in assertion.is_instance(src, RawData).data: if isinstance(line, FormatTag): if line is FormatTag.DESCRIPTION_HEAD: if in_dialogue: tmp.append('\n') in_dialogue = False elif line is FormatTag.DIALOGUE_HEAD: if not in_dialogue: tmp.append('\n') in_dialogue = True elif line is FormatTag.SYMBOL_HEAD: pass elif line is FormatTag.TAG_HEAD: pass else: pass else: assertion.is_str(line) tmp.append(line) return TextList(*tmp)
def execute(self, src: Story) -> ResultData: LOG.info('PLOT_UPDATER: start exec') tmp, is_succeeded, error = assertion.is_tuple(self._exec_internal(src)) return ResultData( assertion.is_instance(tmp, Story), is_succeeded, error)
def __init__(self, mate_type: MaterialType, title: str, *args: Any, outline: str = ''): super().__init__(title, *args, outline=outline) self._mate_type = assertion.is_instance(mate_type, MaterialType)
def __init__(self, title: str): LOG.info('CONFIG: initialize') LOG.debug(f'-- title: {title}') # for specific self._title = assertion.is_str(title) self._copy = assertion.is_str('__catch_copy__') self._oneline = assertion.is_str('__one_line__') self._outline = assertion.is_str('__story_outline__') self._theme = assertion.is_str('__theme__') self._genre = assertion.is_str('__genre__') self._target = assertion.is_str('__target_age__') self._size = assertion.is_str('__size__') self._desc_size = assertion.is_int(0) self._total_size = assertion.is_int(0) self._desc_papers = assertion.is_int_or_float(0) self._total_papers = assertion.is_int_or_float(0) # for story self._priority = assertion.is_int(__PRIORITY_DEFAULT__) self._start = assertion.is_int(0) self._end = assertion.is_int(-1) self._base_date = datetime.date(2020, 1, 1) self._base_time = datetime.time(12, 00) self._version = assertion.is_tuple((0, 0, 1)) self._columns = assertion.is_int(20) self._rows = assertion.is_int(20) self._contest_info = assertion.is_str('') self._caution = assertion.is_str('') self._note = assertion.is_str('') self._sites = assertion.is_listlike([]) self._taginfos = assertion.is_listlike([]) self._modified = datetime.date.today() self._released = datetime.date(2020, 1, 1) # for compile self._is_data = assertion.is_bool(False) self._is_plot = assertion.is_bool(False) self._is_text = assertion.is_bool(False) self._is_scenario = assertion.is_bool(False) self._is_audiodrama = assertion.is_bool(False) self._is_rubi = assertion.is_bool(False) self._is_comment = assertion.is_bool(False) self._is_console = assertion.is_bool(False) self._format_mode = assertion.is_instance(FormatMode.DEFAULT, FormatMode) self._output_mode = assertion.is_instance(OutputMode.FILE, OutputMode) self._filename = assertion.is_str('story') self._builddir = assertion.is_str('build') self._log_level = assertion.is_str('warn')
def _out_to_console(self, src: TextList) -> bool: LOG.info('OUTPUT: out to console') is_succeeded = True for line in assertion.is_instance(src, TextList).data: print(line, end='') print(datetime.datetime.now()) return is_succeeded
def _exec_internal(self, src: Story) -> Tuple[Story, bool, (PlotUpdaterError, None)]: assertion.is_instance(src, Story) tmp = [] is_succeeded = True error = None titles = self._collect_plot_title(src) infos = [] for title in titles: ret = self._updated_plot_info(src, title) if ret: infos.append(PlotInfo(title, *ret)) ret = self._inserted_after_storyinfo(src, infos) return ret, is_succeeded, error
def _to_default(self, src: RawData) -> TextList: LOG.info('FORMAT: to_default') tmp = [] for line in assertion.is_instance(src, RawData).data: if isinstance(line, FormatTag): continue else: tmp.append(line) return TextList(*tmp)
def _exec_internal(self, src: Story, mode: CompileMode) -> list: ret = [] assertion.is_instance(src, Story) if assertion.is_instance(mode, CompileMode) in (CompileMode.NORMAL, CompileMode.NOVEL_TEXT): ret = self._novel_serialized(src) elif mode is CompileMode.PLOT: ret = self._plot_serialized(src) elif mode is CompileMode.STORY_DATA: ret = self._storydata_serialized(src) elif mode is CompileMode.SCENARIO: ret = [] elif mode is CompileMode.AUDIODRAMA: ret = [] else: LOG.error(f'Invalid story object![1]: {type(child)}: {child}') return ret
def _conv_from_end_container(self, src: SCode) -> str: if assertion.is_instance(src, SCode).cmd is SCmd.END_CHAPTER: return '\n--------\n' elif src.cmd is SCmd.END_EPISODE: return '\n\n' elif src.cmd is SCmd.END_SCENE: return '\n' else: return ''
def _has_invalid_symbol(self, src: CodeList) -> Tuple[list, bool]: tmp = [] invalids = [] checker = Checker() for child in assertion.is_instance(src, CodeList).data: assertion.is_instance(child, SCode) if child.cmd in SCmd.get_all_actions(): for line in child.script: if checker.has_tag_symbol(line): invalids.append(line) tmp.append(child) else: # NOTE: それ以外をどうするか。ここはスルーか tmp.append(child) if invalids: return (invalids, False) else: return (CodeList(*tmp), True)
def _updated_scene_info( self, src: (Chapter, Episode, Scene, SCode), camera: Person = None, stage: Stage = None, day: Day = None, time: Time = None ) -> Tuple[(Chapter, Episode, Scene), (Person, None), (Stage, None), ( Day, None), (Time, None)]: if isinstance(src, (Chapter, Episode)): tmp = [] for child in src.children: ret, camera, stage, day, time = self._updated_scene_info( child, camera, stage, day, time) tmp.append(ret) return src.inherited(*tmp), camera, stage, day, time elif isinstance(src, Scene): ret = self._get_scene_info(src) if not ret: LOG.error(f'Not found a SceneInfo!: in {src.title} scene') return src, camera, stage, day, time else: assertion.is_instance(ret, SCode) info = assertion.is_instance(ret.script[0], SceneInfo) camera = info.camera if info.camera else camera stage = info.stage if info.stage else stage day = info.day if info.day else day time = info.time if info.time else time codes = [] for child in src.children: if self._is_scene_info(child): codes.append( child.inherited(script=( SceneInfo(camera, stage, day, time), ))) else: codes.append(child) return src.inherited(*codes), camera, stage, day, time elif isinstance(src, SCode): return src, camera, stage, day, time else: LOG.error(f'Invalid value in updated_scene_info: {src}') return src, camera, stage, day, time