-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ref #1
- Loading branch information
Showing
6 changed files
with
486 additions
and
338 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import {describe, it, expect} from 'vitest'; | ||
import {pianoMap} from '../piano'; | ||
import {CODES_LAYER_1} from '../coordinates'; | ||
|
||
describe('Piano-style index mapper', () => { | ||
it('maps a chromatic scale diatonically starting from KeyA', () => { | ||
const {indexByCode, coordsByIndex} = pianoMap([ | ||
2, // C | ||
1, // C# | ||
2, // D | ||
1, // D# | ||
2, // E | ||
2, // F | ||
1, // F# | ||
2, // G | ||
1, // G# | ||
2, // A | ||
1, // A# | ||
2, // B | ||
2, // c | ||
1, // c# | ||
2, // d | ||
1, // d# | ||
2, // e | ||
2, // f | ||
1, // f# | ||
2, // g | ||
1, // g# | ||
2, // a | ||
1, // a# | ||
2, // b | ||
]); | ||
const asdfRow = CODES_LAYER_1[2] | ||
.slice(1) | ||
.map(code => indexByCode.get(code!)); | ||
const qwertyRow = CODES_LAYER_1[1] | ||
.slice(1) | ||
.map(code => indexByCode.get(code!)); | ||
expect(coordsByIndex).toEqual([ | ||
[0, 2, 1], | ||
[1, 1, 1], | ||
[1, 2, 1], | ||
[2, 1, 1], | ||
[2, 2, 1], | ||
[3, 2, 1], | ||
[4, 1, 1], | ||
[4, 2, 1], | ||
[5, 1, 1], | ||
[5, 2, 1], | ||
[6, 1, 1], | ||
[6, 2, 1], | ||
[7, 2, 1], | ||
[8, 1, 1], | ||
[8, 2, 1], | ||
[9, 1, 1], | ||
[9, 2, 1], | ||
[10, 2, 1], | ||
[11, 1, 1], | ||
[11, 2, 1], | ||
undefined, | ||
undefined, | ||
undefined, | ||
undefined, | ||
]); | ||
expect(asdfRow).toEqual([0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19]); | ||
expect(qwertyRow).toEqual([ | ||
undefined, | ||
1, | ||
3, | ||
undefined, | ||
6, | ||
8, | ||
10, | ||
undefined, | ||
13, | ||
15, | ||
undefined, | ||
18, | ||
]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/* | ||
Split the keyboard into xy-planes along a z-coordinate for different contiguous regions of keys | ||
*/ | ||
|
||
export type Coords3D = [number, number, number]; | ||
|
||
const ORIGIN_LAYER_0 = 0; | ||
/** | ||
* Key codes for the row consisting of Esc and FN keys. | ||
*/ | ||
export const CODES_LAYER_0 = [ | ||
[ | ||
'Escape', | ||
'F1', | ||
'F2', | ||
'F3', | ||
'F4', | ||
'F5', | ||
'F6', | ||
'F7', | ||
'F8', | ||
'F9', | ||
'F10', | ||
'F11', | ||
'F12', | ||
], | ||
]; | ||
|
||
const ORIGIN_LAYER_1 = -1; | ||
/** | ||
* Key codes for the rows containing the digits, qwerty, asdf and zxcv. | ||
*/ | ||
export const CODES_LAYER_1 = [ | ||
[ | ||
'Backquote', | ||
'Digit1', | ||
'Digit2', | ||
'Digit3', | ||
'Digit4', | ||
'Digit5', | ||
'Digit6', | ||
'Digit7', | ||
'Digit8', | ||
'Digit9', | ||
'Digit0', | ||
'Minus', | ||
'Equal', | ||
], | ||
[ | ||
null, | ||
'KeyQ', | ||
'KeyW', | ||
'KeyE', | ||
'KeyR', | ||
'KeyT', | ||
'KeyY', | ||
'KeyU', | ||
'KeyI', | ||
'KeyO', | ||
'KeyP', | ||
'BracketLeft', | ||
'BracketRight', | ||
], | ||
[ | ||
null, | ||
'KeyA', | ||
'KeyS', | ||
'KeyD', | ||
'KeyF', | ||
'KeyG', | ||
'KeyH', | ||
'KeyJ', | ||
'KeyK', | ||
'KeyL', | ||
'Semicolon', | ||
'Quote', | ||
'Backslash', | ||
], | ||
[ | ||
'IntlBackslash', | ||
'KeyZ', | ||
'KeyX', | ||
'KeyC', | ||
'KeyV', | ||
'KeyB', | ||
'KeyN', | ||
'KeyM', | ||
'Comma', | ||
'Period', | ||
'Slash', | ||
], | ||
]; | ||
|
||
const ORIGIN_LAYER_2 = 0; | ||
/** | ||
* Key codes for the cluster of keys with Page Up/Down. | ||
*/ | ||
export const CODES_LAYER_2 = [ | ||
['Insert', 'Home', 'PageUp'], | ||
['Delete', 'End', 'PageDown'], | ||
]; | ||
|
||
const ORIGIN_LAYER_3 = 0; | ||
/** | ||
* Key codes for the numpad. | ||
*/ | ||
export const CODES_LAYER_3 = [ | ||
['NumLock', 'NumpadDivide', 'NumpadMultiply', 'NumpadSubtract'], | ||
['Numpad7', 'Numpad8', 'Numpad9', 'NumpadAdd'], | ||
['Numpad4', 'Numpad5', 'Numpad6'], | ||
['Numpad1', 'Numpad2', 'Numpad3', 'NumpadEnter'], | ||
['Numpad0', null, 'NumpadDecimal'], | ||
]; | ||
|
||
/** | ||
* Mapping from key codes to coordinates of input device geometry. | ||
*/ | ||
export const COORDS_BY_CODE: Map<string, Coords3D> = new Map(); | ||
CODES_LAYER_0.forEach((row, y) => | ||
row.forEach((code, x) => COORDS_BY_CODE.set(code, [ORIGIN_LAYER_0 + x, y, 0])) | ||
); | ||
CODES_LAYER_1.forEach((row, y) => { | ||
row.forEach((code, x) => { | ||
if (code !== null) { | ||
COORDS_BY_CODE.set(code, [ORIGIN_LAYER_1 + x, y, 1]); | ||
} | ||
}); | ||
}); | ||
CODES_LAYER_2.forEach((row, y) => | ||
row.forEach((code, x) => COORDS_BY_CODE.set(code, [ORIGIN_LAYER_2 + x, y, 2])) | ||
); | ||
CODES_LAYER_3.forEach((row, y) => { | ||
row.forEach((code, x) => { | ||
if (code !== null) { | ||
COORDS_BY_CODE.set(code, [ORIGIN_LAYER_3 + x, y, 3]); | ||
} | ||
}); | ||
}); | ||
|
||
const CODE_BY_COORDS: Record<string, string> = {}; | ||
|
||
for (const [code, xyz] of COORDS_BY_CODE) { | ||
const key = xyz.join(','); | ||
CODE_BY_COORDS[key] = code; | ||
} | ||
|
||
/** | ||
* Map 3D coordinates to key codes. | ||
* @param xyz 3D coordinates of the physical key. | ||
* @returns Key code associated with the coordinates or `undefined` if there is no association. | ||
*/ | ||
export function codeByCoords(xyz: Coords3D): string | undefined { | ||
const key = xyz.join(','); | ||
return CODE_BY_COORDS[key]; | ||
} |
Oops, something went wrong.