From ee44e6e828e2d9c8d369b6be95e7da7dc6033dc4 Mon Sep 17 00:00:00 2001
From: Tucker Siegel <tgsiegel@terpmail.umd.edu>
Date: Thu, 16 Mar 2023 15:34:19 -0400
Subject: [PATCH] add failures

---
 controllers/gdd_controller.go |   4 +
 docs/docs.go                  | 422 ++++++++++++++++++++--------------
 docs/swagger.json             | 351 ++++++++++++++++++----------
 docs/swagger.yaml             | 254 ++++++++++++--------
 4 files changed, 647 insertions(+), 384 deletions(-)

diff --git a/controllers/gdd_controller.go b/controllers/gdd_controller.go
index df17328..c99ab81 100644
--- a/controllers/gdd_controller.go
+++ b/controllers/gdd_controller.go
@@ -19,6 +19,8 @@ var GetGddValues = services.GetGddValues
 // @Produce  json
 // @Success 200 {object} models.GddResponse
 // @Failure 400 {object} errors.StandardError
+// @Failure 404 {object} errors.StandardError
+// @Failure 500 {object} errors.StandardError
 // @Param year query int true "Year to get gdd for"
 // @Param product query string true "Crop to calculate gdd for" Enums(corn)
 // @Param latitude query number true "Latitude to search for"
