diff --git a/Graduator/Graduator.xcodeproj/project.pbxproj b/Graduator/Graduator.xcodeproj/project.pbxproj index 8c3656d..2041f39 100644 --- a/Graduator/Graduator.xcodeproj/project.pbxproj +++ b/Graduator/Graduator.xcodeproj/project.pbxproj @@ -20,6 +20,8 @@ EC242B8A2A1FCECA006FE760 /* AverageBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC242B892A1FCECA006FE760 /* AverageBlockView.swift */; }; EC5FE5A52A20882F0028AA5F /* Formatters.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5FE5A42A20882F0028AA5F /* Formatters.swift */; }; EC8BAD162A3465230062226B /* UnitsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8BAD152A3465230062226B /* UnitsStore.swift */; }; + EC8BAD1A2A34BC170062226B /* WeightedGrade.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8BAD192A34BC170062226B /* WeightedGrade.swift */; }; + EC8BAD1C2A34BE4C0062226B /* WeightedAverageCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8BAD1B2A34BE4C0062226B /* WeightedAverageCalculator.swift */; }; ECB2FFCE2A23C4A700FF9F91 /* SubjectFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB2FFCD2A23C4A700FF9F91 /* SubjectFormView.swift */; }; ECB2FFD02A23C4B700FF9F91 /* SubjectFormVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB2FFCF2A23C4B700FF9F91 /* SubjectFormVM.swift */; }; ECC581D22A1D085B006C55EF /* GraduatorApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECC581D12A1D085B006C55EF /* GraduatorApp.swift */; }; @@ -43,6 +45,8 @@ EC242B892A1FCECA006FE760 /* AverageBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AverageBlockView.swift; sourceTree = ""; }; EC5FE5A42A20882F0028AA5F /* Formatters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Formatters.swift; sourceTree = ""; }; EC8BAD152A3465230062226B /* UnitsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsStore.swift; sourceTree = ""; }; + EC8BAD192A34BC170062226B /* WeightedGrade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeightedGrade.swift; sourceTree = ""; }; + EC8BAD1B2A34BE4C0062226B /* WeightedAverageCalculator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeightedAverageCalculator.swift; sourceTree = ""; }; ECB2FFCD2A23C4A700FF9F91 /* SubjectFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubjectFormView.swift; sourceTree = ""; }; ECB2FFCF2A23C4B700FF9F91 /* SubjectFormVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubjectFormVM.swift; sourceTree = ""; }; ECC581CE2A1D085B006C55EF /* Graduator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Graduator.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -183,6 +187,8 @@ EC242B6B2A1F81AE006FE760 /* Subject.swift */, EC242B692A1F8189006FE760 /* Unit.swift */, EC242B6D2A1F81CC006FE760 /* UnitsManager.swift */, + EC8BAD192A34BC170062226B /* WeightedGrade.swift */, + EC8BAD1B2A34BE4C0062226B /* WeightedAverageCalculator.swift */, ); path = Model; sourceTree = ""; @@ -265,6 +271,8 @@ EC8BAD162A3465230062226B /* UnitsStore.swift in Sources */, EC242B7F2A1F83BF006FE760 /* UnitsManagerVM.swift in Sources */, EC242B7B2A1F838C006FE760 /* UnitViewCell.swift in Sources */, + EC8BAD1C2A34BE4C0062226B /* WeightedAverageCalculator.swift in Sources */, + EC8BAD1A2A34BC170062226B /* WeightedGrade.swift in Sources */, EC242B6C2A1F81AE006FE760 /* Subject.swift in Sources */, EC242B8A2A1FCECA006FE760 /* AverageBlockView.swift in Sources */, ECB2FFD02A23C4B700FF9F91 /* SubjectFormVM.swift in Sources */, diff --git a/Graduator/Graduator/Model/Subject.swift b/Graduator/Graduator/Model/Subject.swift index e80cdae..49d21eb 100644 --- a/Graduator/Graduator/Model/Subject.swift +++ b/Graduator/Graduator/Model/Subject.swift @@ -7,7 +7,7 @@ import Foundation -struct Subject : Identifiable, Codable { +struct Subject : Identifiable, Codable, WeightedGrade { let id: UUID var name: String var weight: Int diff --git a/Graduator/Graduator/Model/Unit.swift b/Graduator/Graduator/Model/Unit.swift index 1a1b3d3..445bf2c 100644 --- a/Graduator/Graduator/Model/Unit.swift +++ b/Graduator/Graduator/Model/Unit.swift @@ -7,28 +7,16 @@ import Foundation -struct Unit : Identifiable, Codable { +struct Unit : Identifiable, Codable, WeightedGrade { let id: UUID var name: String var weight: Int + var grade: Double? { getAverage() } var isProfessional: Bool var code: Int var subjects: [Subject] - // FIXME DRY func getAverage() -> Double? { - var totalWeight = 0 - var weightedSum = 0.0 - - for subject in subjects { - if let grade = subject.grade { - totalWeight += subject.weight - weightedSum += grade * Double(subject.weight) - } - } - - guard totalWeight > 0 else { return nil } - - return weightedSum / Double(totalWeight) + return WeightedAverageCalculator.average(elements: subjects) } } diff --git a/Graduator/Graduator/Model/UnitsManager.swift b/Graduator/Graduator/Model/UnitsManager.swift index fac8c28..fe2876f 100644 --- a/Graduator/Graduator/Model/UnitsManager.swift +++ b/Graduator/Graduator/Model/UnitsManager.swift @@ -36,27 +36,11 @@ struct UnitsManager { } func getTotalAverage() -> Double? { - return getAverage(units: units) + return WeightedAverageCalculator.average(elements: units) } func getProfessionalAverage() -> Double? { - return getAverage(units: units.filter { $0.isProfessional }) - } - - // FIXME DRY - func getAverage(units: [Unit]) -> Double? { - var totalWeight = 0 - var weightedSum = 0.0 - - for unit in units { - if let grade = unit.getAverage() { - totalWeight += unit.weight - weightedSum += grade * Double(unit.weight) - } - } - - guard totalWeight > 0 else { return nil } - - return weightedSum / Double(totalWeight) + let professionalUnits = units.filter { $0.isProfessional } + return WeightedAverageCalculator.average(elements: professionalUnits) } } diff --git a/Graduator/Graduator/Model/WeightedAverageCalculator.swift b/Graduator/Graduator/Model/WeightedAverageCalculator.swift new file mode 100644 index 0000000..7ec2a1f --- /dev/null +++ b/Graduator/Graduator/Model/WeightedAverageCalculator.swift @@ -0,0 +1,26 @@ +// +// WeightedAverageCalculator.swift +// Graduator +// +// Created by etudiant on 2023-06-10. +// + +import Foundation + +struct WeightedAverageCalculator { + static func average(elements: [T]) -> Double? { + var totalWeight = 0 + var weightedSum = 0.0 + + for element in elements { + if let grade = element.grade { + totalWeight += element.weight + weightedSum += grade * Double(element.weight) + } + } + + guard totalWeight > 0 else { return nil } + + return weightedSum / Double(totalWeight) + } +} diff --git a/Graduator/Graduator/Model/WeightedGrade.swift b/Graduator/Graduator/Model/WeightedGrade.swift new file mode 100644 index 0000000..8d805c3 --- /dev/null +++ b/Graduator/Graduator/Model/WeightedGrade.swift @@ -0,0 +1,13 @@ +// +// WeightedGrade.swift +// Graduator +// +// Created by etudiant on 2023-06-10. +// + +import Foundation + +protocol WeightedGrade { + var weight: Int { get } + var grade: Double? { get } +}