//fitness and freshness func ff(user types.UserSettings, filter Filter) []types.Ff_data_point { user_id := user.Id ff_data := make([]types.Ff_data_point, 0) //activity day ff_scan_data := make([]types.Ff_data_point, 0) //all days in range var user_data types.Metrics var user_cpms types.CPMs var end_summary_json []byte var cp_data_json []byte var has_power, has_heart bool var activity_start time.Time var firstDate time.Time var firstIter = true var activity_id string cluster := gocql.NewCluster(config.DbHost) cluster.Keyspace = "joulepersecond" cluster.Consistency = gocql.Quorum session, _ := cluster.CreateSession() defer session.Close() var lastNotableCp float64 var thisCp int //get all of the user's data (at least all for now) TODO limit these queries by date if poss. iter := session.Query(`SELECT activity_start, activity_id, end_summary_json, has_power, has_heart FROM joulepersecond.user_activity WHERE user_id = ? ORDER BY activity_start ASC`, user_id).Iter() //loop through each activity for iter.Scan(&activity_start, &activity_id, &end_summary_json, &has_power, &has_heart) { iter := session.Query(`SELECT cp_data_json FROM joulepersecond.proc_activity WHERE activity_id = ? LIMIT 1`, activity_id).Iter() for iter.Scan(&cp_data_json) { json.Unmarshal(cp_data_json, &user_cpms) } if firstIter { firstDate = activity_start firstIter = false } var ff_data_point types.Ff_data_point //unmarshal the activtiy types.Metrics json.Unmarshal(end_summary_json, &user_data) //values for each scanned activity var user_tss int var perc_effort int var mot_level int //check for a tss override value session.Query(`SELECT activity_id, tss_value, motivation_level, perceived_effort FROM activity_meta WHERE activity_id = ?`, activity_id).Scan(&activity_id, &user_tss, &mot_level, &perc_effort) //get a value for tss whether from hr, power or (TODO user set) if user_tss > 0 { ff_data_point.Tss = user_tss } else { if has_power { ff_data_point.Tss = user_data.Tss } else if has_heart { ff_data_point.Tss = user_data.Etss } } if filter.S5 { thisCp = user_cpms.FiveSecondCP } else if filter.S20 { thisCp = user_cpms.TwentySecondCP } else if filter.S60 { thisCp = user_cpms.SixtySecondCP } else if filter.S300 { thisCp = user_cpms.FiveMinuteCP } else if filter.S1200 { thisCp = user_cpms.TwentyMinuteCP } else if filter.S3600 { thisCp = user_cpms.SixtyMinuteCP } if float64(thisCp) > lastNotableCp { lastNotableCp = float64(thisCp) ff_data_point.NotableCp = float64(thisCp) } else { lastNotableCp = lastNotableCp * float64(user.Ncp_rolloff) / 1000 //0.995 default } //get the date ff_data_point.Date = user_data.StartTime //add extended metrics ff_data_point.Meta.MotivationLevel = mot_level ff_data_point.Meta.PerceivedEffort = perc_effort //add date and tss to array slice ff_data = append(ff_data, ff_data_point) } if err := iter.Close(); err != nil { log.Fatal(err) } //calulate the number of days between first recorded activity and current date duration := time.Since(firstDate) //get total duration in time.Duration days := int(duration/day) + 1 //add one day to include current day //loop through each day. for i := 0; i <= days+30; i++ { //add 30 days to show roll off //create a var to hold a sample for each day scanned - it may or maynot contain an activity, but will still contain ctl, atl and tsb vals along with the date var scan_data_point types.Ff_data_point //get each day to be scanned (all days between first activity and current date) scanDate := firstDate.AddDate(0, 0, i) scan_data_point.Date = scanDate //get the date scanYear, scanMonth, scanDay := scanDate.Date() //get date elements that are easier to compare //these so we can print out UTC values to Highcharts scan_data_point.Day = scanDay scan_data_point.Month = int(scanMonth) - 1 //js months start at naught. scan_data_point.Year = scanYear //now get each of the days where we have an activity for _, val := range ff_data { actYear, actMonth, actDay := val.Date.Date() if actYear == scanYear && actMonth == scanMonth && actDay == scanDay { scan_data_point.Meta.PerceivedEffort = val.Meta.PerceivedEffort scan_data_point.Meta.MotivationLevel = val.Meta.MotivationLevel //these are the days where we have activites - add the TSS //we might have more than one activity in a day so append any others TSS on this day scan_data_point.Tss += val.Tss if val.NotableCp > 0 { scan_data_point.NotableCp = val.NotableCp scan_data_point.HasValue = true } else { scan_data_point.HasValue = false } } //else leave TSS as it is (0) } if i > 0 { //don't have a yesterday value on the first day scan_data_point.Atl = ff_scan_data[i-1].Atl + (float64(scan_data_point.Tss)-ff_scan_data[i-1].Atl)/float64(user.Atl_constant) scan_data_point.Ctl = ff_scan_data[i-1].Ctl + (float64(scan_data_point.Tss)-ff_scan_data[i-1].Ctl)/float64(user.Ctl_constant) scan_data_point.Tsb = scan_data_point.Ctl - scan_data_point.Atl //fmt.Printf("Atl: %v Ctl: %v Tsb: %v\n", scan_data_point.Atl, scan_data_point.Ctl, scan_data_point.Tsb) } //add the data to our array slice ff_scan_data = append(ff_scan_data, scan_data_point) } //OPTION (show reduced results) commenting out the follwing lines bypasses filter if len(ff_scan_data) > (filter.Historylen + 30) { ff_scan_data = ff_scan_data[len(ff_scan_data)-(filter.Historylen+30) : len(ff_scan_data)] } return ff_scan_data }
func current_ff(user types.UserSettings) types.Current_ff { user_id := user.Id ff_data := make([]types.Ff_data_point, 0) //activity day ff_scan_data := make([]types.Ff_data_point, 0) //all days in range var current_ff types.Current_ff var user_data types.Metrics var end_summary_json []byte var has_power, has_heart bool var activity_start time.Time var firstDate time.Time var firstIter = true var activity_id string var day = time.Hour * 24 timeNow := time.Now() var recentMonths = timeNow.AddDate(0, -6, 0) cluster := gocql.NewCluster(config.DbHost) cluster.Keyspace = "joulepersecond" cluster.Consistency = gocql.Quorum session, _ := cluster.CreateSession() defer session.Close() //get all of the user's data (at least all for now) TODO limit these queries by date if poss. iter := session.Query(`SELECT activity_start, activity_id, end_summary_json, has_power, has_heart FROM joulepersecond.user_activity WHERE user_id = ? AND activity_start > ? ORDER BY activity_start ASC`, user_id, recentMonths).Iter() //loop through each activity for iter.Scan(&activity_start, &activity_id, &end_summary_json, &has_power, &has_heart) { if firstIter { firstDate = activity_start firstIter = false } var ff_data_point types.Ff_data_point //unmarshal the activtiy metrics json.Unmarshal(end_summary_json, &user_data) //values for each scanned activity var user_tss int //check for a tss override value session.Query(`SELECT activity_id, tss_value FROM activity_meta WHERE activity_id = ?`, activity_id).Scan(&activity_id, &user_tss) //get a value for tss whether from hr, power or (TODO user set) if user_tss > 0 { ff_data_point.Tss = user_tss } else { if has_power { ff_data_point.Tss = user_data.Tss } else if has_heart { ff_data_point.Tss = user_data.Etss } } //get the date ff_data_point.Date = user_data.StartTime //add date and tss to array slice ff_data = append(ff_data, ff_data_point) } if err := iter.Close(); err != nil { fmt.Printf("%v\n", err) } //calulate the number of days between first recorded activity and current date duration := time.Since(firstDate) //get total duration in time.Duration days := int(duration/day) + 1 //add one day to include current day //loop through each day. for i := 0; i <= days+30; i++ { //create a var to hold a sample for each day scanned - it may or maynot contain an activity, but will still contain ctl, atl and tsb vals along with the date var scan_data_point types.Ff_data_point //get each day to be scanned (all days between first activity and current date) scanDate := firstDate.AddDate(0, 0, i) scan_data_point.Date = scanDate //get the date scanYear, scanMonth, scanDay := scanDate.Date() //get date elements that are easier to compare //now get each of the days where we have an activity for _, val := range ff_data { actYear, actMonth, actDay := val.Date.Date() if actYear == scanYear && actMonth == scanMonth && actDay == scanDay { //these are the days where we have activites - add the TSS //we might have more than one activity in a day so append any others TSS on this day scan_data_point.Tss += val.Tss } //else leave TSS as it is (0) } if i > 0 { //don't have a yesterday value on the first day scan_data_point.Atl = ff_scan_data[i-1].Atl + (float64(scan_data_point.Tss)-ff_scan_data[i-1].Atl)/float64(user.Atl_constant) scan_data_point.Ctl = ff_scan_data[i-1].Ctl + (float64(scan_data_point.Tss)-ff_scan_data[i-1].Ctl)/float64(user.Ctl_constant) scan_data_point.Tsb = scan_data_point.Ctl - scan_data_point.Atl } //save off today's fitness and freshness... timeNow := time.Now() if scanDate.Year() == timeNow.Year() && scanDate.Month() == timeNow.Month() && scanDate.Day() == timeNow.Day() { current_ff.Atl = int(scan_data_point.Atl) current_ff.Ctl = int(scan_data_point.Ctl) current_ff.Tsb = int(scan_data_point.Tsb) } //add the data to our array slice ff_scan_data = append(ff_scan_data, scan_data_point) } return current_ff }