From a08b1cac0b288e01431ed7d82cc5a51aabca1b54 Mon Sep 17 00:00:00 2001
From: Tucker Siegel <tgsiegel@terpmail.umd.edu>
Date: Sat, 3 Dec 2022 13:22:45 -0500
Subject: [PATCH] confidence interval repeat years

---
 controllers/misc_controller.go          |  1 +
 models/confidence_interval.go           | 11 +++++++++++
 services/confidence_interval_service.go | 13 +++++++++++--
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/controllers/misc_controller.go b/controllers/misc_controller.go
index e9c4d70..9437775 100644
--- a/controllers/misc_controller.go
+++ b/controllers/misc_controller.go
@@ -53,6 +53,7 @@ func GetAnalogYear(c *fiber.Ctx) error {
 // @Param latitude query number true "Latitude to search for"
 // @Param longitude query number true "Longitude to search for"
 // @Param plantingDate query string true "Plant date, ISO8601 or RFC3339 format"
+// @Param repeatYears query number false "number of times to repeat the request. When included with planting date, will extrapolate plantingdate -> end of repeatYears range"
 // @Router /gdd/confidence [get]
 func GetConfidenceInterval(c *fiber.Ctx) error {
 	r := models.ConfidenceIntervalRequest{}.Build(c)
diff --git a/models/confidence_interval.go b/models/confidence_interval.go
index 4ec6842..f58851c 100644
--- a/models/confidence_interval.go
+++ b/models/confidence_interval.go
@@ -21,6 +21,7 @@ type ConfidenceIntervalRequest struct {
 	Longitude    float64       `json:"longitude"`
 	Interval     float64       `json:"interval"`
 	PlantingDate time.Time     `json:"plantingDate"`
+	RepeatYears  int           `json:"repeatYears"`
 }
 
 type ConfidenceIntervalResposne struct {
@@ -67,6 +68,15 @@ func (r ConfidenceIntervalRequest) Validate() error {
 }
 
 func (r ConfidenceIntervalRequest) Build(c *fiber.Ctx) ConfidenceIntervalRequest {
+	repeatYears, errYears := strconv.Atoi(c.Query("repeatYears", "1"))
+
+	if errYears != nil {
+		panic(errors.NewBadRequest(nil).PutDetail("reason", "repeat years must be an integer"))
+	}
+
+	if repeatYears < 1 || repeatYears > 3 {
+		panic(errors.NewBadRequest(nil).PutDetail("reason", "repeat years must be between 1 and 3 inclusive"))
+	}
 	product := c.Query("product", "NONE")
 	latitude, _ := strconv.ParseFloat(c.Query("latitude", "-100000.0"), 64)
 	longitude, _ := strconv.ParseFloat(c.Query("longitude", "-100000.0"), 64)
@@ -88,6 +98,7 @@ func (r ConfidenceIntervalRequest) Build(c *fiber.Ctx) ConfidenceIntervalRequest
 		Longitude:    longitude,
 		Interval:     interval,
 		PlantingDate: plantingDate,
+		RepeatYears:  repeatYears,
 	}
 
 	if rNew.Validate() != nil {
diff --git a/services/confidence_interval_service.go b/services/confidence_interval_service.go
index afc64ca..69234ac 100644
--- a/services/confidence_interval_service.go
+++ b/services/confidence_interval_service.go
@@ -14,6 +14,11 @@ func GetConfidenceInterval(request models.ConfidenceIntervalRequest) models.Conf
 	// zScore := models.IntervalConvert[request.Interval]
 	// zScore := models.IntervalConvertPercentiles[request.Interval]
 
+	r := 1
+	if request.RepeatYears > 0 {
+		r = request.RepeatYears
+	}
+
 	var lowerBound []float64
 	var upperBound []float64
 
@@ -26,10 +31,14 @@ func GetConfidenceInterval(request models.ConfidenceIntervalRequest) models.Conf
 	}
 
 	rows := [][]float64{}
-	for i := sliceDateInt; i < len(gs[0].MinTemps); i++ {
+	for i := sliceDateInt; i < len(gs[0].MinTemps)*r; i++ {
 		row := []float64{}
+		idx := i
+		if i >= len(gs[0].MinTemps) {
+			idx -= len(gs[0].MinTemps)
+		}
 		for j := 0; j < len(gs); j++ {
-			row = append(row, utils.CalculateSingleGdd(gs[j].MinTemps[i], gs[j].MaxTemps[i], product))
+			row = append(row, utils.CalculateSingleGdd(gs[j].MinTemps[idx], gs[j].MaxTemps[idx], product))
 			if i > sliceDateInt {
 				row[j] += rows[len(rows)-1][j]
 			}
-- 
GitLab