Add pholcode support to annna. - annna - Annna the nice friendly bot. | |
git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws6… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
commit 7c69a018ae0f2c8a92922058333f86fe59d0af20 | |
parent 0da5bb56bf17635438234d4f055e53d0a831b81e | |
Author: Annna Robert-Houdin <[email protected]> | |
Date: Sun, 6 Apr 2025 15:59:47 +0200 | |
Add pholcode support to annna. | |
Thanks Ben Collver! | |
Diffstat: | |
M annna-message-common | 5 +++++ | |
A pohlcode.awk | 265 +++++++++++++++++++++++++++++… | |
2 files changed, 270 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/annna-message-common b/annna-message-common | |
@@ -720,6 +720,11 @@ case "${text}" in | |
suri="$(printf "%s\n" "${word}" | ghost -e)" | |
annna-say -s "${server}" -c "${channel}" "${suri}" | |
;; | |
+"${ircuser}, please pohlish "*) | |
+ word="$(printf "%s\n" "${text}" | cut -c 23- | sed 's,\t, ,g')" | |
+ suri="$(pohlcode.awk "${word}")" | |
+ annna-say -s "${server}" -c "${channel}" "${suri}" | |
+ ;; | |
"${ircuser}, what can I cook with "*) | |
ingredients="$(printf "%s\n" "${text}" | cut -c 29- | sed 's,\t, ,g… | |
case "$ingredients" in | |
diff --git a/pohlcode.awk b/pohlcode.awk | |
@@ -0,0 +1,265 @@ | |
+#!/usr/bin/awk -f | |
+# pohlcode.awk version 3 by Ben Collver | |
+# | |
+# Implement spoken representation of binary numbers described in | |
+# On Binary Digits And Human Habits by Frederik Pohl, 1962. | |
+# | |
+# Dual license: WTFPL and Public Domain | |
+# | |
+# Pohl encode string from decimal number: | |
+# awk -f pohlcode.awk 31337 | |
+# | |
+# Decode decimal number from Pohl encoded string: | |
+# awk -f pohlcode.awk tee two group totter-poot totter-poot | |
+ | |
+# initialize tables used to convert between bases and encodings | |
+ | |
+function init( hl, hu, i) { | |
+ split("pohl poot pahtah pod too tot dye tee", second, " ") | |
+ split("ohly ooty ahtah oddy too totter dye teeter", first, " ") | |
+ split("000 001 010 011 100 101 110 111", trip, " ") | |
+ split("zero one two three four five six seven eight nine", eng, " ") | |
+ split("0 1 2 3 4 5 6 7 8 9 A B C D E F", hex, " ") | |
+ split("0000 0001 0010 0011 0100 0101 0110 0111 " \ | |
+ "1000 1001 1010 1011 1100 1101 1110 1111", bin, " ") | |
+ | |
+ # bin/dec/hex conversion tables | |
+ for (i in hex) { | |
+ hu = hex[i] | |
+ hl = tolower(hu) | |
+ h2b[hl] = h2b[hu] = bin[i] | |
+ h2d[hl] = h2d[hu] = i - 1 | |
+ b2h[bin[i]] = hu | |
+ } | |
+ | |
+ # english digit conversion tables | |
+ for (i in eng) { | |
+ d2e[i - 1] = eng[i] | |
+ e2d[eng[i]] = i - 1 | |
+ } | |
+ | |
+ # Pohl code binary triplet conversion tables | |
+ for (i in trip) { | |
+ f2p[trip[i]] = first[i] | |
+ s2p[trip[i]] = second[i] | |
+ p2f[first[i]] = trip[i] | |
+ p2s[second[i]] = trip[i] | |
+ } | |
+ | |
+ return | |
+} | |
+ | |
+function bin2dec(str, dec, hex) { | |
+ hex = bin2hex(str) | |
+ dec = hex2dec(hex) | |
+ return dec | |
+} | |
+ | |
+function bin2hex(str, chunk, n, i, hex, pad, rem) { | |
+ str = zpad4(str) | |
+ n = length(str) | |
+ for (i = 1; i <= n; i += 4) { | |
+ chunk = zpad4(substr(str, i, 4)) | |
+ hex = hex b2h[chunk] | |
+ } | |
+ return hex | |
+} | |
+ | |
+function bin2pohl(bin, bbuf, groups, p, parts, retval, val) { | |
+ groups = int(length(bin) / 6) | |
+ if (groups > 9) { | |
+ print "Error: groups out of bounds: " groups | |
+ exit 1 | |
+ } | |
+ p = 0 | |
+ bbuf = zpad6(bin) | |
+ if (length(bbuf) > length(bin)) { | |
+ val = substr(bbuf, 1, 6) | |
+ sub(/^000/, "", val) | |
+ bbuf = substr(bbuf, 7) | |
+ p++ | |
+ parts[p] = pohlencode(val) | |
+ } | |
+ if (groups > 0) { | |
+ p++ | |
+ parts[p] = d2e[groups] " group" | |
+ } | |
+ for (i = 1; i <= groups; i++) { | |
+ val = substr(bbuf, 1, 6) | |
+ bbuf = substr(bbuf, 7) | |
+ p++ | |
+ parts[p] = pohlencode(val) | |
+ } | |
+ retval = "" | |
+ for (i = 1; i <= p; i++) { | |
+ if (length(retval) == 0) { | |
+ retval = parts[i] | |
+ } else { | |
+ retval = retval " " parts[i] | |
+ | |
+ } | |
+ } | |
+ return retval | |
+} | |
+ | |
+function dec2bin(dec, hex, bin) { | |
+ hex = sprintf("%x\n", dec) | |
+ bin = hex2bin(hex) | |
+ return bin | |
+} | |
+ | |
+function hex2bin(hex, n, i, bin) { | |
+ n = length(hex) | |
+ for (i = 1; i <= n; i++) { | |
+ bin = bin h2b[substr(hex, i, 1)] | |
+ } | |
+ sub(/^0+/, "", bin) | |
+ if (length(bin) == 0) { | |
+ bin = "0" | |
+ } | |
+ return bin | |
+} | |
+ | |
+function hex2dec(val, out, i, n) { | |
+ if (val ~ /^0x/) { | |
+ val = substr(val, 3) | |
+ } | |
+ n = length(val) | |
+ for (i = 1; i <= n; i++) { | |
+ out = (out * 16) + h2d[substr(val, i, 1)] | |
+ } | |
+ #return sprintf("%.0f", out) | |
+ return out | |
+} | |
+ | |
+function pohl2bin(str, bbuf, eng, groups, i, prefix, result, wnum, \ | |
+ words) | |
+{ | |
+ bbuf = "" | |
+ groups = 1 | |
+ result = match(str, /.* group /) | |
+ if (result > 0) { | |
+ prefix = substr(str, 1, RLENGTH) | |
+ str = substr(str, RLENGTH + 1) | |
+ wnum = split(prefix, words, " ") | |
+ if (wnum == 2) { | |
+ eng = words[1] | |
+ } else if (wnum == 3) { | |
+ eng = words[2] | |
+ bbuf = pohldecode(words[1]) | |
+ sub(/^0*/, "", bbuf) | |
+ } else { | |
+ print "Bad Pohl code prefix: " prefix | |
+ exit 1 | |
+ } | |
+ if (eng in e2d) { | |
+ groups = e2d[eng] | |
+ } else { | |
+ print "Invalid number of groups: " eng | |
+ exit 1 | |
+ } | |
+ } | |
+ wnum = split(str, words, " ") | |
+ if (wnum != groups) { | |
+ print "Expected " groups " group(s) but got: " wnum | |
+ exit 1 | |
+ } | |
+ for (i = 1; i <= wnum ; i++) { | |
+ bbuf = bbuf pohldecode(words[i]) | |
+ } | |
+ return bbuf | |
+} | |
+ | |
+# decode pohl-encoded 6-bit word | |
+ | |
+function pohldecode(word, parts, pnum, retval) { | |
+ pnum = split(word, parts, "-") | |
+ if (pnum == 2 && parts[1] in p2f && parts[2] in p2s) { | |
+ retval = p2f[parts[1]] p2s[parts[2]] | |
+ } else if (pnum == 1 && parts[1] in p2s) { | |
+ retval = "000" p2s[parts[1]] | |
+ } else { | |
+ print "Invalid pohl code word: " word | |
+ exit 1 | |
+ } | |
+ return retval | |
+} | |
+ | |
+# pohl encode 6-bit word | |
+ | |
+function pohlencode(digits, retval, triplet1, triplet2) { | |
+ if (length(digits) == 3) { | |
+ retval = s2p[digits] | |
+ } else { | |
+ triplet1 = substr(digits, 1, 3) | |
+ triplet2 = substr(digits, 4, 6) | |
+ retval = f2p[triplet1] "-" s2p[triplet2] | |
+ } | |
+ return retval | |
+} | |
+ | |
+# zero pad number until length is a multiple of 4 digits | |
+ | |
+function zpad4(str, pad, rem) { | |
+ rem = length(str) % 4 | |
+ if (rem > 0) { | |
+ pad = substr("0000", 1, 4 - rem) | |
+ str = pad str | |
+ } | |
+ return str | |
+} | |
+ | |
+# zero pad number until length is a multiple of 6 digits | |
+ | |
+function zpad6(str, pad, rem) { | |
+ rem = length(str) % 6 | |
+ if (rem > 0) { | |
+ pad = substr("000000", 1, 6 - rem) | |
+ str = pad str | |
+ } | |
+ return str | |
+} | |
+ | |
+function main( i, result, val) { | |
+ for (i = 1; i < ARGC; i++) { | |
+ if (length(val) == 0) { | |
+ val = ARGV[i] | |
+ } else { | |
+ val = val " " ARGV[i] | |
+ } | |
+ } | |
+ if (length(val) == 0) { | |
+ print "Usage: pohlcode.awk [code|number|test]" | |
+ print "" | |
+ print "[code]: Converts Pohl code to decimal." | |
+ print "[number]: Converts decimal to Pohl code." | |
+ print "test: Print test output." | |
+ exit 1 | |
+ } | |
+ sub(/\n$/, "", val) | |
+ init() | |
+ if (val == "test") { | |
+ test() | |
+ } else if (val ~ /^[0-9][0-9]*$/) { | |
+ result = bin2pohl(dec2bin(val)) | |
+ } else { | |
+ result = bin2dec(pohl2bin(val)) | |
+ } | |
+ print result | |
+ return | |
+} | |
+ | |
+function test( code, i, j) { | |
+ return | |
+ for (i = 0; i < 1024; i++) { | |
+ code = bin2pohl(dec2bin(i)) | |
+ j = bin2dec(pohl2bin(code)) | |
+ printf "%d\t%s\t%d\n", i, code, j | |
+ } | |
+ return | |
+} | |
+ | |
+BEGIN { | |
+ main() | |
+ exit 0 | |
+} |