This repository has been archived by the owner on May 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
bimap.js
111 lines (105 loc) · 2.64 KB
/
bimap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// an immutable bidirectional map of string <-> number
class StrNbrBiMap { // needs to be sublassed in order to be filled with data
constructor() {
this._strNbr = {};
this._nbrStr = [];
}
getNbr(str) {
return this._strNbr[str];
}
*[Symbol.iterator]() {
// we cannot iterate over `_strNbr` (which seem more efficient) because the order in a for...in loop in arbitrary
for (let key of this._nbrStr) {
yield {
str: key,
nbr: this.getNbr(key)
};
}
}
}
export class EnumMap extends StrNbrBiMap {
// the numbers corresponding to each strings are like those of an enum, starting at 0 with a step of 1
constructor(...fields) {
super();
let val = 0;
for (let field of fields) {
this._strNbr[field] = val;
this._nbrStr.push(field);
++val;
}
}
getStr(nbr) {
return this._nbrStr[nbr];
}
}
export class BitmaskMap extends StrNbrBiMap {
// the numbers corresponding to each strings are like those of an bitmask, 0b000000001 -> 0b00000010 -> 0b000000100 -> 0b00001000 -> etc. You get the point
constructor(...fields) {
super();
let val = 1;
for (let field of fields) {
this._strNbr[field] = val;
this._nbrStr.push(field);
val <<= 1;
}
}
getStr(nbr) {
return this._nbrStr[Math.log2(nbr)];
}
}
// a mutable bidirectional map of string <-> string
// an action can be mapped to multiple keyboard keys, but a keyboard key can only be mapped to one action
export class KeyActionMap { // note: `key` here does not refer to a key as in 'key <-> value' but as in 'keyboard key'
constructor(str) {
if (str !== undefined) this.parse(str);
else {
this._actions = {};
this._keys = {};
}
}
keyTaken(key) {
if (this._keys[key] !== undefined) return true;
return false;
}
addMapping(action, key) {
if (this._actions[action] === undefined) this._actions[action] = new Set();
this._actions[action].add(key);
this._keys[key] = action;
}
deleteKey(key) {
this._actions[this._keys[key]].delete(key);
delete this._keys[key];
}
getAction(key) {
return this._keys[key];
}
getKeys(action) {
return this._actions[action];
}
stringify() {
return JSON.stringify(this._keys);
}
parse(str) {
this._actions = {};
this._keys = JSON.parse(str);
for (let key in this._keys) {
let action = this._keys[key];
if (this._actions[action] === undefined) this._actions[action] = new Set();
this._actions[action].add(key);
}
}
compare(defaultKeymap) {
for (let key in this._keys) {
if (this._keys[key] !== defaultKeymap[key]) return false;
}
return true;
}
*[Symbol.iterator]() {
for (let action in this._actions) {
yield {
action,
associatedKeys: this.getKeys(action)
};
}
}
}