Skip to content

Instantly share code, notes, and snippets.

@bryanhelmig
Last active January 12, 2024 03:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bryanhelmig/2cc72b92e5d3c6afd71ed86c8247a4f8 to your computer and use it in GitHub Desktop.
Save bryanhelmig/2cc72b92e5d3c6afd71ed86c8247a4f8 to your computer and use it in GitHub Desktop.
A short snippet of Python that detects keyboard mashing like dsuyafgsgafiuyas.
import itertools
import math
def tokenize_keyboard(board):
return [list(row.strip()) for row in board]
def invert_grid(grid):
out = {}
for row_i, row in enumerate(grid):
for col_i, cell in enumerate(row):
if cell:
out[cell] = (float(row_i), float(col_i))
return out
KEYBOARD = [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '='],
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', "'"],
['z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'],
['', '', '', '', ' ', '', '', '', '', ''],
]
KEYBOARD_GRID = invert_grid(KEYBOARD)
SHIFTED_KEYBOARD = [
['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+'],
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"'],
['Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?'],
['', '', '', '', ' ', '', '', '', '', ''],
]
SHIFTED_KEYBOARD_GRID = invert_grid(SHIFTED_KEYBOARD)
def get_distance(a, b):
a_pos = KEYBOARD_GRID.get(a) or SHIFTED_KEYBOARD_GRID.get(a)
b_pos = KEYBOARD_GRID.get(b) or SHIFTED_KEYBOARD_GRID.get(b)
if a_pos and b_pos:
return math.hypot(a_pos[0] - b_pos[0], a_pos[1] - b_pos[1])
return 0.0
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
def score_not_mashing(text):
"Returns a float - higher score is less likely to be mashing."
distance = 0.0
for a, b in pairwise(text):
distance += (get_distance(a, b) - 1)
return distance / len(text)
def is_mashing(text, cutoff=1.75):
return score_not_mashing(text) < cutoff
import detect_mashing
def test_get_distance():
assert detect_mashing.get_distance('q', 'w') == 1.0
assert detect_mashing.get_distance('q', 'e') == 2.0
assert detect_mashing.get_distance('q', 'a') == 1.0
assert str(detect_mashing.get_distance('q', 's')) == str(1.41421356237)
def test_mashing():
assert not detect_mashing.is_mashing('hello world!')
assert not detect_mashing.is_mashing('to be or not to be, that is the question')
assert not detect_mashing.is_mashing('bryan@zapier.com')
assert not detect_mashing.is_mashing('Bryan Helmig')
assert detect_mashing.is_mashing('djhfgdsiuyfatdgs')
assert detect_mashing.is_mashing('aw67tre967rteir6w86')
assert detect_mashing.is_mashing('qwertyuiop')
assert detect_mashing.is_mashing('sdakjhfghbk@awre879argh78.com')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment