URI: 
       Add pholcode support to annna. - annna - Annna the nice friendly bot.
  HTML git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/annna/
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
       ---
   DIR commit 7c69a018ae0f2c8a92922058333f86fe59d0af20
   DIR parent 0da5bb56bf17635438234d4f055e53d0a831b81e
  HTML Author: Annna Robert-Houdin <annna@bitreich.org>
       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(-)
       ---
   DIR 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
   DIR 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
       +}