From b11506f6de67823d0c87c12e569e482f3df35179 Mon Sep 17 00:00:00 2001 From: Gene Mecija Date: Sat, 21 Dec 2019 14:48:36 -0800 Subject: [PATCH] Initial commit --- src/App.css | 142 ++++++++++++++++++----- src/App.js | 163 +++++++++++++++++++++++---- src/MorseCard.css | 4 + src/components/AlphaNumeric.js | 23 ++++ src/components/DitDah.js | 23 ++++ src/components/DitDahDisplay.js | 12 ++ src/components/MorseBufferDisplay.js | 44 ++++++++ src/components/MorseButton.js | 10 ++ src/components/MorseCard.js | 35 ++++++ src/components/MorseDisplay.js | 17 +++ src/data/morse-reverse.json | 47 ++++++++ 11 files changed, 471 insertions(+), 49 deletions(-) create mode 100644 src/MorseCard.css create mode 100644 src/components/AlphaNumeric.js create mode 100644 src/components/DitDah.js create mode 100644 src/components/DitDahDisplay.js create mode 100644 src/components/MorseBufferDisplay.js create mode 100644 src/components/MorseButton.js create mode 100644 src/components/MorseCard.js create mode 100644 src/components/MorseDisplay.js create mode 100644 src/data/morse-reverse.json diff --git a/src/App.css b/src/App.css index 74b5e05..5aaefc8 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +1,122 @@ -.App { - text-align: center; +html, body { + margin: 0px; + padding: 0px; + height: 100%; + width: 100%; +} +#root { + height: 100%; + display: flex; + justify-content: center; + align-items: center; + width: 100%; +} +#root div { + width: 95vw; } -.App-logo { - height: 40vmin; - pointer-events: none; +#morseButton { + width: 200px !important; + height: 200px; + background: goldenrod; + border-radius: 100px; } -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } +#morseBufferDisplay { + display: flex; + justify-content: center; + /* border: 1px solid green; */ + width: 100%; + height: 40px; +} +/* #morseBufferDisplay div { + width: 50% !important; + border: 1px dotted orange; +} */ +#morseBufferDisplay #ditDahs { + width: 50%; + padding-right: 5px; + border-right: 2px solid #000; + + display: flex; + flex-direction: row; + justify-content: flex-end; +} +.ditDah { + background: #DDD; + height: 40px; + width: 30px !important; + margin-left: 3px; + box-shadow: 0px 1px 0px #000; + display: flex; + justify-content: center; + align-items: center; + font-size: 35px; + font-family: 'Courier'; + font-weight: bold; +} +.space { + font-size: 20px; +} +.morseError { + background: rgba(255,0,0,0.4); } -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; +#morseBufferDisplay #alphanumeric { + padding-left: 5px; + border-left: 2px solid #000; + width: 50%; + font-size: 40px; + font-family: 'Courier'; + font-weight: bold; } - -.App-link { - color: #61dafb; +#morseDisplay { + /* border: 2px solid red; */ + display: flex; + flex-direction: row; } - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +#cardContainer div .morseCard:nth-child(1){ + opacity: 100%; } +#cardContainer div .morseCard:nth-child(2){ + opacity: 70%; +} +#cardContainer div .morseCard:nth-child(3){ + opacity: 50%; +} +#cardContainer div .morseCard:nth-child(4){ + opacity: 30%; +} +#cardContainer div .morseCard:nth-child(5){ + opacity: 10%; +} +.morseCard { + display: flex; + flex-direction: row !important; + justify-content: center; + /* border: 1px solid blue; */ + margin-bottom: 2px; + font-size: 40px; + font-family: 'Courier'; + font-weight: bold; +} +.morseCard div { + /* border: 1px solid green; */ + padding: 5px; + margin: 2px; + /* border: 1px solid #EEE; */ + background: #EEE; + /* box-shadow: 0px 2px 2px -2px #666; */ +} +.morseCard .ditDahs { + display: flex; + justify-content: flex-end; +} +/* #morseBufferDisplay { + border: 1px solid green; +} +#morseDisplay #cardContainer div { + display: flex; + flex-direction: column; + flex-grow: 1; +} */ diff --git a/src/App.js b/src/App.js index ce9cbd2..27281a6 100644 --- a/src/App.js +++ b/src/App.js @@ -1,26 +1,149 @@ -import React from 'react'; -import logo from './logo.svg'; +import React, { useEffect, useState } from 'react'; import './App.css'; +import MorseDisplay from './components/MorseDisplay' +import MorseBufferDisplay from './components/MorseBufferDisplay' +import MorseButton from './components/MorseButton' +// import LettersDisplay from './components/LettersDisplay' function App() { - return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
-
- ); + + const [morseCharBuffer, setMorseCharBuffer] = useState('') // e.g. '-..' + // const [morseLettersBuffer, setMorseLettersBuffer] = useState([]) // e.g. ['-..','.','-,'] + const [morseWords, setMorseWords] = useState([]) // e.g. [['-..','.','-,'], ['...','---','...']] + + let charTimer = 0 + let charTime = 0 + let gapTimer = 0 + let gapTime = 0 + + const timingUnit = 15 // default: 25 + + const ditMaxTime = 5 // default: 3 + const letterGapMinTime = ditMaxTime*3 + const wordGapMaxTime = ditMaxTime*7 + const morseHistorySize = 3 + + let context = new AudioContext() + let o + + + function handleInputStart(event) { + if ((event.keyCode !== 32 && event.target.id !== "morseButton") || + (event.repeat)) { + return + } + // if (gapTimer===0) { setMorseLettersBuffer('') } + checkGapBetweenInputs() + clearInterval(gapTimer) + + o = context.createOscillator() + o.type = "sine" + let frequency = 550.0 + o.frequency.value = frequency + o.connect(context.destination) + o.start() + + startCharTimer() + } + function startCharTimer() { + // Reset character time + charTime = 0 + // Start Character Timer + charTimer = setInterval(() => { + charTime += 1 + }, timingUnit); + } + + function handleInputEnd(event) { + if ((event.keyCode !== 32 && event.target.id !== "morseButton") || + (event.repeat)) { + return + } + + if (charTime <= ditMaxTime) { + setMorseCharBuffer(prev => prev + '.') + } else { + setMorseCharBuffer(prev => prev + '-') + } + + stopCharTimer() + startGapTimer() + o.stop() + } + + function stopCharTimer() { + clearInterval(charTimer) + charTimer = 0 + } + + function startGapTimer() { + gapTime = 0 + gapTimer = setInterval(() => { + gapTime += 1 + + // Gap between words + if (gapTime >= wordGapMaxTime) { + setMorseCharBuffer(prev => prev + '/') + clearInterval(gapTimer) + gapTimer = 0 + gapTime = 0 + } + }, timingUnit); + } + + function checkGapBetweenInputs() { + // Check Gap between letters + if ((gapTime >= letterGapMinTime) && (gapTime < wordGapMaxTime)) { + // setMorseLettersBuffer(prev => [...prev, morseCharBuffer]) + setMorseCharBuffer(prev => prev + ' ') + // morseLettersBuffer = [...morseLettersBuffer, morseCharBuffer] + // setMorseCharBuffer('') + + clearInterval(gapTimer) + gapTimer = 0 + } + } + + useEffect(() => { + document.addEventListener('keydown', handleInputStart) + document.addEventListener('keyup', handleInputEnd) + document.getElementById('morseButton').addEventListener('mousedown', handleInputStart) + document.getElementById('morseButton').addEventListener('mouseup', handleInputEnd) + // eslint-disable-next-line + }, []) + + useEffect(() => { + if (morseCharBuffer.slice(-1) === ' ') { + // setMorseLettersBuffer([morseCharBuffer]) + // setMorseCharBuffer('') + } + if (morseCharBuffer.slice(-1) === '/') { + // Remove forward slash + let val = morseCharBuffer.slice(0,morseCharBuffer.length-1) + console.log('val: ', val); + + setMorseWords(prev => [val, ...prev]) + + if (morseWords.length >= morseHistorySize) { + setMorseWords(prev => prev.slice(0,prev.length-1)) + } + + setMorseCharBuffer('') + } + + // setMorseLettersBuffer(prev => [...prev, morseCharBuffer]) + // eslint-disable-next-line + }, [morseCharBuffer]) + + return ( +
charTime: {charTime}
+ + morseCharBuffer:
+
+ + +
+ ); } export default App; diff --git a/src/MorseCard.css b/src/MorseCard.css new file mode 100644 index 0000000..ef427df --- /dev/null +++ b/src/MorseCard.css @@ -0,0 +1,4 @@ +.morseCard { + border: 1px solid blue; + margin-bottom: 2px; +} \ No newline at end of file diff --git a/src/components/AlphaNumeric.js b/src/components/AlphaNumeric.js new file mode 100644 index 0000000..ea04c2a --- /dev/null +++ b/src/components/AlphaNumeric.js @@ -0,0 +1,23 @@ +import React from "react" +import morseCode from '../data/morse-reverse.json' + +function AlphaNumeric(props) { + + if (props.morseLetter === '') { + return ( + + ) + } else { + if (morseCode[props.morseLetter] === undefined) { + return ( + [?] + ) + } else { + return ( + {morseCode[props.morseLetter].toUpperCase()} + ) + } + } +} + +export default AlphaNumeric \ No newline at end of file diff --git a/src/components/DitDah.js b/src/components/DitDah.js new file mode 100644 index 0000000..00f205a --- /dev/null +++ b/src/components/DitDah.js @@ -0,0 +1,23 @@ +import React from "react" +import morseCode from '../data/morse-reverse.json' + +function DitDah(props) { + + if (props.morseLetter === '') { + return ( +   + ) + } else { + if (morseCode[props.morseLetter] === undefined) { + return ( + {props.morseLetter} + ) + } else { + return ( + {props.morseLetter} + ) + } + } +} + +export default DitDah \ No newline at end of file diff --git a/src/components/DitDahDisplay.js b/src/components/DitDahDisplay.js new file mode 100644 index 0000000..a5e755d --- /dev/null +++ b/src/components/DitDahDisplay.js @@ -0,0 +1,12 @@ +import React from "react" + +function DitDahDisplay(props) { + + return ( +
+ {props.dd} +
+ ) +} + +export default DitDahDisplay \ No newline at end of file diff --git a/src/components/MorseBufferDisplay.js b/src/components/MorseBufferDisplay.js new file mode 100644 index 0000000..b2b3de1 --- /dev/null +++ b/src/components/MorseBufferDisplay.js @@ -0,0 +1,44 @@ +import React from "react" +import DitDahDisplay from "./DitDahDisplay" +import morseCode from '../data/morse-reverse.json' + +function MorseBufferDisplay(props) { + + let ditDahs = props.buffer.split('').map((ditdah,index) => ) + + let alphanumeric = '' + if (props.buffer.includes(' ')) { + let letters = props.buffer.split(' ') + for (let i in letters) { + if (letters[i] === ' ') { + alphanumeric += ' ' + } else { + if (morseCode[letters[i]] === undefined) { + // alphanumeric += '[?]' + } else { + alphanumeric += morseCode[letters[i]] + } + } + } + } else if (props.buffer !== '') { + let letters = props.buffer + if (morseCode[letters] === undefined) { + alphanumeric += '[?]' + } else { + alphanumeric += morseCode[letters] + } + } + + return ( +
+
+ {ditDahs} +
+
+ {alphanumeric.toUpperCase()} +
+
+ ) +} + +export default MorseBufferDisplay \ No newline at end of file diff --git a/src/components/MorseButton.js b/src/components/MorseButton.js new file mode 100644 index 0000000..d43b362 --- /dev/null +++ b/src/components/MorseButton.js @@ -0,0 +1,10 @@ +import React from "react" + +function MorseButton() { + + return ( +
+ ) +} + +export default MorseButton \ No newline at end of file diff --git a/src/components/MorseCard.js b/src/components/MorseCard.js new file mode 100644 index 0000000..cb58b25 --- /dev/null +++ b/src/components/MorseCard.js @@ -0,0 +1,35 @@ +import React from "react" +import AlphaNumeric from './AlphaNumeric' +import DitDah from './DitDah' + +function MorseCard(props) { + + let morseComponent + let alphaNumericsComponent + + if (props.morse.includes(' ')) { + let letters = props.morse.split(' ').join(' ').split(' ') + morseComponent = letters.map((letter, index) => ) + + alphaNumericsComponent = letters.map((letter, index) => ) + } + else { + let letter = props.morse + + morseComponent = + alphaNumericsComponent = + } + + return ( +
+
+ {morseComponent} +
+
+ {alphaNumericsComponent} +
+
+ ) +} + +export default MorseCard \ No newline at end of file diff --git a/src/components/MorseDisplay.js b/src/components/MorseDisplay.js new file mode 100644 index 0000000..90d9e21 --- /dev/null +++ b/src/components/MorseDisplay.js @@ -0,0 +1,17 @@ +import React from "react" +import MorseCard from './MorseCard' + +function MorseDisplay(props) { + + let morseCards = props.morseWords.map((word,index) => ) + + return ( +
+
+
{morseCards}
+
+
+ ) +} + +export default MorseDisplay \ No newline at end of file diff --git a/src/data/morse-reverse.json b/src/data/morse-reverse.json new file mode 100644 index 0000000..5646997 --- /dev/null +++ b/src/data/morse-reverse.json @@ -0,0 +1,47 @@ +{ + "-----": "0", + ".----": "1", + "..---": "2", + "...--": "3", + "....-": "4", + ".....": "5", + "-....": "6", + "--...": "7", + "---..": "8", + "----.": "9", + ".-": "a", + "-...": "b", + "-.-.": "c", + "-..": "d", + ".": "e", + "..-.": "f", + "--.": "g", + "....": "h", + "..": "i", + ".---": "j", + "-.-": "k", + ".-..": "l", + "--": "m", + "-.": "n", + "---": "o", + ".--.": "p", + "--.-": "q", + ".-.": "r", + "...": "s", + "-": "t", + "..-": "u", + "...-": "v", + ".--": "w", + "-..-": "x", + "-.--": "y", + "--..": "z", + ".-.-.-": ".", + "--..--": ",", + "..--..": "?", + "-.-.--": "!", + "-....-": "-", + "-..-.": "/", + ".--.-.": "@", + "-.--.": "(", + "-.--.-": ")" + } \ No newline at end of file