Flash Cards now used stored lesson information

This commit is contained in:
Avery Pace 2021-11-09 13:17:22 -05:00
parent 287c9fb8ac
commit 1c928fa876
7 changed files with 151 additions and 42 deletions

View File

@ -19,6 +19,7 @@
7E716B4027398ABD009E2CF6 /* toki-lessons.json in Resources */ = {isa = PBXBuildFile; fileRef = 7E716B3F27398ABD009E2CF6 /* toki-lessons.json */; };
7E716B4227398CDF009E2CF6 /* FlashCardLessonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E716B4127398CDF009E2CF6 /* FlashCardLessonsView.swift */; };
7E716B4427398D3D009E2CF6 /* FlashCardLessonsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E716B4327398D3D009E2CF6 /* FlashCardLessonsViewModel.swift */; };
7E716B462739B968009E2CF6 /* FlashCardLessonResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E716B452739B968009E2CF6 /* FlashCardLessonResultsView.swift */; };
7E71E6ED2735D70C007CFF72 /* FlashCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E71E6EC2735D70C007CFF72 /* FlashCardView.swift */; };
7E71E6F12736DAE4007CFF72 /* FlashCardsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E71E6F02736DAE4007CFF72 /* FlashCardsViewModel.swift */; };
7E943A21273211C200E7DDF4 /* Toki_TrainerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E943A20273211C200E7DDF4 /* Toki_TrainerApp.swift */; };
@ -43,6 +44,7 @@
7E716B3F27398ABD009E2CF6 /* toki-lessons.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "toki-lessons.json"; path = "../../../../../Desktop/toki-pona-dict-json/output/toki-lessons.json"; sourceTree = "<group>"; };
7E716B4127398CDF009E2CF6 /* FlashCardLessonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashCardLessonsView.swift; sourceTree = "<group>"; };
7E716B4327398D3D009E2CF6 /* FlashCardLessonsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashCardLessonsViewModel.swift; sourceTree = "<group>"; };
7E716B452739B968009E2CF6 /* FlashCardLessonResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashCardLessonResultsView.swift; sourceTree = "<group>"; };
7E71E6EC2735D70C007CFF72 /* FlashCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashCardView.swift; sourceTree = "<group>"; };
7E71E6F02736DAE4007CFF72 /* FlashCardsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashCardsViewModel.swift; sourceTree = "<group>"; };
7E943A1D273211C200E7DDF4 /* Toki Trainer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Toki Trainer.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -86,6 +88,7 @@
7E71E6EC2735D70C007CFF72 /* FlashCardView.swift */,
7EF546152737B8FA00537AE6 /* FlashCardResultsView.swift */,
7E716B4127398CDF009E2CF6 /* FlashCardLessonsView.swift */,
7E716B452739B968009E2CF6 /* FlashCardLessonResultsView.swift */,
);
path = Views;
sourceTree = "<group>";
@ -236,6 +239,7 @@
7E2811172733027F0063DC78 /* TokiDictionary.swift in Sources */,
7E71E6ED2735D70C007CFF72 /* FlashCardView.swift in Sources */,
7E943A21273211C200E7DDF4 /* Toki_TrainerApp.swift in Sources */,
7E716B462739B968009E2CF6 /* FlashCardLessonResultsView.swift in Sources */,
7E2811182733027F0063DC78 /* TokiJSONLoader.swift in Sources */,
7E716B3E273986E5009E2CF6 /* TokiLesson.swift in Sources */,
7E28112227330DD30063DC78 /* Constants.swift in Sources */,

View File

@ -39,4 +39,11 @@ struct K {
return request
}
static var getLessonAnswersFetchRequest: NSFetchRequest<LessonAnswer> {
let request: NSFetchRequest<LessonAnswer> = LessonAnswer.fetchRequest()
request.sortDescriptors = []
return request
}
}

View File

@ -8,8 +8,14 @@
<entity name="Item" representedClassName="Item" syncable="YES" codeGenerationType="class">
<attribute name="timestamp" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
</entity>
<entity name="LessonAnswer" representedClassName="LessonAnswer" syncable="YES" codeGenerationType="class">
<attribute name="correctCount" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="lesson" optional="YES" attributeType="String"/>
<attribute name="triesCount" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
</entity>
<elements>
<element name="FlashCardAnswer" positionX="-54" positionY="0" width="128" height="74"/>
<element name="Item" positionX="-63" positionY="-18" width="128" height="44"/>
<element name="LessonAnswer" positionX="-54" positionY="18" width="128" height="74"/>
</elements>
</model>

