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:
@@ -19,7 +19,7 @@
|
||||
6CEF7F7D2BC457E600E205F6 /* DataController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F7C2BC457E600E205F6 /* DataController.swift */; };
|
||||
6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 6CEF7F7F2BC4694900E205F6 /* WordAXCD.xcdatamodeld */; };
|
||||
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 */; };
|
||||
6CF439542B83541D004C3543 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CF439532B83541D004C3543 /* MainView.swift */; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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; };
|
||||
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>"; };
|
||||
@@ -76,8 +76,8 @@
|
||||
6CEF7F7B2BC456A100E205F6 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6CEF7F8B2BC5613F00E205F6 /* Flashcard+CoreDataProperties.swift */,
|
||||
6CEF7F822BC46B5900E205F6 /* Flashcard+CoreDataClass.swift */,
|
||||
6CEF7F832BC46B5900E205F6 /* Flashcard+CoreDataProperties.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
@@ -206,7 +206,7 @@
|
||||
6CEF7F812BC4694900E205F6 /* WordAXCD.xcdatamodeld in Sources */,
|
||||
6C81850C2B8BA6BC0033CF46 /* FlashCardListRowView.swift in Sources */,
|
||||
6CEF7F842BC46B5900E205F6 /* Flashcard+CoreDataClass.swift in Sources */,
|
||||
6CEF7F852BC46B5900E205F6 /* Flashcard+CoreDataProperties.swift in Sources */,
|
||||
6CEF7F8D2BC5613F00E205F6 /* Flashcard+CoreDataProperties.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,8 @@ import CoreData
|
||||
|
||||
class DataController: ObservableObject {
|
||||
let container = NSPersistentContainer(name: "WordAXCD")
|
||||
static let shared = DataController()
|
||||
// static let shared = DataController()
|
||||
typealias SpacedRepetitionMilestoneEnum = Flashcard.SpacedRepetitionMilestoneEnum
|
||||
|
||||
var viewContext: NSManagedObjectContext {
|
||||
container.viewContext
|
||||
@@ -25,6 +26,7 @@ class DataController: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
// public func addFlashcard(name: String, description: String) {
|
||||
public func addFlashcard(name: String, description: String) {
|
||||
let flashcard = Flashcard(context: viewContext)
|
||||
flashcard.id = UUID()
|
||||
@@ -38,8 +40,48 @@ class DataController: ObservableObject {
|
||||
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")
|
||||
if predicate != nil {
|
||||
request.predicate = predicate
|
||||
}
|
||||
|
||||
do {
|
||||
return try viewContext.fetch(request)
|
||||
@@ -47,4 +89,41 @@ class DataController: ObservableObject {
|
||||
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
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -11,8 +11,42 @@ import CoreData
|
||||
|
||||
@objc(Flashcard)
|
||||
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 {
|
||||
return SpacedRepetitionMilestoneEnum.getMilestoneFromInt(value: self.nextSpacedRepetitionMilestone)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Flashcard+CoreDataProperties.swift
|
||||
// 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 {
|
||||
// TODO: Get rid of shown and instead just use lastSeenOn == nil
|
||||
|
||||
@nonobjc public class func fetchRequest() -> NSFetchRequest<Flashcard> {
|
||||
return NSFetchRequest<Flashcard>(entityName: "Flashcard")
|
||||
|
||||
@@ -11,7 +11,7 @@ struct AddFlashCard: View {
|
||||
@State var text: String = ""
|
||||
@State var description: String = ""
|
||||
@Binding var isShowing: Bool
|
||||
var addFlashCard: (String, String) -> Void
|
||||
@Environment(\.managedObjectContext) var moc
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
@@ -31,7 +31,16 @@ struct AddFlashCard: View {
|
||||
}
|
||||
ToolbarItemGroup(placement: .topBarTrailing) {
|
||||
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
|
||||
}, label: {
|
||||
Text("Create")
|
||||
@@ -46,8 +55,5 @@ struct AddFlashCard: View {
|
||||
|
||||
#Preview {
|
||||
@State var isShowing = true
|
||||
func add(name: String, desc: String) {
|
||||
return
|
||||
}
|
||||
return AddFlashCard(isShowing: $isShowing, addFlashCard: add)
|
||||
return AddFlashCard(isShowing: $isShowing)
|
||||
}
|
||||
|
||||
@@ -6,27 +6,40 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import CoreData
|
||||
|
||||
struct AnkiView: View {
|
||||
@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
|
||||
var flashcard: Flashcard? {
|
||||
model.getFlashCardsToDisplay()
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if flashcard != nil {
|
||||
if !flashcards.isEmpty && flashcards.first != nil {
|
||||
GeometryReader { geometry in
|
||||
VStack {
|
||||
FlashCardView(flashcard: flashcard!, showDescription: $showDescription)
|
||||
if showDescription {
|
||||
if flashcards.first != nil {
|
||||
FlashCardView(flashcard: flashcards.first!, showDescription: $showDescription)
|
||||
}
|
||||
if showDescription && flashcards.first != nil {
|
||||
// Text("How did you do?")
|
||||
// .font(.subheadline)
|
||||
// .foregroundStyle(.gray)
|
||||
HStack(alignment: .center) {
|
||||
NextRepetitionButtonView(
|
||||
buttonText: "Wrong",
|
||||
nextMilestone: flashcard!.getSpacedRepetitionMilestone(),
|
||||
flashcardId: flashcard!.id!,
|
||||
nextMilestone: flashcards.first!.getSpacedRepetitionMilestone(),
|
||||
flashcardId: flashcards.first!.id!,
|
||||
width: geometry.size.width,
|
||||
color: .red,
|
||||
geometry: geometry,
|
||||
@@ -35,8 +48,8 @@ struct AnkiView: View {
|
||||
)
|
||||
NextRepetitionButtonView(
|
||||
buttonText: "Correct",
|
||||
nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcard!.getSpacedRepetitionMilestone()),
|
||||
flashcardId: flashcard!.id!,
|
||||
nextMilestone: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcards.first!.getSpacedRepetitionMilestone()),
|
||||
flashcardId: flashcards.first!.id!,
|
||||
width:geometry.size.width,
|
||||
color: .orange,
|
||||
geometry: geometry,
|
||||
@@ -45,8 +58,8 @@ struct AnkiView: View {
|
||||
)
|
||||
NextRepetitionButtonView(
|
||||
buttonText: "Easy",
|
||||
nextMilestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: WordAX.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcard!.getSpacedRepetitionMilestone())),
|
||||
flashcardId: flashcard!.id!,
|
||||
nextMilestone: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: Flashcard.SpacedRepetitionMilestoneEnum.getNext(milestone: flashcards.first!.getSpacedRepetitionMilestone())),
|
||||
flashcardId: flashcards.first!.id!,
|
||||
width: geometry.size.width,
|
||||
color: .green,
|
||||
geometry: geometry,
|
||||
|
||||
@@ -11,12 +11,14 @@ struct FlashCardListView: View {
|
||||
@EnvironmentObject var model: WordAXModelView
|
||||
@State var showDescription = true
|
||||
@State var addFlashcard = false
|
||||
// @ObservedObject var flashcards = DataController.shared.getAllFlashcards()
|
||||
@FetchRequest(sortDescriptors: []) var flashcards: FetchedResults<Flashcard>
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
NavigationSplitView {
|
||||
Group {
|
||||
if !DataController.shared.getAllFlashcards().isEmpty {
|
||||
List(DataController.shared.getAllFlashcards()) { flashcard in
|
||||
if !flashcards.isEmpty {
|
||||
List(flashcards) { flashcard in
|
||||
NavigationLink {
|
||||
FlashCardView(flashcard: flashcard, showDescription: $showDescription)
|
||||
} label: {
|
||||
@@ -44,13 +46,13 @@ struct FlashCardListView: View {
|
||||
Text("Select word to get details about")
|
||||
}
|
||||
.sheet(isPresented: $addFlashcard, content: {
|
||||
AddFlashCard(isShowing: $addFlashcard, addFlashCard: model.addFlashCard)
|
||||
AddFlashCard(isShowing: $addFlashcard)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
FlashCardListView()
|
||||
.environmentObject(WordAXModelView())
|
||||
}
|
||||
//#Preview {
|
||||
// FlashCardListView()
|
||||
// .environmentObject(WordAXModelView())
|
||||
//}
|
||||
|
||||
@@ -24,6 +24,7 @@ struct FlashCardView: View {
|
||||
Text("Last seen: " + model.getDateFormatter().string(from: flashcard.lastSeenOn!))
|
||||
.font(.subheadline)
|
||||
}
|
||||
Text("Next spaced repetition milestone: \(flashcard.nextSpacedRepetitionMilestone)")
|
||||
if showDescription {
|
||||
flashcardText
|
||||
.textSelection(.enabled)
|
||||
@@ -47,6 +48,6 @@ struct FlashCardView: View {
|
||||
|
||||
#Preview {
|
||||
@State var showDescription = false
|
||||
return FlashCardView(flashcard: DataController.shared.getAllFlashcards()[0], showDescription: $showDescription)
|
||||
return FlashCardView(flashcard: DataController().getAllFlashcards()[0], showDescription: $showDescription)
|
||||
.environmentObject(WordAXModelView())
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import SwiftUI
|
||||
|
||||
struct NextRepetitionButtonView: View {
|
||||
let buttonText: String
|
||||
let nextMilestone: WordAX.SpacedRepetitionMilestoneEnum?
|
||||
let nextMilestone: Flashcard.SpacedRepetitionMilestoneEnum?
|
||||
let flashcardId: UUID
|
||||
let width: CGFloat
|
||||
let color: Color
|
||||
@@ -21,7 +21,8 @@ struct NextRepetitionButtonView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
var body: some View {
|
||||
Button(action: {
|
||||
model.ankiButtonClicked(flashcardId: flashcardId, milestone: nextMilestone)
|
||||
// TODO: Fix this anki button clicked function
|
||||
// model.ankiButtonClicked(flashcardId: flashcardId, milestone: nextMilestone)
|
||||
self.showDescription = false
|
||||
}) {
|
||||
VStack {
|
||||
@@ -49,6 +50,6 @@ extension ShapeStyle where Self == Color {
|
||||
|
||||
//#Preview {
|
||||
// @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())
|
||||
//}
|
||||
|
||||
@@ -8,112 +8,47 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct WordAX {
|
||||
struct FlashCard: Identifiable, Hashable {
|
||||
var id: Int
|
||||
var name: String
|
||||
var description: String
|
||||
var shown: Bool = false
|
||||
var nextSpacedRepetitionMilestone: SpacedRepetitionMilestoneEnum?
|
||||
var lastSeenOn: Date?
|
||||
var shownCount: Int = 0
|
||||
}
|
||||
|
||||
enum FrequencyEnum: Int {
|
||||
case Daily = 1
|
||||
case Weekly = 7
|
||||
case BiWeekly = 14
|
||||
case Monthly = 30
|
||||
}
|
||||
|
||||
|
||||
public mutating func add(flashcard: FlashCard) {
|
||||
self.flashcards.append(flashcard)
|
||||
}
|
||||
|
||||
|
||||
@objc 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 = 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))
|
||||
}
|
||||
|
||||
}
|
||||
//struct WordAX {
|
||||
// struct FlashCard: Identifiable, Hashable {
|
||||
// var id: Int
|
||||
// var name: String
|
||||
// var description: String
|
||||
// var shown: Bool = false
|
||||
// var nextSpacedRepetitionMilestone: Flashcard.SpacedRepetitionMilestoneEnum?
|
||||
// var lastSeenOn: Date?
|
||||
// var shownCount: Int = 0
|
||||
// }
|
||||
//
|
||||
// enum FrequencyEnum: Int {
|
||||
// case Daily = 1
|
||||
// case Weekly = 7
|
||||
// case BiWeekly = 14
|
||||
// case Monthly = 30
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public mutating func add(flashcard: FlashCard) {
|
||||
// self.flashcards.append(flashcard)
|
||||
// }
|
||||
//
|
||||
//
|
||||
// struct Settings {
|
||||
// var frequency: FrequencyEnum = .Daily
|
||||
// var lastShownNew: Date?
|
||||
// var dateFormatter: DateFormatter
|
||||
// }
|
||||
//
|
||||
//
|
||||
// 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))
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
@@ -6,63 +6,35 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
class WordAXModelView: ObservableObject {
|
||||
@Published private var model: WordAX
|
||||
typealias FlashCard = WordAX.FlashCard
|
||||
typealias SpacedRepetitionMilestoneEnum = WordAX.SpacedRepetitionMilestoneEnum
|
||||
typealias SpacedRepetitionMilestoneEnum = Flashcard.SpacedRepetitionMilestoneEnum
|
||||
|
||||
let settings: Settings
|
||||
|
||||
init() {
|
||||
model = WordAX()
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "dd/MM/YYYY"
|
||||
self.settings = Settings(dateFormatter: dateFormatter)
|
||||
}
|
||||
|
||||
public var flashcards: [Flashcard] {
|
||||
DataController.shared.getAllFlashcards()
|
||||
struct Settings {
|
||||
var dateFormatter: DateFormatter
|
||||
}
|
||||
|
||||
public func getFlashcards(moc: DataController) -> [Flashcard] {
|
||||
moc.getAllFlashcards()
|
||||
}
|
||||
|
||||
public func getDateFormatter() -> DateFormatter {
|
||||
model.settings.dateFormatter
|
||||
self.settings.dateFormatter
|
||||
}
|
||||
|
||||
public func getFlashCardsToDisplay() -> Flashcard? {
|
||||
let flashcards = self.flashcards
|
||||
|
||||
if flashcards.count > 0 {
|
||||
let notShownFlashCards = flashcards.filter({!$0.shown})
|
||||
if notShownFlashCards.count == 0 {
|
||||
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)
|
||||
public func ankiButtonClicked(flashcardId: UUID, milestone: Flashcard.SpacedRepetitionMilestoneEnum?, moc: DataController) {
|
||||
moc.setSpacedRepetitionMilestone(flashcardId: flashcardId, milestone: milestone)
|
||||
moc.flashcardShown(flashcardId: flashcardId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,11 +65,11 @@ extension Date {
|
||||
return selfDate.year! < paramDate.year! || selfDate.month! < paramDate.month! || selfDate.day! < paramDate.day!
|
||||
}
|
||||
|
||||
func addFrequency(frequency: WordAX.FrequencyEnum) -> Date {
|
||||
self.addingTimeInterval(TimeInterval(frequency.rawValue * 24 * 60 * 60))
|
||||
}
|
||||
// func addFrequency(frequency: WordAX.FrequencyEnum) -> Date {
|
||||
// self.addingTimeInterval(TimeInterval(frequency.rawValue * 24 * 60 * 60))
|
||||
// }
|
||||
|
||||
func addSpacedRepetitionMilestone(milestone: WordAX.SpacedRepetitionMilestoneEnum?) -> Date {
|
||||
func addSpacedRepetitionMilestone(milestone: Flashcard.SpacedRepetitionMilestoneEnum?) -> Date {
|
||||
if milestone == nil {
|
||||
return self
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user