vail/static/scripts/decoder.js

147 lines
3.5 KiB
JavaScript

const morseToAlphabet = new Map([
["12", "A"],
["2111", "B"],
["2121", "C"],
["211", "D"],
["1", "E"],
["1121", "F"],
["221", "G"],
["1111", "H"],
["11", "I"],
["1222", "J"],
["212", "K"],
["1211", "L"],
["22", "M"],
["21", "N"],
["222", "O"],
["1221", "P"],
["2212", "Q"],
["121", "R"],
["111", "S"],
["2", "T"],
["112", "U"],
["1112", "V"],
["122", "W"],
["2112", "X"],
["2122", "Y"],
["2211", "Z"],
["12222", "1"],
["11222", "2"],
["11122", "3"],
["11112", "4"],
["11111", "5"],
["21111", "6"],
["22111", "7"],
["22211", "8"],
["22221", "9"],
["22222", "0"],
["121212", "."],
["221122", ","],
["21121", "/"],
["112211", "?"],
["212122", "!"],
["211112", "-"],
["21221", "("],
["212212", ")"],
["222111", ":"],
]);
class Decoder {
constructor(onLetterDecoded) {
this.onLetterDecoded = onLetterDecoded; // Store the callback function
this.lastLetter = '';
this.decodeArray = '';
this.unit = 80; // adjustment: short dit reduces, long dah lengthens
this.keyStartTime = null;
this.keyEndTime = null;
this.spaceTimer = null;
this.farnsworth = 3;
this.wordTimer = null; // Timer for word boundaries
this.wordTimeout = this.unit * 7; // A typical word gap is 7 units
}
keyOn() {
clearTimeout(this.spaceTimer);
clearTimeout(this.wordTimer); // Clear the wordTimer as well since we are receiving input
this.keyStartTime = Date.now();
//var pauseDuration = (this.keyEndTime) ? this.keyStartTime - this.keyEndTime : 0;
//if (pauseDuration > this.unit + (this.unit/10)) { // end sequence and decode letter
//this.registerLetter();
//}
}
keyOff() {
this.keyEndTime = Date.now();
var keyDuration = (this.keyStartTime) ? this.keyEndTime - this.keyStartTime : 0;
if (keyDuration < this.unit) {
// reduce unit based on short dit
this.unit = (keyDuration + this.unit) / 2;
this.registerDit();
} else if (keyDuration > this.unit * 3) {
// lengthen unit based on long dah
this.unit = ((keyDuration / 3) + this.unit) / 2;
this.registerDah();
} else {
var ditAndDahThreshold = (this.unit * 2);
if (keyDuration >= ditAndDahThreshold) {
this.registerDah();
} else {
this.registerDit();
}
}
let spaceTime = this.unit * this.farnsworth;
this.spaceTimer = setTimeout(() => { // end sequence and decode letter
this.updateLastLetter(this.morseToLetter(this.decodeArray));
this.decodeArray = '';
this.startWordTimer(); // Start the word timer after finishing a letter
}, spaceTime, "keyOff");
}
registerDit() {
this.decodeArray += '1';
}
registerDah() {
this.decodeArray += '2';
}
updateLastLetter(letter) {
//updateCurrentLetter(letter);
this.lastLetter = letter;
//console.log(this.lastLetter);
// Notify the callback function that a new letter is decoded
if (this.onLetterDecoded) {
this.onLetterDecoded(letter);
}
}
morseToLetter(sequence) {
var letter = morseToAlphabet.get(sequence);
if (letter) {
return letter;
} else {
return '*';
}
}
startWordTimer() {
// Set up the word timer to add a space after a word boundary
this.wordTimer = setTimeout(() => {
// Update with a space to indicate a word boundary
if (this.onLetterDecoded) {
this.onLetterDecoded(' ');
}
}, this.wordTimeout);
}
calculateWpm() {
return 60000 / (this.unit * 50);
}
setFarnsworth(farnsworth) {
this.farnsworth = farnsworth;
}
}
export { Decoder };