Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Stored TotalYield and TotalDuration sum in session
- struct SessionData {
- private(set) var totalYield: Double
- private(set) var totalDuration: Double
- init(totalYield: Double, totalDuration: Double) {
- self.totalYield = totalYield
- self.totalDuration = totalDuration
- }
- // update stored values
- // O(1)
- mutating func add(totalYield: Double, totalDuration: Double) {
- self.totalYield += totalYield
- self.totalDuration += totalDuration
- }
- }
- /// Stored SessionData for Animal splited by session number
- struct AnimalData {
- // dict: session number -> sessions datas (for this sesion id)
- private(set) var sessions: [Int: SessionData]
- private(set) var animalTotalYield: Double
- private(set) var animalTotalDuration: Double
- init(session: Int, totalYield: Double, totalDuration: Double) {
- self.sessions = [:]
- self.sessions[session] = SessionData(totalYield: totalYield, totalDuration: totalDuration)
- self.animalTotalYield = totalYield
- self.animalTotalDuration = totalDuration
- }
- // update with session data
- // O(1)
- mutating func addSessionData(session: Int, totalYield: Double, totalDuration: Double) {
- // check if session already exist
- if sessions[session] != nil {
- // if true update it
- sessions[session]?.add(totalYield: totalYield, totalDuration: totalDuration)
- } else {
- // if not create new one
- sessions[session] = SessionData(totalYield: totalYield, totalDuration: totalDuration)
- }
- animalTotalYield += totalYield
- animalTotalDuration += totalDuration
- }
- }
- /// Stored AnimalData for Day splited by animal id
- struct DayReports {
- // dict: animalId -> animals datas (for this animal id)
- private(set) var animalData: [String: AnimalData]
- init(animalId: String, totalYield: Double, totalDuration: Double, session: Int) {
- self.animalData = [:]
- self.animalData[animalId] = AnimalData(session: session, totalYield: totalYield, totalDuration: totalDuration)
- }
- // update with animal report's data
- // O(1)
- mutating func addAnimalData(animalId: String, totalYield: Double, totalDuration: Double, session: Int) {
- // check if animal aleardy exist
- if animalData[animalId] != nil {
- // if true udpdate it
- animalData[animalId]?.addSessionData(session: session, totalYield: totalYield, totalDuration: totalDuration)
- } else {
- // if not create new one
- animalData[animalId] = AnimalData(session: session, totalYield: totalYield, totalDuration: totalDuration)
- }
- }
- }
- // Stored DayReports splited by date in string format
- struct ReportsPerDays {
- // dict: dateString -> days datas (for this day)
- private(set) var daysReports: [String: DayReports]
- init() {
- daysReports = [:]
- }
- init(daysReports: [String: DayReports]) {
- self.daysReports = daysReports
- }
- // insert report in proper day
- // O(1)
- mutating func addReport(dateString: String, animalId: String, totalYield: Double, totalDuration: Double, session: Int) {
- // check if report's day already exist
- if daysReports[dateString] != nil {
- // if true udpdate it
- daysReports[dateString]?.addAnimalData(animalId: animalId, totalYield: totalYield, totalDuration: totalDuration, session: session)
- } else {
- // if not create new one
- daysReports[dateString] = DayReports(animalId: animalId, totalYield: totalYield, totalDuration: totalDuration, session: session)
- }
- }
- }
- /// Split reports per uniq Days, couting additional data (totalYield, totalDuration)
- /// O(n) where n - number of reports
- ///
- /// - Parameter reports: reports to split
- /// - Returns: reports splited per uniq Days
- func splitReportsByDays(_ reports: [Report]) -> ReportsPerDays {
- // init empty result, will be fulfilled in this function and returned at the end
- var result: ReportsPerDays = ReportsPerDays()
- // iterate over reports to build result
- reports.forEach { report in
- // extract useful data from report
- guard let animalId = report.cowID?.stringValue,
- let session = report.milkingSession as? Int,
- let totalYield = report.totalYield as? Double,
- let totalDuration = report.totalDuration as? Double else {
- print("Reports with invalid data will be skipped")
- return
- }
- let timestamp = report.startTimeTimestamp
- let dataString = Utilities.stringDateFromTimestamp(timestamp, dateFormat: "dd.MM.yy")
- // add report
- result.addReport(dateString: dataString, animalId: animalId, totalYield: totalYield, totalDuration: totalDuration, session: session)
- }
- // return result
- return result
- }
- /// Filter Correct-Days
- /// Correct-Day, Day where exist al least one Animal where:
- /// - animal contains at least two sessions
- /// - sum of Total Yield for every sessions is greater than 500g
- /// O(d * a * s) where d - number of days, a - number of animals s - number of session in day
- ///
- /// if you provide data from `func splitReportsByDays(_ reports: [Report])`
- /// you can assume that every day, animal and session is uniq in this datasource so O(d + a + s)
- ///
- /// - Parameter reportsSplitedPerDeys: all days with reports
- /// - Returns: Correct-Datys with reports
- func filterCorrectDays(from reportsSplitedPerDays: ReportsPerDays) -> ReportsPerDays {
- // it will be store all Correct-Days
- // dict: dateString -> days datas (for this day)
- let correctDaysReports: [String: DayReports] = reportsSplitedPerDays.daysReports.filter { (_, dayReports: DayReports) in
- // count correct animals in day
- let numberOfCorrectAnimalsInDay: Int = dayReports.animalData.values.reduce(0) { counter, sessionsDatas in
- // count correct sessions for animal
- let numberOfCorrectSessionForAnimal: Int = sessionsDatas.sessions.values.reduce(0) { counter, sessionData in
- // session is correct when total yield is greater than 500g, if true increment counter
- return sessionData.totalYield > 500 ? counter + 1 : counter
- }
- // animal is correct if contains at least two correct sessions
- return numberOfCorrectSessionForAnimal >= 2 ? counter + 1 : counter
- }
- // day is correct when contains at least one correct animal
- return numberOfCorrectAnimalsInDay > 0
- }
- // return result
- return ReportsPerDays(daysReports: correctDaysReports)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement