diff options
author | Ryan Ascheman <rascheman@groupon.com> | 2016-10-18 21:42:02 +0200 |
---|---|---|
committer | Ryan Ascheman <rascheman@groupon.com> | 2016-10-18 21:42:02 +0200 |
commit | 55b8b8477cc6aee82dfe6792eea4e589cac433d5 (patch) | |
tree | ce5bfbd1b0ee59dbffdc2044bcf90c89614392ed /keyboards/ergodox/keymaps/algernon/tools | |
parent | d1c70328f8d8ded6ce1e5422b468fc41ef315e7d (diff) | |
parent | 04df74f6360464661bcc1e6794e9fd3549084390 (diff) | |
download | qmk_firmware-55b8b8477cc6aee82dfe6792eea4e589cac433d5.tar.gz qmk_firmware-55b8b8477cc6aee82dfe6792eea4e589cac433d5.tar.xz |
Merge remote-tracking branch 'upstream/master'
* upstream/master: (1239 commits)
Update ez.c
removes planck/rev3 temporarily
Move hand_swap_config to ez.c, removes error for infinity
Update Makefile
ergodox: Update algernon's keymap to v1.9
Added VS Code dir to .gitignore
Support the Pegasus Hoof controller.
[Jack & Erez] Simplifies and documents TO
add readme
use wait_ms instead of _delay_ms
add messenger
init keymap
Add example keymap
Adding whiskey_tango_foxtrot_capslock ergodox keymap
Unicode map framework. Allow unicode up to 0xFFFFF using separate mapping table
CIE 1931 dim curve
Apply the dim curve to the RGB output
Update the Cluecard readme files
Tune snake and knight intervals for Cluecard
Tunable RGB light intervals
...
Diffstat (limited to 'keyboards/ergodox/keymaps/algernon/tools')
5 files changed, 1493 insertions, 0 deletions
diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json new file mode 100644 index 000000000..e09efecc4 --- /dev/null +++ b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json @@ -0,0 +1,486 @@ +[ + { + "backcolor": "#ffffff", + "name": "ErgoDox - algernon's layout: Heatmap", + "author": "Gergely Nagy <kbd@gergo.csillger.hu>", + "notes": "See [here](https://github.com/algernon/ergodox-layout#readme) for the QMK keymap source.", + "switchMount": "cherry", + "switchBrand": "gateron", + "switchType": "KS-3-Tea", + "pcb": true, + "css": ".keyborder { -webkit-filter: blur(5px); filter: blur(5px); } .keytop { -webkit-filter: blur(10px); } .keylabels { border: 1px solid black; }" + }, + [ + { + "x": 3.5, + "fa": [ + 0, + 0, + 2 + ] + }, + "*\n5\nF5", + { + "x": 10.5, + "a": 4, + "fa": [ + 0, + 0, + 2 + ] + }, + "#\n4\nF4" + ], + [ + { + "y": -0.875, + "x": 2.5 + }, + "@\n7\nF7", + { + "x": 1 + }, + "^\n3\nF3", + { + "x": 8.5 + }, + "!\n2\nF2", + { + "x": 1 + }, + "&\n6\nF6" + ], + [ + { + "y": -0.875, + "x": 5.5 + }, + "$\n1\nF1", + { + "a": 7, + "f": 3 + }, + "F11", + { + "x": 4.5, + "f": 3 + }, + "Fx", + { + "a": 4, + "f": 3, + "fa": [ + 0, + 0, + 2 + ] + }, + "%\n0\nF10" + ], + [ + { + "y": -0.875, + "f": 9, + "a": 6, + "w": 1.5 + }, + "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>", + { + "f": 3, + "a": 4, + "fa": [ + 0, + 0, + 2 + ] + }, + " \n9\nF9", + { + "x": 14.5 + }, + " \n8\nF8", + { + "a": 7, + "w": 1.5 + }, + "STENO" + ], + [ + { + "y": -0.375, + "x": 3.5, + "a": 6 + }, + "C", + { + "x": 10.5 + }, + "L" + ], + [ + { + "y": -0.875, + "x": 2.5, + "a": 6 + }, + "W", + { + "x": 1, + "a": 6 + }, + "H", + { + "x": 8.5 + }, + "G", + { + "x": 1 + }, + "P" + ], + [ + { + "y": -0.875, + "x": 5.5 + }, + "F", + { + "a": 4, + "fa": [0, 0, 0], + "h": 1.5 + }, + "{\n(\n[", + { + "x": 4.5, + "h": 1.5 + }, + "}\n)\n]", + { + "a": 6 + }, + "M" + ], + [ + { + "y": -0.875, + "f": 3, + "a": 4, + "w": 1.5 + }, + "\n\n|\n\\", + { + "a": 6, + "f": 3 + }, + "X", + { + "x": 14.5, + "a": 4 + }, + "/\n?", + { + "a": 4, + "w": 1.5 + }, + "~\n`" + ], + [ + { + "y": -0.375, + "x": 3.5, + "a": 6 + }, + "E", + { + "x": 10.5 + }, + "T" + ], + [ + { + "y": -0.875, + "x": 2.5 + }, + "O", + { + "x": 1, + "n": true + }, + "I", + { + "x": 8.5, + "n": true + }, + "R", + { + "x": 1 + }, + "N" + ], + [ + { + "y": -0.875, + "x": 5.5 + }, + "U", + { + "x": 6.5 + }, + "D" + ], + [ + { + "y": -0.875, + "fa": [ + 6 + ], + "w": 1.5 + }, + "<i class='fa fa-arrows'></i>\n\nTab", + { + "f": 3 + }, + "A", + { + "x": 14.5, + "f": 3 + }, + "S", + { + "a": 4, + "fa": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 6 + ], + "w": 1.5 + }, + "+\n=" + ], + [ + { + "y": -0.625, + "x": 6.5, + "a": 7, + "f": 9, + "h": 1.5 + }, + "<i class='fa fa-columns'></i>", + { + "x": 4.5, + "h": 1.5 + }, + "<i class='fa fa-table'></i>" + ], + [ + { + "y": -0.75, + "x": 3.5, + "a": 4, + "f": 3 + }, + "\"\n'", + { + "x": 10.5, + "a": 6, + "f": 3 + }, + "V" + ], + [ + { + "y": -0.875, + "x": 2.5, + "a": 6 + }, + "Q", + { + "x": 1, + "a": 4 + }, + "<\n,", + { + "x": 8.5, + "a": 6 + }, + "K", + { + "x": 1 + }, + "Y" + ], + [ + { + "y": -0.875, + "x": 5.5, + "a": 4 + }, + ">\n.", + { + "x": 6.5, + "a": 6 + }, + "B" + ], + [ + { + "y": -0.875, + "f": 9, + "w": 1.5, + "g": true + }, + "", + { + "a": 6, + "f": 3, + "g": false + }, + "Z", + { + "x": 14.5 + }, + "J", + { + "f": 9, + "g": true, + "w": 1.5, + "a": 4 + }, + "" + ], + [ + { + "y": -0.375, + "x": 3.5, + "g": true, + "a": 7, + "f": 3 + }, + "", + { + "x": 10.5 + }, + "" + ], + [ + { + "y": -0.875, + "x": 2.5 + }, + "", + { + "x": 1, + "g": false, + "a": 5 + }, + ";\n:", + { + "x": 8.5 + }, + "_\n-", + { + "x": 1, + "g": true, + "a": 7 + }, + "" + ], + [ + { + "y": -0.75, + "x": 0.5 + }, + "", + {}, + "", + { + "x": 14.5 + }, + "", + {}, + "" + ], + [ + { + "r": 30, + "rx": 6.5, + "ry": 4.25, + "y": -1, + "x": 1, + "g": false + }, + "Alt", + { + "a": 4, + "fa": [ + 0, + 0, + 0, + 9 + ] + }, + "\n\n\n<i class='kb kb-logo-linux-debian fa-large'></i>" + ], + [ + { + "a": 7, + "f": 9, + "h": 2 + }, + "<i class='kb kb-Unicode-BackSpace-DeleteLeft-Big'></i>", + { + "h": 2 + }, + "<i class='fa fa-angle-double-up'></i>", + { + "f": 3 + }, + "Ctrl" + ], + [ + { + "x": 2 + }, + "ESC" + ], + [ + { + "r": -30, + "rx": 13, + "y": -1, + "x": -3, + "f": 2 + }, + "MEDIA", + {}, + "DEL" + ], + [ + { + "x": -3 + }, + "HUN", + { + "f": 9, + "h": 2 + }, + "<i class='kb kb-Return-2'></i>", + { + "f": 3, + "h": 2 + }, + "SPC" + ], + [ + { + "x": -3, + "f": 2 + }, + "LEAD" + ] +] diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json new file mode 100644 index 000000000..1e53281c5 --- /dev/null +++ b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json @@ -0,0 +1,477 @@ +[ + { + "backcolor": "#ffffff", + "name": "ErgoDox - algernon's layout: Heatmap", + "author": "Gergely Nagy <kbd@gergo.csillger.hu>", + "notes": "See [here](https://github.com/algernon/ergodox-layout#readme) for the QMK keymap source.", + "switchMount": "cherry", + "switchBrand": "gateron", + "switchType": "KS-3-Tea", + "pcb": true, + "css": ".keyborder { -webkit-filter: blur(5px); filter: blur(5px); } .keytop { -webkit-filter: blur(10px); } .keylabels { border: 1px solid black; }" + }, + [ + { + "x": 3.5, + "fa": [ + 0, + 0, + 2 + ] + }, + "*\n5\nF5", + { + "x": 10.5, + "a": 4, + "fa": [ + 0, + 0, + 2 + ] + }, + "#\n4\nF4" + ], + [ + { + "y": -0.875, + "x": 2.5 + }, + "@\n7\nF7", + { + "x": 1 + }, + "^\n3\nF3", + { + "x": 8.5 + }, + "!\n2\nF2", + { + "x": 1 + }, + "&\n6\nF6" + ], + [ + { + "y": -0.875, + "x": 5.5 + }, + "$\n1\nF1", + { + "a": 7, + "f": 3 + }, + "F11", + { + "x": 4.5, + "f": 3 + }, + "Fx", + { + "a": 4, + "f": 3, + "fa": [ + 0, + 0, + 2 + ] + }, + "%\n0\nF10" + ], + [ + { + "y": -0.875, + "f": 6, + "a": 6, + "w": 1.5 + }, + "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>", + { + "f": 3, + "a": 4, + "fa": [ + 0, + 0, + 2 + ] + + }, + " \n9\nF9", + { + "x": 14.5 + }, + " \n8\nF8", + { + "a": 7, + "w": 1.5 + }, + "STENO" + ], + [ + { + "y": -0.375, + "x": 3.5, + "a": 4 + }, + ">\n.", + { + "x": 10.5, + "a": 6 + }, + "C" + ], + [ + { + "y": -0.875, + "x": 2.5, + "a": 4 + }, + "<\n,", + { + "x": 1, + "a": 6 + }, + "P", + { + "x": 8.5 + }, + "G", + { + "x": 1 + }, + "R" + ], + [ + { + "y": -0.875, + "x": 5.5 + }, + "Y", + { + "a": 4, + "h": 1.5 + }, + "{\n(\n[", + { + "x": 4.5, + "h": 1.5 + }, + "}\n)\n]", + { + "a": 6 + }, + "F" + ], + [ + { + "y": -0.875, + "f": 3, + "a": 4, + "w": 1.5 + }, + "\n\n~\n`", + { + "a": 4, + "f": 3 + }, + "\"\n'", + { + "x": 14.5, + "a": 6 + }, + "L", + { + "a": 4, + "w": 1.5 + }, + "|\n\\" + ], + [ + { + "y": -0.375, + "x": 3.5, + "a": 6 + }, + "E", + { + "x": 10.5 + }, + "T" + ], + [ + { + "y": -0.875, + "x": 2.5 + }, + "O", + { + "x": 1, + "n": true + }, + "U", + { + "x": 8.5, + "n": true + }, + "H", + { + "x": 1 + }, + "N" + ], + [ + { + "y": -0.875, + "x": 5.5 + }, + "I", + { + "x": 6.5 + }, + "D" + ], + [ + { + "y": -0.875, + "fa": [ + 6 + ], + "w": 1.5 + }, + "<i class='fa fa-arrows'></i>\n\nTab", + { + "f": 3 + }, + "A", + { + "x": 14.5, + "f": 3 + }, + "S", + { + "a": 4, + "fa": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 6 + ], + "w": 1.5 + }, + "+\n=" + ], + [ + { + "y": -0.625, + "x": 6.5, + "a": 7, + "f": 9, + "h": 1.5 + }, + "<i class='fa fa-columns'></i>", + { + "x": 4.5, + "h": 1.5 + }, + "<i class='fa fa-table'></i>" + ], + [ + { + "y": -0.75, + "x": 3.5, + "f": 3, + "a": 6 + }, + "J", + { + "x": 10.5 + }, + "W" + ], + [ + { + "y": -0.875, + "x": 2.5 + }, + "Q", + { + "x": 1 + }, + "K", + { + "x": 8.5 + }, + "M", + { + "x": 1 + }, + "V" + ], + [ + { + "y": -0.875, + "x": 5.5 + }, + "X", + { + "x": 6.5 + }, + "B" + ], + [ + { + "y": -0.875, + "f": 9, + "w": 1.5 + }, + "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>", + { + "a": 4, + "f": 3 + }, + "?\n/", + { + "x": 14.5, + "a": 6 + }, + "Z", + { + "f": 9, + "w": 1.5 + }, + "<i class='kb kb-Multimedia-Stop'></i>" + ], + [ + { + "y": -0.375, + "x": 3.5, + "g": true, + "a": 7, + "f": 3 + }, + "", + { + "x": 10.5 + }, + "" + ], + [ + { + "y": -0.875, + "x": 2.5 + }, + "", + { + "x": 1, + "g": false, + "a": 5 + }, + ";\n:", + { + "x": 8.5 + }, + "_\n-", + { + "x": 1, + "g": true, + "a": 7 + }, + "" + ], + [ + { + "y": -0.75, + "x": 0.5 + }, + "", + {}, + "", + { + "x": 14.5 + }, + "", + {}, + "" + ], + [ + { + "r": 30, + "rx": 6.5, + "ry": 4.25, + "y": -1, + "x": 1, + "g": false + }, + "Alt", + { + "a": 4, + "fa": [ + 0, + 0, + 0, + 9 + ] + }, + "\n\n\n<i class='kb kb-logo-linux-debian fa-large'></i>" + ], + [ + { + "a": 7, + "f": 9, + "h": 2 + }, + "<i class='kb kb-Unicode-BackSpace-DeleteLeft-Big'></i>", + { + "h": 2 + }, + "<i class='fa fa-angle-double-up'></i>", + { + "f": 3 + }, + "Ctrl" + ], + [ + { + "x": 2 + }, + "ESC" + ], + [ + { + "r": -30, + "rx": 13, + "y": -1, + "x": -3, + "f": 2 + }, + "MEDIA", + {}, + "DEL" + ], + [ + { + "x": -3 + }, + "LEAD", + { + "f": 9, + "h": 2 + }, + "<i class='kb kb-Return-2'></i>", + { + "f": 3, + "h": 2 + }, + "SPC" + ], + [ + { + "x": -3, + "f": 2 + }, + "HUN" + ] +] diff --git a/keyboards/ergodox/keymaps/algernon/tools/hid-commands b/keyboards/ergodox/keymaps/algernon/tools/hid-commands new file mode 100755 index 000000000..a29d38f41 --- /dev/null +++ b/keyboards/ergodox/keymaps/algernon/tools/hid-commands @@ -0,0 +1,79 @@ +#!/bin/bash +set -e + +LAST_APPSEL_START=0 + +cmd_wm () { + WIN="$(xdotool getactivewindow)" + wmctrl -i -r ${WIN} -b remove,maximized_vert,maximized_horz + xdotool windowsize ${WIN} 100% 100% + wmctrl -i -r ${WIN} -b add,maximized_vert,maximized_horz +} + +_cmd_appsel () { + wmctrl -x -a $1 || true + xdotool key Escape +} + +cmd_appsel_music () { + wmctrl -x -a rhythmbox || wmctrl -x -a spotify || wmctrl -x -a kodi || true + xdotool key Escape +} + +cmd_appsel_slack () { + _cmd_appsel slack +} + +cmd_appsel_emacs () { + _cmd_appsel emacs +} + +cmd_appsel_term () { + _cmd_appsel gnome-terminal +} + +cmd_appsel_chrome () { + _cmd_appsel chromium +} + +cmd_appsel_start () { + if [ ! -z "${DISABLE_APPSEL_START}" ]; then + return + fi + + APPSEL_START=$(date +%s) + if [ $APPSEL_START -lt $(expr $LAST_APPSEL_START + 10) ]; then + return + fi + LAST_APPSEL_START=$APPSEL_START + notify-send -t 1000 "Please select an application!" -c device -u low \ + -i /usr/share/icons/Adwaita/24x24/devices/video-display.png +} + +cmd_reflash () { + teensy_loader_cli -v -w ~/src/ext/qmk_firmware/algernon.hex --mcu atmega32u4 || true +} + +cmd_help () { + cat <<EOF +Use the source, Luke! +EOF +} + +while read l; do + case "$l" in + "CMD:"*) + ;; + *) + continue + ;; + esac + + cmd="$(echo $l | cut -d: -f2-)" + + echo "Got command: ${cmd}" + + if type cmd_${cmd} >/dev/null 2>&1; then + cmd_${cmd} + fi +done diff --git a/keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py b/keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py new file mode 100755 index 000000000..e927e0e39 --- /dev/null +++ b/keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py @@ -0,0 +1,344 @@ +#! /usr/bin/env python3 +import json +import os +import sys +import re +import argparse +import time + +from math import floor +from os.path import dirname +from subprocess import Popen, PIPE, STDOUT +from blessings import Terminal + +class Heatmap(object): + coords = [ + [ + # Row 0 + [ 4, 0], [ 4, 2], [ 2, 0], [ 1, 0], [ 2, 2], [ 3, 0], [ 3, 2], + [ 3, 4], [ 3, 6], [ 2, 4], [ 1, 2], [ 2, 6], [ 4, 4], [ 4, 6], + ], + [ + # Row 1 + [ 8, 0], [ 8, 2], [ 6, 0], [ 5, 0], [ 6, 2], [ 7, 0], [ 7, 2], + [ 7, 4], [ 7, 6], [ 6, 4], [ 5, 2], [ 6, 6], [ 8, 4], [ 8, 6], + ], + [ + # Row 2 + [12, 0], [12, 2], [10, 0], [ 9, 0], [10, 2], [11, 0], [ ], + [ ], [11, 2], [10, 4], [ 9, 2], [10, 6], [12, 4], [12, 6], + ], + [ + # Row 3 + [17, 0], [17, 2], [15, 0], [14, 0], [15, 2], [16, 0], [13, 0], + [13, 2], [16, 2], [15, 4], [14, 2], [15, 6], [17, 4], [17, 6], + ], + [ + # Row 4 + [20, 0], [20, 2], [19, 0], [18, 0], [19, 2], [], [], [], [], + [19, 4], [18, 2], [19, 6], [20, 4], [20, 6], [], [], [], [] + ], + [ + # Row 5 + [ ], [23, 0], [22, 2], [22, 0], [22, 4], [21, 0], [21, 2], + [24, 0], [24, 2], [25, 0], [25, 4], [25, 2], [26, 0], [ ], + ], + ] + + def set_attr_at(self, block, n, attr, fn, val): + blk = self.heatmap[block][n] + if attr in blk: + blk[attr] = fn(blk[attr], val) + else: + blk[attr] = fn(None, val) + + def coord(self, col, row): + return self.coords[row][col] + + @staticmethod + def set_attr(orig, new): + return new + + def set_bg(self, coords, color): + (block, n) = coords + self.set_attr_at(block, n, "c", self.set_attr, color) + #self.set_attr_at(block, n, "g", self.set_attr, False) + + def set_tap_info(self, coords, count, cap): + (block, n) = coords + def _set_tap_info(o, _count, _cap): + ns = 4 - o.count ("\n") + return o + "\n" * ns + "%.02f%%" % (float(_count) / float(_cap) * 100) + + if not cap: + cap = 1 + self.heatmap[block][n + 1] = _set_tap_info (self.heatmap[block][n + 1], count, cap) + + @staticmethod + def heatmap_color (v): + colors = [ [0.3, 0.3, 1], [0.3, 1, 0.3], [1, 1, 0.3], [1, 0.3, 0.3]] + fb = 0 + if v <= 0: + idx1, idx2 = 0, 0 + elif v >= 1: + idx1, idx2 = len(colors) - 1, len(colors) - 1 + else: + val = v * (len(colors) - 1) + idx1 = int(floor(val)) + idx2 = idx1 + 1 + fb = val - float(idx1) + + r = (colors[idx2][0] - colors[idx1][0]) * fb + colors[idx1][0] + g = (colors[idx2][1] - colors[idx1][1]) * fb + colors[idx1][1] + b = (colors[idx2][2] - colors[idx1][2]) * fb + colors[idx1][2] + + r, g, b = [x * 255 for x in (r, g, b)] + return "#%02x%02x%02x" % (int(r), int(g), int(b)) + + def __init__(self, layout): + self.log = {} + self.total = 0 + self.max_cnt = 0 + self.layout = layout + + def update_log(self, coords): + (c, r) = coords + if not (c, r) in self.log: + self.log[(c, r)] = 0 + self.log[(c, r)] = self.log[(c, r)] + 1 + self.total = self.total + 1 + if self.max_cnt < self.log[(c, r)]: + self.max_cnt = self.log[(c, r)] + + def get_heatmap(self): + with open("%s/heatmap-layout.%s.json" % (dirname(sys.argv[0]), self.layout), "r") as f: + self.heatmap = json.load (f) + + ## Reset colors + for row in self.coords: + for coord in row: + if coord != []: + self.set_bg (coord, "#d9dae0") + + for (c, r) in self.log: + coords = self.coord(c, r) + b, n = coords + cap = self.max_cnt + if cap == 0: + cap = 1 + v = float(self.log[(c, r)]) / cap + self.set_bg (coords, self.heatmap_color (v)) + self.set_tap_info (coords, self.log[(c, r)], self.total) + return self.heatmap + + def get_stats(self): + usage = [ + # left hand + [0, 0, 0, 0, 0], + # right hand + [0, 0, 0, 0, 0] + ] + finger_map = [0, 0, 1, 2, 3, 3, 3, 1, 1, 1, 2, 3, 4, 4] + for (c, r) in self.log: + if r == 5: # thumb cluster + if c <= 6: # left side + usage[0][4] = usage[0][4] + self.log[(c, r)] + else: + usage[1][0] = usage[1][0] + self.log[(c, r)] + elif r == 4 and (c == 4 or c == 9): # bottom row thumb keys + if c <= 6: # left side + usage[0][4] = usage[0][4] + self.log[(c, r)] + else: + usage[1][0] = usage[1][0] + self.log[(c, r)] + else: + fc = c + hand = 0 + if fc >= 7: + hand = 1 + fm = finger_map[fc] + usage[hand][fm] = usage[hand][fm] + self.log[(c, r)] + hand_usage = [0, 0] + for f in usage[0]: + hand_usage[0] = hand_usage[0] + f + for f in usage[1]: + hand_usage[1] = hand_usage[1] + f + + total = self.total + if total == 0: + total = 1 + stats = { + "total-keys": total, + "hands": { + "left": { + "usage": round(float(hand_usage[0]) / total * 100, 2), + "fingers": { + "pinky": 0, + "ring": 0, + "middle": 0, + "index": 0, + "thumb": 0, + } + }, + "right": { + "usage": round(float(hand_usage[1]) / total * 100, 2), + "fingers": { + "thumb": 0, + "index": 0, + "middle": 0, + "ring": 0, + "pinky": 0, + } + }, + } + } + + hmap = ['left', 'right'] + fmap = ['pinky', 'ring', 'middle', 'index', 'thumb', + 'thumb', 'index', 'middle', 'ring', 'pinky'] + for hand_idx in range(len(usage)): + hand = usage[hand_idx] + for finger_idx in range(len(hand)): + stats['hands'][hmap[hand_idx]]['fingers'][fmap[finger_idx + hand_idx * 5]] = round(float(hand[finger_idx]) / total * 100, 2) + return stats + +def dump_all(out_dir, heatmaps): + stats = {} + t = Terminal() + t.clear() + sys.stdout.write("\x1b[2J\x1b[H") + + print ('{t.underline}{outdir}{t.normal}\n'.format(t=t, outdir=out_dir)) + + keys = list(heatmaps.keys()) + keys.sort() + + for layer in keys: + if len(heatmaps[layer].log) == 0: + continue + + with open ("%s/%s.json" % (out_dir, layer), "w") as f: + json.dump(heatmaps[layer].get_heatmap(), f) + stats[layer] = heatmaps[layer].get_stats() + + left = stats[layer]['hands']['left'] + right = stats[layer]['hands']['right'] + + print ('{t.bold}{layer}{t.normal} ({total:,} taps):'.format(t=t, layer=layer, + total=int(stats[layer]['total-keys'] / 2))) + print (('{t.underline} | ' + \ + 'left ({l[usage]:6.2f}%) | ' + \ + 'right ({r[usage]:6.2f}%) |{t.normal}').format(t=t, l=left, r=right)) + print ((' {t.bright_magenta}pinky{t.white} | {left[pinky]:6.2f}% | {right[pinky]:6.2f}% |\n' + \ + ' {t.bright_cyan}ring{t.white} | {left[ring]:6.2f}% | {right[ring]:6.2f}% |\n' + \ + ' {t.bright_blue}middle{t.white} | {left[middle]:6.2f}% | {right[middle]:6.2f}% |\n' + \ + ' {t.bright_green}index{t.white} | {left[index]:6.2f}% | {right[index]:6.2f}% |\n' + \ + ' {t.bright_red}thumb{t.white} | {left[thumb]:6.2f}% | {right[thumb]:6.2f}% |\n' + \ + '').format(left=left['fingers'], right=right['fingers'], t=t)) + +def process_line(line, heatmaps, opts, stamped_log = None): + m = re.search ('KL: col=(\d+), row=(\d+), pressed=(\d+), layer=(.*)', line) + if not m: + return False + if stamped_log is not None: + if line.startswith("KL:"): + print ("%10.10f %s" % (time.time(), line), + file = stamped_log, end = '') + else: + print (line, + file = stamped_log, end = '') + stamped_log.flush() + + (c, r, l) = (int(m.group (2)), int(m.group (1)), m.group (4)) + if (c, r) not in opts.allowed_keys: + return False + + heatmaps[l].update_log ((c, r)) + + return True + +def setup_allowed_keys(opts): + if len(opts.only_key): + incmap={} + for v in opts.only_key: + m = re.search ('(\d+),(\d+)', v) + if not m: + continue + (c, r) = (int(m.group(1)), int(m.group(2))) + incmap[(c, r)] = True + else: + incmap={} + for r in range(0, 6): + for c in range(0, 14): + incmap[(c, r)] = True + + for v in opts.ignore_key: + m = re.search ('(\d+),(\d+)', v) + if not m: + continue + (c, r) = (int(m.group(1)), int(m.group(2))) + del(incmap[(c, r)]) + + return incmap + +def main(opts): + heatmaps = {"Dvorak": Heatmap("Dvorak"), + "ADORE": Heatmap("ADORE") + } + cnt = 0 + out_dir = opts.outdir + + if not os.path.exists(out_dir): + os.makedirs(out_dir) + + opts.allowed_keys = setup_allowed_keys(opts) + + if not opts.one_shot: + + try: + with open("%s/stamped-log" % out_dir, "r") as f: + while True: + line = f.readline() + if not line: + break + if not process_line(line, heatmaps, opts): + continue + except: + pass + + stamped_log = open ("%s/stamped-log" % (out_dir), "a+") + else: + stamped_log = None + + while True: + line = sys.stdin.readline() + if not line: + break + if not process_line(line, heatmaps, opts, stamped_log): + continue + + cnt = cnt + 1 + + if opts.dump_interval != -1 and cnt >= opts.dump_interval and not opts.one_shot: + cnt = 0 + dump_all(out_dir, heatmaps) + + dump_all (out_dir, heatmaps) + +if __name__ == "__main__": + parser = argparse.ArgumentParser (description = "keylog to heatmap processor") + parser.add_argument ('outdir', action = 'store', + help = 'Output directory') + parser.add_argument ('--dump-interval', dest = 'dump_interval', action = 'store', type = int, + default = 100, help = 'Dump stats and heatmap at every Nth event, -1 for dumping at EOF only') + parser.add_argument ('--ignore-key', dest = 'ignore_key', action = 'append', type = str, + default = [], help = 'Ignore the key at position (x, y)') + parser.add_argument ('--only-key', dest = 'only_key', action = 'append', type = str, + default = [], help = 'Only include key at position (x, y)') + parser.add_argument ('--one-shot', dest = 'one_shot', action = 'store_true', + help = 'Do not load previous data, and do not update it, either.') + args = parser.parse_args() + if len(args.ignore_key) and len(args.only_key): + print ("--ignore-key and --only-key are mutually exclusive, please only use one of them!", + file = sys.stderr) + sys.exit(1) + main(args) diff --git a/keyboards/ergodox/keymaps/algernon/tools/text-to-log.py b/keyboards/ergodox/keymaps/algernon/tools/text-to-log.py new file mode 100755 index 000000000..f080c32cd --- /dev/null +++ b/keyboards/ergodox/keymaps/algernon/tools/text-to-log.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +import os +import sys + +charmap = { + '9': [[1, 0]], + '7': [[2, 0]], '@': [[2, 5], [2, 0]], + '5': [[3, 0]], '*': [[2, 5], [3, 0]], + '3': [[4, 0]], '^': [[2, 5], [4, 0]], + '1': [[5, 0]], '$': [[2, 5], [5, 0]], + '0': [[8, 0]], '%': [[2, 5], [8, 0]], + '2': [[9, 0]], '!': [[2, 5], [9, 0]], + '4': [[10, 0]], '#': [[2, 5], [10, 0]], + '6': [[11, 0]], '&': [[2, 5], [11, 0]], + '8': [[12, 0]], + + '\\': [[0, 1]], '|': [[2, 5], [0, 1]], + 'x': [[1, 1]], 'X': [[2, 5], [1, 1]], + 'w': [[2, 1]], 'W': [[2, 5], [2, 1]], + 'c': [[3, 1]], 'C': [[2, 5], [3, 1]], + 'h': [[4, 1]], 'H': [[2, 5], [4, 1]], + 'f': [[5, 1]], 'F': [[2, 5], [5, 1]], + '[': [[6, 1]], '{': [[2, 5], [6, 1]], '(': [[6, 1], [6, 1]], + ']': [[7, 1]], '}': [[2, 5], [7, 1]], ')': [[7, 1], [7, 1]], + 'm': [[8, 1]], 'M': [[2, 5], [8, 1]], + 'g': [[9, 1]], 'G': [[2, 5], [9, 1]], + 'l': [[10, 1]], 'L': [[2, 5], [10, 1]], + 'p': [[11, 1]], 'P': [[2, 5], [11, 1]], + '/': [[12, 1]], '?': [[2, 5], [12, 1]], + '`': [[13, 1]], '~': [[2, 5], [13, 1]], + + '\t': [[0, 2]], + 'a': [[1, 2]], 'A': [[2, 5], [1, 2]], + 'o': [[2, 2]], 'O': [[2, 5], [2, 2]], + 'e': [[3, 2]], 'E': [[2, 5], [3, 2]], + 'i': [[4, 2]], 'I': [[2, 5], [4, 2]], + 'u': [[5, 2]], 'U': [[2, 5], [5, 2]], + 'd': [[8, 2]], 'D': [[2, 5], [8, 2]], + 'r': [[9, 2]], 'R': [[2, 5], [9, 2]], + 't': [[10, 2]], 'T': [[2, 5], [10, 2]], + 'n': [[11, 2]], 'N': [[2, 5], [11, 2]], + 's': [[12, 2]], 'S': [[2, 5], [12, 2]], + '=': [[13, 2]], '+': [[2, 5], [13, 2]], + + 'z': [[1, 3]], 'Z': [[2, 5], [1, 3]], + 'q': [[2, 3]], 'Q': [[2, 5], [2, 3]], + '\'': [[3, 3]], '"': [[2, 5], [3, 3]], + ',': [[4, 3]], '<': [[2, 5], [4, 3]], + '.': [[5, 3]], '>': [[2, 5], [5, 3]], + 'b': [[8, 3]], 'B': [[2, 5], [8, 3]], + 'k': [[9, 3]], 'K': [[2, 5], [9, 3]], + 'v': [[10, 3]], 'V': [[2, 5], [10, 3]], + 'y': [[11, 3]], 'Y': [[2, 5], [11, 3]], + 'j': [[12, 3]], 'J': [[2, 5], [12, 3]], + + ':': [[4, 4]], ';': [[4, 4], [4, 4]], + '-': [[9, 4]], '_': [[2, 5], [9, 4]], + + ' ': [[10, 5]], + '\n': [[11, 5]], + + ## Layered things + # Hungarian + 'á': [[9, 5], [1, 2]], 'Á': [[2, 5], [9, 5], [1, 2]], + 'ó': [[9, 5], [2, 2]], 'Ó': [[2, 5], [9, 5], [2, 2]], + 'ő': [[9, 5], [2, 1]], 'Ő': [[2, 5], [9, 5], [2, 1]], + 'ö': [[9, 5], [2, 3]], 'Ö': [[2, 5], [9, 5], [2, 3]], + 'é': [[9, 5], [3, 2]], 'É': [[2, 5], [9, 5], [3, 2]], + 'ú': [[9, 5], [4, 2]], 'Ú': [[2, 5], [9, 5], [4, 2]], + 'ű': [[9, 5], [4, 1]], 'Ű': [[2, 5], [9, 5], [4, 1]], + 'ü': [[9, 5], [4, 3]], 'Ü': [[2, 5], [9, 5], [4, 3]], + 'í': [[9, 5], [5, 2]], 'Í': [[2, 5], [9, 5], [5, 2]], +} + +def lookup_char(layer, ch): + if ch in charmap: + return charmap[ch] + return None + +def process_char(layer, ch, out=sys.stdout): + keys = lookup_char(layer, ch) + if not keys: + print ("Unknown char: %s" % ch, file=sys.stderr) + else: + for (c, r) in keys: + print ("KL: col=%d, row=%d, pressed=1, layer=%s" % (r, c, layer), file=out) + print ("KL: col=%d, row=%d, pressed=0, layer=%s" % (r, c, layer), file=out) + +def process_file(fn, layer, out=sys.stdout): + with open(fn, "r") as f: + ch = f.read(1) + while ch: + process_char(layer, ch, out) + ch = f.read(1) + +if sys.argv[1] == '-': + out='/dev/stdin' +else: + out=sys.argv[1] + +if len(sys.argv) >= 2: + layer = 'ADORE' +else: + layer = sys.argv[2] + +process_file(out, layer = layer) |