diff --git a/LearnEnglish/LearnEnglish/Models/NumberWords.swift b/LearnEnglish/LearnEnglish/Models/NumberWords.swift index 7e34855..d286d95 100644 --- a/LearnEnglish/LearnEnglish/Models/NumberWords.swift +++ b/LearnEnglish/LearnEnglish/Models/NumberWords.swift @@ -1,9 +1,10 @@ import Foundation enum NumberWords { - static let range = 1...999 + static let range = 0...999 - private static let atomNumbers: [String: Int] = [ + static let atomNumbers: [String: Int] = [ + "zero": 0, "one": 1, "two": 2, "three": 3, "four": 4, "five": 5, "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10, "eleven": 11, "twelve": 12, "thirteen": 13, "fourteen": 14, "fifteen": 15, @@ -41,11 +42,17 @@ enum NumberWords { byNumber[number] = atom } } - return range.map { byNumber[$0] ?? makeWord($0) } + return range.filter { n in + n <= 9 + || (n >= 10 && n <= 99 && n % 10 == 0) + || n == 100 + }.map { byNumber[$0] ?? makeWord($0) } } static func english(_ n: Int) -> String { switch n { + case 0: + return "zero" case 1...19: return ones[n - 1] case 20...99: @@ -56,6 +63,16 @@ enum NumberWords { let head = "\(ones[n / 100 - 1]) hundred" let rest = n % 100 return rest == 0 ? head : "\(head) \(english(rest))" + case 1_000...999_999: + let thousands = n / 1_000 + let rest = n % 1_000 + let head = "\(english(thousands)) thousand" + return rest == 0 ? head : "\(head) \(english(rest))" + case 1_000_000...999_999_999: + let millions = n / 1_000_000 + let rest = n % 1_000_000 + let head = "\(english(millions)) million" + return rest == 0 ? head : "\(head) \(english(rest))" default: return "\(n)" } @@ -63,6 +80,8 @@ enum NumberWords { static func phonetic(_ n: Int) -> String { switch n { + case 0: + return "ˈzɪroʊ" case 1...19: return onesPhonetics[n - 1] case 20...99: @@ -73,6 +92,16 @@ enum NumberWords { let head = "\(onesPhonetics[n / 100 - 1]) ˈhʌndrəd" let rest = n % 100 return rest == 0 ? head : "\(head) \(phonetic(rest))" + case 1_000...999_999: + let thousands = n / 1_000 + let rest = n % 1_000 + let head = "\(phonetic(thousands)) ˈθaʊznd" + return rest == 0 ? head : "\(head) \(phonetic(rest))" + case 1_000_000...999_999_999: + let millions = n / 1_000_000 + let rest = n % 1_000_000 + let head = "\(phonetic(millions)) ˈmɪljən" + return rest == 0 ? head : "\(head) \(phonetic(rest))" default: return "" } @@ -100,11 +129,39 @@ enum NumberWords { default: return head + digits[rest / 10] + "十" + (rest % 10 == 0 ? "" : digits[rest % 10]) } + case 1_000...9_999: + let head = digits[n / 1_000] + "千" + let rest = n % 1_000 + guard rest > 0 else { return head } + return rest < 100 ? head + "零" + chinese(rest) : head + chinese(rest) + case 10_000...99_999_999: + let head = chinese(n / 10_000) + "万" + let rest = n % 10_000 + guard rest > 0 else { return head } + return rest < 1_000 ? head + "零" + chinese(rest) : head + chinese(rest) + case 100_000_000...999_999_999: + let head = digits[n / 100_000_000] + "亿" + let rest = n % 100_000_000 + guard rest > 0 else { return head } + return rest < 10_000_000 ? head + "零" + chinese(rest) : head + chinese(rest) default: return "\(n)" } } + static func randomWord() -> Word { + let n = Int.random(in: 0...999_999_999) + return Word(word: english(n), + phonetic: "/\(phonetic(n))/", + meaning: chinese(n), + example: "The number is \(english(n)).", + exampleMeaning: "这个数字是\(chinese(n))。") + } + + static func randomWords(count: Int) -> [Word] { + (0.. Word { Word(word: english(n), phonetic: "/\(phonetic(n))/", diff --git a/LearnEnglish/LearnEnglish/Resources/words.json b/LearnEnglish/LearnEnglish/Resources/words.json index a3fff4b..15ffd67 100644 --- a/LearnEnglish/LearnEnglish/Resources/words.json +++ b/LearnEnglish/LearnEnglish/Resources/words.json @@ -147,6 +147,7 @@ "name": "数字", "icon": "number", "words": [ + { "word": "zero", "phonetic": "/ˈzɪroʊ/", "meaning": "零", "example": "Zero means nothing.", "exampleMeaning": "零表示没有。" }, { "word": "one", "phonetic": "/wʌn/", "meaning": "一", "example": "I have one book.", "exampleMeaning": "我有一本书。" }, { "word": "two", "phonetic": "/tuː/", "meaning": "二", "example": "Two birds are singing.", "exampleMeaning": "两只鸟在唱歌。" }, { "word": "three", "phonetic": "/θriː/", "meaning": "三", "example": "Three cats are sleeping.", "exampleMeaning": "三只猫在睡觉。" }, @@ -174,7 +175,13 @@ { "word": "seventy", "phonetic": "/ˈsevnti/", "meaning": "七十", "example": "My grandmother is seventy.", "exampleMeaning": "我奶奶七十岁。" }, { "word": "eighty", "phonetic": "/ˈeɪti/", "meaning": "八十", "example": "He can count to eighty.", "exampleMeaning": "他能数到八十。" }, { "word": "ninety", "phonetic": "/ˈnaɪnti/", "meaning": "九十", "example": "The book has ninety pages.", "exampleMeaning": "这本书有九十页。" }, - { "word": "hundred", "phonetic": "/ˈhʌndrəd/", "meaning": "百", "example": "One hundred people came.", "exampleMeaning": "来了一百个人。" } + { "word": "hundred", "phonetic": "/ˈhʌndrəd/", "meaning": "百", "example": "One hundred people came.", "exampleMeaning": "来了一百个人。" }, + { "word": "thousand", "phonetic": "/ˈθaʊznd/", "meaning": "千", "example": "This library has thousands of books.", "exampleMeaning": "这个图书馆有数千本书。" }, + { "word": "ten thousand", "phonetic": "/ten ˈθaʊznd/", "meaning": "一万", "example": "Ten thousand people ran in the race.", "exampleMeaning": "一万人参加了赛跑。" }, + { "word": "hundred thousand", "phonetic": "/ˈhʌndrəd ˈθaʊznd/", "meaning": "十万", "example": "The house is worth two hundred thousand dollars.", "exampleMeaning": "这房子价值二十万美元。" }, + { "word": "million", "phonetic": "/ˈmɪljən/", "meaning": "百万", "example": "The city has a population of one million.", "exampleMeaning": "这个城市有一百万人口。" }, + { "word": "ten million", "phonetic": "/ten ˈmɪljən/", "meaning": "千万", "example": "Ten million viewers watched the show.", "exampleMeaning": "一千万观众看了这个节目。" }, + { "word": "hundred million", "phonetic": "/ˈhʌndrəd ˈmɪljən/", "meaning": "亿", "example": "Over a hundred million people speak Japanese.", "exampleMeaning": "超过一亿人说日语。" } ] }, { diff --git a/LearnEnglish/LearnEnglish/Services/WordStore.swift b/LearnEnglish/LearnEnglish/Services/WordStore.swift index 78fb553..dac8d9a 100644 --- a/LearnEnglish/LearnEnglish/Services/WordStore.swift +++ b/LearnEnglish/LearnEnglish/Services/WordStore.swift @@ -29,8 +29,11 @@ final class WordStore { let decoded = try JSONDecoder().decode(WordBank.self, from: data) let categories = decoded.categories.map { category -> WordCategory in guard category.id == "numbers" else { return category } + var words = NumberWords.makeWords(atoms: category.words) + let extras = category.words.filter { NumberWords.atomNumbers[$0.word] == nil } + words.append(contentsOf: extras) return WordCategory(id: category.id, name: category.name, icon: category.icon, - words: NumberWords.makeWords(atoms: category.words)) + words: words) } bank = WordBank(version: decoded.version, categories: categories) } catch { diff --git a/LearnEnglish/LearnEnglish/Views/WordListViewController.swift b/LearnEnglish/LearnEnglish/Views/WordListViewController.swift index 8ef165c..79c4475 100644 --- a/LearnEnglish/LearnEnglish/Views/WordListViewController.swift +++ b/LearnEnglish/LearnEnglish/Views/WordListViewController.swift @@ -119,7 +119,13 @@ final class WordListViewController: UIViewController { private func startQuiz() { Haptics.selection() - let request = QuizSetupRequest(words: category.words) + let words: [Word] + if category.id == "numbers" { + words = NumberWords.randomWords(count: 50) + } else { + words = category.words + } + let request = QuizSetupRequest(words: words) navigationController?.pushViewController(QuizSetupViewController(request: request), animated: true) }