@@ -40,6 +42,8 @@ func GetDailyGdd(c *fiber.Ctx) error {
 // @Produce  json
 // @Success 200 {object} models.GddResponse
 // @Failure 400 {object} errors.StandardError
+// @Failure 404 {object} errors.StandardError
+// @Failure 500 {object} errors.StandardError
 // @Param product query string true "Crop to calculate gdd for" Enums(corn)
 // @Param latitude query number true "Latitude to search for"
 // @Param longitude query number true "Longitude to search for"
diff --git a/docs/docs.go b/docs/docs.go
index a1aea39..adcef14 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -1,17 +1,9 @@
-// Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
-// This file was generated by swaggo/swag
+// Code generated by swaggo/swag. DO NOT EDIT
 package docs
 
-import (
-	"bytes"
-	"encoding/json"
-	"strings"
-	"text/template"
+import "github.com/swaggo/swag"
 
-	"github.com/swaggo/swag"
-)
-
-var doc = `{
+const docTemplate = `{
     "schemes": {{ marshal .Schemes }},
     "swagger": "2.0",
     "info": {
@@ -72,7 +64,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -117,7 +109,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -192,7 +184,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -264,6 +256,19 @@ var doc = `{
                         "name": "longitude",
                         "in": "query",
                         "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Plant date, ISO8601 or RFC3339 format",
+                        "name": "plantingDate",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "number of times to repeat the request. When included with planting date, will extrapolate plantingdate -\u003e end of repeatYears range",
+                        "name": "repeatYears",
+                        "in": "query"
                     }
                 ],
                 "responses": {
@@ -276,7 +281,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -434,7 +439,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -442,7 +447,11 @@ var doc = `{
         },
         "/gdd/daily": {
             "get": {
-                "description": "get gdd values",
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
                 "consumes": [
                     "application/json"
                 ],
@@ -450,9 +459,10 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "Gdd"
+                    "Gdd",
+                    "public"
                 ],
-                "summary": "Get gdd values",
+                "summary": "Get GDD Values for given year",
                 "parameters": [
                     {
                         "type": "integer",
@@ -463,20 +473,7 @@ var doc = `{
                     },
                     {
                         "enum": [
-                            "corn",
-                            "soybean",
-                            "sunflower",
-                            "tomato",
-                            "sugar_beet",
-                            "peanut",
-                            "cotton",
-                            "potato",
-                            "wheat",
-                            "pea",
-                            "oat",
-                            "spring_wheat",
-                            "rice",
-                            "sorghum"
+                            "corn"
                         ],
                         "type": "string",
                         "description": "Crop to calculate gdd for",
@@ -504,6 +501,13 @@ var doc = `{
                         "name": "accumulate",
                         "in": "query",
                         "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Plant date RFC3339 format",
+                        "name": "plantingDate",
+                        "in": "query",
+                        "required": true
                     }
                 ],
                 "responses": {
@@ -516,7 +520,152 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
+                        }
+                    }
+                }
+            }
+        },
+        "/gdd/forecast/freezing": {
+            "get": {
+                "description": "Get stages",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Forecast"
+                ],
+                "summary": "Get stages",
+                "parameters": [
+                    {
+                        "type": "number",
+                        "description": "Latitude to search for",
+                        "name": "latitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "Longitude to search for",
+                        "name": "longitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "Freezing temperature to use",
+                        "name": "freezing_temp",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "object",
+                            "additionalProperties": {
+                                "type": "array",
+                                "items": {
+                                    "type": "string"
+                                }
+                            }
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/errors.StandardError"
+                        }
+                    }
+                }
+            }
+        },
+        "/gdd/forecast/stages": {
+            "get": {
+                "description": "Get stages",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Forecast"
+                ],
+                "summary": "Get stages",
+                "parameters": [
+                    {
+                        "type": "number",
+                        "description": "Latitude to search for",
+                        "name": "latitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "Longitude to search for",
+                        "name": "longitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Plant date, ISO8601 or RFC3339 format",
+                        "name": "plant_date",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Mode, rm or gdds_to_maturity",
+                        "name": "mode",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "Value of mode",
+                        "name": "value",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "anchoring stage",
+                        "name": "anchor_stage",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "anchoring date",
+                        "name": "anchor_date",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "comparison. -1 for normals, or any int between 1981 and 2021 for a single year",
+                        "name": "comparison",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "object",
+                            "additionalProperties": {
+                                "$ref": "#/definitions/models.Bins"
+                            }
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -591,7 +740,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -713,7 +862,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -750,7 +899,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -816,7 +965,7 @@ var doc = `{
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -824,7 +973,11 @@ var doc = `{
         },
         "/gdd/normals": {
             "get": {
-                "description": "get gdd normals",
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
                 "consumes": [
                     "application/json"
                 ],
@@ -832,26 +985,14 @@ var doc = `{
                     "application/json"
                 ],
                 "tags": [
-                    "Gdd"
+                    "Gdd",
+                    "public"
                 ],
-                "summary": "Get gdd normals",
+                "summary": "Get GDD normals over the past 30 years",
                 "parameters": [
                     {
                         "enum": [
-                            "corn",
-                            "soybean",
-                            "sunflower",
-                            "tomato",
-                            "sugar_beet",
-                            "peanut",
-                            "cotton",
-                            "potato",
-                            "wheat",
-                            "pea",
-                            "oat",
-                            "spring_wheat",
-                            "rice",
-                            "sorghum"
+                            "corn"
                         ],
                         "type": "string",
                         "description": "Crop to calculate gdd for",
@@ -879,91 +1020,25 @@ var doc = `{
                         "name": "accumulate",
                         "in": "query",
                         "required": true
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "$ref": "#/definitions/models.GddResponse"
-                        }
                     },
-                    "400": {
-                        "description": "Bad Request",
-                        "schema": {
-                            "$ref": "#/definitions/common.StandardError"
-                        }
-                    }
-                }
-            }
-        },
-        "/gdd/stages": {
-            "get": {
-                "description": "Get stages",
-                "consumes": [
-                    "application/json"
-                ],
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "Maturity"
-                ],
-                "summary": "Get stages",
-                "parameters": [
                     {
                         "type": "number",
-                        "description": "Latitude to search for",
-                        "name": "latitude",
-                        "in": "query",
-                        "required": true
-                    },
-                    {
-                        "type": "number",
-                        "description": "Longitude to search for",
-                        "name": "longitude",
-                        "in": "query",
-                        "required": true
-                    },
-                    {
-                        "type": "string",
-                        "description": "Plant date, ISO8601 or RFC3339 format",
-                        "name": "plant_date",
-                        "in": "query",
-                        "required": true
-                    },
-                    {
-                        "type": "string",
-                        "description": "Mode, rm or gdds_to_maturity",
-                        "name": "mode",
-                        "in": "query",
-                        "required": true
-                    },
-                    {
-                        "type": "integer",
-                        "description": "Value of mode",
-                        "name": "value",
-                        "in": "query",
-                        "required": true
+                        "description": "number of times to repeat the request. When included with planting date, will extrapolate plantingdate -\u003e end of repeatYears range",
+                        "name": "repeatYears",
+                        "in": "query"
                     }
                 ],
                 "responses": {
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "object",
-                            "additionalProperties": {
-                                "type": "array",
-                                "items": {
-                                    "type": "string"
-                                }
-                            }
+                            "$ref": "#/definitions/models.GddResponse"
                         }
                     },
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -971,7 +1046,7 @@ var doc = `{
         }
     },
     "definitions": {
-        "common.StandardError": {
+        "errors.StandardError": {
             "type": "object",
             "properties": {
                 "description": {
@@ -1005,6 +1080,34 @@ var doc = `{
                 }
             }
         },
