functions/public/Calculate-RateOfGain.ps1
|
function Calculate-RateOfGain { <# .SYNOPSIS Calculates rate of gain between two weight records .DESCRIPTION Computes the Average Daily Gain (ADG) for an animal between two dates by finding the closest weight measurements and calculating the rate of weight increase. Returns total weight gain, days elapsed, and ADG in lbs/day. .PARAMETER CattleID Database ID of the cattle to analyze (required) .PARAMETER StartDate Beginning date for the calculation period (required). Uses the weight record closest to this date. .PARAMETER EndDate Ending date for the calculation period (required). Uses the weight record closest to this date. .OUTPUTS PSCustomObject with the following properties: - CattleID: ID of the animal - StartWeight: Weight at beginning of period (lbs) - EndWeight: Weight at end of period (lbs) - StartDate: Actual date of start weight measurement - EndDate: Actual date of end weight measurement - DaysOnFeed: Number of days between measurements - TotalWeightGain: Total pounds gained - AverageDailyGain: Weight gain per day (lbs/day) .EXAMPLE Calculate-RateOfGain -CattleID 5 -StartDate "2025-09-01" -EndDate "2025-12-01" Calculates 90-day rate of gain for cattle ID 5 .EXAMPLE $cattle = Get-AllCattle $cattle | ForEach-Object { Calculate-RateOfGain -CattleID $_.CattleID -StartDate (Get-Date).AddDays(-120) -EndDate (Get-Date) } Calculates 120-day ADG for all active cattle .NOTES Requires at least two weight records for the specified animal within the date range. The function finds the closest weight records to the specified dates, so exact matches are not required. #> param( [Parameter(Mandatory)] [int]$CattleID, [Parameter(Mandatory)] [DateTime]$StartDate, [Parameter(Mandatory)] [DateTime]$EndDate ) # Get the weight records closest to the specified dates # If start date is before all records, use the earliest weight # If end date is after all records, use the latest weight $startDateValue = ConvertTo-SqlValue -Value ($StartDate.ToString('yyyy-MM-dd')) $endDateValue = ConvertTo-SqlValue -Value ($EndDate.ToString('yyyy-MM-dd')) $startQuery = @" SELECT WeightRecordID, WeightDate, Weight FROM WeightRecords WHERE CattleID = $CattleID AND DATE(WeightDate) <= DATE($startDateValue) ORDER BY WeightDate DESC LIMIT 1 "@ # Fallback: get earliest weight if no weight found on or before start date $earliestQuery = @" SELECT WeightRecordID, WeightDate, Weight FROM WeightRecords WHERE CattleID = $CattleID ORDER BY WeightDate ASC LIMIT 1 "@ $endQuery = @" SELECT WeightRecordID, WeightDate, Weight FROM WeightRecords WHERE CattleID = $CattleID AND DATE(WeightDate) <= DATE($endDateValue) ORDER BY WeightDate DESC LIMIT 1 "@ # Try to get weight on or before start date $startRecord = Invoke-UniversalSQLiteQuery -Path $script:DatabasePath -Query $startQuery # If no weight found before/on start date, use the earliest available weight if (-not $startRecord) { $startRecord = Invoke-UniversalSQLiteQuery -Path $script:DatabasePath -Query $earliestQuery if ($startRecord) { Write-Verbose "No weight found on or before $(Format-Date $StartDate). Using earliest weight from $(Format-Date $startRecord.WeightDate)" } } $endRecord = Invoke-UniversalSQLiteQuery -Path $script:DatabasePath -Query $endQuery if (-not $startRecord -or -not $endRecord) { Write-Warning "Could not find weight records for the specified date range" return $null } # Parse dates from strings $startWeightDate = Parse-Date $startRecord.WeightDate $endWeightDate = Parse-Date $endRecord.WeightDate # Calculate metrics $weightGain = $endRecord.Weight - $startRecord.Weight $daysBetween = ($endWeightDate - $startWeightDate).Days if ($daysBetween -le 0) { Write-Warning "End date must be after start date" return $null } $avgDailyGain = $weightGain / $daysBetween # Save calculation - prepare values for SQL $startWeightRecordId = $startRecord.WeightRecordID $endWeightRecordId = $endRecord.WeightRecordID $startDateStr = ConvertTo-SqlValue -Value ($startWeightDate.ToString('yyyy-MM-dd HH:mm:ss')) $endDateStr = ConvertTo-SqlValue -Value ($endWeightDate.ToString('yyyy-MM-dd HH:mm:ss')) $startWeight = $startRecord.Weight $endWeight = $endRecord.Weight $saveQuery = @" INSERT INTO RateOfGainCalculations (CattleID, StartWeightRecordID, EndWeightRecordID, StartDate, EndDate, StartWeight, EndWeight, TotalWeightGain, DaysBetween, AverageDailyGain) VALUES ($CattleID, $startWeightRecordId, $endWeightRecordId, $startDateStr, $endDateStr, $startWeight, $endWeight, $weightGain, $daysBetween, $avgDailyGain) "@ Invoke-UniversalSQLiteQuery -Path $script:DatabasePath -Query $saveQuery # Return calculation results return [PSCustomObject]@{ CattleID = $CattleID StartDate = $startWeightDate EndDate = $endWeightDate StartWeight = $startRecord.Weight EndWeight = $endRecord.Weight TotalWeightGain = [Math]::Round($weightGain, 2) DaysBetween = $daysBetween AverageDailyGain = [Math]::Round($avgDailyGain, 4) MonthlyGain = [Math]::Round($avgDailyGain * 30, 2) } } |