Skip to content

Instantly share code, notes, and snippets.

@dimitropoulos
Created December 4, 2021 03:29
Show Gist options
  • Save dimitropoulos/227c0cfd502d5e537675ae329644519e to your computer and use it in GitHub Desktop.
Save dimitropoulos/227c0cfd502d5e537675ae329644519e to your computer and use it in GitHub Desktop.
typing
const enum Finger {
LeftPinky = 1,
LeftRing = 2,
LeftMiddle = 3,
LeftIndex = 4,
Thumb = 5,
RightIndex = 6,
RightMiddle = 7,
RightRing = 8,
RightPinky = 9,
}
const isolatedKeystroke: Record<string, Finger> = {
'`': Finger.LeftPinky,
'1': Finger.LeftPinky,
// eslint-disable-next-line no-tabs -- it boggles my mind that this rule doesn't allow this...
' ': Finger.LeftPinky,
q: Finger.LeftPinky,
a: Finger.LeftPinky,
z: Finger.LeftPinky,
'2': Finger.LeftRing,
w: Finger.LeftRing,
s: Finger.LeftRing,
x: Finger.LeftRing,
'3': Finger.LeftMiddle,
e: Finger.LeftMiddle,
d: Finger.LeftMiddle,
c: Finger.LeftMiddle,
'4': Finger.LeftIndex,
r: Finger.LeftIndex,
f: Finger.LeftIndex,
v: Finger.LeftIndex,
'5': Finger.LeftIndex,
t: Finger.LeftIndex,
g: Finger.LeftIndex,
b: Finger.LeftIndex,
' ': Finger.Thumb,
'6': Finger.RightIndex,
y: Finger.RightIndex,
h: Finger.RightIndex,
n: Finger.RightIndex,
'7': Finger.RightIndex,
u: Finger.RightIndex,
j: Finger.RightIndex,
m: Finger.RightIndex,
'8': Finger.RightMiddle,
i: Finger.RightMiddle,
k: Finger.RightMiddle,
',': Finger.RightMiddle,
'9': Finger.RightRing,
o: Finger.RightRing,
l: Finger.RightRing,
'.': Finger.RightRing,
'0': Finger.RightPinky,
p: Finger.RightPinky,
';': Finger.RightPinky,
'/': Finger.RightPinky,
'-': Finger.RightPinky,
'[': Finger.RightPinky,
"'": Finger.RightPinky,
'=': Finger.RightPinky,
']': Finger.RightPinky,
'\\': Finger.RightPinky,
'\n': Finger.RightPinky, // Enter
};
const requiresShiftKey = (character: string) => isolatedKeystroke[character] === undefined;
/**
* If the previous character had to be typed by the same hand there's a bit of an added time tax to pay because it takes time to physically
*/
const sequentialKeysSameFinger = (character: string, previousCharacter: string) => (
isolatedKeystroke[character] === isolatedKeystroke[previousCharacter]
);
/**
* If the previous character matches, we want to go faster.
*
* Consider the situation of multiple spaces for indenting, multiple sequential line returns, or words with repeated characters (e.g. "llama"). In these situations it's natural that someone would type the repeated character much faster.
*/
const isDoubleKeypress = (character: string, previousCharacter: string) => (
character === previousCharacter
);
const hardcodedDelays: Record<string, number | undefined> = {
' ': 4,
'\n': 8,
';': 5,
'=': 2,
'>': 3,
'(': 3,
')': 2,
'{': 2,
'}': 3,
'.': 6,
};
/** give an extra little randomness to the typing */
const getJitter = () => {
const min = 100;
const max = 150; // so, up to 50% randomness
const result = Math.floor(min + (Math.random() * (max + 1 - min)));
return result / 100;
};
export const getDelayMultiplier = (character: string, previousCharacter: string) => {
if (isDoubleKeypress(character, previousCharacter)) {
return 2;
}
const hardcodedDelayMultiplier = hardcodedDelays[character];
if (hardcodedDelayMultiplier !== undefined) {
return hardcodedDelayMultiplier;
}
if (requiresShiftKey(character)) {
return 3;
}
if (sequentialKeysSameFinger(character, previousCharacter)) {
return 3;
}
return 1;
};
export const getWaitTime = (milliseconds: number) => (character: string, previousCharacter: string) => {
const jitter = getJitter();
const delayMultiplier = getDelayMultiplier(character, previousCharacter);
return milliseconds * delayMultiplier * jitter;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment