learn-morse-code/src/hooks/useStraightKey.js

204 lines
6.1 KiB
JavaScript
Raw Normal View History

import {useEffect, useContext} from 'react'
import {MorseBufferContext} from '../contexts/morseBufferContext'
2020-01-14 11:37:04 +01:00
import config from '../config.json'
2020-01-09 10:06:38 +01:00
2020-01-15 09:41:40 +01:00
// STRAIGHT KEY TELEGRAPH
function useStraightKey() {
2020-01-09 10:06:38 +01:00
const {morseCharBuffer, setMorseCharBuffer, morseWords, setMorseWords} = useContext(MorseBufferContext)
2020-01-14 11:37:04 +01:00
2020-01-09 10:06:38 +01:00
let charTimer = 0
let charTime = 0
let gapTimer = 0
let gapTime = 0
2020-01-14 11:37:04 +01:00
const timingUnit = config.timingUnit
const ditMaxTime = config.practiceSpeed.normal
2020-01-09 10:06:38 +01:00
const letterGapMinTime = ditMaxTime*3
const wordGapMaxTime = ditMaxTime*7
const morseHistorySize = config.historySize
2020-01-09 10:06:38 +01:00
// Tone Setup
let AudioContext = window.AudioContext || window.webkitAudioContext || false
let context
window.AudioContext = window.AudioContext || window.webkitAudioContext;
if (AudioContext) {
context = new AudioContext()
} else {
context = null
}
2020-01-14 11:37:04 +01:00
let o // Oscillator Node
let g // Gain Node
2020-01-15 09:41:40 +01:00
let frequency = config.frequency
let isRunning = false
2020-01-09 10:06:38 +01:00
function clearHistory() {
setMorseWords([])
}
function handleInputStart(event) {
event.preventDefault()
if (isRunning) {
2020-01-09 10:06:38 +01:00
return
} else {
isRunning = true
// TODO:
// Make sure only one touchdown event registered at a time
if ((event.keyCode !== 32 && event.target.id !== "morseButton") ||
(event.repeat)) {
return
}
if (context.state === 'interrupted') {
context.resume()
}
o = context.createOscillator()
o.frequency.value = frequency
o.type = "sine"
2020-01-14 11:37:04 +01:00
g = context.createGain()
g.gain.exponentialRampToValueAtTime(config.mainVolume, context.currentTime)
o.connect(g)
g.connect(context.destination)
o.start()
checkGapBetweenInputs()
clearInterval(gapTimer)
startCharTimer()
2020-01-09 10:06:38 +01:00
}
}
2020-01-14 11:37:04 +01:00
2020-01-09 10:06:38 +01:00
function startCharTimer() {
// Reset character time
charTime = 0
// Start Character Timer
charTimer = setInterval(() => {
charTime += 1
}, timingUnit);
}
function handleInputEnd(event) {
event.preventDefault()
if (isRunning) {
isRunning = false
if ((event.keyCode !== 32 && event.target.id !== "morseButton") ||
(event.repeat)) {
return
}
2020-01-14 11:37:04 +01:00
// if (event.repeat) {
// return
// }
if (charTime <= ditMaxTime) {
setMorseCharBuffer(prev => prev + '.')
} else {
setMorseCharBuffer(prev => prev + '-')
}
stopCharTimer()
startGapTimer()
2020-01-14 11:37:04 +01:00
if (o.context.state === 'running') {
g.gain.setTargetAtTime(0.0001, context.currentTime, 0.001)
o.stop(context.currentTime + 0.01)
}
} else { return }
2020-01-09 10:06:38 +01:00
}
function stopCharTimer() {
clearInterval(charTimer)
charTimer = 0
}
function startGapTimer() {
gapTime = 0
gapTimer = setInterval(() => {
gapTime += 1
// Gap between words
if (gapTime >= wordGapMaxTime) {
2020-01-09 10:06:38 +01:00
setMorseCharBuffer(prev => prev + '/')
clearInterval(gapTimer)
gapTimer = 0
gapTime = 0
}
// if (mode === 'challenge' && gapTime >= letterGapMinTime) {
// setMorseCharBuffer(prev => prev + '_')
// clearInterval(gapTimer)
// gapTimer = 0
// gapTime = 0
// }
2020-01-09 10:06:38 +01:00
}, timingUnit);
}
function checkGapBetweenInputs() {
// Check Gap between letters
2020-01-10 03:24:54 +01:00
2020-01-10 09:56:38 +01:00
if (gapTime >= letterGapMinTime && gapTime < wordGapMaxTime) {
// if (mode === 'practice') {
2020-01-10 09:56:38 +01:00
setMorseCharBuffer(prev => prev + ' ')
// } else if (mode === 'challenge') {
// setMorseCharBuffer(prev => prev + '_')
// }
2020-01-09 10:06:38 +01:00
clearInterval(gapTimer)
gapTimer = 0
}
}
useEffect(() => {
document.addEventListener('keydown', handleInputStart)
document.addEventListener('keyup', handleInputEnd)
const morseButton = document.getElementById('morseButton')
morseButton.addEventListener('mousedown', handleInputStart)
morseButton.addEventListener('touchstart', handleInputStart)
morseButton.addEventListener('mouseup', handleInputEnd)
morseButton.addEventListener('touchend', handleInputEnd)
return function cleanup() {
document.removeEventListener('keydown', handleInputStart)
document.removeEventListener('keyup', handleInputEnd)
const morseButton = document.getElementById('morseButton')
morseButton.removeEventListener('mousedown', handleInputStart)
morseButton.removeEventListener('touchstart', handleInputStart)
morseButton.removeEventListener('mouseup', handleInputEnd)
morseButton.removeEventListener('touchend', handleInputEnd)
2020-01-10 03:24:54 +01:00
clearHistory()
2020-01-09 10:06:38 +01:00
}
// eslint-disable-next-line
}, [])
useEffect(() => {
2020-01-10 03:24:54 +01:00
// PRACTICE MODE
if (morseCharBuffer.slice(-1) === '/') {
2020-01-09 10:06:38 +01:00
// Remove forward slash
let val = morseCharBuffer.slice(0,morseCharBuffer.length-1)
setMorseWords(prev => [val, ...prev])
if (morseWords.length >= morseHistorySize) {
setMorseWords(prev => prev.slice(0,prev.length-1))
}
setMorseCharBuffer('')
}
2020-01-10 03:24:54 +01:00
// CHALLENGE MODE: leave forward slash there; to be parsed by ChallengeDisplay.js
// else if (morseCharBuffer.slice(-1) === '/' && mode === 'challenge') {
// }
2020-01-09 10:06:38 +01:00
// eslint-disable-next-line
}, [morseCharBuffer])
return {morseCharBuffer, morseWords, clearHistory, setMorseCharBuffer, setMorseWords}
}
export default useStraightKey