Advertisement
Guest User

Untitled

a guest
Jun 19th, 2018
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 7.46 KB | None | 0 0
  1.     /// Stored TotalYield and TotalDuration sum in session
  2.     struct SessionData {
  3.        
  4.         private(set) var totalYield: Double
  5.         private(set) var totalDuration: Double
  6.        
  7.         init(totalYield: Double, totalDuration: Double) {
  8.             self.totalYield = totalYield
  9.             self.totalDuration = totalDuration
  10.         }
  11.        
  12.         // update stored values
  13.         // O(1)
  14.         mutating func add(totalYield: Double, totalDuration: Double) {
  15.             self.totalYield += totalYield
  16.             self.totalDuration += totalDuration
  17.         }
  18.     }
  19.    
  20.     /// Stored SessionData for Animal splited by session number
  21.     struct AnimalData {
  22.        
  23.         // dict: session number -> sessions datas (for this sesion id)
  24.         private(set) var sessions: [Int: SessionData]
  25.         private(set) var animalTotalYield: Double
  26.         private(set) var animalTotalDuration: Double
  27.        
  28.         init(session: Int, totalYield: Double, totalDuration: Double) {
  29.             self.sessions = [:]
  30.             self.sessions[session] = SessionData(totalYield: totalYield, totalDuration: totalDuration)
  31.             self.animalTotalYield = totalYield
  32.             self.animalTotalDuration = totalDuration
  33.         }
  34.        
  35.         // update with session data
  36.         // O(1)
  37.         mutating func addSessionData(session: Int, totalYield: Double, totalDuration: Double) {
  38.             // check if session already exist
  39.             if sessions[session] != nil {
  40.                 // if true update it
  41.                 sessions[session]?.add(totalYield: totalYield, totalDuration: totalDuration)
  42.             } else {
  43.                 // if not create new one
  44.                 sessions[session] = SessionData(totalYield: totalYield, totalDuration: totalDuration)
  45.             }
  46.            
  47.             animalTotalYield += totalYield
  48.             animalTotalDuration += totalDuration
  49.         }
  50.     }
  51.    
  52.     /// Stored AnimalData for Day splited by animal id
  53.     struct DayReports {
  54.        
  55.         // dict: animalId -> animals datas (for this animal id)
  56.         private(set) var animalData: [String: AnimalData]
  57.        
  58.         init(animalId: String, totalYield: Double, totalDuration: Double, session: Int) {
  59.             self.animalData = [:]
  60.             self.animalData[animalId] = AnimalData(session: session, totalYield: totalYield, totalDuration: totalDuration)
  61.         }
  62.        
  63.         // update with animal report's data
  64.         // O(1)
  65.         mutating func addAnimalData(animalId: String, totalYield: Double, totalDuration: Double, session: Int) {
  66.             // check if animal aleardy exist
  67.             if animalData[animalId] != nil {
  68.                 // if true udpdate it
  69.                 animalData[animalId]?.addSessionData(session: session, totalYield: totalYield, totalDuration: totalDuration)
  70.             } else {
  71.                 // if not create new one
  72.                 animalData[animalId] = AnimalData(session: session, totalYield: totalYield, totalDuration: totalDuration)
  73.             }
  74.         }
  75.     }
  76.    
  77.     // Stored DayReports splited by date in string format
  78.     struct ReportsPerDays {
  79.        
  80.         // dict: dateString -> days datas (for this day)
  81.         private(set) var daysReports: [String: DayReports]
  82.        
  83.         init() {
  84.             daysReports = [:]
  85.         }
  86.        
  87.         init(daysReports: [String: DayReports]) {
  88.             self.daysReports = daysReports
  89.         }
  90.        
  91.         // insert report in proper day
  92.         // O(1)
  93.         mutating func addReport(dateString: String, animalId: String, totalYield: Double, totalDuration: Double, session: Int) {
  94.             // check if report's day already exist
  95.             if daysReports[dateString] != nil {
  96.                 // if true udpdate it
  97.                 daysReports[dateString]?.addAnimalData(animalId: animalId, totalYield: totalYield, totalDuration: totalDuration, session: session)
  98.             } else {
  99.                 // if not create new one
  100.                 daysReports[dateString] = DayReports(animalId: animalId, totalYield: totalYield, totalDuration: totalDuration, session: session)
  101.             }
  102.         }
  103.     }
  104.    
  105.     /// Split reports per uniq Days, couting additional data (totalYield, totalDuration)
  106.     /// O(n) where n - number of reports
  107.     ///
  108.     /// - Parameter reports: reports to split
  109.     /// - Returns: reports splited per uniq Days
  110.     func splitReportsByDays(_ reports: [Report]) -> ReportsPerDays {
  111.         // init empty result, will be fulfilled in this function and returned at the end
  112.         var result: ReportsPerDays = ReportsPerDays()
  113.        
  114.         // iterate over reports to build result
  115.         reports.forEach { report in
  116.             // extract useful data from report
  117.             guard let animalId = report.cowID?.stringValue,
  118.                 let session = report.milkingSession as? Int,
  119.                 let totalYield = report.totalYield as? Double,
  120.                 let totalDuration = report.totalDuration as? Double else {
  121.                
  122.                 print("Reports with invalid data will be skipped")
  123.                 return
  124.             }
  125.             let timestamp = report.startTimeTimestamp
  126.             let dataString = Utilities.stringDateFromTimestamp(timestamp, dateFormat: "dd.MM.yy")
  127.            
  128.             // add report
  129.             result.addReport(dateString: dataString, animalId: animalId, totalYield: totalYield, totalDuration: totalDuration, session: session)
  130.         }
  131.        
  132.         // return result
  133.         return result
  134.     }
  135.    
  136.     /// Filter Correct-Days
  137.     /// Correct-Day, Day where exist al least one Animal where:
  138.     ///     - animal contains at least two sessions
  139.     ///     - sum of Total Yield for every sessions is greater than 500g
  140.     /// O(d * a * s) where d - number of days, a - number of animals s - number of session in day
  141.     ///
  142.     /// if you provide data from `func splitReportsByDays(_ reports: [Report])`
  143.     /// you can assume that every day, animal and session is uniq in this datasource so O(d + a + s)
  144.     ///
  145.     /// - Parameter reportsSplitedPerDeys: all days with reports
  146.     /// - Returns: Correct-Datys with reports
  147.     func filterCorrectDays(from reportsSplitedPerDays: ReportsPerDays) -> ReportsPerDays {
  148.         // it will be store all Correct-Days
  149.         // dict: dateString -> days datas (for this day)
  150.         let correctDaysReports: [String: DayReports] = reportsSplitedPerDays.daysReports.filter { (_, dayReports: DayReports) in
  151.             // count correct animals in day
  152.             let numberOfCorrectAnimalsInDay: Int = dayReports.animalData.values.reduce(0) { counter, sessionsDatas in
  153.                 // count correct sessions for animal
  154.                 let numberOfCorrectSessionForAnimal: Int = sessionsDatas.sessions.values.reduce(0) { counter, sessionData in
  155.                     // session is correct when total yield is greater than 500g, if true increment counter
  156.                     return sessionData.totalYield > 500 ? counter + 1 : counter
  157.                 }
  158.                
  159.                 // animal is correct if contains at least two correct sessions
  160.                 return numberOfCorrectSessionForAnimal >= 2 ? counter + 1 : counter
  161.             }
  162.            
  163.             // day is correct when contains at least one correct animal
  164.             return numberOfCorrectAnimalsInDay > 0
  165.         }
  166.        
  167.         // return result
  168.         return ReportsPerDays(daysReports: correctDaysReports)
  169.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement