Got rid of WordAX class

(so far without deleting, just to make sure if it's needed in the future)
Moved AnkiView to use FetchRequest, still a couple of TODOs left
This commit is contained in:
2024-04-10 11:54:42 +02:00
parent 5ce5ca2637
commit 301e545f47
11 changed files with 240 additions and 196 deletions

View File

@@ -19,7 +19,7 @@
6CEF7F7D2BC457E600E205F6 /* DataController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F7C2BC457E600E205F6 /* DataController.swift */; }; 6CEF7F7D2BC457E600E205F6 /* DataController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F7C2BC457E600E205F6 /* DataController.swift */; };
6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F7F2BC4694900E205F6 /* WordAXCD.xcdatamodeld */; }; 6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F7F2BC4694900E205F6 /* WordAXCD.xcdatamodeld */; };
6CEF7F842BC46B5900E205F6 /* Flashcard+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F822BC46B5900E205F6 /* Flashcard+CoreDataClass.swift */; }; 6CEF7F842BC46B5900E205F6 /* Flashcard+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F822BC46B5900E205F6 /* Flashcard+CoreDataClass.swift */; };
6CEF7F852BC46B5900E205F6 /* Flashcard+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F832BC46B5900E205F6 /* Flashcard+CoreDataProperties.swift */; }; 6CEF7F8D2BC5613F00E205F6 /* Flashcard+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F8B2BC5613F00E205F6 /* Flashcard+CoreDataProperties.swift */; };
6CF439522B83541D004C3543 /* WordAXApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CF439512B83541D004C3543 /* WordAXApp.swift */; }; 6CF439522B83541D004C3543 /* WordAXApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CF439512B83541D004C3543 /* WordAXApp.swift */; };
6CF439542B83541D004C3543 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CF439532B83541D004C3543 /* MainView.swift */; }; 6CF439542B83541D004C3543 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CF439532B83541D004C3543 /* MainView.swift */; };
6CF439562B83541E004C3543 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CF439552B83541E004C3543 /* Assets.xcassets */; }; 6CF439562B83541E004C3543 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CF439552B83541E004C3543 /* Assets.xcassets */; };
@@ -39,7 +39,7 @@
6CEF7F7C2BC457E600E205F6 /* DataController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DataController.swift; path = WordAX/Model/DataController.swift; sourceTree = "<group>"; }; 6CEF7F7C2BC457E600E205F6 /* DataController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DataController.swift; path = WordAX/Model/DataController.swift; sourceTree = "<group>"; };
6CEF7F802BC4694900E205F6 /* WordAX.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = WordAX.xcdatamodel; sourceTree = "<group>"; }; 6CEF7F802BC4694900E205F6 /* WordAX.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = WordAX.xcdatamodel; sourceTree = "<group>"; };
6CEF7F822BC46B5900E205F6 /* Flashcard+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Flashcard+CoreDataClass.swift"; sourceTree = "<group>"; }; 6CEF7F822BC46B5900E205F6 /* Flashcard+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Flashcard+CoreDataClass.swift"; sourceTree = "<group>"; };
6CEF7F832BC46B5900E205F6 /* Flashcard+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Flashcard+CoreDataProperties.swift"; sourceTree = "<group>"; }; 6CEF7F8B2BC5613F00E205F6 /* Flashcard+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Flashcard+CoreDataProperties.swift"; sourceTree = "<group>"; };
6CF4394E2B83541D004C3543 /* WordAX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WordAX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6CF4394E2B83541D004C3543 /* WordAX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WordAX.app; sourceTree = BUILT_PRODUCTS_DIR; };
6CF439512B83541D004C3543 /* WordAXApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordAXApp.swift; sourceTree = "<group>"; }; 6CF439512B83541D004C3543 /* WordAXApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordAXApp.swift; sourceTree = "<group>"; };
6CF439532B83541D004C3543 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; }; 6CF439532B83541D004C3543 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
@@ -76,8 +76,8 @@
6CEF7F7B2BC456A100E205F6 /* Model */ = { 6CEF7F7B2BC456A100E205F6 /* Model */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
6CEF7F8B2BC5613F00E205F6 /* Flashcard+CoreDataProperties.swift */,
6CEF7F822BC46B5900E205F6 /* Flashcard+CoreDataClass.swift */, 6CEF7F822BC46B5900E205F6 /* Flashcard+CoreDataClass.swift */,
6CEF7F832BC46B5900E205F6 /* Flashcard+CoreDataProperties.swift */,
); );
path = Model; path = Model;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -206,7 +206,7 @@
6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */, 6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */,
6C81850C2B8BA6BC0033CF46 /* FlashCardListRowView.swift in Sources */, 6C81850C2B8BA6BC0033CF46 /* FlashCardListRowView.swift in Sources */,
6CEF7F842BC46B5900E205F6 /* Flashcard+CoreDataClass.swift in Sources */, 6CEF7F842BC46B5900E205F6 /* Flashcard+CoreDataClass.swift in Sources */,
6CEF7F852BC46B5900E205F6 /* Flashcard+CoreDataProperties.swift in Sources */, 6CEF7F8D2BC5613F00E205F6 /* Flashcard+CoreDataProperties.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@@ -10,7 +10,8 @@ import CoreData
class DataController: ObservableObject { class DataController: ObservableObject {
let container = NSPersistentContainer(name: "WordAXCD") let container = NSPersistentContainer(name: "WordAXCD")
static let shared = DataController() // static let shared = DataController()
typealias SpacedRepetitionMilestoneEnum = Flashcard.SpacedRepetitionMilestoneEnum
var viewContext: NSManagedObjectContext { var viewContext: NSManagedObjectContext {
container.viewContext container.viewContext
@@ -25,6 +26,7 @@ class DataController: ObservableObject {
} }
} }
// public func addFlashcard(name: String, description: String) {
public func addFlashcard(name: String, description: String) { public func addFlashcard(name: String, description: String) {
let flashcard = Flashcard(context: viewContext) let flashcard = Flashcard(context: viewContext)
flashcard.id = UUID() flashcard.id = UUID()
@@ -38,8 +40,48 @@ class DataController: ObservableObject {
try? viewContext.save() try? viewContext.save()
} }
public func getAllFlashcards() -> [Flashcard]{ // TODO: Figure out if this does anything?
public func setNextSpacedRepetitionMilestone(flashcard: Flashcard) {
let current = SpacedRepetitionMilestoneEnum.allCasesSorted.firstIndex(of: flashcard.getSpacedRepetitionMilestone()) ?? SpacedRepetitionMilestoneEnum.allCases.count
let predicate = NSPredicate(format: "id == %@", flashcard.id! as CVarArg)
let flashcards = self.getAllFlashcards(predicate: predicate)
if !flashcards.isEmpty {
if current + 1 < SpacedRepetitionMilestoneEnum.allCases.count {
flashcards[0].nextSpacedRepetitionMilestone = SpacedRepetitionMilestoneEnum.allCasesSorted[current + 1].rawValue
}
}
}
public func setSpacedRepetitionMilestone(flashcardId: UUID, milestone: SpacedRepetitionMilestoneEnum?) {
let predicate = NSPredicate(format: "id == %@", flashcardId as CVarArg)
let flashcards = self.getAllFlashcards(predicate: predicate)
if !flashcards.isEmpty {
if milestone != nil {
flashcards[0].nextSpacedRepetitionMilestone = milestone!.rawValue
} else {
flashcards[0].nextSpacedRepetitionMilestone = 0
}
if !flashcards[0].shown {
flashcards[0].shown = true
}
flashcards[0].lastSeenOn = Date()
}
}
public func flashcardShown(flashcardId: UUID) {
let predicate = NSPredicate(format: "id == %@", flashcardId as CVarArg)
let flashcards = self.getAllFlashcards(predicate: predicate)
if !flashcards.isEmpty {
flashcards[0].shownCount += 1
try? viewContext.save()
}
}
public func getAllFlashcards(predicate: NSPredicate? = nil) -> [Flashcard]{
let request = NSFetchRequest<Flashcard>(entityName: "Flashcard") let request = NSFetchRequest<Flashcard>(entityName: "Flashcard")
if predicate != nil {
request.predicate = predicate
}
do { do {
return try viewContext.fetch(request) return try viewContext.fetch(request)
@@ -47,4 +89,41 @@ class DataController: ObservableObject {
return [] return []
} }
} }
// public func getFlashCardsToDisplay() -> Flashcard? {
// let flashcards = self.getAllFlashcards()
//
// if flashcards.count > 0 {
// let notShownFlashCards = flashcards.filter({!$0.shown})
// // if today is the date they're supposed to be shown
//
// let displayToday = flashcards.filter({
// $0.lastSeenOn != nil &&
// $0.lastSeenOn!.addSpacedRepetitionMilestone(
// milestone: SpacedRepetitionMilestoneEnum.getMilestoneFromInt(
// value: $0.nextSpacedRepetitionMilestone))
// .isBeforeTodayOrToday()
// })
// if displayToday.count > 0 {
// return displayToday.first!
// }
//
//// let shownWords = words.filter({ $0.shown })
//// if shownWords.count == 0 {
// if notShownFlashCards.count == 0 {
// return nil
// }
// return notShownFlashCards.sorted(by: {$0.id < $1.id}).first
//// }
// // if today is the day to show a new word
//// let settings = model.settings
//// if shownWords.count == 0 ||
//// settings.lastShownNew == nil ||
//// settings.lastShownNew!.addFrequency(frequency: settings.frequency).isAfterToday() {
//// return words.first!
//// }
// }
// // otherwise show nothing
// return nil
// }
} }

View File

@@ -11,7 +11,41 @@ import CoreData
@objc(Flashcard) @objc(Flashcard)
public class Flashcard: NSManagedObject { public class Flashcard: NSManagedObject {
typealias SpacedRepetitionMilestoneEnum = WordAX.SpacedRepetitionMilestoneEnum enum SpacedRepetitionMilestoneEnum: Int64, CaseIterable {
case Now = 0 // starting value
case OneMinute = 60 // 60 * 1
case TenMinutes = 600 // 60 * 10
case OneHour = 3600 // 60 * 60
case OneDay = 86_400 // 24 * 60 * 60
case OneWeek = 604_800 // 24 * 60 * 60 * 7
case TwoWeeks = 1_209_600 // 24 * 60 * 60 * 14
case OneMonth = 2_592_000 // 24 * 60 * 60 * 30
case TwoMonths = 5_184_000 // 24 * 60 * 60 * 60
case FiveMonths = 12_960_000 // 24 * 60 * 60 * 150
case OneYear = 31_536_000 // 24 * 60 * 60 * 365
static var allCasesSorted: [SpacedRepetitionMilestoneEnum] {
allCases.sorted {$0.rawValue < $1.rawValue }
}
static func getNext(milestone: SpacedRepetitionMilestoneEnum?) -> SpacedRepetitionMilestoneEnum? {
let sorted = SpacedRepetitionMilestoneEnum.allCasesSorted
if milestone == nil {
return sorted.first
}
let milestoneIndex = sorted.firstIndex(where: {$0.rawValue == milestone!.rawValue})!
if milestoneIndex < SpacedRepetitionMilestoneEnum.allCasesSorted.count {
return sorted[milestoneIndex + 1]
}
return nil
}
static func getMilestoneFromInt(value: Int64) -> SpacedRepetitionMilestoneEnum {
return SpacedRepetitionMilestoneEnum.allCasesSorted.first(where: {$0.rawValue == value}) ?? SpacedRepetitionMilestoneEnum.Now
}
}
func getSpacedRepetitionMilestone() -> SpacedRepetitionMilestoneEnum { func getSpacedRepetitionMilestone() -> SpacedRepetitionMilestoneEnum {
return SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: self.nextSpacedRepetitionMilestone) return SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: self.nextSpacedRepetitionMilestone)

View File

@@ -2,7 +2,7 @@
// Flashcard+CoreDataProperties.swift // Flashcard+CoreDataProperties.swift
// WordAX // WordAX
// //
// Created by Oliver Hnát on 08.04.2024. // Created by Oliver Hnát on 09.04.2024.
// //
// //
@@ -11,6 +11,7 @@ import CoreData
extension Flashcard { extension Flashcard {
// TODO: Get rid of shown and instead just use lastSeenOn == nil
@nonobjc public class func fetchRequest() -> NSFetchRequest<Flashcard> { @nonobjc public class func fetchRequest() -> NSFetchRequest<Flashcard> {
return NSFetchRequest<Flashcard>(entityName: "Flashcard") return NSFetchRequest<Flashcard>(entityName: "Flashcard")

View File

@@ -11,7 +11,7 @@ struct AddFlashCard: View {
@State var text: String = "" @State var text: String = ""
@State var description: String = "" @State var description: String = ""
@Binding var isShowing: Bool @Binding var isShowing: Bool
var addFlashCard: (String, String) -> Void @Environment(\.managedObjectContext) var moc
var body: some View { var body: some View {
NavigationStack { NavigationStack {
List { List {
@@ -31,7 +31,16 @@ struct AddFlashCard: View {
} }
ToolbarItemGroup(placement: .topBarTrailing) { ToolbarItemGroup(placement: .topBarTrailing) {
Button(action: { Button(action: {
self.addFlashCard(self.text, self.description) let flashcard = Flashcard(context: moc)
flashcard.id = UUID()
flashcard.name = self.text
flashcard.desc = self.description
flashcard.shown = false
flashcard.nextSpacedRepetitionMilestone = 0
flashcard.lastSeenOn = nil
flashcard.shownCount = 0
flashcard.dateAdded = Date()
try? moc.save()
self.isShowing = false self.isShowing = false
}, label: { }, label: {
Text("Create") Text("Create")
@@ -46,8 +55,5 @@ struct AddFlashCard: View {
#Preview { #Preview {
@State var isShowing = true @State var isShowing = true
func add(name: String, desc: String) { return AddFlashCard(isShowing: $isShowing)
return
}
return AddFlashCard(isShowing: $isShowing, addFlashCard: add)
} }

View File

@@ -6,27 +6,40 @@
// //
import SwiftUI import SwiftUI
import CoreData
struct AnkiView: View { struct AnkiView: View {
@EnvironmentObject var model: WordAXModelView @EnvironmentObject var model: WordAXModelView
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: [
NSSortDescriptor(key: "nextSpacedRepetitionMilestone", ascending: false),
NSSortDescriptor(key: "lastSeenOn", ascending: true)
], predicate: NSCompoundPredicate(type: .or, subpredicates: [
NSCompoundPredicate(type: .and, subpredicates: [
NSPredicate(format: "%K != nil", "lastSeenOn"),
NSPredicate(format: "lastSeenOn + nextSpacedRepetitionMilestone < %@", Date() as CVarArg)
]),
NSPredicate(format: "lastSeenOn == nil")
])) var flashcards: FetchedResults<Flashcard>
@State var showDescription = false @State var showDescription = false
var flashcard: Flashcard? {
model.getFlashCardsToDisplay()
}
var body: some View { var body: some View {
if flashcard != nil { if !flashcards.isEmpty && flashcards.first != nil {
GeometryReader { geometry in GeometryReader { geometry in
VStack { VStack {
FlashCardView(flashcard: flashcard!, showDescription: $showDescription) if flashcards.first != nil {
if showDescription { FlashCardView(flashcard: flashcards.first!, showDescription: $showDescription)
}
if showDescription && flashcards.first != nil {
// Text("How did you do?") // Text("How did you do?")
// .font(.subheadline) // .font(.subheadline)
// .foregroundStyle(.gray) // .foregroundStyle(.gray)
HStack(alignment: .center) { HStack(alignment: .center) {
NextRepetitionButtonView( NextRepetitionButtonView(
buttonText: "Wrong", buttonText: "Wrong",
nextMilestone: flashcard!.getSpacedRepetitionMilestone(), nextMilestone: flashcards.first!.getSpacedRepetitionMilestone(),
flashcardId: flashcard!.id!, flashcardId: flashcards.first!.id!,
width: geometry.size.width, width: geometry.size.width,
color: .red, color: .red,
geometry: geometry, geometry: geometry,
@@ -35,8 +48,8 @@ struct AnkiView: View {
) )
NextRepetitionButtonView( NextRepetitionButtonView(
buttonText: "Correct", buttonText: "Correct",
nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcard!.getSpacedRepetitionMilestone()), nextMilestone: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcards.first!.getSpacedRepetitionMilestone()),
flashcardId: flashcard!.id!, flashcardId: flashcards.first!.id!,
width:geometry.size.width, width:geometry.size.width,
color: .orange, color: .orange,
geometry: geometry, geometry: geometry,
@@ -45,8 +58,8 @@ struct AnkiView: View {
) )
NextRepetitionButtonView( NextRepetitionButtonView(
buttonText: "Easy", buttonText: "Easy",
nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcard!.getSpacedRepetitionMilestone())), nextMilestone: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcards.first!.getSpacedRepetitionMilestone())),
flashcardId: flashcard!.id!, flashcardId: flashcards.first!.id!,
width: geometry.size.width, width: geometry.size.width,
color: .green, color: .green,
geometry: geometry, geometry: geometry,

View File

@@ -11,12 +11,14 @@ struct FlashCardListView: View {
@EnvironmentObject var model: WordAXModelView @EnvironmentObject var model: WordAXModelView
@State var showDescription = true @State var showDescription = true
@State var addFlashcard = false @State var addFlashcard = false
// @ObservedObject var flashcards = DataController.shared.getAllFlashcards()
@FetchRequest(sortDescriptors: []) var flashcards: FetchedResults<Flashcard>
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
NavigationSplitView { NavigationSplitView {
Group { Group {
if !DataController.shared.getAllFlashcards().isEmpty { if !flashcards.isEmpty {
List(DataController.shared.getAllFlashcards()) { flashcard in List(flashcards) { flashcard in
NavigationLink { NavigationLink {
FlashCardView(flashcard: flashcard, showDescription: $showDescription) FlashCardView(flashcard: flashcard, showDescription: $showDescription)
} label: { } label: {
@@ -44,13 +46,13 @@ struct FlashCardListView: View {
Text("Select word to get details about") Text("Select word to get details about")
} }
.sheet(isPresented: $addFlashcard, content: { .sheet(isPresented: $addFlashcard, content: {
AddFlashCard(isShowing: $addFlashcard, addFlashCard: model.addFlashCard) AddFlashCard(isShowing: $addFlashcard)
}) })
} }
} }
} }
#Preview { //#Preview {
FlashCardListView() // FlashCardListView()
.environmentObject(WordAXModelView()) // .environmentObject(WordAXModelView())
} //}

View File

@@ -24,6 +24,7 @@ struct FlashCardView: View {
Text("Last seen: " + model.getDateFormatter().string(from: flashcard.lastSeenOn!)) Text("Last seen: " + model.getDateFormatter().string(from: flashcard.lastSeenOn!))
.font(.subheadline) .font(.subheadline)
} }
Text("Next spaced repetition milestone: \(flashcard.nextSpacedRepetitionMilestone)")
if showDescription { if showDescription {
flashcardText flashcardText
.textSelection(.enabled) .textSelection(.enabled)
@@ -47,6 +48,6 @@ struct FlashCardView: View {
#Preview { #Preview {
@State var showDescription = false @State var showDescription = false
return FlashCardView(flashcard: DataController.shared.getAllFlashcards()[0], showDescription: $showDescription) return FlashCardView(flashcard: DataController().getAllFlashcards()[0], showDescription: $showDescription)
.environmentObject(WordAXModelView()) .environmentObject(WordAXModelView())
} }

View File

@@ -9,7 +9,7 @@ import SwiftUI
struct NextRepetitionButtonView: View { struct NextRepetitionButtonView: View {
let buttonText: String let buttonText: String
let nextMilestone: WordAX.SpacedRepetitionMilestoneEnum? let nextMilestone: Flashcard.SpacedRepetitionMilestoneEnum?
let flashcardId: UUID let flashcardId: UUID
let width: CGFloat let width: CGFloat
let color: Color let color: Color
@@ -21,7 +21,8 @@ struct NextRepetitionButtonView: View {
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
var body: some View { var body: some View {
Button(action: { Button(action: {
model.ankiButtonClicked(flashcardId: flashcardId, milestone: nextMilestone) // TODO: Fix this anki button clicked function
// model.ankiButtonClicked(flashcardId: flashcardId, milestone: nextMilestone)
self.showDescription = false self.showDescription = false
}) { }) {
VStack { VStack {
@@ -49,6 +50,6 @@ extension ShapeStyle where Self == Color {
//#Preview { //#Preview {
// @State var showDescription = false // @State var showDescription = false
// return NextRepetitionButtonView(buttonText: "Excellent", nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.OneDay, wordId: 0, showDescription: $showDescription) // return NextRepetitionButtonView(buttonText: "Excellent", nextMilestone: Flashcard.SpacedRepetitionMilestoneEnum.OneDay, wordId: 0, showDescription: $showDescription)
// .environmentObject(WordAXModelView()) // .environmentObject(WordAXModelView())
//} //}

View File

@@ -8,112 +8,47 @@
import Foundation import Foundation
import SwiftUI import SwiftUI
struct WordAX { //struct WordAX {
struct FlashCard: Identifiable, Hashable { // struct FlashCard: Identifiable, Hashable {
var id: Int // var id: Int
var name: String // var name: String
var description: String // var description: String
var shown: Bool = false // var shown: Bool = false
var nextSpacedRepetitionMilestone: SpacedRepetitionMilestoneEnum? // var nextSpacedRepetitionMilestone: Flashcard.SpacedRepetitionMilestoneEnum?
var lastSeenOn: Date? // var lastSeenOn: Date?
var shownCount: Int = 0 // var shownCount: Int = 0
} // }
//
enum FrequencyEnum: Int { // enum FrequencyEnum: Int {
case Daily = 1 // case Daily = 1
case Weekly = 7 // case Weekly = 7
case BiWeekly = 14 // case BiWeekly = 14
case Monthly = 30 // case Monthly = 30
} // }
//
//
public mutating func add(flashcard: FlashCard) { // public mutating func add(flashcard: FlashCard) {
self.flashcards.append(flashcard) // self.flashcards.append(flashcard)
} // }
//
//
@objc enum SpacedRepetitionMilestoneEnum: Int64, CaseIterable { // struct Settings {
case Now = 0 // starting value // var frequency: FrequencyEnum = .Daily
case OneMinute = 60 // 60 * 1 // var lastShownNew: Date?
case TenMinutes = 600 // 60 * 10 // var dateFormatter: DateFormatter
case OneHour = 3600 // 60 * 60 // }
case OneDay = 86_400 // 24 * 60 * 60 //
case OneWeek = 604_800 // 24 * 60 * 60 * 7 //
case TwoWeeks = 1_209_600 // 24 * 60 * 60 * 14 // var flashcards: [FlashCard] = []
case OneMonth = 2_592_000 // 24 * 60 * 60 * 30 // var settings: Settings
case TwoMonths = 5_184_000 // 24 * 60 * 60 * 60 //
case FiveMonths = 12_960_000 // 24 * 60 * 60 * 150 // init() {
case OneYear = 31_536_000 // 24 * 60 * 60 * 365 // self.flashcards = []
// let dateFormatter = DateFormatter()
static var allCasesSorted: [SpacedRepetitionMilestoneEnum] { // dateFormatter.dateFormat = "dd/MM/YYYY"
allCases.sorted {$0.rawValue < $1.rawValue } // self.settings = Settings(dateFormatter: dateFormatter)
} //// self.flashcards.append(FlashCard(id: 0, name: "Magnificent", description: "When something is awesome. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", shown: false))
//// self.flashcards.append(FlashCard(id: 1, name: "Mesmerising", description: "When something is beautiful", shown: false))
static func getNext(milestone: SpacedRepetitionMilestoneEnum?) -> SpacedRepetitionMilestoneEnum? { // }
let sorted = WordAX.SpacedRepetitionMilestoneEnum.allCasesSorted //
if milestone == nil { //}
return sorted.first
}
let milestoneIndex = sorted.firstIndex(where: {$0.rawValue == milestone!.rawValue})!
if milestoneIndex < WordAX.SpacedRepetitionMilestoneEnum.allCasesSorted.count {
return sorted[milestoneIndex + 1]
}
return nil
}
static func getMilestoneFromInt(value: Int64) -> SpacedRepetitionMilestoneEnum {
return SpacedRepetitionMilestoneEnum.allCasesSorted.first(where: {$0.rawValue == value}) ?? SpacedRepetitionMilestoneEnum.Now
}
}
struct Settings {
var frequency: FrequencyEnum = .Daily
var lastShownNew: Date?
var dateFormatter: DateFormatter
}
public mutating func setNextSpacedRepetitionMilestone(flashcard: FlashCard) {
if flashcard.nextSpacedRepetitionMilestone != nil {
let current = SpacedRepetitionMilestoneEnum.allCasesSorted.firstIndex(of: flashcard.nextSpacedRepetitionMilestone!) ?? SpacedRepetitionMilestoneEnum.allCases.count
let index = flashcards.firstIndex(where:{$0.id == flashcard.id}) ?? nil
if current + 1 < SpacedRepetitionMilestoneEnum.allCases.count && index != nil {
flashcards[index!].nextSpacedRepetitionMilestone = SpacedRepetitionMilestoneEnum.allCasesSorted[current + 1]
} else if index != nil {
flashcards[index!].nextSpacedRepetitionMilestone = nil
}
}
}
public mutating func setSpacedRepetitionMilestone(flashcardId: Int, milestone: SpacedRepetitionMilestoneEnum?) {
let index = flashcards.firstIndex(where:{$0.id == flashcardId}) ?? nil
if index != nil {
flashcards[index!].nextSpacedRepetitionMilestone = milestone
if !flashcards[index!].shown {
flashcards[index!].shown = true
}
flashcards[index!].lastSeenOn = Date()
}
}
public mutating func flashcardShown(flashcardId: Int) {
let index = flashcards.firstIndex(where:{$0.id == flashcardId}) ?? nil
if index != nil {
flashcards[index!].shownCount += 1
}
}
var flashcards: [FlashCard] = []
var settings: Settings
init() {
self.flashcards = []
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/YYYY"
self.settings = Settings(dateFormatter: dateFormatter)
// self.flashcards.append(FlashCard(id: 0, name: "Magnificent", description: "When something is awesome. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", shown: false))
// self.flashcards.append(FlashCard(id: 1, name: "Mesmerising", description: "When something is beautiful", shown: false))
}
}

View File

@@ -6,63 +6,35 @@
// //
import Foundation import Foundation
import SwiftUI
class WordAXModelView: ObservableObject { class WordAXModelView: ObservableObject {
@Published private var model: WordAX typealias SpacedRepetitionMilestoneEnum = Flashcard.SpacedRepetitionMilestoneEnum
typealias FlashCard = WordAX.FlashCard
typealias SpacedRepetitionMilestoneEnum = WordAX.SpacedRepetitionMilestoneEnum let settings: Settings
init() { init() {
model = WordAX() let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/YYYY"
self.settings = Settings(dateFormatter: dateFormatter)
} }
public var flashcards: [Flashcard] { struct Settings {
DataController.shared.getAllFlashcards() var dateFormatter: DateFormatter
}
public func getFlashcards(moc: DataController) -> [Flashcard] {
moc.getAllFlashcards()
} }
public func getDateFormatter() -> DateFormatter { public func getDateFormatter() -> DateFormatter {
model.settings.dateFormatter self.settings.dateFormatter
} }
public func getFlashCardsToDisplay() -> Flashcard? {
let flashcards = self.flashcards
if flashcards.count > 0 { public func ankiButtonClicked(flashcardId: UUID, milestone: Flashcard.SpacedRepetitionMilestoneEnum?, moc: DataController) {
let notShownFlashCards = flashcards.filter({!$0.shown}) moc.setSpacedRepetitionMilestone(flashcardId: flashcardId, milestone: milestone)
if notShownFlashCards.count == 0 { moc.flashcardShown(flashcardId: flashcardId)
return nil
}
// if today is the date they're supposed to be shown
let displayToday = flashcards.filter({ $0.lastSeenOn != nil && $0.lastSeenOn!.addSpacedRepetitionMilestone(milestone: SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: $0.nextSpacedRepetitionMilestone)).isBeforeTodayOrToday()})
if displayToday.count > 0 {
return displayToday.first!
}
// let shownWords = words.filter({ $0.shown })
// if shownWords.count == 0 {
return notShownFlashCards.sorted(by: {$0.id < $1.id}).first
// }
// if today is the day to show a new word
// let settings = model.settings
// if shownWords.count == 0 ||
// settings.lastShownNew == nil ||
// settings.lastShownNew!.addFrequency(frequency: settings.frequency).isAfterToday() {
// return words.first!
// }
}
// otherwise show nothing
return nil
}
public func ankiButtonClicked(flashcardId: UUID, milestone: WordAX.SpacedRepetitionMilestoneEnum?) {
// TODO: Fix this with Core Data
// model.setSpacedRepetitionMilestone(flashcardId: flashcardId, milestone: milestone)
// model.flashcardShown(flashcardId: flashcardId)
}
public func addFlashCard(name: String, description: String) {
// self.model.add(flashcard: FlashCard(id: (self.flashcards.map{$0.id}.max() ?? -1) + 1, name: name, description: description))
DataController.shared.addFlashcard(name: name, description: description)
} }
} }
@@ -93,11 +65,11 @@ extension Date {
return selfDate.year! < paramDate.year! || selfDate.month! < paramDate.month! || selfDate.day! < paramDate.day! return selfDate.year! < paramDate.year! || selfDate.month! < paramDate.month! || selfDate.day! < paramDate.day!
} }
func addFrequency(frequency: WordAX.FrequencyEnum) -> Date { // func addFrequency(frequency: WordAX.FrequencyEnum) -> Date {
self.addingTimeInterval(TimeInterval(frequency.rawValue * 24 * 60 * 60)) // self.addingTimeInterval(TimeInterval(frequency.rawValue * 24 * 60 * 60))
} // }
func addSpacedRepetitionMilestone(milestone: WordAX.SpacedRepetitionMilestoneEnum?) -> Date { func addSpacedRepetitionMilestone(milestone: Flashcard.SpacedRepetitionMilestoneEnum?) -> Date {
if milestone == nil { if milestone == nil {
return self return self
} }