Added kjv.
This commit is contained in:
parent
1bba902145
commit
dffcf0c22f
2
Makefile
2
Makefile
@ -43,7 +43,7 @@ bin/test-kjv: build/text.o build/pair.o build/kjvcite.o build/test_kjv.o
|
||||
bin/kjv: build/text.o build/pair.o build/journal.o build/kjvcite.o build/kjv.o build/source.o
|
||||
bin/flight: build/text.o build/pair.o build/journal.o build/source.o build/flights.o build/flighthours.o
|
||||
bin/score: build/text.o build/pair.o build/journal.o build/scores.o
|
||||
bin/scan: build/text.o build/journal.o build/pair.o build/scan.o build/driver.o
|
||||
bin/scan: build/text.o build/journal.o build/kjvcite.o build/pair.o build/scan.o build/driver.o
|
||||
|
||||
bin/%:
|
||||
@echo "\033[1;36mlinking $@\033[0m"
|
||||
|
@ -40,6 +40,10 @@ int main(void) {
|
||||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
scan_flight_graph(&scn);
|
||||
|
||||
intent = "derived/kjv.gnu";
|
||||
if(!freopen(intent, "w", stdout)) goto catch;
|
||||
scan_kjv_graph(&scn);
|
||||
|
||||
intent = 0;
|
||||
goto finally;
|
||||
catch:
|
||||
|
@ -75,7 +75,7 @@ static int scan(struct flight_tree *const f,
|
||||
= {{ (uint32_t)line, {{ date.day, date.month, date.year }} }};
|
||||
assert(!flight);
|
||||
if(line > UINT32_MAX) { why = "line overflow"; goto catch; }
|
||||
switch(flight_tree_try(f, key, &flight)) {
|
||||
switch(flight_tree_assign(f, key, &flight)) { /* fixme */
|
||||
case TREE_PRESENT: why = "duplicate key";
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT: flight->type = GLIDER; break;
|
||||
@ -148,7 +148,7 @@ static int scan(struct flight_tree *const f,
|
||||
= {{ (uint32_t)line, {{ date.day, date.month, date.year }} }};
|
||||
assert(!flight);
|
||||
if(line > UINT32_MAX) { why = "line overflow"; goto catch; }
|
||||
switch(flight_tree_try(f, key, &flight)) {
|
||||
switch(flight_tree_assign(f, key, &flight)) {
|
||||
case TREE_PRESENT: why = "duplicate key";
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT: flight->type = POWER; break;
|
||||
|
@ -169,7 +169,7 @@ static int scan(union date32 date, const char *const buffer,
|
||||
const union line64 key
|
||||
= {{ (uint32_t)line, {{ date.day, date.month, date.year }} }};
|
||||
struct kjvrange *value;
|
||||
switch(kjvline_tree_try(lines, key, &value)) {
|
||||
switch(kjvline_tree_assign(lines, key, &value)) { /* fixme */
|
||||
case TREE_PRESENT: why = "duplicate key";
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT:
|
||||
|
10
src/scan.h
10
src/scan.h
@ -64,6 +64,14 @@ struct flight {
|
||||
#include "../src/tree.h"
|
||||
|
||||
|
||||
#include "kjvcite.h"
|
||||
#define TREE_NAME kjvline
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct kjvrange
|
||||
#define TREE_HEAD
|
||||
#include "../src/tree.h"
|
||||
|
||||
|
||||
struct scan {
|
||||
struct {
|
||||
struct source_array array;
|
||||
@ -77,6 +85,7 @@ struct scan {
|
||||
} scores;
|
||||
struct glider_tree gliders;
|
||||
struct flight_tree flights;
|
||||
struct kjvline_tree kjvs;
|
||||
};
|
||||
|
||||
void scan_(struct scan *);
|
||||
@ -84,3 +93,4 @@ struct scan scan(struct journal *);
|
||||
void scan_score_graph(struct scan *);
|
||||
void scan_glider_graph(struct scan *);
|
||||
void scan_flight_graph(struct scan *);
|
||||
void scan_kjv_graph(struct scan *);
|
||||
|
249
src/scan.re.c
249
src/scan.re.c
@ -65,7 +65,6 @@ static int glider_compare(const union line64 a, const union line64 b)
|
||||
#define TREE_BODY
|
||||
#include "../src/tree.h"
|
||||
|
||||
|
||||
/* Flight tree. */
|
||||
static void flight_to_string(const union line64 line, const struct flight *f,
|
||||
char (*const a)[12]) { (void)f; date32_to_string(line.date, a); }
|
||||
@ -79,12 +78,25 @@ static int flight_compare(const union line64 a, const union line64 b)
|
||||
#define TREE_BODY
|
||||
#include "../src/tree.h"
|
||||
|
||||
/* KJV tree. */
|
||||
static void kjvline_to_string(const union line64 line, const struct kjvrange *u,
|
||||
char (*const a)[12]) { (void)u; date32_to_string(line.date, a); }
|
||||
static int kjvline_compare(const union line64 a, const union line64 b)
|
||||
{ return a.u64 > b.u64; }
|
||||
#define TREE_NAME kjvline
|
||||
#define TREE_KEY union line64
|
||||
#define TREE_VALUE struct kjvrange
|
||||
#define TREE_COMPARE
|
||||
#define TREE_TO_STRING
|
||||
#define TREE_BODY
|
||||
#include "../src/tree.h"
|
||||
|
||||
|
||||
/*!conditions:re2c*/
|
||||
|
||||
static int scan_day(struct scan *const scan, union date32 date,
|
||||
const char *const buffer) {
|
||||
const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *s0, *s1, *t0, *t1;
|
||||
const char *YYCURSOR, *YYMARKER, *yyt1, *yyt2, *yyt3, *s0, *s1, *t0, *t1;
|
||||
enum YYCONDTYPE condition = yycline;
|
||||
size_t line = 1;
|
||||
char datestr[12] = {0};
|
||||
@ -92,6 +104,9 @@ static int scan_day(struct scan *const scan, union date32 date,
|
||||
struct score *new_score = 0;
|
||||
struct glider *new_glider = 0;
|
||||
struct flight *new_flight = 0;
|
||||
enum kjv_book book = Revelation;
|
||||
uint32_t chapter = 0, verse = 0, verse_end = 0;
|
||||
|
||||
assert(scan && date.u32 && buffer);
|
||||
YYCURSOR = YYMARKER = yyt1 = buffer;
|
||||
/*!re2c /**/
|
||||
@ -112,6 +127,10 @@ static int scan_day(struct scan *const scan, union date32 date,
|
||||
date = natural "-" [0-1][0-9] "-" [0-3][0-9];
|
||||
minutes = [0-5][0-9];
|
||||
airport = [A-Z0-9]{4,4};
|
||||
kjvlookat = ws* natural ":" natural [ab]? ("-" natural [ab]?)? ws+ "--" ws+;
|
||||
first = ("I" | "1") " "?;
|
||||
second = ("II" | "2") " "?;
|
||||
third = ("III" | "3") " "?;
|
||||
*/
|
||||
for( ; ; ) {
|
||||
/*!re2c /**/
|
||||
@ -379,6 +398,125 @@ static int scan_day(struct scan *const scan, union date32 date,
|
||||
{ new_flight->remarks.a = s0, new_flight->remarks.b = s1;
|
||||
new_flight = 0; line++; continue; }
|
||||
|
||||
|
||||
/* Books in KJV. */
|
||||
<line> "Genesis" / kjvlookat => book { book = Genesis; continue; }
|
||||
<line> "Exodus" / kjvlookat => book { book = Exodus; continue; }
|
||||
<line> "Leviticus" / kjvlookat => book { book = Leviticus; continue; }
|
||||
<line> "Numbers" / kjvlookat => book { book = Numbers; continue; }
|
||||
<line> "Deuteronomy" / kjvlookat => book
|
||||
{ book = Deuteronomy; continue; }
|
||||
<line> "Joshua" / kjvlookat => book { book = Joshua; continue; }
|
||||
<line> "Judges" / kjvlookat => book { book = Judges; continue; }
|
||||
<line> "Ruth" / kjvlookat => book { book = Ruth; continue; }
|
||||
<line> first "Samuel" / kjvlookat => book { book = ISamuel; continue; }
|
||||
<line> second "Samuel" / kjvlookat => book { book = IISamuel; continue; }
|
||||
<line> first "Kings" / kjvlookat => book { book = IKings; continue; }
|
||||
<line> second "Kings" / kjvlookat => book { book = IIKings; continue; }
|
||||
<line> first "Chronicles" / kjvlookat
|
||||
=> book { book = IChronicles; continue; }
|
||||
<line> second "Chronicles" / kjvlookat
|
||||
=> book { book = IIChronicles; continue; }
|
||||
<line> "Ezra" / kjvlookat => book { book = Ezra; continue; }
|
||||
<line> "Nehemiah" / kjvlookat => book { book = Nehemiah; continue; }
|
||||
<line> "Esther" / kjvlookat => book { book = Esther; continue; }
|
||||
<line> "Job" / kjvlookat => book { book = Job; continue; }
|
||||
<line> "Psalms" / kjvlookat => book { book = Psalms; continue; }
|
||||
<line> "Proverbs" / kjvlookat => book { book = Proverbs; continue; }
|
||||
<line> "Ecclesiastes" / kjvlookat
|
||||
=> book { book = Ecclesiastes; continue; }
|
||||
<line> "Song of Solomon" / kjvlookat
|
||||
=> book { book = Song_of_Solomon; continue; }
|
||||
<line> "Isaiah" / kjvlookat => book { book = Isaiah; continue; }
|
||||
<line> "Jeremiah" / kjvlookat => book { book = Jeremiah; continue; }
|
||||
<line> "Lamentations" / kjvlookat
|
||||
=> book { book = Lamentations; continue; }
|
||||
<line> "Ezekiel" / kjvlookat => book { book = Ezekiel; continue; }
|
||||
<line> "Daniel" / kjvlookat => book { book = Daniel; continue; }
|
||||
<line> "Hosea" / kjvlookat => book { book = Hosea; continue; }
|
||||
<line> "Joel" / kjvlookat => book { book = Joel; continue; }
|
||||
<line> "Amos" / kjvlookat => book { book = Amos; continue; }
|
||||
<line> "Obadiah" / kjvlookat => book { book = Obadiah; continue; }
|
||||
<line> "Jonah" / kjvlookat => book { book = Jonah; continue; }
|
||||
<line> "Micah" / kjvlookat => book { book = Micah; continue; }
|
||||
<line> "Nahum" / kjvlookat => book { book = Nahum; continue; }
|
||||
<line> "Habakkuk" / kjvlookat => book { book = Habakkuk; continue; }
|
||||
<line> "Zephaniah" / kjvlookat => book { book = Zephaniah; continue; }
|
||||
<line> "Haggai" / kjvlookat => book { book = Haggai; continue; }
|
||||
<line> "Zechariah" / kjvlookat => book { book = Zechariah; continue; }
|
||||
<line> "Malachi" / kjvlookat => book { book = Malachi; continue; }
|
||||
<line> "Matthew" / kjvlookat => book { book = Matthew; continue; }
|
||||
<line> "Mark" / kjvlookat => book { book = Mark; continue; }
|
||||
<line> "Luke" / kjvlookat => book { book = Luke; continue; }
|
||||
<line> "John" / kjvlookat => book { book = John; continue; }
|
||||
<line> "Acts" / kjvlookat => book { book = Acts; continue; }
|
||||
<line> "Romans" / kjvlookat => book { book = Romans; continue; }
|
||||
<line> first "Corinthians" / kjvlookat
|
||||
=> book { book = ICorinthians; continue; }
|
||||
<line> second "Corinthians" / kjvlookat
|
||||
=> book { book = IICorinthians; continue; }
|
||||
<line> "Galatians" / kjvlookat => book { book = Galatians; continue; }
|
||||
<line> "Ephesians" / kjvlookat => book { book = Ephesians; continue; }
|
||||
<line> "Philippians" / kjvlookat => book
|
||||
{ book = Philippians; continue; }
|
||||
<line> "Colossians" / kjvlookat => book { book = Colossians; continue; }
|
||||
<line> first "Thessalonians" / kjvlookat
|
||||
=> book { book = IThessalonians; continue; }
|
||||
<line> second "Thessalonians" / kjvlookat
|
||||
=> book { book = IIThessalonians; continue; }
|
||||
<line> first "Timothy" / kjvlookat => book
|
||||
{ book = ITimothy; continue; }
|
||||
<line> second "Timothy" / kjvlookat => book
|
||||
{ book = IITimothy; continue; }
|
||||
<line> "Titus" / kjvlookat => book { book = Titus; continue; }
|
||||
<line> "Philemon" / kjvlookat => book { book = Philemon; continue; }
|
||||
<line> "Hebrews" / kjvlookat => book { book = Hebrews; continue; }
|
||||
<line> "James" / kjvlookat => book { book = James; continue; }
|
||||
<line> first "Peter" / kjvlookat => book { book = IPeter; continue; }
|
||||
<line> second "Peter" / kjvlookat => book { book = IIPeter; continue; }
|
||||
<line> first "John" / kjvlookat => book { book = IJohn; continue; }
|
||||
<line> second "John" / kjvlookat => book { book = IIJohn; continue; }
|
||||
<line> third "John" / kjvlookat => book { book = IIIJohn; continue; }
|
||||
<line> "Jude" / kjvlookat => book { book = Jude; continue; }
|
||||
<line> "Revelation" / kjvlookat => book { book = Revelation; continue; }
|
||||
<book> * { fail = "kjv unrecognized"; goto catch; }
|
||||
/* 19:15a, just ignore the a. */
|
||||
<book> ws+ @s0 natural @s1 ":" @t0 natural @t1 [ab]? {
|
||||
if(chapter || verse || verse_end)
|
||||
{ fail = "kjv reference"; goto catch; }
|
||||
if(!pair_to_natural(s0, s1, &chapter)
|
||||
|| !pair_to_natural(t0, t1, &verse))
|
||||
{ fail = "kjv reference numerical error"; goto catch; }
|
||||
continue;
|
||||
}
|
||||
<book> "-" @s0 natural @s1 [ab]? { /* Verse range. */
|
||||
if(!chapter || !verse || verse_end)
|
||||
{ fail = "kjv range unrecognized"; goto catch; }
|
||||
if(!pair_to_natural(s0, s1, &verse_end))
|
||||
{ fail = "kjv range numerical error"; goto catch; }
|
||||
continue;
|
||||
}
|
||||
<book> ws+ "--" ws+ => skip {
|
||||
if(!chapter || !verse)
|
||||
{ fail = "kjv missing information"; goto catch; }
|
||||
if(verse_end && verse_end <= verse)
|
||||
{ fail = "kjv interval error"; goto catch; }
|
||||
const union line64 key = {{ (uint32_t)line, date }};
|
||||
struct kjvrange *value;
|
||||
switch(kjvline_tree_bulk_assign(&scan->kjvs, key, &value)) {
|
||||
case TREE_PRESENT: fail = "kjv duplicate key";
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT:
|
||||
value->start.book = book;
|
||||
value->start.chapter = chapter;
|
||||
value->start.verse = verse;
|
||||
value->verse_end = verse_end;
|
||||
break;
|
||||
}
|
||||
book = Revelation, chapter = 0, verse = 0, verse_end = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
*/ }
|
||||
assert(0); /* Never gets here. */
|
||||
catch:
|
||||
@ -424,14 +562,9 @@ struct scan scan(struct journal *const jrnl) {
|
||||
if(!linemap_tree_bulk_finish(&scan.sources.dates)
|
||||
|| !linemap_tree_bulk_finish(&scan.scores.dates)
|
||||
|| !glider_tree_bulk_finish(&scan.gliders)
|
||||
|| !flight_tree_bulk_finish(&scan.flights)) goto catch;
|
||||
|| !flight_tree_bulk_finish(&scan.flights)
|
||||
|| !kjvline_tree_bulk_finish(&scan.kjvs)) goto catch;
|
||||
|
||||
fprintf(stderr, "List of scores: %s.\n"
|
||||
"Mapped to indices: %s.\n"
|
||||
"Date-line tree: %s.\n",
|
||||
score_array_to_string(&scan.scores.array),
|
||||
pair_map_table_to_string(&scan.scores.map),
|
||||
linemap_tree_to_string(&scan.scores.dates));
|
||||
goto finally;
|
||||
catch:
|
||||
scan_(&scan);
|
||||
@ -652,3 +785,101 @@ void scan_flight_graph(struct scan *const scan) {
|
||||
" (43200):(total/2.):(getIndex(strcol(2))) w boxxy lc var, \\\n"
|
||||
" for [i=1:words(Uniqs)] keyentry w boxxy lc i ti Uniq(i)\n");
|
||||
}
|
||||
|
||||
void scan_kjv_graph(struct scan *const scan) {
|
||||
struct kjvcount_table count = {0};
|
||||
struct kjvset_table set = kjv_set();
|
||||
size_t no_total;
|
||||
const char *reason = 0;
|
||||
|
||||
count = kjv_count(&no_total);
|
||||
fprintf(stderr, "KJV count: %s.\n", kjv_count_to_string(&count));
|
||||
if(!no_total) { reason = "kjv failed to load"; goto catch; }
|
||||
|
||||
fprintf(stderr, "KJV lines: %s.\n", kjvline_tree_to_string(&scan->kjvs));
|
||||
|
||||
struct kjvline_tree_iterator it = kjvline_tree_iterator(&scan->kjvs);
|
||||
|
||||
/* https://stackoverflow.com/a/12601553 */
|
||||
printf("set terminal pngcairo dashed transparent truecolor"
|
||||
" size 840, 480 fontscale 1\n"
|
||||
"set output \"kjv.png\"\n");
|
||||
printf("$Data <<EOD\n"
|
||||
"# date, verse, words, set / %zu, source\n", no_total);
|
||||
while(kjvline_tree_next(&it)) {
|
||||
char citestr[12], datestr[12];
|
||||
const union line64 line = kjvline_tree_key(&it);
|
||||
const struct kjvrange *const range = kjvline_tree_value(&it);
|
||||
size_t words = 0, newwords = 0;
|
||||
const struct source *src = source_lookup(scan, line);
|
||||
if(!src || !src->name.a) { errno = EDOM; goto catch; }
|
||||
date32_to_string(line.date, &datestr); /* Date. */
|
||||
kjvcite_to_string(range->start, &citestr); /* KJV cite. */
|
||||
for(union kjvcite c = range->start; ; c.verse++) {
|
||||
size_t w = kjv_count_get(&count, c);
|
||||
words += w;
|
||||
switch (kjv_set_add(&set, c)) {
|
||||
case TABLE_ERROR: goto catch;
|
||||
case TABLE_ABSENT: newwords += w;
|
||||
case TABLE_PRESENT: break;
|
||||
} /* while(); */
|
||||
if(!range->verse_end || range->verse_end <= c.verse) break;
|
||||
}
|
||||
printf("%s, %s", datestr, citestr);
|
||||
if(range->verse_end) printf("-%" PRIu32, range->verse_end);
|
||||
printf(", %zu, %zu, %.*s\n",
|
||||
words, newwords, (int)(src->name.b - src->name.a), src->name.a);
|
||||
}
|
||||
printf("EOD\n"
|
||||
"# theozh https://stackoverflow.com/a/75466214/2472827\n"
|
||||
"# get a unique list from datablock\n"
|
||||
"addToList(list,col) = list.( strstrt(list,'\"'.strcol(col).'\"') \\\n"
|
||||
" > 0 ? '' : ' \"'.strcol(col).'\"')\n"
|
||||
"Uniqs = ''\n"
|
||||
"stats $Data u (Uniqs=addToList(Uniqs,5)) nooutput\n"
|
||||
"Uniq(i) = word(Uniqs,i)\n"
|
||||
"getIndex(s) = sum [_i=1:words(Uniqs)] s eq word(Uniqs,_i) ? _i : 0\n"
|
||||
"\n"
|
||||
"stats $Data u 3 nooutput\n"
|
||||
"cumsum = STATS_sum\n"
|
||||
"stats $Data u 4 nooutput\n"
|
||||
"setsum = STATS_sum\n"
|
||||
"\n"
|
||||
"myTimeFmt = \"%%Y-%%m-%%d\"\n"
|
||||
"set format x myTimeFmt timedate\n"
|
||||
"set xtics format myTimeFmt rotate by -30\n"
|
||||
"set format y \"%%g%%%%\"\n"
|
||||
"set grid\n"
|
||||
"set key out reverse Left noautotitle\n"
|
||||
"set style fill solid 0.5\n"
|
||||
"unset border\n"
|
||||
"set autoscale xfix # max? hack: can't get x to extend further\n"
|
||||
"\n"
|
||||
"set label sprintf(\"%%u cumulative words (duplicate verses counted)\","
|
||||
" cumsum) center at graph 0.5, first cumsum*100/%zu offset 0,0.5\n"
|
||||
"set label sprintf(\"%%u unique KJV verse words memorized\", setsum) "
|
||||
"center at graph 0.5, first setsum*100/%zu offset 0,0.5\n"
|
||||
"\n"
|
||||
"plot \\\n"
|
||||
" cumsum*100/%zu w l lc \"grey\" dt 2 lw 1, \\\n"
|
||||
" total=0 $Data u"
|
||||
" (timecolumn(1,myTimeFmt)):(dy=$3*100/%zu,total=total+dy) \\\n"
|
||||
" w steps lc \"grey\" dt 2 lw 1, \\\n" /* `pngcairo` has trouble :[. */
|
||||
" total=0 $Data u"
|
||||
" (timecolumn(1,myTimeFmt)):(dy=$4*100/%zu,total=total+dy) \\\n"
|
||||
" w steps lc \"black\" dt 1 lw 1, \\\n"
|
||||
" setsum*100/%zu w l lc \"black\" dt 1 lw 1, \\\n"
|
||||
" total=0 '' u \\\n"
|
||||
" (timecolumn(1,myTimeFmt)): \\\n"
|
||||
" (dy=$4*100/%zu,total=total+dy,total/2.): \\\n"
|
||||
" (43200): \\\n"
|
||||
" (total/2.): \\\n"
|
||||
" (getIndex(strcol(5))) w boxxy lc var lw 1, \\\n"
|
||||
" for [i=1:words(Uniqs)] keyentry w boxxy lc i ti Uniq(i)\n",
|
||||
no_total, no_total, no_total, no_total, no_total, no_total, no_total);
|
||||
goto finally;
|
||||
catch:
|
||||
perror(reason);
|
||||
finally:
|
||||
kjv_count_(&count);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ static int scan(union date32 date, const char *const buffer,
|
||||
if(scores->list.data[idx].last.u32 >= date.u32)
|
||||
{ why = "duplicate key in same day"; goto catch; }
|
||||
scores->list.data[idx].last.u32 = date.u32;
|
||||
switch(score_tree_bulk_try(&scores->dates, key, &pidx)) {
|
||||
switch(score_tree_bulk_assign(&scores->dates, key, &pidx)) {
|
||||
case TREE_PRESENT: assert(0); why = "duplicate key"; /* _Sic_. */
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT: *pidx = idx; break;
|
||||
|
@ -82,7 +82,8 @@ static int scan(union date32 date, const char *const buffer,
|
||||
{ errno = ERANGE; why = "too many lines of text"; goto catch; }
|
||||
if(!(i = pair_map_table_get(&s->map, keyword)))
|
||||
{ why = "keyword not introduced"; goto catch; }
|
||||
switch(source_tree_try(&s->dates, key, &pi)) {
|
||||
/* fixme: bulk */
|
||||
switch(source_tree_assign(&s->dates, key, &pi)) {
|
||||
case TREE_PRESENT: why = "duplicate key"; /* _Sic_. */
|
||||
case TREE_ERROR: goto catch;
|
||||
case TREE_ABSENT: *pi = i; break;
|
||||
|
Loading…
Reference in New Issue
Block a user