@@ -47,7 +47,7 @@ class DiningAnalyticsViewModel: ObservableObject {
4747 Storage . remove ( DiningAnalyticsViewModel . swipeHistoryDirectory, from: . documents)
4848 }
4949 }
50- func refresh( ) {
50+ func refresh( ) async {
5151 guard let diningToken = KeychainAccessible . instance. getDiningToken ( ) else {
5252 return
5353 }
@@ -56,6 +56,7 @@ class DiningAnalyticsViewModel: ObservableObject {
5656 startDate = Calendar . current. date ( byAdding: . day, value: 1 , to: startDate) !
5757 }
5858 let startDateStr = formatter. string ( from: startDate)
59+ let planStartDateResult = await DiningAPI . instance. getDiningPlanStartDate ( diningToken: diningToken)
5960 DiningAPI . instance. getPastDiningBalances ( diningToken: diningToken, startDate: startDateStr) { ( balances) in
6061 guard let balances = balances else {
6162 return
@@ -76,19 +77,41 @@ class DiningAnalyticsViewModel: ObservableObject {
7677 let maxSwipeBalance = ( self . swipeHistory. max { $0. balance < $1. balance } ) else {
7778 return
7879 }
79- let dollarPredictions = self . getPredictions ( firstBalance: maxDollarBalance, lastBalance: lastDollarBalance)
80+ // If no dining plan found, refresh will return, these are just placeholders
81+ var startDollarBalance = maxDollarBalance
82+ var startSwipeBalance = maxSwipeBalance
83+ switch planStartDateResult {
84+ case . failure:
85+ return
86+ case . success( let planStartDate) :
87+ // If dining plan found, start prediction from the date dining plan started
88+ startDollarBalance = ( self . dollarHistory. first { $0. date == planStartDate } ) ?? startDollarBalance
89+ startSwipeBalance = ( self . swipeHistory. first { $0. date == planStartDate } ) ?? startSwipeBalance
90+ // However, it's possible that people recharged dining dollars (swipes maybe?), and if so, predict from this date (most recent increase)
91+ for (i, day) in self . dollarHistory. enumerated ( ) {
92+ if i != 0 && day. date > planStartDate && day. balance > self . dollarHistory [ i - 1 ] . balance {
93+ startDollarBalance = day
94+ }
95+ }
96+ for (i, day) in self . swipeHistory. enumerated ( ) {
97+ if i != 0 && day. date > planStartDate && day. balance > self . swipeHistory [ i - 1 ] . balance {
98+ startSwipeBalance = day
99+ }
100+ }
101+ }
102+ let dollarPredictions = self . getPredictions ( firstBalance: startDollarBalance, lastBalance: lastDollarBalance, maxBalance: maxDollarBalance)
80103 self . dollarSlope = dollarPredictions. slope
81104 self . dollarPredictedZeroDate = dollarPredictions. predictedZeroDate
82105 self . predictedDollarSemesterEndBalance = dollarPredictions. predictedEndBalance
83106 self . dollarAxisLabel = self . getAxisLabelsYX ( from: self . dollarHistory)
84- let swipePredictions = self . getPredictions ( firstBalance: maxSwipeBalance , lastBalance: lastSwipeBalance)
107+ let swipePredictions = self . getPredictions ( firstBalance: startSwipeBalance , lastBalance: lastSwipeBalance, maxBalance : maxSwipeBalance )
85108 self . swipeSlope = swipePredictions. slope
86109 self . swipesPredictedZeroDate = swipePredictions. predictedZeroDate
87110 self . predictedSwipesSemesterEndBalance = swipePredictions. predictedEndBalance
88111 self . swipeAxisLabel = self . getAxisLabelsYX ( from: self . swipeHistory)
89112 }
90113 }
91- func getPredictions( firstBalance: DiningAnalyticsBalance , lastBalance: DiningAnalyticsBalance ) -> ( slope: Double , predictedZeroDate: Date , predictedEndBalance: Double ) {
114+ func getPredictions( firstBalance: DiningAnalyticsBalance , lastBalance: DiningAnalyticsBalance , maxBalance : DiningAnalyticsBalance ) -> ( slope: Double , predictedZeroDate: Date , predictedEndBalance: Double ) {
92115 if firstBalance. date == lastBalance. date || firstBalance. balance == lastBalance. balance {
93116 let zeroDate = Calendar . current. date ( byAdding: . day, value: 1 , to: Date . endOfSemester) !
94117 return ( Double ( 0.0 ) , zeroDate, lastBalance. balance)
@@ -97,10 +120,11 @@ class DiningAnalyticsViewModel: ObservableObject {
97120 var slope = self . getSlope ( firstBalance: firstBalance, lastBalance: lastBalance)
98121 let zeroDate = self . predictZeroDate ( firstBalance: firstBalance, lastBalance: lastBalance, slope: slope)
99122 let endBalance = self . predictSemesterEndBalance ( firstBalance: firstBalance, lastBalance: lastBalance, slope: slope)
100- let fullSemester = firstBalance . date . distance ( to: Date . endOfSemester)
123+ let fullSemester = Date . startOfSemester . distance ( to: Date . endOfSemester)
101124 let fullZeroDistance = firstBalance. date. distance ( to: zeroDate)
102125 let deltaX = fullZeroDistance / fullSemester
103- slope = - 1 / deltaX // Resetting slope to different value for graph format
126+ let deltaY = firstBalance. balance / maxBalance. balance
127+ slope = - deltaY / deltaX // Resetting slope to different value for graph format
104128 return ( slope, zeroDate, endBalance)
105129 }
106130 }
0 commit comments