diff options
Diffstat (limited to 'awk')
-rw-r--r-- | awk/files.awk | 18 | ||||
-rw-r--r-- | awk/filter_due.awk | 8 | ||||
-rw-r--r-- | awk/index_cards.awk | 46 | ||||
-rw-r--r-- | awk/index_positions.awk | 69 | ||||
-rw-r--r-- | awk/stats_cards.awk | 47 | ||||
-rw-r--r-- | awk/stats_positions.awk | 40 | ||||
-rw-r--r-- | awk/stats_reviews.awk | 53 | ||||
-rw-r--r-- | awk/utils.awk | 23 |
8 files changed, 304 insertions, 0 deletions
diff --git a/awk/files.awk b/awk/files.awk new file mode 100644 index 0000000..6926408 --- /dev/null +++ b/awk/files.awk @@ -0,0 +1,18 @@ +BEGIN { + FS="|"; +} + +BEGINFILE { + has_card = 0; +} + +# Flashcard headings +/^\*+ .*:fc:.*$/ { + has_card = 1; +} + +ENDFILE { + if (has_card == 1) { + print FILENAME; + } +} diff --git a/awk/filter_due.awk b/awk/filter_due.awk new file mode 100644 index 0000000..b85fdfe --- /dev/null +++ b/awk/filter_due.awk @@ -0,0 +1,8 @@ +BEGIN { + FS="\t"; + now = strftime("%FT%T", systime(), 1); +} + +$4 == "0" && $9 < now { + print $0 +} diff --git a/awk/index_cards.awk b/awk/index_cards.awk new file mode 100644 index 0000000..27c50b9 --- /dev/null +++ b/awk/index_cards.awk @@ -0,0 +1,46 @@ +BEGIN { + FS="|"; + + fc_tag = ":" or_default(fc_tag, "fc") ":"; + suspended_tag = ":" or_default(suspended_tag, "suspended") ":"; + review_data_drawer = ":" or_default(review_data_drawer, "REVIEW_DATA") ":"; + type_property = or_default(type_property, "FC_TYPE"); + created_property = or_default(created_property, "FC_CREATED"); +} + +## Heading Parsing + +/^\*+[ \t]+.*$/ { + # tag re based on org-tag-re + match($0, /^\*+[ \t]+.*[ \t]+(:([a-zA-Z0-9_@#%]+:)+)$/, a) + tags = a[1] + id = "none"; + + if (tags ~ fc_tag) { + in_card = 1; + suspended = (tags ~ suspended_tag); + } else { + in_card = 0; + } + next +} + +## Property parsing + +in_card && /:PROPERTIES:/ { + in_properties = 1; + delete properties; +} + +in_properties && match($0, /^[ \t]*:([a-zA-Z0-9_]+):[ \t]*(.+)$/, a) { + properties[a[1]] = trim_surrounding(a[2]); +} + +in_properties && /:END:/ { + id = properties["ID"]; + type = properties[type_property]; + created = properties[created_property]; + print FILENAME "\t" id "\t" type "\t" suspended "\t" created; + in_properties = 0; + in_card = 0; +} diff --git a/awk/index_positions.awk b/awk/index_positions.awk new file mode 100644 index 0000000..36e9cbe --- /dev/null +++ b/awk/index_positions.awk @@ -0,0 +1,69 @@ +BEGIN { + FS="|"; + + fc_tag = ":" or_default(fc_tag, "fc") ":"; + suspended_tag = ":" or_default(suspended_tag, "suspended") ":"; + review_data_drawer = ":" or_default(review_data_drawer, "REVIEW_DATA") ":"; + type_property = or_default(type_property, "FC_TYPE"); + created_property = or_default(created_property, "FC_CREATED"); +} + +## Heading Parsing + +/^\*+[ \t]+.*$/ { + # tag re based on org-tag-re + match($0, /^\*+[ \t]+.*[ \t]+(:([a-zA-Z0-9_@#%]+:)+)$/, a) + tags = a[1] + + id = "none"; + + if (tags ~ fc_tag) { + in_card = 1; + suspended = (tags ~ suspended_tag); + } else { + in_card = 0; + } + next +} + +## Property parsing + +in_card && /:PROPERTIES:/ { + in_properties = 1; + delete properties; +} + +in_properties && match($0, /^[ \t]*:([a-zA-Z0-9_]+):[ \t]*(.+)$/, a) { + properties[a[1]] = trim_surrounding(a[2]); +} + +in_properties && /:END:/ { + in_properties = 0; +} + +## Review data parsing + +in_card && $0 ~ review_data_drawer { + in_data = 1; +} + +in_data && /:END:/ { + in_data = 0; +} + +in_data && /^\|.*\|$/ { + # Make sure we're inside a data block, + # check NF to skip the |--+--| table separator + # match on $2 to skip the table header + if (in_data == 1 && NF == 7 && $2 !~ "position") { + id = properties["ID"]; + type = properties[type_property]; + + position = trim($2); + ease = trim($3); + box = trim($4); + interval = trim($5); + due = trim_surrounding($6); + print FILENAME "\t" id "\t" type "\t" suspended "\t" position "\t" ease "\t" box "\t" interval "\t" due; + } +} diff --git a/awk/stats_cards.awk b/awk/stats_cards.awk new file mode 100644 index 0000000..3f29338 --- /dev/null +++ b/awk/stats_cards.awk @@ -0,0 +1,47 @@ +BEGIN { + FS="\t"; + total = 0; + suspended = 0; + + t_day = time_days_ago(1); + t_week = time_days_ago(7); + t_month = time_days_ago(30); + + created["day"] = 0; + created["week"] = 0; + created["month"] = 0; +} + +{ + total += 1; + + type = $3; + by_type[type] += 1; + + if ($4 == "1") { + suspended++; + } + + if ($5 > t_day) { + created["day"]++; + } + + if ($5 > t_week) { + created["week"]++; + } + + if ($5 > t_month) { + created["month"]++; + } +} + +END { + print "total" "\t" total; + print "suspended" "\t" suspended; + print "created-day" "\t" created["day"]; + print "created-week" "\t" created["week"]; + print "created-month" "\t" created["month"]; + for (var in by_type) { + print "type-" var "\t" by_type[var]; + } +} diff --git a/awk/stats_positions.awk b/awk/stats_positions.awk new file mode 100644 index 0000000..d38d2cd --- /dev/null +++ b/awk/stats_positions.awk @@ -0,0 +1,40 @@ +BEGIN { + FS="\t"; + total = 0; + suspended = 0; + ease = 0; + interval = 0; + box = 0; + due = 0; + now = strftime("%FT%T", systime(), 1); +} + +{ + total += 1; + + type = $3; + by_type[type] += 1; + + ease += $6; + box += $7; + interval += $8; + + if ($4 == "1") { + suspended += 1; + } + if ($4 == "0" && $9 < now) { + due += 1; + } +} + +END { + print "total" "\t" total; + print "suspended" "\t" suspended; + print "due" "\t" due; + for (var in by_type) { + print "type-" var "\t" by_type[var]; + } + print "avg-ease" "\t" ease / NR; + print "avg-box" "\t" box / NR; + print "avg-interval" "\t" interval / NR; +} diff --git a/awk/stats_reviews.awk b/awk/stats_reviews.awk new file mode 100644 index 0000000..bacafb2 --- /dev/null +++ b/awk/stats_reviews.awk @@ -0,0 +1,53 @@ +BEGIN { + FS="\t" + t_day = time_days_ago(1); + t_week = time_days_ago(7); + t_month = time_days_ago(30); +} + +{ + date = $1; + file = $2; + id = $3; + position = $4; + ease = $5; + box = $6; + interval = $7; + rating = $8; + + if (box >= 2) { + if (date > t_day) { + ratings_day[rating]++; + n_day++; + } + + if (date > t_week) { + ratings_week[rating]++; + n_week++; + } + + if (date > t_month) { + ratings_month[rating]++; + n_month++; + } + + ratings_all[rating]++; + n_all++; + } +} + +END { + report(ratings_all, n_all); + report(ratings_month, n_month); + report(ratings_week, n_week); + report(ratings_day, n_day); +} + +function report(values, n) { + if (n == 0) { + print 0 "\t" 0 "\t" 0 "\t" 0 "\t" 0; + } else { + print n "\t" values["again"] / n "\t" values["hard"] / n "\t" values["good"] /n "\t" values["easy"] / n; + + } +} diff --git a/awk/utils.awk b/awk/utils.awk new file mode 100644 index 0000000..00045de --- /dev/null +++ b/awk/utils.awk @@ -0,0 +1,23 @@ +## Helper functions + +# Remove all whitespace in str +function trim(str) { + gsub(/[ \t]/, "", str); + return str; +} + +# Remove all whitespace around str +function trim_surrounding(str) { + gsub(/^[ \t]*/, "", str); + gsub(/[ \t]*$/, "", str); + return str; +} + +# Time n days before the current time +function time_days_ago(n) { + return strftime("%FT%T", systime() - 24 * 60 * 60 * n, 1); +} + +function or_default(var, def) { + return var ? var : def; +} |