+        "models.Bin": {
+            "type": "object",
+            "properties": {
+                "date": {
+                    "type": "string"
+                },
+                "value": {
+                    "type": "number"
+                }
+            }
+        },
+        "models.Bins": {
+            "type": "object",
+            "properties": {
+                "bins": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/models.Bin"
+                    }
+                },
+                "comparison_mean": {
+                    "type": "string"
+                },
+                "count": {
+                    "type": "integer"
+                }
+            }
+        },
         "models.CfsGddResponse": {
             "type": "object",
             "properties": {
@@ -1212,59 +1315,28 @@ var doc = `{
                 }
             }
         }
+    },
+    "securityDefinitions": {
+        "ApiKeyAuth": {
+            "type": "apiKey",
+            "name": "Authorization",
+            "in": "header"
+        }
     }
 }`
 
-type swaggerInfo struct {
-	Version     string
-	Host        string
-	BasePath    string
-	Schemes     []string
-	Title       string
-	Description string
-}
-
 // SwaggerInfo holds exported Swagger Info so clients can modify it
-var SwaggerInfo = swaggerInfo{
-	Version:     "",
-	Host:        "",
-	BasePath:    "",
-	Schemes:     []string{},
-	Title:       "Dawn GDD Service",
-	Description: "All operations for GDD/Freezing Date data",
-}
-
-type s struct{}
-
-func (s *s) ReadDoc() string {
-	sInfo := SwaggerInfo
-	sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
-
-	t, err := template.New("swagger_info").Funcs(template.FuncMap{
-		"marshal": func(v interface{}) string {
-			a, _ := json.Marshal(v)
-			return string(a)
-		},
-		"escape": func(v interface{}) string {
-			// escape tabs
-			str := strings.Replace(v.(string), "\t", "\\t", -1)
-			// replace " with \", and if that results in \\", replace that with \\\"
-			str = strings.Replace(str, "\"", "\\\"", -1)
-			return strings.Replace(str, "\\\\\"", "\\\\\\\"", -1)
-		},
-	}).Parse(doc)
-	if err != nil {
-		return doc
-	}
-
-	var tpl bytes.Buffer
-	if err := t.Execute(&tpl, sInfo); err != nil {
-		return doc
-	}
-
-	return tpl.String()
+var SwaggerInfo = &swag.Spec{
+	Version:          "",
+	Host:             "",
+	BasePath:         "",
+	Schemes:          []string{},
+	Title:            "Dawn GDD Service",
+	Description:      "",
+	InfoInstanceName: "swagger",
+	SwaggerTemplate:  docTemplate,
 }
 
 func init() {
-	swag.Register("swagger", &s{})
+	swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
 }
diff --git a/docs/swagger.json b/docs/swagger.json
index 5cafb1b..334dbdd 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -1,7 +1,6 @@
 {
     "swagger": "2.0",
     "info": {
-        "description": "All operations for GDD/Freezing Date data",
         "title": "Dawn GDD Service",
         "contact": {
             "name": "API Support",
@@ -55,7 +54,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -100,7 +99,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -175,7 +174,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -247,6 +246,19 @@
                         "name": "longitude",
                         "in": "query",
                         "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Plant date, ISO8601 or RFC3339 format",
+                        "name": "plantingDate",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "number of times to repeat the request. When included with planting date, will extrapolate plantingdate -\u003e end of repeatYears range",
+                        "name": "repeatYears",
+                        "in": "query"
                     }
                 ],
                 "responses": {
@@ -259,7 +271,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -417,7 +429,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -425,7 +437,11 @@
         },
         "/gdd/daily": {
             "get": {
-                "description": "get gdd values",
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
                 "consumes": [
                     "application/json"
                 ],
@@ -433,9 +449,10 @@
                     "application/json"
                 ],
                 "tags": [
-                    "Gdd"
+                    "Gdd",
+                    "public"
                 ],
-                "summary": "Get gdd values",
+                "summary": "Get GDD Values for given year",
                 "parameters": [
                     {
                         "type": "integer",
@@ -446,20 +463,7 @@
                     },
                     {
                         "enum": [
-                            "corn",
-                            "soybean",
-                            "sunflower",
-                            "tomato",
-                            "sugar_beet",
-                            "peanut",
-                            "cotton",
-                            "potato",
-                            "wheat",
-                            "pea",
-                            "oat",
-                            "spring_wheat",
-                            "rice",
-                            "sorghum"
+                            "corn"
                         ],
                         "type": "string",
                         "description": "Crop to calculate gdd for",
@@ -487,6 +491,13 @@
                         "name": "accumulate",
                         "in": "query",
                         "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Plant date RFC3339 format",
+                        "name": "plantingDate",
+                        "in": "query",
+                        "required": true
                     }
                 ],
                 "responses": {
@@ -499,7 +510,152 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
+                        }
+                    }
+                }
+            }
+        },
+        "/gdd/forecast/freezing": {
+            "get": {
+                "description": "Get stages",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Forecast"
+                ],
+                "summary": "Get stages",
+                "parameters": [
+                    {
+                        "type": "number",
+                        "description": "Latitude to search for",
+                        "name": "latitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "Longitude to search for",
+                        "name": "longitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "Freezing temperature to use",
+                        "name": "freezing_temp",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "object",
+                            "additionalProperties": {
+                                "type": "array",
+                                "items": {
+                                    "type": "string"
+                                }
+                            }
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/errors.StandardError"
+                        }
+                    }
+                }
+            }
+        },
+        "/gdd/forecast/stages": {
+            "get": {
+                "description": "Get stages",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Forecast"
+                ],
+                "summary": "Get stages",
+                "parameters": [
+                    {
+                        "type": "number",
+                        "description": "Latitude to search for",
+                        "name": "latitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "number",
+                        "description": "Longitude to search for",
+                        "name": "longitude",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Plant date, ISO8601 or RFC3339 format",
+                        "name": "plant_date",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "Mode, rm or gdds_to_maturity",
+                        "name": "mode",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "Value of mode",
+                        "name": "value",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "anchoring stage",
+                        "name": "anchor_stage",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "anchoring date",
+                        "name": "anchor_date",
+                        "in": "query"
+                    },
+                    {
+                        "type": "integer",
+                        "description": "comparison. -1 for normals, or any int between 1981 and 2021 for a single year",
+                        "name": "comparison",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "type": "object",
+                            "additionalProperties": {
+                                "$ref": "#/definitions/models.Bins"
+                            }
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -574,7 +730,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -696,7 +852,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -733,7 +889,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -799,7 +955,7 @@
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -807,7 +963,11 @@
         },
         "/gdd/normals": {
             "get": {
-                "description": "get gdd normals",
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
                 "consumes": [
                     "application/json"
                 ],
@@ -815,26 +975,14 @@
                     "application/json"
                 ],
                 "tags": [
-                    "Gdd"
+                    "Gdd",
+                    "public"
                 ],
-                "summary": "Get gdd normals",
+                "summary": "Get GDD normals over the past 30 years",
                 "parameters": [
                     {
                         "enum": [
-                            "corn",
-                            "soybean",
-                            "sunflower",
-                            "tomato",
-                            "sugar_beet",
-                            "peanut",
-                            "cotton",
-                            "potato",
-                            "wheat",
-                            "pea",
-                            "oat",
-                            "spring_wheat",
-                            "rice",
-                            "sorghum"
+                            "corn"
                         ],
                         "type": "string",
                         "description": "Crop to calculate gdd for",
@@ -862,91 +1010,25 @@
                         "name": "accumulate",
                         "in": "query",
                         "required": true
-                    }
-                ],
-                "responses": {
-                    "200": {
-                        "description": "OK",
-                        "schema": {
-                            "$ref": "#/definitions/models.GddResponse"
-                        }
-                    },
-                    "400": {
-                        "description": "Bad Request",
-                        "schema": {
-                            "$ref": "#/definitions/common.StandardError"
-                        }
-                    }
-                }
-            }
-        },
-        "/gdd/stages": {
-            "get": {
-                "description": "Get stages",
-                "consumes": [
-                    "application/json"
-                ],
-                "produces": [
-                    "application/json"
-                ],
-                "tags": [
-                    "Maturity"
-                ],
-                "summary": "Get stages",
-                "parameters": [
-                    {
-                        "type": "number",
-                        "description": "Latitude to search for",
-                        "name": "latitude",
-                        "in": "query",
-                        "required": true
                     },
                     {
                         "type": "number",
-                        "description": "Longitude to search for",
-                        "name": "longitude",
-                        "in": "query",
-                        "required": true
-                    },
-                    {
-                        "type": "string",
-                        "description": "Plant date, ISO8601 or RFC3339 format",
-                        "name": "plant_date",
-                        "in": "query",
-                        "required": true
-                    },
-                    {
-                        "type": "string",
-                        "description": "Mode, rm or gdds_to_maturity",
-                        "name": "mode",
-                        "in": "query",
-                        "required": true
-                    },
-                    {
-                        "type": "integer",
-                        "description": "Value of mode",
-                        "name": "value",
-                        "in": "query",
-                        "required": true
+                        "description": "number of times to repeat the request. When included with planting date, will extrapolate plantingdate -\u003e end of repeatYears range",
+                        "name": "repeatYears",
+                        "in": "query"
                     }
                 ],
                 "responses": {
                     "200": {
                         "description": "OK",
                         "schema": {
-                            "type": "object",
-                            "additionalProperties": {
-                                "type": "array",
-                                "items": {
-                                    "type": "string"
-                                }
-                            }
+                            "$ref": "#/definitions/models.GddResponse"
                         }
                     },
                     "400": {
                         "description": "Bad Request",
                         "schema": {
-                            "$ref": "#/definitions/common.StandardError"
+                            "$ref": "#/definitions/errors.StandardError"
                         }
                     }
                 }
@@ -954,7 +1036,7 @@
         }
     },
     "definitions": {
-        "common.StandardError": {
+        "errors.StandardError": {
             "type": "object",
             "properties": {
                 "description": {
@@ -988,6 +1070,34 @@
                 }
             }
         },
+        "models.Bin": {
+            "type": "object",
+            "properties": {
+                "date": {
+                    "type": "string"
+                },
+                "value": {
+                    "type": "number"
+                }
+            }
+        },
+        "models.Bins": {
+            "type": "object",
+            "properties": {
+                "bins": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/models.Bin"
+                    }
+                },
+                "comparison_mean": {
+                    "type": "string"
+                },
+                "count": {
+                    "type": "integer"
+                }
+            }
+        },
         "models.CfsGddResponse": {
             "type": "object",
             "properties": {
@@ -1195,5 +1305,12 @@
                 }
             }
         }
