ForFarm/backend/internal/services/analytics_service.go

129 lines
3.5 KiB
Go

package services
import (
"math/rand"
"time"
"github.com/forfarm/backend/internal/domain"
)
type AnalyticsService struct {
}
func NewAnalyticsService() *AnalyticsService {
return &AnalyticsService{}
}
func (s *AnalyticsService) CalculatePlantHealth(status string, growthStage string) string {
switch status {
case "Problem", "Diseased", "Infested":
return "warning"
case "Fallow", "Harvested":
return "n/a"
default:
// 20% chance of warning even if status is 'growing'
if rand.Intn(10) < 2 {
return "warning"
}
return "good"
}
}
func (s *AnalyticsService) SuggestNextAction(growthStage string, lastUpdated time.Time) (action *string, dueDate *time.Time) {
nextActionStr := "Monitor crop health"
nextDueDate := time.Now().Add(24 * time.Hour)
switch growthStage {
case "Planned", "Planting":
nextActionStr = "Prepare soil and planting"
nextDueDate = time.Now().Add(12 * time.Hour)
case "Germination", "Seedling":
nextActionStr = "Check for germination success and early pests"
nextDueDate = time.Now().Add(48 * time.Hour)
case "Vegetative":
nextActionStr = "Monitor growth and apply nutrients if needed"
nextDueDate = time.Now().Add(72 * time.Hour)
case "Flowering", "Budding":
nextActionStr = "Check pollination and manage pests/diseases"
nextDueDate = time.Now().Add(48 * time.Hour)
case "Fruiting", "Ripening":
nextActionStr = "Monitor fruit development and prepare for harvest"
nextDueDate = time.Now().Add(7 * 24 * time.Hour)
case "Harvesting":
nextActionStr = "Proceed with harvest"
nextDueDate = time.Now().Add(24 * time.Hour)
}
// Only suggest if due date is >1hr after last update
if nextDueDate.After(lastUpdated.Add(1 * time.Hour)) {
return &nextActionStr, &nextDueDate
}
return nil, nil
}
func (s *AnalyticsService) GetNutrientLevels(cropID string) *struct {
Nitrogen *float64 `json:"nitrogen,omitempty"`
Phosphorus *float64 `json:"phosphorus,omitempty"`
Potassium *float64 `json:"potassium,omitempty"`
} {
// 70% chance of having dummy data
if rand.Intn(10) < 7 {
n := float64(50 + rand.Intn(40)) // 50-89
p := float64(40 + rand.Intn(40)) // 40-79
k := float64(45 + rand.Intn(40)) // 45-84
return &struct {
Nitrogen *float64 `json:"nitrogen,omitempty"`
Phosphorus *float64 `json:"phosphorus,omitempty"`
Potassium *float64 `json:"potassium,omitempty"`
}{
Nitrogen: &n,
Phosphorus: &p,
Potassium: &k,
}
}
return nil
}
func (s *AnalyticsService) GetEnvironmentalData(farmAnalytics *domain.FarmAnalytics) (temp, humidity, wind, rain, sunlight, soilMoisture *float64) {
temp, humidity, wind, rain, sunlight, soilMoisture = nil, nil, nil, nil, nil, nil
if farmAnalytics != nil && farmAnalytics.Weather != nil {
temp = farmAnalytics.Weather.TempCelsius
humidity = farmAnalytics.Weather.Humidity
wind = farmAnalytics.Weather.WindSpeed
rain = farmAnalytics.Weather.RainVolume1h
}
// Provide dummy values only if data is missing
if temp == nil {
t := float64(18 + rand.Intn(15)) // 18-32 C
temp = &t
}
if humidity == nil {
h := float64(40 + rand.Intn(50)) // 40-89 %
humidity = &h
}
if wind == nil {
w := float64(rand.Intn(15)) // 0-14 m/s
wind = &w
}
if rain == nil {
r := 0.0
if rand.Intn(10) < 2 { // 20% chance of rain
r = float64(rand.Intn(5)) // 0-4 mm
}
rain = &r
}
if sunlight == nil {
sl := float64(60 + rand.Intn(40)) // 60-99 %
sunlight = &sl
}
if soilMoisture == nil {
sm := float64(30 + rand.Intn(50)) // 30-79 %
soilMoisture = &sm
}
return
}