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 (
-
- );
+
+ 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 (
+
+ )
+}
+
+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