+    },
+    "securityDefinitions": {
+        "ApiKeyAuth": {
+            "type": "apiKey",
+            "name": "Authorization",
+            "in": "header"
+        }
     }
 }
\ No newline at end of file
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 0504d12..f5e7d4c 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -1,5 +1,5 @@
 definitions:
-  common.StandardError:
+  errors.StandardError:
     properties:
       description:
         type: string
@@ -21,6 +21,24 @@ definitions:
       closest_longitude:
         type: number
     type: object
+  models.Bin:
+    properties:
+      date:
+        type: string
+      value:
+        type: number
+    type: object
+  models.Bins:
+    properties:
+      bins:
+        items:
+          $ref: '#/definitions/models.Bin'
+        type: array
+      comparison_mean:
+        type: string
+      count:
+        type: integer
+    type: object
   models.CfsGddResponse:
     properties:
       closest_latitude:
@@ -160,7 +178,6 @@ info:
   contact:
     email: tgsiegel@umd.edu
     name: API Support
-  description: All operations for GDD/Freezing Date data
   title: Dawn GDD Service
 paths:
   /freezing-dates:
@@ -194,7 +211,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: get freezing dates
       tags:
       - Freezing Dates
@@ -224,7 +241,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get analog year
       tags:
       - Gdd
@@ -279,7 +296,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get GDD values calculated from CFS
       tags:
       - Gdd
