0

I'm working on a sport analytic platform,I'm using Laravel framework . I have a WORKOUT table as follows

| workoutDay |TSS|    
| ---------- |---|    
| 2020-10-01 | 20|  
| 2020-10-10 | 50|
| 2020-10-15 | 30|

so we will have an array from select query :

 $tssData=  [
     [2020-10-01,20],
     [2020-10-10,50],
     [2020-10-15,30],
    ]

I also have a formula for calculating athlete's fitness which is recursive

 $count = count($tssData);
        $fitness[] = 0;
        $result= [];
        for ($i = 1; $i < $count + 1; $i++) {
            $result[] = [
                $workoutDay[] = $tssData[$i - 1][0],
                $fitness[] = $fitness[$i - 1] + (($tssData[$i - 1][1] - $fitness[$i - 1]) / 7),

        }
        return $result;
    }

I need to calculate the fitness for everyday in a row even for those date which are not available in the table
I think if we can fill the array with the missed date it works but how :

$tssData=  [
     [2020-10-01,20],
     [2020-10-02,0],
     [2020-10-03,0],
     ... ,
     [2020-10-10,50],
     [2020-10-11,0],
     [2020-10-12,0],
     [2020-10-13,0],
     .... ,
     [2020-10-15,30],
    ]

and I don't think it would be a proper solution to add all days one after one in the db table with 0 TSS.

Ehsan Pro
  • 15
  • 3
  • The logic would be the following: take the min and max date from your table data, create a [`DatePeriod`](https://www.php.net/manual/en/class.dateperiod.php), iterate the period and search for the current date in the loop inside your data array. If found, use the data, if not, use a zero. – El_Vanja Feb 25 '21 at 10:17
  • A small point of clarification: by current date I mean the date of the current iteration in the loop. – El_Vanja Feb 25 '21 at 10:24
  • You could generate your complete list of dates in the SQL including the TSS value for the dates it applies to. https://stackoverflow.com/questions/2157282/generate-days-from-date-range – Mark B Feb 25 '21 at 10:55
  • Loop over `$tssData` and create new proper array (lets call it `$arrNew`) for accessing with form `'date' => 'value'` (your first entry would be `'2020-10-01' => '20'`). [Use already existing code to loop through dates, dont reinvent the wheel](https://stackoverflow.com/questions/3207749/i-have-2-dates-in-php-how-can-i-run-a-foreach-loop-to-go-through-all-of-those-d). While looping through dates, check if `isset($arrNew['currentDateInLoop'])` if so use the present value otherwise use 0. – Definitely not Rafal Feb 25 '21 at 11:05
  • @definitely-not-rafal thanks guys for your solutions ,so I used DatePeriod but I optimized it with Laravel collection merging instead of comparing one by one because of speed, I will send the answer and please response your feedback – Ehsan Pro Feb 25 '21 at 20:54

1 Answers1

0

Thanks guys for your solutions I created the target array and fixed it by using CarbonPeriod and Laravel Collection merging as followings:

        // Fetch workouts
        $tssData = Workout::select('workoutDay', 'tss')->get();
        
        //changing the data to Key:value
        $sumTss = $tssData->groupBy('workoutDay')->map(function ($item) {
            return $item[0]['tss'];
        });

        // creating default array included the all missed dates  with zero value
        $date2 = new Carbon($tssData->last()->workoutDay);
        $date1 = new Carbon($tssData->first()->workoutDay);
        $period = CarbonPeriod::create($date1, $date2);
        foreach ($period as $date) {
            $p[$date->format('Y-m-d')] = 0;
        }

       // using collection merging for comparing and replacing quickly
        $tssData = collect($p)->merge(collect($sumTss))->toArray();
        return $tssData;
Ehsan Pro
  • 15
  • 3