Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions ios/ReviewSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,46 @@ class ReviewSession {
_ = services.localCachingClient?.updateStudyMaterial(activeStudyMaterials!)
}

private func sortReviewType() {
// Settings.secondaryReviewOrder -> (radical, kanji, vocab) order ranks
var subjectOrder = [UInt: (Int, Int, Int)]()
// Instead of more complex logic, let's have structed data and few sorting cases
subjectOrder[SecondaryReviewOrder.unsorted.rawValue] = (0, 0, 0) // Default, no sort
subjectOrder[SecondaryReviewOrder.radicalKanjiVocabulary.rawValue] = (1, 2, 3)
subjectOrder[SecondaryReviewOrder.radicalVocabularyKanji.rawValue] = (1, 3, 2)
subjectOrder[SecondaryReviewOrder.kanjiRadicalVocabulary.rawValue] = (2, 1, 3)
subjectOrder[SecondaryReviewOrder.kanjiVocabularyRadical.rawValue] = (3, 1, 2)
subjectOrder[SecondaryReviewOrder.vocabularyRadicalKanji.rawValue] = (2, 3, 1)
subjectOrder[SecondaryReviewOrder.vocabularyKanjiRadical.rawValue] = (3, 2, 1)

let (radicalRank, kanjiRank, vocabRank) = subjectOrder[Settings.secondaryReviewOrder.rawValue]!

let subjectRank = [TKMSubject.TypeEnum.radical.rawValue: radicalRank,
TKMSubject.TypeEnum.kanji.rawValue: kanjiRank,
TKMSubject.TypeEnum.vocabulary.rawValue: vocabRank]

switch Settings.secondaryReviewOrder {
case .radicalKanjiVocabulary: fallthrough
case .radicalVocabularyKanji: fallthrough
case .kanjiRadicalVocabulary: fallthrough
case .kanjiVocabularyRadical: fallthrough
case .vocabularyRadicalKanji: fallthrough
case .vocabularyKanjiRadical:
reviewQueue.sort { (a, b: ReviewItem) -> Bool in
if subjectRank[a.assignment.subjectType.rawValue]! <
subjectRank[b.assignment.subjectType.rawValue]! { return true }
if subjectRank[a.assignment.subjectType.rawValue]! >
subjectRank[b.assignment.subjectType.rawValue]! { return false }
return false
}
case .unsorted:
break

@unknown default:
fatalError()
}
}

private func sortReviewQueue() {
reviewQueue.shuffle()
switch Settings.reviewOrder {
Expand Down Expand Up @@ -269,6 +309,8 @@ class ReviewSession {
@unknown default:
fatalError()
}
// Apply (secondary) review type sort, if applicable.
sortReviewType()
}

private func availableRatio(_ assignment: TKMAssignment) -> TimeInterval {
Expand Down
19 changes: 18 additions & 1 deletion ios/ReviewSettingsViewController.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022 David Sansome
// Copyright 2023 David Sansome
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -45,6 +45,12 @@ class ReviewSettingsViewController: UITableViewController, TKMViewController {
accessoryType: .disclosureIndicator,
target: self,
action: #selector(didTapReviewOrder(_:))))
model.add(BasicModelItem(style: .value1,
title: "Subject Order",
subtitle: secondaryReviewOrderValueText,
accessoryType: .disclosureIndicator,
target: self,
action: #selector(didTapSecondaryReviewOrder(_:))))
model.add(SwitchModelItem(style: .subtitle,
title: "Back-to-back",
subtitle: "Group Meaning and Reading together",
Expand Down Expand Up @@ -204,6 +210,10 @@ class ReviewSettingsViewController: UITableViewController, TKMViewController {
Settings.reviewOrder.description
}

private var secondaryReviewOrderValueText: String {
Settings.secondaryReviewOrder.description
}

private var taskOrderValueText: String {
Settings.meaningFirst ? "Meaning first" : "Reading first"
}
Expand Down Expand Up @@ -313,6 +323,13 @@ class ReviewSettingsViewController: UITableViewController, TKMViewController {
navigationController?.pushViewController(vc, animated: true)
}

@objc private func didTapSecondaryReviewOrder(_: BasicModelItem) {
let vs = SettingChoiceListViewController(setting: Settings.$secondaryReviewOrder,
title: "Review Subject Order")
vs.addChoicesFromEnum()
navigationController?.pushViewController(vs, animated: true)
}

@objc private func didTapFonts(_: BasicModelItem) {
performSegue(withIdentifier: "fonts", sender: self)
}
Expand Down
24 changes: 24 additions & 0 deletions ios/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ typealias SettingEnum = RawRepresentable & Codable & CaseIterable & CustomString
}
}

@objc enum SecondaryReviewOrder: UInt, SettingEnum {
case unsorted = 1
case radicalKanjiVocabulary = 2 // (rkv)
case radicalVocabularyKanji = 3 // (rvk)
case kanjiRadicalVocabulary = 4 // (krv)
case kanjiVocabularyRadical = 5 // (kvr)
case vocabularyRadicalKanji = 6 // (vrk)
case vocabularyKanjiRadical = 7 // (vkr)

var description: String {
switch self {
case .unsorted: return "Unsorted"
case .radicalKanjiVocabulary: return "Radical, Kanji, Vocabulary"
case .radicalVocabularyKanji: return "Radical, Vocabulary, Kanji"
case .kanjiRadicalVocabulary: return "Kanji, Radical, Vocabulary"
case .kanjiVocabularyRadical: return "Kanji, Vocabulary, Radical"
case .vocabularyRadicalKanji: return "Vocabulary, Radical, Kanji"
case .vocabularyKanjiRadical: return "Vocabulary, Kanji, Radical"
}
}
}

@objc enum InterfaceStyle: UInt, SettingEnum {
case system = 1
case light = 2
Expand Down Expand Up @@ -176,6 +198,8 @@ protocol SettingProtocol {
@Setting(true, #keyPath(showStatsSection)) static var showStatsSection: Bool

@EnumSetting(ReviewOrder.random, #keyPath(reviewOrder)) static var reviewOrder: ReviewOrder
@EnumSetting(SecondaryReviewOrder.unsorted,
#keyPath(secondaryReviewOrder)) static var secondaryReviewOrder: SecondaryReviewOrder
@Setting(5, #keyPath(reviewBatchSize)) static var reviewBatchSize: Int
@Setting(Int.max, #keyPath(apprenticeLessonsLimit)) static var apprenticeLessonsLimit: Int
@Setting(false, #keyPath(groupMeaningReading)) static var groupMeaningReading: Bool
Expand Down