@@ -332,6 +349,16 @@ paths:
         name: longitude
         required: true
         type: number
+      - description: Plant date, ISO8601 or RFC3339 format
+        in: query
+        name: plantingDate
+        required: true
+        type: string
+      - description: number of times to repeat the request. When included with planting
+          date, will extrapolate plantingdate -> end of repeatYears range
+        in: query
+        name: repeatYears
+        type: number
       produces:
       - application/json
       responses:
@@ -342,7 +369,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get confidence interval
       tags:
       - Gdd
@@ -452,7 +479,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get gdd data csv
       tags:
       - Gdd
@@ -460,7 +487,6 @@ paths:
     get:
       consumes:
       - application/json
-      description: get gdd values
       parameters:
       - description: Year to get gdd for
         in: query
@@ -470,19 +496,6 @@ paths:
       - description: Crop to calculate gdd for
         enum:
         - corn
-        - soybean
-        - sunflower
-        - tomato
-        - sugar_beet
-        - peanut
-        - cotton
-        - potato
-        - wheat
-        - pea
-        - oat
-        - spring_wheat
-        - rice
-        - sorghum
         in: query
         name: product
         required: true
@@ -502,6 +515,11 @@ paths:
         name: accumulate
         required: true
         type: boolean
+      - description: Plant date RFC3339 format
+        in: query
+        name: plantingDate
+        required: true
+        type: string
       produces:
       - application/json
       responses:
