Create Morse Code and Play it - Morse Code Creator
This article is part of a series in which a morse code player is implemented. As a first step, a class is implemented, which converts text to morse code.
The class MorseCodeCreator creates two outputs. One is an AttributedString with differing colours for each encoded word. The other is a sequence of character, which can be later used to play the morse code with all the typical pauses already in place.
For easier transformation, the text is first converted into an array of words. Punctuation is here treated as separate words, because it is easier to play later on.
class MorseCodeCreator {
let morseCodeDict: [String: String] = [
// Letters
"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": "--..",
// Punctuation
".": ".-.-.-",
",": "--..--",
"?": "..--..",
"'": ".----.",
"!": "-.-.--",
"/": "-..-.",
"(": "-.--.",
")": "-.--.-",
"&": ".-...",
":": "---...",
";": "-.-.-.",
"=": "-...-",
"+": ".-.-.",
"-": "-....-",
"_": "..--.-",
"\"": ".-..-.",
"$": "...-..-",
"@": ".--.-."
]
let colors: [Color] = [.red, .green, .blue, .yellow, .orange, .purple, .pink, .mint, .teal, .indigo, .brown, .cyan]
func textToWords(_ text: String) -> [[String]] {
var words: [String] = []
var word: String = ""
for char in text.lowercased() {
let schar = String(char)
if char == " " {
if !word.isEmpty { words.append(word) }
word = ""
} else if schar.range(of: "^[a-z0-9]$", options: .regularExpression) == nil {
if !word.isEmpty { words.append(word) }
words.append(schar)
word = ""
} else {
word.append(char)
}
}
if !word.isEmpty { words.append(word) }
let morseWords = words.map({ w in
w.map({ c in self.morseCodeDict[String(c)] ?? "" })
})
return morseWords
}
func textToMorse(_ text: String) -> (String, AttributedString) {
let words: [[String]] = textToWords(text)
var displayString: AttributedString = AttributedString()
var playString: String = ""
let awords = words.enumerated().map({ word in
let str = word.element.joined(separator: " ")
var a = AttributedString(str)
a.foregroundColor = colors[word.offset % colors.count]
return a
})
awords.forEach({
displayString.append($0)
displayString.append(AttributedString(" "))
})
let pwords = words.map({ w in
w.map({ cstr in
let cout = cstr.map({ String($0) }).joined(separator: " ")
return cout
})
.joined(separator: " ")
}).joined(separator: " ")
playString += pwords
return (playString, displayString)
}
}