Skip to content

Commit

Permalink
refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
mcvnh committed Sep 3, 2020
1 parent edb53b8 commit 4f179bc
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 56 deletions.
2 changes: 1 addition & 1 deletion Kana.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |spec|

spec.name = "Kana"
spec.version = "1.0.0"
spec.version = "1.1.0"
spec.summary = " An utitity Swift package to generate Japanese basic characters or convert between Katakana, Hiragana, and Romaji "

spec.homepage = "https://github.com/anhmv/Kana"
Expand Down
79 changes: 40 additions & 39 deletions Sources/Kana/Kana.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@

import Foundation

public struct Kana: Equatable {

public static let invalidKana = Kana()
public struct Kana: Equatable, Hashable {

// MARK: - Properties

public let romaji: String?
public let katakana: String?
public let hiragana: String?

public var isInvalid: Bool {
if romaji == nil || katakana == nil || hiragana == nil {
return true
}

return false
}

public var isValid: Bool {
return !self.isInvalid
}

// MARK: - Enums

Expand All @@ -26,25 +35,13 @@ public struct Kana: Equatable {
case romaji
}

public enum VoiceType {
case seion
case dakuon
case yoon
}

public enum KanaError: Error {
case characterNotFound
}


// MARK: - Constructors

private init() {
romaji = nil
katakana = nil
hiragana = nil
}


public init(romaji: String) {
if let hiragana = Kana.toHiragana(of: romaji, in: .romaji) {
self.romaji = romaji
Expand All @@ -70,10 +67,6 @@ public struct Kana: Equatable {

// MARK: - Static methods and properties

static let seionColumns = [0, 1, 3, 5, 7, 10, 11, 12, 13, 14, 15]
static let dakuonColumns = [2, 4, 6, 8, 9]
static let yoonColumns = [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]

static let romajiChart: [[String]] = [
["a", "ka", "ga", "sa" , "za" , "ta" , "da", "na", "ha", "ba", "pa", "ma", "ya", "ra", "wa", "n", "kya", "gya", "ja", "sha", "cha", "nya", "hya", "bya", "pya", "mya", "rya"],
["i", "ki", "gi", "shi", "ji", "chi", "di", "ni", "hi", "bi", "pi", "mi", "" , "ri", "" , "" , "", "", "", "", "", "", "", "", "", "", ""],
Expand All @@ -98,22 +91,13 @@ public struct Kana: Equatable {
["", "", "", "", "", "", "", "", "", "", "", "", "", "", "" , "" , "キョ", "ギョ", "ジョ", "ショ", "チョ", "ニョ", "ヒョ", "ビョ", "ピョ", "ニョ", "リョ"],
]

public static func getTable(_ of: VoiceType) -> KanaTable {
var columns: [Int]?

switch of {
case .seion:
columns = seionColumns
case .dakuon:
columns = dakuonColumns
case .yoon:
columns = yoonColumns
}
public static func getTable(with keys: [KanaColumns.Keys]) -> KanaTable {
let columns: [Int] = keys.map { $0.rawValue }

var kanaTable: [[Kana]] = []
for i in 0..<romajiChart.count {
kanaTable.append([])
for j in columns! {
for j in columns {
let romaji = romajiChart[i][j]
let kana = Kana(romaji: romaji)
kanaTable[i].append(kana)
Expand Down Expand Up @@ -211,15 +195,14 @@ public struct Kana: Equatable {
}
}

public static func random(in voiceType: VoiceType) -> Kana {
let table = getTable(voiceType)
public static func random(in table: KanaTable) -> Kana {
var randomKana: Kana?

while true {
let row = Int.random(in: 0..<table.count)
let col = Int.random(in: 0..<table[row].count)

if table[row][col] != invalidKana {
if table[row][col].isValid {
randomKana = table[row][col]
break
}
Expand All @@ -228,10 +211,29 @@ public struct Kana: Equatable {
return randomKana!
}

public static func random(in voiceType: VoiceType, count number: Int) -> [Kana] {
return (0..<number).map { _ in
Kana.random(in: voiceType)
public static func random(with columns: [KanaColumns.Keys]) -> Kana {
let table = getTable(with: columns)
return self.random(in: table)
}

public static func random(in table: KanaTable, count number: Int, uniq repeatable: Bool = false) -> [Kana] {
if repeatable {
return (0..<number).map { _ in
Kana.random(in: table)
}
}

var randomItems = Set<Kana>()
while randomItems.count < number {
randomItems.insert(Kana.random(in: table))
}

return Array(randomItems)
}

public static func random(with columns: [KanaColumns.Keys], count number: Int, uniq repeatable: Bool = false) -> [Kana] {
let table = getTable(with: columns)
return self.random(in: table, count: number, uniq: repeatable)
}
}

Expand Down Expand Up @@ -259,4 +261,3 @@ fileprivate extension CFStringTokenizer {
return mutableString as String
}
}

30 changes: 30 additions & 0 deletions Sources/Kana/KanaColumns.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// KanaColumns.swift
//
//
// Created by Mac Van Anh on 8/31/20.
// Copyright © 2020 Mac Van Anh. All rights reserved.
//


import Foundation

public struct KanaColumns {

public enum Keys: Int {
case a = 0, ka, ga, sa , za , ta , da, na, ha, ba, pa, ma, ya, ra, wa, n, kya, gya, ja, sha, cha, nya, hya, bya, pya, mya, rya
}

public static var seion: [KanaColumns.Keys] {
return [.a, .ka, .sa, .ta, .na, .ha, .ma, .ya, .ra, .wa, .n]
}

public static var dakuon: [KanaColumns.Keys] {
return [.ga, .za, .da, .ba, .pa]
}

public static var yoon: [KanaColumns.Keys] {
return [.kya, .gya, .ja, .sha, .cha, .nya, .hya, .bya, .pya, .mya, .rya]
}

}
8 changes: 8 additions & 0 deletions Sources/Kana/KanaTable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,13 @@ public struct KanaTable {
public subscript(row: Int) -> [Kana] {
return values[row]
}

public static func + (left: KanaTable, right: KanaTable) -> KanaTable {
let values: [[Kana]] = (0..<left.count).map { row in
return left[row] + right[row]
}

return KanaTable(values: values)
}
}

31 changes: 31 additions & 0 deletions Tests/KanaTests/KanaColumnsTestCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// KanaColumnsTestCase.swift
//
//
// Created by Mac Van Anh on 9/3/20.
//

import XCTest
@testable import Kana

final class KanaColumnsTestCase: XCTestCase {
func test_seionColumns() {
let seionColumns = [0, 1, 3, 5, 7, 8, 11, 12, 13, 14, 15]

XCTAssertEqual(seionColumns, KanaColumns.seion.map { $0.rawValue })
}

func test_dakuonColumns() {
let dakuonColumns = [2, 4, 6, 9, 10]

XCTAssertEqual(dakuonColumns, KanaColumns.dakuon.map { $0.rawValue })

}

func test_yoonColumns() {
let yoonColumns = [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]

XCTAssertEqual(yoonColumns, KanaColumns.yoon.map { $0.rawValue })

}
}
13 changes: 13 additions & 0 deletions Tests/KanaTests/KanaTableTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,23 @@ final class KanaTableTestCase: XCTestCase {
override func setUp() {
self.continueAfterFailure = true
}

func test_subscript() {
let kanaTable = KanaTable(values: [[Kana(romaji: "a")]])

XCTAssertEqual(kanaTable[0].count, kanaTable.values[0].count)
XCTAssertEqual(kanaTable[0][0], kanaTable.values[0][0])
}

func test_plusOperator() {
let t1 = KanaTable(values: [[Kana(romaji: "a")]])
let t2 = KanaTable(values: [[Kana(romaji: "i")]])

let t3 = t1 + t2

XCTAssertEqual(t3.count, 1)
XCTAssertEqual(t3[0].count, 2)
XCTAssertEqual(t3[0][0].romaji, "a")
XCTAssertEqual(t3[0][1].romaji, "i")
}
}
50 changes: 34 additions & 16 deletions Tests/KanaTests/KanaTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ final class KanaTestCase: XCTestCase {
XCTAssertEqual(Kana(romaji: "a").hiragana, "")
XCTAssertEqual(Kana(romaji: "a").katakana, "")

XCTAssertEqual(Kana(romaji: ""), Kana.invalidKana)
XCTAssertEqual(Kana(romaji: " "), Kana.invalidKana)
XCTAssertEqual(Kana(romaji: "world"), Kana.invalidKana)
XCTAssertTrue(Kana(romaji: "").isInvalid)
XCTAssertTrue(Kana(romaji: " ").isInvalid)
XCTAssertTrue(Kana(romaji: "world").isInvalid)
}

func test_initFromHiragana() {
Expand All @@ -62,9 +62,9 @@ final class KanaTestCase: XCTestCase {
XCTAssertEqual(character.katakana, "")
XCTAssertEqual(character.romaji, "mu")

XCTAssertEqual(Kana(hiragana: ""), Kana.invalidKana)
XCTAssertEqual(Kana(hiragana: " "), Kana.invalidKana)
XCTAssertEqual(Kana(hiragana: "world"), Kana.invalidKana)
XCTAssertTrue(Kana(hiragana: "").isInvalid)
XCTAssertTrue(Kana(hiragana: " ").isInvalid)
XCTAssertTrue(Kana(hiragana: "world").isInvalid)
}

func test_initFromKatakana() {
Expand All @@ -73,9 +73,9 @@ final class KanaTestCase: XCTestCase {
XCTAssertEqual(character.hiragana, "")
XCTAssertEqual(character.romaji, "ka")

XCTAssertEqual(Kana(katakana: ""), Kana.invalidKana)
XCTAssertEqual(Kana(katakana: " "), Kana.invalidKana)
XCTAssertEqual(Kana(katakana: "world"), Kana.invalidKana)
XCTAssertTrue(Kana(katakana: "").isInvalid)
XCTAssertTrue(Kana(katakana: " ").isInvalid)
XCTAssertTrue(Kana(katakana: "world").isInvalid)
}

func test_convert() {
Expand All @@ -100,23 +100,41 @@ final class KanaTestCase: XCTestCase {
XCTAssertEqual(outputWithGyon, "sakuraishoukatakana")
}

func test_random() {
let randomKana = Kana.random(in: .seion)
func test_randomInVoiceType() {
let randomKana = Kana.random(with: KanaColumns.seion)

XCTAssertNotEqual(randomKana.romaji, "")
XCTAssertNotEqual(randomKana.hiragana, "")
XCTAssertNotEqual(randomKana.katakana, "")

let randomKanas = Kana.random(in: .seion, count: 3)
let randomKanas = Kana.random(with: KanaColumns.seion, count: 3)
XCTAssertEqual(randomKanas.count, 3)

let uniqRandomKanas = Kana.random(with: KanaColumns.seion, count: 3, uniq: true)
XCTAssertEqual(uniqRandomKanas.count, 3)
}

func test_randomInVoiceTypes() {
let randomKana = Kana.random(with: KanaColumns.seion + KanaColumns.dakuon)

XCTAssertNotEqual(randomKana.romaji, "")
XCTAssertNotEqual(randomKana.hiragana, "")
XCTAssertNotEqual(randomKana.katakana, "")

let randomKanas = Kana.random(with: KanaColumns.seion + KanaColumns.dakuon, count: 3)
XCTAssertEqual(randomKanas.count, 3)

let uniqRandomKanas = Kana.random(with: KanaColumns.seion + KanaColumns.dakuon, count: 3, uniq: true)
XCTAssertEqual(uniqRandomKanas.count, 3)
}


func test_table() {
func withoutEmpty(_ table: KanaTable) -> Int {
var count = 0
table.values.forEach { row in
row.forEach { kana in
if kana != Kana.invalidKana {
if kana.isValid {
count += 1
}
}
Expand All @@ -125,21 +143,21 @@ final class KanaTestCase: XCTestCase {
return count
}

let seion = Kana.getTable(.seion)
let seion = Kana.getTable(with: KanaColumns.seion)
let numberOfSeionWithEmptyCells = seion.count * seion[0].count
let numberOfSeions = withoutEmpty(seion)

XCTAssertEqual(numberOfSeionWithEmptyCells, 55)
XCTAssertEqual(numberOfSeions, 46)

let dakuon = Kana.getTable(.dakuon)
let dakuon = Kana.getTable(with: KanaColumns.dakuon)
let numberOfDakuonWithEmptyCells = dakuon.count * dakuon[0].count
let numberOfDakuons = withoutEmpty(dakuon)

XCTAssertEqual(numberOfDakuonWithEmptyCells, 25)
XCTAssertEqual(numberOfDakuons, 25)

let yoon = Kana.getTable(.yoon)
let yoon = Kana.getTable(with: KanaColumns.yoon)
let numberOfYoonWithEmptyCells = yoon.count * yoon[0].count
let numberOfYoons = withoutEmpty(yoon)

Expand Down

0 comments on commit 4f179bc

Please sign in to comment.