View File

@ -0,0 +1,20 @@
//
// FlashCardLessonsResultsView.swift
// Toki Trainer
//
// Created by Avery Ada Pace on 11/8/21.
//
import SwiftUI
struct FlashCardLessonsResultsView: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
struct FlashCardLessonsResultsView_Previews: PreviewProvider {
static var previews: some View {
FlashCardLessonsResultsView()
}
}

View File

@ -8,14 +8,76 @@
import SwiftUI
struct FlashCardLessonsView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(fetchRequest: K.getFlashCardAnswersFetchRequest) var answers: FetchedResults<FlashCardAnswer>
@FetchRequest(fetchRequest: K.getLessonAnswersFetchRequest) var lessonAnswers: FetchedResults<LessonAnswer>
@ObservedObject var flashCardLessonsVM = FlashCardLessonsViewModel()
@State private var lessonStatistics: [String: Double] = [:]
@State private var statisticsCalculated = false
func calculateStatistics(_ lesson: TokiLesson) {
for lessonAnswer in lessonAnswers {
if lessonAnswer.lesson == lesson.lesson {
self.lessonStatistics[lesson.lesson] = (Double(lessonAnswer.correctCount) / Double(lessonAnswer.triesCount) * 100)
}
}
self.statisticsCalculated = true
}
// func calculateStatistics(_ lesson: TokiLesson) {
// for answer in answers {
// wordStatistics[answer.word!] = (Double(answer.correctCount) / Double(answer.triesCount)) * 100
// }
//
//
// for word in lesson.words {
// buildLessonStatistics[lesson.lesson] = []
// buildLessonStatistics[lesson.lesson]?.append(wordStatistics[word.word]!)
// }
//
// for (key, value) in buildLessonStatistics {
// let sumArray = value.reduce(0, +)
// let avgArrayValue = sumArray / Double(value.count)
// lessonStatistics[key] = avgArrayValue
// }
//
//
//// for word in lesson.words {
//// for answer in answers {
//// if answer.word == word.word {
//// lessonStatistics[lesson.lesson] = (Double(answer.correctCount) / Double(answer.triesCount)) * 100
//// }
//// }
//// }
// self.statisticsCalculated = true
// }
func calculateBackgroundColor(_ percent: Double) -> Color {
if percent >= 80 {
return Color.green
} else if percent >= 40 {
return Color.yellow
} else {
return Color.red
}
}
var body: some View {
NavigationView {
List(flashCardLessonsVM.lessons, id: \.lesson) { lesson in
NavigationLink(destination: FlashCardView(lesson.words)) {
NavigationLink(destination: FlashCardView(lesson: lesson.lesson, passedDictionary: lesson.words)) {
Text(lesson.lesson)
.bold()
.onAppear {
calculateStatistics(lesson)
}
Spacer()
if statisticsCalculated && lessonStatistics[lesson.lesson] != 0.0 && lessonStatistics[lesson.lesson] != nil {
Text("\(String(format: "%.0f", lessonStatistics[lesson.lesson]!)) %")
.multilineTextAlignment(.leading)
}
}
}
.navigationBarTitle("Lessons")

View File

@ -16,7 +16,6 @@ struct FlashCardResultsView: View {
@State private var wordStatistics: [String: Double] = [:]
@State private var sortedWordStatistics: [(String, Double)] = []
@State private var statistics = 0.0
func calculateStatistics() {
for answer in answers {
@ -38,7 +37,6 @@ struct FlashCardResultsView: View {
} else {
return Color.red
}
}
@ -57,13 +55,6 @@ struct FlashCardResultsView: View {
}
}
extension Double {
func formatAsPercent(places: Int) -> String {
let formattedValue = String(format: "%.2f", self)
return formattedValue
}
}
struct FlashCardResultView_Previews: PreviewProvider {
static var previews: some View {
FlashCardResultsView()

View File

@ -18,30 +18,28 @@ struct FlashCardView: View {
@ObservedObject var flashCardsViewModel = FlashCardsViewModel()
@State var dictionary: [TokiDictEntry]?
@State var currentLesson: String
@State var dictionary: [TokiDictEntry]
init(_ passedDictionary: [TokiDictEntry]?) {
if passedDictionary != nil {
if let safePassedDictionary = passedDictionary {
self.dictionary = safePassedDictionary
}
}
init(lesson: String, passedDictionary: [TokiDictEntry]) {
self.dictionary = passedDictionary
currentLesson = lesson
}
var body: some View {
VStack {
FlashCardStack(dictionary: getDictionary())
FlashCardStack(currentLesson: currentLesson, dictionary: dictionary)
}
}
func getDictionary() -> [TokiDictEntry] {
if dictionary != nil {
dictionary?.shuffle()
return dictionary ?? []
} else {
return flashCardsViewModel.randomDictionary
}
}
// func getDictionary() -> [TokiDictEntry] {
// if dictionary != nil {
// dictionary?.shuffle()
// return dictionary ?? []
// } else {
// return flashCardsViewModel.randomDictionary
// }
// }
}
extension Binding {
@ -59,7 +57,9 @@ struct FlashCardStack: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(fetchRequest: K.getFlashCardAnswersFetchRequest) var flashCardAnswers: FetchedResults<FlashCardAnswer>
@FetchRequest(fetchRequest: K.getLessonAnswersFetchRequest) var lessonAnswers: FetchedResults<LessonAnswer>
var currentLesson: String
var dictionary: [TokiDictEntry]
@State private var flashCards: [FlashCard] = []
@State private var topFlashCard: FlashCard? = nil
@ -135,6 +135,28 @@ struct FlashCardStack: View {
}
}
var lessonInDatabase = false
for lessonAnswer in lessonAnswers {
if lessonAnswer.lesson == currentLesson {
lessonInDatabase = true
lessonAnswer.setValue((lessonAnswer.triesCount + 1), forKey: "triesCount")
if correct {
lessonAnswer.setValue((lessonAnswer.correctCount + 1), forKey: "correctCount")
}
print("lesson found in database")
}
}
if lessonInDatabase == false {
let lessonAnswer = LessonAnswer(context: viewContext)
lessonAnswer.lesson = currentLesson
lessonAnswer.triesCount = 1
if correct {
lessonAnswer.correctCount = 1
}
print("lesson not found in database")
}
if cardInDatabase == false {
let answer = FlashCardAnswer(context: viewContext)
answer.word = dictionary[currentFlashCard].word
@ -145,15 +167,6 @@ struct FlashCardStack: View {
print("answer not found in database")
}
// for answer in flashCardAnswers {
// if answer.word == dictionary[currentFlashCard].word {
// flashCardAnswer.word = answer.word
// flashCardAnswer.triesCount = answer.triesCount + 1
// if correct {
// flashCardAnswer.correctCount = answer.correctCount + 1
// }
// }
// }
try? viewContext.save()
}
@ -169,23 +182,27 @@ struct FlashCardStack: View {
}
func nextFlashCard() {
currentFlashCard += 1
if(currentFlashCard > 0 ) {
flashCardsVertOffset[currentFlashCard - 1] = -1000
flashCardsVertOffset[currentFlashCard] = -1000
if currentFlashCard == (flashCards.count - 1) {
return
}
currentFlashCard += 1
flashCardsVertOffset[currentFlashCard] = 50
flashCardsAreInteractive[currentFlashCard] = true
self.fadeOutOverlay = true
if flashCards.count - currentFlashCard >= 3 {
if ((flashCards.count - 1) - currentFlashCard) > 3 {
print("flashCards: \(flashCards.count)")
print("currentFlashCard: \(currentFlashCard)")
flashCardsVertOffset[currentFlashCard + 1] = 310
flashCardsVertOffset[currentFlashCard + 2] = 340
flashCardsVertOffset[currentFlashCard + 3] = 370
} else if flashCards.count - currentFlashCard == 2 {
} else if (flashCards.count - 1) - currentFlashCard > 2 {
flashCardsVertOffset[currentFlashCard + 1] = 310
flashCardsVertOffset[currentFlashCard + 2] = 340
} else if flashCards.count - currentFlashCard == 1 {
} else if (flashCards.count - 1) - currentFlashCard > 1 {
flashCardsVertOffset[currentFlashCard + 1] = 310
}
}
@ -317,7 +334,9 @@ struct CardFlipModifier: AnimatableModifier {
}
struct FlashCardView_Previews: PreviewProvider {
static var viewModel = TokiDictionaryViewModel()
static var previews: some View {
FlashCardView(nil).environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
FlashCardView(lesson: "Preview", passedDictionary: viewModel.dictionary).environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}