#!/usr/bin/env python3
"""Render groups.json + records.json + options_by_entry.json as one self-contained page: REFERENCE.html."""
import html, json, pathlib
here = pathlib.Path(__file__).parent
d = json.loads((here / 'groups.json').read_text())
recs = {r['chunk']: r for r in json.loads((here / 'records.json').read_text())}
stories = json.loads((here.parent / 'stories.json').read_text())
obe = json.loads((here / 'options_by_entry.json').read_text())
new = obe.pop('_new_entries')
e = html.escape
SRC = {'archetype': 'archetype', 'filled': 'filled gap'}
def src(o):
if o['source'].startswith('scene:'):
n = o['source'].split(':')[1]
return f'from fable {n}' + ('' if o['in_group'] else ' (outside this group)')
return SRC[o['source']]
def moves(m): return ' '.join(f'{e(k)} {e(v)}' for k, v in m.items())
def scene(c):
r = recs[c]
moral = f'
Moral: {e(r["moral"])}' if r['moral'] else ''
return (f'{c} · {e(stories[r["story"]]["title"])} — {e(r["predicament"])}
'
f'{e(r["summary"])}{moral}
')
def section(g):
tag = ' small group, below the 13-fable rule' if g['small'] else ''
return f'''{g["id"]} · {e(g["name"])}{tag}
{e(g["predicament"])}
{e(g["sentence"])} · {len(g["members"])} fables · stage {g["stage"]}
Options
{"".join(f"- {e(o['text'])} {src(o)}
{moves(o['moves'])} " for o in g["options"])}
Fables
{"".join(scene(m["chunk"]) for m in g["members"])}'''
big = ''.join(section(g) for g in d['groups'] if not g['small'])
small = ''.join(section(g) for g in d['groups'] if g['small'])
un = ''.join(scene(c) for c in d['unassigned'])
def entry(k, v):
name = new[k]['name'] + ' (new)' if k in new else e(k)
rows = ''.join(f'
{e(o["text"])} {moves(o["moves"])} fable {o["source"].split(":")[1]} · '
f'{"stated" if o["stated"] else "inferred"}
“{e(o["evidence"])}”'
for o in v)
return f'{name} — {len(v)} options, {sum(o["stated"] for o in v)} stated
'
opts = [o for v in obe.values() for o in v]
meas = ''.join(entry(k, v) for k, v in obe.items())
page = f'''
Aesop Reference Groups
Aesop's Fables: reference groups
Three Hundred Aesop's Fables, tr. George Fyler Townsend, 1867 (Project Gutenberg). 313 fables, one scene
per fable. Summaries, predicaments, groups, options and the options measurement written by Claude reading every fable:
no inference of any kind. A comparison baseline, not a pack. Option moves give a direction only, never a number.
{big}
Small groups (5-12 fables)
Situations that recur, but below the 13-fable rule this corpus's size sets.
{small}
Unassigned ({len(d["unassigned"])})
Fables that fit no situation recurring in five or more fables.
{un}
Fables as an option source
{len(opts)} options for {len(obe)} catalogue situations, {sum(o["stated"] for o in opts)} of them
stated: the fable's own outcome or moral shows where every move goes. The rest are inferred.
{meas}
'''
(here / 'REFERENCE.html').write_text(page, encoding='utf-8')
print('wrote', here / 'REFERENCE.html', len(page), 'bytes')