Add basic backend for showing words
This commit is contained in:
77
WordAX.xcodeproj/xcshareddata/xcschemes/WordAX.xcscheme
Normal file
77
WordAX.xcodeproj/xcshareddata/xcschemes/WordAX.xcscheme
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1520"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "6CF4394D2B83541D004C3543"
|
||||||
|
BuildableName = "WordAX.app"
|
||||||
|
BlueprintName = "WordAX"
|
||||||
|
ReferencedContainer = "container:WordAX.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "6CF4394D2B83541D004C3543"
|
||||||
|
BuildableName = "WordAX.app"
|
||||||
|
BlueprintName = "WordAX"
|
||||||
|
ReferencedContainer = "container:WordAX.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "6CF4394D2B83541D004C3543"
|
||||||
|
BuildableName = "WordAX.app"
|
||||||
|
BlueprintName = "WordAX"
|
||||||
|
ReferencedContainer = "container:WordAX.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -10,5 +10,13 @@
|
|||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict>
|
||||||
|
<key>6CF4394D2B83541D004C3543</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -6,3 +6,62 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
struct WordAX {
|
||||||
|
struct Word: Identifiable {
|
||||||
|
var id: Int
|
||||||
|
var name: String
|
||||||
|
var description: String
|
||||||
|
var shown: Bool
|
||||||
|
var nextSpacedRepetitionMilestone: SpacedRepetitionMilestoneEnum?
|
||||||
|
var displayOn: Date?
|
||||||
|
}
|
||||||
|
enum FrequencyEnum: Int {
|
||||||
|
case Daily = 1
|
||||||
|
case Weekly = 7
|
||||||
|
case BiWeekly = 14
|
||||||
|
case Monthly = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SpacedRepetitionMilestoneEnum: Int, CaseIterable {
|
||||||
|
case OneDay = 1
|
||||||
|
case OneWeek = 7
|
||||||
|
case TwoWeeks = 14
|
||||||
|
case OneMonth = 30
|
||||||
|
case TwoMonths = 60
|
||||||
|
case FiveMonths = 150
|
||||||
|
case OneYear = 365
|
||||||
|
|
||||||
|
static var allCasesSorted: [SpacedRepetitionMilestoneEnum] {
|
||||||
|
allCases.sorted {$0.rawValue < $1.rawValue }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Settings {
|
||||||
|
var frequency: FrequencyEnum = .Daily
|
||||||
|
var lastShownNew: Date?
|
||||||
|
}
|
||||||
|
|
||||||
|
private mutating func setNextSpacedRepetitionMilestone(word: Word) {
|
||||||
|
if word.nextSpacedRepetitionMilestone != nil {
|
||||||
|
let current = SpacedRepetitionMilestoneEnum.allCasesSorted.firstIndex(of: word.nextSpacedRepetitionMilestone!) ?? SpacedRepetitionMilestoneEnum.allCases.count
|
||||||
|
let index = words.firstIndex(where:{$0.id == word.id}) ?? nil
|
||||||
|
if current + 1 < SpacedRepetitionMilestoneEnum.allCases.count && index != nil {
|
||||||
|
words[index!].nextSpacedRepetitionMilestone = SpacedRepetitionMilestoneEnum.allCasesSorted[current + 1]
|
||||||
|
} else if index != nil {
|
||||||
|
words[index!].nextSpacedRepetitionMilestone = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var words: [Word] = []
|
||||||
|
var settings: Settings
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.words = []
|
||||||
|
self.settings = Settings()
|
||||||
|
self.words.append(Word(id: 0, name: "Magnificent", description: "When something is awesome", shown: false))
|
||||||
|
self.words.append(Word(id: 1, name: "Mesmerising", description: "When something is beautiful", shown: false))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,62 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class WordAXModelView: ObservableObject {
|
class WordAXModelView: ObservableObject {
|
||||||
|
@Published private var model: WordAX
|
||||||
|
typealias Word = WordAX.Word
|
||||||
init() {
|
init() {
|
||||||
|
model = WordAX()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func getWordToDisplay() -> Word? {
|
||||||
|
let words = model.words
|
||||||
|
|
||||||
|
if words.count > 0 {
|
||||||
|
// if today is the date they're supposed to be shown
|
||||||
|
let displayToday = words.filter({ $0.displayOn != nil && $0.displayOn!.isToday()})
|
||||||
|
if displayToday.count > 0 {
|
||||||
|
return displayToday.first!
|
||||||
|
}
|
||||||
|
|
||||||
|
// first word ever shown
|
||||||
|
let shownWords = words.filter({ $0.shown })
|
||||||
|
if shownWords.count == 0 {
|
||||||
|
return words.first!
|
||||||
|
}
|
||||||
|
// if today is the day to show a new word
|
||||||
|
let settings = model.settings
|
||||||
|
if shownWords.count == 0 ||
|
||||||
|
settings.lastShownNew == nil ||
|
||||||
|
settings.lastShownNew!.addingTimeInterval(TimeInterval(settings.frequency.rawValue * 24 * 60 * 60)).isAfterToday() {
|
||||||
|
return words.first!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise show nothing
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension Date {
|
||||||
|
private func getOnlyDate(date: Date) -> DateComponents {
|
||||||
|
Calendar.current.dateComponents([.day, .month, .year], from: date)
|
||||||
|
}
|
||||||
|
func isSameAs(_ date: Date) -> Bool {
|
||||||
|
let selfDate = getOnlyDate(date: self)
|
||||||
|
let paramDate = getOnlyDate(date: date)
|
||||||
|
return selfDate.day == paramDate.day && selfDate.month == paramDate.month && selfDate.year == paramDate.year
|
||||||
|
}
|
||||||
|
|
||||||
|
func isToday() -> Bool {
|
||||||
|
self.isSameAs(Date())
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAfter(_ date: Date) -> Bool {
|
||||||
|
let selfDate = getOnlyDate(date: self)
|
||||||
|
let paramDate = getOnlyDate(date: date)
|
||||||
|
return selfDate.year! > paramDate.year! || selfDate.month! > paramDate.month! || selfDate.day! > paramDate.day!
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAfterToday() -> Bool {
|
||||||
|
self.isAfter(Date())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user