nx_writehub_score.nx source
↩ module page · 67 lines · 4001 B
1// nx_writehub_score.nx -- WRITING HUB shared LIB: the immune-scoring core, extracted from nx_writehub_loop so the
2// loop AND the self-improvement conductor share ONE scorer (consolidation -- no duplicated scoring logic, per the
3// operator's no-dup doctrine). Pure composition of nx_writecraft (readability) + nx_writestyle (adverb/passive/
4// weak/hard-sentence) -> a composite quality permil + the worst-dimension directive. No main, no I/O beyond scratch
5// mmap, so any organ can import it. Thresholds are heuristic consts here (move to a writehub_rubric data store
6// next, per nx_writestyle's own "consts -> DATA" note). license_tier: ORIGINAL module: nishi-core.writehub.score
7import "nx_writestyle.nx"
8import "nx_syscalls.nx"
9
10const WHL_ADVERB_TGT: i64 = 15 // adverbs per 1000 words tolerated before penalty
11const WHL_PASSIVE_TGT: i64 = 10 // passive constructions per 1000 words tolerated
12const WHL_WEAK_TGT: i64 = 8 // weak qualifiers per 1000 words tolerated
13const WHL_ADVERB_W: i64 = 6 // penalty permil per (rate-over-target)/10
14const WHL_PASSIVE_W: i64 = 10
15const WHL_WEAK_W: i64 = 8
16const WHL_HARD_W: i64 = 300 // penalty permil at 100% hard sentences
17const WHL_READ_W: i64 = 80 // flat penalty when grade exceeds the band
18const WHL_FK_MAX: i64 = 12000 // FK grade x1000 ceiling (grade ~12); above = too dense
19const WHL_KEEP: i64 = 700 // composite permil at/above which a draft is KEPT
20
21// score t[0..n); fill rep[0..15]; return composite quality permil.
22// rep: 0 words 1 sents 2 fk_milli 3 adv 4 pass 5 weak 6 dia_milli 7 longest 8 hard
23// 9 pen_adv 10 pen_pass 11 pen_weak 12 pen_hard 13 pen_read 14 permil 15 worst-dim
24func whl_eval(t: *u8, n: i64, rep: *i64) -> i64 {
25 let wc: *i64 = sys_mmap(64) as *i64
26 wc_counts(t, n, wc)
27 let words: i64 = wc[1]; let sents: i64 = wc[2]
28 var w: i64 = words; if w < 1 { w = 1 }
29 var s: i64 = sents; if s < 1 { s = 1 }
30 let fk: i64 = wc_fk_grade(wc)
31 let ss: *i64 = sys_mmap(64) as *i64
32 ws_signals(t, n, ss)
33 let adv: i64 = ss[0]; let pas: i64 = ss[1]; let wk: i64 = ss[2]; let dia: i64 = ss[3]; let lng: i64 = ss[4]; let hard: i64 = ss[5]
34 let adv_rate: i64 = adv * 1000 / w
35 let pas_rate: i64 = pas * 1000 / w
36 let wk_rate: i64 = wk * 1000 / w
37 let hard_frac: i64 = hard * 1000 / s
38 var pen_adv: i64 = 0
39 if adv_rate > WHL_ADVERB_TGT { pen_adv = (adv_rate - WHL_ADVERB_TGT) * WHL_ADVERB_W / 10 }
40 var pen_pass: i64 = 0
41 if pas_rate > WHL_PASSIVE_TGT { pen_pass = (pas_rate - WHL_PASSIVE_TGT) * WHL_PASSIVE_W / 10 }
42 var pen_weak: i64 = 0
43 if wk_rate > WHL_WEAK_TGT { pen_weak = (wk_rate - WHL_WEAK_TGT) * WHL_WEAK_W / 10 }
44 let pen_hard: i64 = hard_frac * WHL_HARD_W / 1000
45 var pen_read: i64 = 0
46 if fk > WHL_FK_MAX { pen_read = WHL_READ_W }
47 var permil: i64 = 1000 - pen_adv - pen_pass - pen_weak - pen_hard - pen_read
48 if permil < 0 { permil = 0 }
49 var worst: i64 = 0; var wv: i64 = pen_adv
50 if pen_pass > wv { wv = pen_pass; worst = 1 }
51 if pen_weak > wv { wv = pen_weak; worst = 2 }
52 if pen_hard > wv { wv = pen_hard; worst = 3 }
53 if pen_read > wv { wv = pen_read; worst = 4 }
54 if wv == 0 { worst = 5 }
55 rep[0]=words; rep[1]=sents; rep[2]=fk; rep[3]=adv; rep[4]=pas; rep[5]=wk; rep[6]=dia; rep[7]=lng; rep[8]=hard
56 rep[9]=pen_adv; rep[10]=pen_pass; rep[11]=pen_weak; rep[12]=pen_hard; rep[13]=pen_read; rep[14]=permil; rep[15]=worst
57 return permil
58}
59
60func whl_directive(worst: i64) -> *u8 {
61 if worst==0 { return "cut adverbs -- replace -ly words with stronger verbs" as *u8 }
62 if worst==1 { return "convert passive constructions to active voice" as *u8 }
63 if worst==2 { return "remove weak qualifiers (very/really/just/quite...)" as *u8 }
64 if worst==3 { return "break up the long sentences (split the longest into 2-3)" as *u8 }
65 if worst==4 { return "simplify -- shorter sentences, plainer words" as *u8 }
66 return "none -- keep" as *u8
67}