From 70c2241e91186055cce60df46a90a1ea08234f2e Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Thu, 30 Apr 2020 13:34:23 -0700 Subject: [PATCH] Implement article constraint analysis --- amanuensis/lexicon/gameloop.py | 82 +++++++++++++++++++++++++++------- amanuensis/parser/analyze.py | 8 ++-- 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/amanuensis/lexicon/gameloop.py b/amanuensis/lexicon/gameloop.py index 089a1d5..f12fe5e 100644 --- a/amanuensis/lexicon/gameloop.py +++ b/amanuensis/lexicon/gameloop.py @@ -126,25 +126,77 @@ def content_constraint_analysis( infos: list = [] warnings: list = [] errors: list = [] - character = lexicon.cfg.character.get(cid)# noqa content_analysis: ConstraintAnalysis = ( parsed.render(ConstraintAnalysis(lexicon))) - with lexicon.ctx.read('info') as info:# noqa + with lexicon.ctx.read('info') as info: # I: Word count infos.append(f'Word count: {content_analysis.word_count}') - # Self-citation when forbidden - pass - # A new citation matches a character's name - pass # warning + # E: Self-citation when forbidden + for citation in content_analysis.citations: + citation_info = info.get(citation) + if (citation_info and citation_info.character == cid + and not lexicon.cfg.article.citation.allow_self): + errors.append(f'Cited your own article: {citation}') + # W: A new citation matches a character's name + if not citation_info: + for char in lexicon.cfg.character.values(): + if len(char.name) > 10 and citation == char.name: + warnings.append(f'"{citation}" is the name of a ' + ' character. Are you sure you want to do that?') # A new citation would create more articles than can be written - # Not enough extant citations - # Too many extant citations - # Not enough phantom citations - # Too many phantom citations - # Not enough total citations - # Too many total citations - # Not enough characters' articles cited - # Too many characters' articles cited + pass # TODO + # E: Not enough extant citations + citation_cfg = lexicon.cfg.article.citation + extant_count = len(set([ + c for c in content_analysis.citations + if c in info and info[c].character])) + if (citation_cfg.min_extant is not None + and extant_count < citation_cfg.min_extant): + errors.append('Not enough extant articles cited ' + f'({extant_count}/{citation_cfg.min_extant})') + # E: Too many extant citations + if (citation_cfg.max_extant is not None + and extant_count > citation_cfg.max_extant): + errors.append('Too many extant articles cited ' + f'({extant_count}/{citation_cfg.max_extant})') + # E: Not enough phantom citations + phantom_count = len(set([ + c for c in content_analysis.citations + if c not in info or not info[c].character])) + if (citation_cfg.min_phantom is not None + and phantom_count < citation_cfg.min_phantom): + errors.append('Not enough phantom articles cited ' + f'({phantom_count}/{citation_cfg.min_phantom})') + # E: Too many phantom citations + if (citation_cfg.max_phantom is not None + and phantom_count > citation_cfg.max_phantom): + errors.append('Too many phantom articles cited ' + f'({phantom_count}/{citation_cfg.max_phantom})') + # E: Not enough total citations + total_count = len(set(content_analysis.citations)) + if (citation_cfg.min_total is not None + and total_count < citation_cfg.min_total): + errors.append('Not enough articles cited ' + f'({total_count}/{citation_cfg.min_total})') + # E: Too many total citations + if (citation_cfg.max_total is not None + and total_count > citation_cfg.max_total): + errors.append('Too many articles cited ' + f'({total_count}/{citation_cfg.max_total})') + # E: Not enough characters' articles cited + char_count = len(set([ + info[c].character + for c in content_analysis.citations + if c in info and info[c].character])) + if (citation_cfg.min_chars is not None + and char_count < citation_cfg.min_chars): + errors.append('Not enough characters cited ' + f'({char_count}/{citation_cfg.min_chars})') + # E: Too many characters' articles cited + if (citation_cfg.max_chars is not None + and char_count > citation_cfg.max_chars): + errors.append('Too many characters cited ' + f'({char_count}/{citation_cfg.max_chars})') # E: Exceeded hard word limit if (lexicon.cfg.article.word_limit.hard is not None and content_analysis.word_count > lexicon.cfg.article.word_limit.hard): @@ -161,8 +213,6 @@ def content_constraint_analysis( # W: Multiple signatures if content_analysis.signatures > 1: warnings.append('Multiple signatures') - # Signature altered from default - pass # warning return infos, warnings, errors diff --git a/amanuensis/parser/analyze.py b/amanuensis/parser/analyze.py index 8eb9e8f..bf52354 100644 --- a/amanuensis/parser/analyze.py +++ b/amanuensis/parser/analyze.py @@ -30,9 +30,9 @@ class ConstraintAnalysis(RenderableVisitor): self.warning: List[str] = [] self.error: List[str] = [] - self.word_count = 0 - self.citation_count = 0 - self.signatures = 0 + self.word_count: int = 0 + self.citations: list = [] + self.signatures: int = 0 def TextSpan(self, span): self.word_count += len(re.split(r'\s+', span.innertext.strip())) @@ -44,6 +44,6 @@ class ConstraintAnalysis(RenderableVisitor): return self def CitationSpan(self, span): - self.citation_count += 1 + self.citations.append(span.cite_target) span.recurse(self) return self