@@ -512,10 +530,112 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
-      summary: Get gdd values
+            $ref: '#/definitions/errors.StandardError'
+      security:
+      - ApiKeyAuth: []
+      summary: Get GDD Values for given year
       tags:
       - Gdd
+      - public
+  /gdd/forecast/freezing:
+    get:
+      consumes:
+      - application/json
+      description: Get stages
+      parameters:
+      - description: Latitude to search for
+        in: query
+        name: latitude
+        required: true
+        type: number
+      - description: Longitude to search for
+        in: query
+        name: longitude
+        required: true
+        type: number
+      - description: Freezing temperature to use
+        in: query
+        name: freezing_temp
+        required: true
+        type: number
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            additionalProperties:
+              items:
+                type: string
+              type: array
+            type: object
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/errors.StandardError'
+      summary: Get stages
+      tags:
+      - Forecast
+  /gdd/forecast/stages:
+    get:
+      consumes:
+      - application/json
+      description: Get stages
+      parameters:
+      - description: Latitude to search for
+        in: query
+        name: latitude
+        required: true
+        type: number
+      - description: Longitude to search for
+        in: query
+        name: longitude
+        required: true
+        type: number
+      - description: Plant date, ISO8601 or RFC3339 format
+        in: query
+        name: plant_date
+        required: true
+        type: string
+      - description: Mode, rm or gdds_to_maturity
+        in: query
+        name: mode
+        required: true
+        type: string
+      - description: Value of mode
+        in: query
+        name: value
+        required: true
+        type: integer
+      - description: anchoring stage
+        in: query
+        name: anchor_stage
+        type: string
+      - description: anchoring date
+        in: query
+        name: anchor_date
+        type: string
+      - description: comparison. -1 for normals, or any int between 1981 and 2021
+          for a single year
+        in: query
+        name: comparison
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            additionalProperties:
+              $ref: '#/definitions/models.Bins'
+            type: object
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/errors.StandardError'
+      summary: Get stages
+      tags:
+      - Forecast
   /gdd/gefs:
     get:
       consumes:
