diff --git a/config/routes.go b/config/routes.go index dabf3a5561f6836aa5b38088ba835198bcc6ab09..e95b5f2b7d16e92d8df7ca478308a4a05aff7ddf 100644 --- a/config/routes.go +++ b/config/routes.go @@ -10,6 +10,7 @@ func GddRoutes(route fiber.Router) { route.Get("gdd/daily", controllers.GetDailyGdd) route.Get("gdd/normals", controllers.GetNormalGdd) route.Get("gdd/gefs", controllers.GetGefsGDD) + route.Get("gdd/cfs", controllers.GetCfsGDD) route.Get("gdd/analog", controllers.GetAnalogYear) route.Get("gdd/confidence", controllers.GetConfidenceInterval) } diff --git a/controllers/misc_controller.go b/controllers/misc_controller.go index ec2daa1ac5963860ce75c2b30db0101c252e4fa5..b8b3e9b63aa0bd95a7e159208c7653703e3ddf47 100644 --- a/controllers/misc_controller.go +++ b/controllers/misc_controller.go @@ -45,6 +45,7 @@ func GetAnalogYear(c *fiber.Ctx) error { // @Produce json // @Success 200 {object} models.ConfidenceIntervalResposne // @Failure 400 {object} errors.StandardError +// @Param product query string true "Crop to calculate gdd for" Enums(corn, soybean, sunflower, tomato, sugar_beet, peanut, cotton, potato, wheat, pea, oat, spring_wheat, rice, sorghum) // @Param latitude query number true "Latitude to search for" // @Param longitude query number true "Longitude to search for" // @Router /api/weather/gdd/confidence [get] diff --git a/controllers/nomads_controller.go b/controllers/nomads_controller.go index a5325f9baa22e4cb1954606108b8e49240bb49d9..eb5cec13d1aa094debfee7b6b18197da3340b40c 100644 --- a/controllers/nomads_controller.go +++ b/controllers/nomads_controller.go @@ -24,3 +24,21 @@ func GetGefsGDD(c *fiber.Ctx) error { request := models.GddRequest{}.Build(c) return c.Status(fiber.StatusOK).JSON(services.GetGefsGddValues(request)) } + +// GetCfsGDD godoc +// @Summary Get GDD values calculated from CFS +// @Tags Gdd +// @Description Get GDD values calculated from CFS +// @Accept json +// @Produce json +// @Success 200 {object} models.CfsGddResponse +// @Failure 400 {object} errors.StandardError +// @Param product query string true "Crop to calculate gdd for" Enums(corn, soybean, sunflower, tomato, sugar_beet, peanut, cotton, potato, wheat, pea, oat, spring_wheat, rice, sorghum) +// @Param latitude query number true "Latitude to search for" +// @Param longitude query number true "Longitude to search for" +// @Param accumulate query boolean true "Accumulate gdd values" +// @Router /api/weather/gdd/cfs [get] +func GetCfsGDD(c *fiber.Ctx) error { + request := models.GddRequest{}.Build(c) + return c.Status(fiber.StatusOK).JSON(services.GetCfsGddValues(request)) +} diff --git a/docs/docs.go b/docs/docs.go index 74c9abafd8b9c3787a3c64295b83282b7f565124..4058d36cbf9f606ababdbee58d38b74f35fbaa43 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -72,6 +72,51 @@ var doc = `{ } } }, + "/api/weather/gdd/confidence": { + "get": { + "description": "Get confidence interval", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Gdd" + ], + "summary": "Get confidence interval", + "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 + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.ConfidenceIntervalResposne" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.StandardError" + } + } + } + } + }, "/api/weather/gdd/daily": { "get": { "description": "get gdd values", @@ -337,17 +382,46 @@ var doc = `{ "analog_year": { "type": "integer" }, - "nearest_latitude": { + "closest_latitude": { "type": "number" }, - "nearest_longitude": { + "closest_longitude": { "type": "number" } } }, + "models.ConfidenceIntervalResposne": { + "type": "object", + "properties": { + "closestLatitude": { + "type": "number" + }, + "closestLongitude": { + "type": "number" + }, + "lowerBound": { + "type": "array", + "items": { + "type": "number" + } + }, + "upperBound": { + "type": "array", + "items": { + "type": "number" + } + } + } + }, "models.GddResponse": { "type": "object", "properties": { + "closest_latitude": { + "type": "number" + }, + "closest_longitude": { + "type": "number" + }, "gdd_values": { "type": "array", "items": { @@ -357,12 +431,6 @@ var doc = `{ "last_date": { "type": "string" }, - "nearest_latitude": { - "type": "number" - }, - "nearest_longitude": { - "type": "number" - }, "product": { "type": "string" } @@ -371,6 +439,12 @@ var doc = `{ "models.GefsGddResponse": { "type": "object", "properties": { + "closest_latitude": { + "type": "number" + }, + "closest_longitude": { + "type": "number" + }, "first_date": { "type": "string" }, @@ -383,12 +457,6 @@ var doc = `{ "last_date": { "type": "string" }, - "nearest_latitude": { - "type": "number" - }, - "nearest_longitude": { - "type": "number" - }, "product": { "type": "string" } diff --git a/docs/swagger.json b/docs/swagger.json index 9d9fb309f3d69c9b27f69de1636398a01493f128..270dcfa80555a5ff9cfbc599773d7a870a2fea73 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -57,6 +57,51 @@ } } }, + "/api/weather/gdd/confidence": { + "get": { + "description": "Get confidence interval", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Gdd" + ], + "summary": "Get confidence interval", + "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 + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/models.ConfidenceIntervalResposne" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/errors.StandardError" + } + } + } + } + }, "/api/weather/gdd/daily": { "get": { "description": "get gdd values", @@ -322,17 +367,46 @@ "analog_year": { "type": "integer" }, - "nearest_latitude": { + "closest_latitude": { "type": "number" }, - "nearest_longitude": { + "closest_longitude": { "type": "number" } } }, + "models.ConfidenceIntervalResposne": { + "type": "object", + "properties": { + "closestLatitude": { + "type": "number" + }, + "closestLongitude": { + "type": "number" + }, + "lowerBound": { + "type": "array", + "items": { + "type": "number" + } + }, + "upperBound": { + "type": "array", + "items": { + "type": "number" + } + } + } + }, "models.GddResponse": { "type": "object", "properties": { + "closest_latitude": { + "type": "number" + }, + "closest_longitude": { + "type": "number" + }, "gdd_values": { "type": "array", "items": { @@ -342,12 +416,6 @@ "last_date": { "type": "string" }, - "nearest_latitude": { - "type": "number" - }, - "nearest_longitude": { - "type": "number" - }, "product": { "type": "string" } @@ -356,6 +424,12 @@ "models.GefsGddResponse": { "type": "object", "properties": { + "closest_latitude": { + "type": "number" + }, + "closest_longitude": { + "type": "number" + }, "first_date": { "type": "string" }, @@ -368,12 +442,6 @@ "last_date": { "type": "string" }, - "nearest_latitude": { - "type": "number" - }, - "nearest_longitude": { - "type": "number" - }, "product": { "type": "string" } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index f67b608aeae93b54a7ad773f13880cdc4942ffb5..1c95e8169f7b2cd7079439323e7276bbea54e9d7 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -20,28 +20,47 @@ definitions: properties: analog_year: type: integer - nearest_latitude: + closest_latitude: type: number - nearest_longitude: + closest_longitude: type: number type: object + models.ConfidenceIntervalResposne: + properties: + closestLatitude: + type: number + closestLongitude: + type: number + lowerBound: + items: + type: number + type: array + upperBound: + items: + type: number + type: array + type: object models.GddResponse: properties: + closest_latitude: + type: number + closest_longitude: + type: number gdd_values: items: type: number type: array last_date: type: string - nearest_latitude: - type: number - nearest_longitude: - type: number product: type: string type: object models.GefsGddResponse: properties: + closest_latitude: + type: number + closest_longitude: + type: number first_date: type: string gdd_values: @@ -50,10 +69,6 @@ definitions: type: array last_date: type: string - nearest_latitude: - type: number - nearest_longitude: - type: number product: type: string type: object @@ -96,6 +111,36 @@ paths: summary: Get analog year tags: - Gdd + /api/weather/gdd/confidence: + get: + consumes: + - application/json + description: Get confidence interval + 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 + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/models.ConfidenceIntervalResposne' + "400": + description: Bad Request + schema: + $ref: '#/definitions/errors.StandardError' + summary: Get confidence interval + tags: + - Gdd /api/weather/gdd/daily: get: consumes: diff --git a/main.go b/main.go index 7759daf131fe5b2546c280534e40449380cd291e..536e9e48be7781b5d996874de2249c69992705a4 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,7 @@ func registerSwagger(app *fiber.App) { func registerCors(app *fiber.App) { app.Use(cors.New(cors.Config{ - AllowOrigins: "http://localhost:3000, http://localhost:4200", + AllowOrigins: "http://localhost:3000, http://localhost:4200, http://localhost:5000", AllowHeaders: "Origin, Content-Type, Accept", })) } diff --git a/models/cfs.go b/models/cfs.go new file mode 100644 index 0000000000000000000000000000000000000000..fdfd0711366282aa240f77120fa8cc40247d3832 --- /dev/null +++ b/models/cfs.go @@ -0,0 +1,11 @@ +package models + +import "time" + +type CfsGddResponse struct { + Product string `json:"product"` + ClosestLatitude float64 `json:"closest_latitude"` + ClosestLongitude float64 `json:"closest_longitude"` + GddValues []float64 `json:"gdd_values"` + FirstDate time.Time `json:"first_date"` +} diff --git a/models/confidence_interval.go b/models/confidence_interval.go index d9e862003ed508fa1d8dce16ec3b19050e60eee0..f7091c1cd58c40ee5a2ec42cf2b607c7d3fe615e 100644 --- a/models/confidence_interval.go +++ b/models/confidence_interval.go @@ -19,10 +19,10 @@ type ConfidenceIntervalRequest struct { } type ConfidenceIntervalResposne struct { - LowerBound []float64 `bson:"lower_bound,omitempty"` - UpperBound []float64 `bson:"upper_bound,omitempty"` - ClosestLatitude float64 `bson:"closest_latitude,omitempty"` - ClosestLongitude float64 `bson:"closest_longitude,omitempty"` + LowerBound []float64 `json:"lower_bound,omitempty"` + UpperBound []float64 `json:"upper_bound,omitempty"` + ClosestLatitude float64 `json:"closest_latitude,omitempty"` + ClosestLongitude float64 `json:"closest_longitude,omitempty"` } var IntervalConvert = map[float64]float64{ diff --git a/persistence/entities/gdd.go b/persistence/entities/gdd.go index 4b5c39c31641f6775b83d318c2b0321a05bfc149..b0a1de06315811a7079c2b35ea08474048d26679 100644 --- a/persistence/entities/gdd.go +++ b/persistence/entities/gdd.go @@ -28,3 +28,11 @@ type GefsGdd struct { MaxTemp float64 `bson:"max_temp,omitempty"` Date primitive.DateTime `bson:"date,omitempty"` } + +type CfsGdd struct { + ID string `bson:"_id,omitempty"` + Location Location `bson:"location,omitempty"` + MinTemps []float64 `bson:"min_temps,omitempty"` + MaxTemps []float64 `bson:"max_temps,omitempty"` + StartDate primitive.DateTime `bson:"start_date,omitempty"` +} diff --git a/persistence/mongodb.go b/persistence/mongodb.go index f88745d24b000339c407cef8630ab7666c606f31..faf0902cfecd6713ec168cf174ccc4afdda1daa4 100644 --- a/persistence/mongodb.go +++ b/persistence/mongodb.go @@ -136,6 +136,20 @@ func GefsFindAllByLocation(location entities.Location) []entities.GefsGdd { return results } +func CfsFindAllByLocation(location entities.Location) entities.CfsGdd { + coll := Conn.Database(viper.GetString("db.database")).Collection("cfs") + + filter := buildLocationRequest(location, nil) + + var g entities.CfsGdd + err := coll.FindOne(Ctx, filter).Decode(&g) + if err != nil { + panic(errors.NO_DATA_FOUND) + } + + return g +} + func FindAnalogYear(location entities.Location) models.AnalogResponse { coll := Conn.Database(viper.GetString("db.database")).Collection("gdd_current") diff --git a/services/confidence_interval_service.go b/services/confidence_interval_service.go index 7641ee26aeb924178e4d652fcd417c470bf7cbb3..6a1bbd2510bdd30af483aaeda47d2052626e54e5 100644 --- a/services/confidence_interval_service.go +++ b/services/confidence_interval_service.go @@ -45,7 +45,7 @@ func GetConfidenceInterval(request models.ConfidenceIntervalRequest) models.Conf gddMinSum += minGddValue gddMaxSum += maxGddValue - lowerBound = append(lowerBound, minGddValue) + lowerBound = append(lowerBound, gddMinSum) upperBound = append(upperBound, gddMaxSum) } diff --git a/services/nomads_service.go b/services/nomads_service.go index 19ea1498db617922f83f722cdbdde5c17ced1ae4..b480821b0ab889dcb4a1879fb3e9a9ae62464c1e 100644 --- a/services/nomads_service.go +++ b/services/nomads_service.go @@ -29,8 +29,34 @@ func GetGefsGddValues(request models.GddRequest) models.GefsGddResponse { ClosestLatitude: location.Coordinates[1], ClosestLongitude: location.Coordinates[0], GddValues: gdds, - FirstDate: g[0].Date.Time(), - LastDate: g[9].Date.Time(), + FirstDate: g[0].Date.Time().UTC(), + LastDate: g[9].Date.Time().UTC(), + } + return returnGdds +} + +func GetCfsGddValues(request models.GddRequest) models.CfsGddResponse { + product := enums.GetProductFromString(request.Product) + location := request.BuildLocation() + g := persistence.CfsFindAllByLocation(location) + var returnGdds models.CfsGddResponse + + var gdds []float64 + + for i := 0; i < len(g.MaxTemps); i++ { + value := utils.CalculateSingleGdd(g.MinTemps[i], g.MaxTemps[i], product) + if request.Accumulate && i > 0 { + value += gdds[len(gdds)-1] + } + gdds = append(gdds, value) + } + + returnGdds = models.CfsGddResponse{ + Product: product.Name, + ClosestLatitude: location.Coordinates[1], + ClosestLongitude: location.Coordinates[0], + GddValues: gdds, + FirstDate: g.StartDate.Time().UTC(), } return returnGdds }