"""Bounded tests of keys derived from the visually read Babylonian numerals.
The reading is separate from the unproven hypothesis that these numbers are keys.
"""
import json
from word_core import *
KEYS={'sexagesimal_both':[17,13,55,1],'sexagesimal_top':[17,13],'sexagesimal_bottom':[55,1],'integers':[1033,3301],'decimal_digits':[1,0,3,3,3,3,0,1]}

def sweep(source):
    v=vals(source);words=tokenize(source);lengths=[len(w['values']) for w in words];cutwords=int(len(words)*.6);cut=sum(lengths[:cutwords]);out=[];count=0
    for reset,markers in [('section',''),('page','%'),('paragraph','&$§'),('word','-,.&$§;')]:
        # Derive word counters from the same parser used to score words.
        ix=np.concatenate([np.arange(n) for n in lengths]) if reset=='word' else positions(source,markers)[0]
        for name,seq in KEYS.items():
            for rev in [False,True]:
                key=np.array(seq[::-1] if rev else seq)
                for convention in [0,-1]:
                    k=(key+convention)%29
                    shifted=k[(np.arange(len(k))[:,None]+ix)%len(k)]
                    for cs,ks in [(1,1),(1,-1),(-1,1),(-1,-1)]:
                        decoded=(cs*v+ks*shifted)%29;count+=len(k)
                        train=FULL_MODEL.score(decoded[:,:cut],lengths[:cutwords]);hold=FULL_MODEL.score(decoded[:,cut:],lengths[cutwords:])
                        for phase in range(len(k)):
                            out.append(dict(key=name,reverse=rev,numeric_offset=convention,reset=reset,cipher_sign=cs,key_sign=ks,phase=phase,training_score=float(train[phase]),heldout_score=float(hold[phase]),text=render(source,decoded[phase])))
    out.sort(key=lambda x:x['training_score'],reverse=True)
    return dict(settings=count,runes=len(v),training_runes=cut,heldout_runes=len(v)-cut,top=out[:10])

def main():
    assert 17*60+13==1033 and 55*60+1==3301
    plain='%'.join([lp[57],lp[57]]);p=vals(plain);k=np.array(KEYS['sexagesimal_both'])%29;ix=positions(plain,'%')[0];c=(p+k[(ix+3)%len(k)])%29
    control=sweep(replace_values(plain,c));assert control['top'][0]['text']==render(plain,p)
    source='%'.join(lp[33:40]);result=sweep(source)
    marked='%'.join(lp[:56]).split('$')[7];marked_result=sweep(marked)
    out=dict(reading=dict(top_digits=[17,13],bottom_digits=[55,1],top_integer=1033,bottom_integer=3301,method='Manual visual comparison of archived LP2 pages33,39 to MacTutor numeral chart; conventional integer place-value reading.'),keys=KEYS,control=dict(exact_recovery=True,runes=len(p),best=control['top'][0]),target='LP2 pages33–39 and delimiter-defined marked section7, separately',result=result,marked_section_result=marked_result,limitations=['Hypothesis that the inscriptions are keys is unproven.','Only five key representations, two direction choices, all cyclic phases, two numeric offsets, four reset rules and four additive sign combinations.','Modern-English scoring only; no Sumerian or Akkadian language decoding attempted.','Candidates selected using first60% of complete words, then checked unchanged on the remainder.','No verified new plaintext.'])
    (ROOT/'cuneiform_results.json').write_text(json.dumps(out,indent=2));print({label:dict(settings=r['settings'],runes=r['runes'],training_score=r['top'][0]['training_score'],heldout_score=r['top'][0]['heldout_score']) for label,r in [('page_block',result),('marked_section',marked_result)]})
if __name__=='__main__':main()