@@ -567,7 +687,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get GDD values calculated from GEFS
       tags:
       - Gdd
@@ -652,7 +772,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get expected maturity date
       tags:
       - Maturity
@@ -676,7 +796,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get all generic corn cultivars
       tags:
       - Maturity
@@ -721,7 +841,7 @@ paths:
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
+            $ref: '#/definitions/errors.StandardError'
       summary: Get expected maturity date
       tags:
       - Maturity
@@ -729,24 +849,10 @@ paths:
     get:
       consumes:
       - application/json
-      description: get gdd normals
       parameters:
       - description: Crop to calculate gdd for
         enum:
         - corn
-        - soybean
-        - sunflower
-        - tomato
-        - sugar_beet
-        - peanut
-        - cotton
-        - potato
-        - wheat
-        - pea
-        - oat
-        - spring_wheat
-        - rice
-        - sorghum
         in: query
         name: product
         required: true
@@ -766,67 +872,31 @@ paths:
         name: accumulate
         required: true
         type: boolean
-      produces:
-      - application/json
-      responses:
-        "200":
-          description: OK
-          schema:
-            $ref: '#/definitions/models.GddResponse'
-        "400":
-          description: Bad Request
-          schema:
-            $ref: '#/definitions/common.StandardError'
-      summary: Get gdd normals
-      tags:
-      - Gdd
-  /gdd/stages:
-    get:
-      consumes:
-      - application/json
-      description: Get stages
-      parameters:
-      - description: Latitude to search for
+      - description: number of times to repeat the request. When included with planting
+          date, will extrapolate plantingdate -> end of repeatYears range
         in: query
-        name: latitude
-        required: true
+        name: repeatYears
         type: number
-      - description: Longitude to search for
-        in: query
-        name: longitude
-        required: true
-        type: number
-      - description: Plant date, ISO8601 or RFC3339 format
-        in: query
-        name: plant_date
-        required: true
-        type: string
-      - description: Mode, rm or gdds_to_maturity
-        in: query
-        name: mode
-        required: true
-        type: string
-      - description: Value of mode
-        in: query
-        name: value
-        required: true
-        type: integer
       produces:
       - application/json
       responses:
         "200":
           description: OK
           schema:
-            additionalProperties:
-              items:
-                type: string
-              type: array
-            type: object
+            $ref: '#/definitions/models.GddResponse'
         "400":
           description: Bad Request
           schema:
-            $ref: '#/definitions/common.StandardError'
-      summary: Get stages
+            $ref: '#/definitions/errors.StandardError'
+      security:
+      - ApiKeyAuth: []
+      summary: Get GDD normals over the past 30 years
       tags:
-      - Maturity
+      - Gdd
+      - public
+securityDefinitions:
+  ApiKeyAuth:
+    in: header
+    name: Authorization
+    type: apiKey
 swagger: "2.0"
-- 
GitLab