Skip to content
Snippets Groups Projects
Commit 3a7b7436 authored by Tucker Gary Siegel's avatar Tucker Gary Siegel
Browse files

fix csv

parent 8945d608
No related branches found
No related tags found
No related merge requests found
......@@ -2,9 +2,12 @@ package errors
import (
"fmt"
"log"
"os"
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/spf13/viper"
"log"
)
type BaseError interface {
......@@ -14,6 +17,7 @@ type BaseError interface {
type DawnError struct {
Name string `json:"name"`
Description string `json:"description"`
LogDetails string `json:"log_details,omitempty"`
Code int `json:"code"`
}
......@@ -38,26 +42,44 @@ func (err *DawnError) BuildStandardError(ctx *fiber.Ctx) StandardError {
return StandardError{Source: viper.GetString("app.name"), ErrorCode: err.Name, Description: err.Description, Details: details}
}
func (err *DawnError) AddLogDetails(logDetails string) *DawnError {
err.LogDetails = logDetails
return err
}
func (err *StandardError) LogJson() {
log.Println(err)
}
func (err *DawnError) LogString(c *fiber.Ctx) {
requestId := c.Locals("requestId")
output := strconv.Itoa(os.Getpid()) + " " + fmt.Sprintf("%s", requestId) + " " + strconv.Itoa(err.Code) + " - " + c.Method() + " " + c.Route().Path + " - " + err.Error() + " - " + err.LogDetails
fmt.Println(output)
}
func INVALID_PRODUCT(passedProduct string) *DawnError {
return &DawnError{
"INVALID_PRODUCT",
"Product type '" + passedProduct + "' is invalid",
400,
Name: "INVALID_PRODUCT",
Description: "Product type '" + passedProduct + "' is invalid",
Code: 400,
}
}
var BAD_REQUEST = &DawnError{
"BAD_REQUEST",
"Bad request was submitted",
400,
Name: "BAD_REQUEST",
Description: "Bad request was submitted",
Code: 400,
}
var NO_DATA_FOUND = &DawnError{
"NO_DATA_FOUND",
"No data found for request",
404,
Name: "NO_DATA_FOUND",
Description: "No data found for request",
Code: 404,
}
// 500s
var DATE_PARSE_FAILURE = &DawnError{
Name: "DATE_PARSE_FAILURE",
Description: "Date parse failure",
Code: 500,
}
......@@ -4,6 +4,7 @@ import (
"dawn-weather/config"
"dawn-weather/errors"
"dawn-weather/persistence"
"fmt"
"github.com/ansrivas/fiberprometheus/v2"
swagger "github.com/arsmn/fiber-swagger/v2"
......@@ -67,8 +68,11 @@ func createFiberConfig() fiber.Config {
if e, ok := err.(*errors.DawnError); ok {
code = e.Code
message = err.(*errors.DawnError).BuildStandardError(ctx)
err.(*errors.DawnError).LogString(ctx)
} else {
fmt.Println(err)
}
message.LogJson()
// message.LogJson()
err = ctx.Status(code).JSON(message)
......
......@@ -32,7 +32,7 @@ type CSVRequest struct {
Primary bool `json:"primary"`
ComparisonYear int `json:"comparison_year"`
Product string `json:"product"`
Range int `json:"range"`
Range float64 `json:"range"`
Temperature int `json:"temperature"`
Year int `json:"year"`
Latitude float64 `json:"latitude"`
......@@ -76,6 +76,7 @@ func (r CSVRequest) Build(c *fiber.Ctx) CSVRequest {
latitude, _ := strconv.ParseFloat(c.Query("latitude", "-1000.0"), 64)
longitude, _ := strconv.ParseFloat(c.Query("longitude", "-1000.0"), 64)
_range, _ := strconv.ParseFloat(c.Query("range", "-1000.0"), 64)
newRequest := CSVRequest{
Analog: parseBool(c.Query("analog")),
......@@ -93,7 +94,7 @@ func (r CSVRequest) Build(c *fiber.Ctx) CSVRequest {
ComparisonYear: atoi(c.Query("comparison_year", "0")),
Product: c.Query("product", "NONE"),
Range: atoi(c.Query("range", "0")),
Range: _range,
Temperature: atoi(c.Query("temperature", "0")),
Year: atoi(c.Query("year", "0")),
Latitude: latitude,
......
......@@ -3,6 +3,7 @@ package services
import (
"dawn-weather/errors"
"dawn-weather/models"
"dawn-weather/models/enums"
"dawn-weather/persistence"
"dawn-weather/persistence/entities"
"encoding/csv"
......@@ -12,47 +13,56 @@ import (
"math"
"os"
"strconv"
"strings"
"time"
"github.com/google/uuid"
)
type CSVData struct {
Date []time.Time
Analog []float64
Cfs []float64
CfsLower []float64
CfsUpper []float64
Comparison []float64
FirstFreezing []int
LastFreezing []int
GEFS []float64
Maximum []float64
Minimum []float64
Normals []float64
Primary []float64
}
func fillKeys(request models.CSVRequest) []string {
keys := []string{}
if request.Analog {
keys = append(keys, "Date")
}
keys = append(keys, "Date")
if request.Analog {
keys = append(keys, "Analog Year GDD")
}
// if request.Cfs {
// keys = append(keys, "CFS GDD")
// }
// if request.CfsLower {
// keys = append(keys, "CFS Lower Boundary GDD")
// }
// if request.CfsUpper {
// keys = append(keys, "CFS Upper Boundary GDD")
// }
// if request.Comparison {
// keys = append(keys, "Comparison Year GDD")
// }
// if request.FirstFreezing {
// keys = append(keys, "First Freezing Date Counts")
// }
// if request.Gefs {
// keys = append(keys, "GEFS GDD")
// }
// if request.LastFreezing {
// keys = append(keys, "Last Freezing Date Counts")
// }
// if request.Maximum {
// keys = append(keys, "Confidence Interval Upper Boundary")
// }
// if request.Minimum {
// keys = append(keys, "Confidence Interval Lower Boundary")
// }
if request.Cfs || request.CfsLower || request.CfsUpper {
keys = append(keys, "CFS GDD")
keys = append(keys, "CFS Lower Boundary GDD")
keys = append(keys, "CFS Upper Boundary GDD")
}
if request.Comparison {
keys = append(keys, "Comparison Year GDD ("+strconv.Itoa(request.ComparisonYear)+")")
}
if request.FirstFreezing || request.LastFreezing {
keys = append(keys, "First Freezing Date Counts")
keys = append(keys, "Last Freezing Date Counts")
}
if request.Gefs {
keys = append(keys, "GEFS GDD")
}
if request.Maximum {
keys = append(keys, "Confidence Interval Upper Boundary")
}
if request.Minimum {
keys = append(keys, "Confidence Interval Lower Boundary")
}
if request.Normals {
keys = append(keys, "Thirty Year Normal GDD")
}
......@@ -137,6 +147,282 @@ func getAnalogYear(request models.CSVRequest, dates []time.Time) []float64 {
return gddValues
}
func _parseDate(date string) time.Time {
const layout = "2006-Jan-02"
newDate, e := time.Parse(layout, date)
if e != nil {
panic(errors.DATE_PARSE_FAILURE.AddLogDetails(e.Error()))
}
return newDate
}
func parseDate(date string) time.Time {
split := strings.Split(date, "-")
day := split[1]
switch split[0] {
case "01":
return _parseDate("1981-Jan-" + day)
case "02":
return _parseDate("1981-Feb-" + day)
case "03":
return _parseDate("1981-Mar-" + day)
case "04":
return _parseDate("1981-Apr-" + day)
case "05":
return _parseDate("1981-May-" + day)
case "06":
return _parseDate("1981-Jun-" + day)
case "07":
return _parseDate("1981-Jul-" + day)
case "08":
return _parseDate("1981-Aug-" + day)
case "09":
return _parseDate("1981-Sep-" + day)
case "10":
return _parseDate("1981-Oct-" + day)
case "11":
return _parseDate("1981-Nov-" + day)
case "12":
return _parseDate("1981-Dev-" + day)
}
panic(errors.DATE_PARSE_FAILURE.AddLogDetails("Failed converting " + date + " to proper format."))
}
func getFreezingDates(request models.CSVRequest, dates []time.Time) [][]int {
freezingRequest := models.FreezingDateRequest{
Latitude: request.Latitude,
Longitude: request.Longitude,
FreezingTemp: request.Temperature,
}
response := GetFreezingDate(freezingRequest)
firstFreezingDates := make(map[time.Time]int)
lastFreezingDates := make(map[time.Time]int)
for k, v := range response.LastDateCounts {
date := parseDate(k)
lastFreezingDates[date] = v
}
for k, v := range response.FirstDateCounts {
date := parseDate(k)
firstFreezingDates[date] = v
}
date := time.Date(1981, time.January, 1, 0, 0, 0, 0, time.UTC)
lastFreezingValues := []int{}
firstFreezingValues := []int{}
for i := 0; i < 366; i++ {
if val, ok := lastFreezingDates[date]; ok {
lastFreezingValues = append(lastFreezingValues, val)
firstFreezingValues = append(firstFreezingValues, int(math.NaN()))
} else if val, ok := firstFreezingDates[date]; ok {
firstFreezingValues = append(firstFreezingValues, val)
lastFreezingValues = append(lastFreezingValues, int(math.NaN()))
} else {
firstFreezingValues = append(firstFreezingValues, int(math.NaN()))
lastFreezingValues = append(lastFreezingValues, int(math.NaN()))
}
date = date.Add(time.Duration(24) * time.Hour)
}
return [][]int{firstFreezingValues, lastFreezingValues}
}
func getComparisonYear(request models.CSVRequest, dates []time.Time) []float64 {
gddRequest := models.GddRequest{
Year: request.ComparisonYear,
Product: request.Product,
Latitude: request.Latitude,
Longitude: request.Longitude,
Accumulate: true,
}
gddValues := GetGddValues(gddRequest).GddValues
for len(gddValues) < 365 {
gddValues = append(gddValues, math.NaN())
}
return gddValues
}
func getConfidenceInterval(request models.CSVRequest, dates []time.Time) [][]float64 {
ciRequest := models.ConfidenceIntervalRequest{
Interval: request.Range,
Product: enums.GetProductFromString(request.Product),
Latitude: request.Latitude,
Longitude: request.Longitude,
}
response := GetConfidenceInterval(ciRequest)
return [][]float64{response.LowerBound, response.UpperBound}
}
func getCfsData(request models.CSVRequest, dates []time.Time) [][]float64 {
gddRequest := models.GddRequest{
Year: request.Year,
Product: request.Product,
Latitude: request.Latitude,
Longitude: request.Longitude,
Accumulate: true,
}
response := GetCfsGddValues(gddRequest)
fullGddValues := []float64{}
fullLowerBound := []float64{}
fullUpperBound := []float64{}
in := false
after := false
c := 0
date := time.Date(response.FirstDate.Year(), time.January, 1, 0, 0, 0, 0, time.UTC)
for i := 0; i < 366; i++ {
if response.FirstDate.After(date) {
fullGddValues = append(fullGddValues, math.NaN())
fullLowerBound = append(fullLowerBound, math.NaN())
fullUpperBound = append(fullUpperBound, math.NaN())
} else {
if in || response.FirstDate == date {
if c >= len(response.GddValues) {
in = false
after = true
} else {
in = true
fullGddValues = append(fullGddValues, response.GddValues[c])
fullLowerBound = append(fullLowerBound, response.LowerBound[c])
fullUpperBound = append(fullUpperBound, response.UpperBound[c])
c += 1
}
} else if after {
fullGddValues = append(fullGddValues, math.NaN())
fullLowerBound = append(fullLowerBound, math.NaN())
fullUpperBound = append(fullUpperBound, math.NaN())
}
}
date = date.Add(time.Duration(24) * time.Hour)
}
return [][]float64{fullGddValues, fullLowerBound, fullUpperBound}
}
func getGefsData(request models.CSVRequest, dates []time.Time) []float64 {
gddRequest := models.GddRequest{
Year: request.Year,
Product: request.Product,
Latitude: request.Latitude,
Longitude: request.Longitude,
Accumulate: true,
}
response := GetGefsGddValues(gddRequest)
fullGddValues := []float64{}
in := false
after := false
c := 0
date := time.Date(response.FirstDate.Year(), time.January, 1, 0, 0, 0, 0, time.UTC)
for i := 0; i < 366; i++ {
if response.FirstDate.After(date) {
fullGddValues = append(fullGddValues, math.NaN())
} else {
if in || response.FirstDate == date {
if c >= len(response.GddValues) {
in = false
after = true
} else {
in = true
fullGddValues = append(fullGddValues, response.GddValues[c])
c += 1
}
} else if after {
fullGddValues = append(fullGddValues, math.NaN())
}
}
date = date.Add(time.Duration(24) * time.Hour)
}
return fullGddValues
}
func pullData(request models.CSVRequest) CSVData {
returnData := CSVData{}
dates := fillDates()
returnData.Date = dates
if request.Analog {
returnData.Analog = getAnalogYear(request, dates)
}
if request.Cfs || request.CfsLower || request.CfsUpper {
t := getCfsData(request, dates)
returnData.Cfs = t[0]
returnData.CfsLower = t[1]
returnData.CfsUpper = t[2]
}
if request.Comparison {
returnData.Comparison = getComparisonYear(request, dates)
}
if request.FirstFreezing || request.LastFreezing {
t := getFreezingDates(request, dates)
returnData.FirstFreezing = t[0]
returnData.LastFreezing = t[1]
}
if request.Gefs {
returnData.GEFS = getGefsData(request, dates)
}
if request.Maximum || request.Minimum {
ci := getConfidenceInterval(request, dates)
returnData.Maximum = ci[1]
returnData.Minimum = ci[0]
}
if request.Normals {
returnData.Normals = getNormals(request, dates)
}
if request.Primary {
returnData.Primary = getPrimary(request, dates)
}
return returnData
}
func createRecords(keys []string, data CSVData) [][]string {
records := [][]string{keys}
for i := 1; i < 366; i++ {
temp := []string{timeToString(data.Date[i-1])}
if len(data.Analog) != 0 {
temp = append(temp, fmt.Sprintf("%f", data.Analog[i-1]))
}
if len(data.Cfs) != 0 {
temp = append(temp, fmt.Sprintf("%f", data.Cfs[i-1]))
temp = append(temp, fmt.Sprintf("%f", data.CfsLower[i-1]))
temp = append(temp, fmt.Sprintf("%f", data.CfsUpper[i-1]))
}
if len(data.Comparison) != 0 {
temp = append(temp, fmt.Sprintf("%f", data.Comparison[i-1]))
}
if len(data.FirstFreezing) != 0 {
temp = append(temp, fmt.Sprintf("%d", data.FirstFreezing[i-1]))
temp = append(temp, fmt.Sprintf("%d", data.LastFreezing[i-1]))
}
if len(data.GEFS) != 0 {
temp = append(temp, fmt.Sprintf("%f", data.GEFS[i-1]))
}
if len(data.Maximum) != 0 {
temp = append(temp, fmt.Sprintf("%f", data.Maximum[i-1]))
temp = append(temp, fmt.Sprintf("%f", data.Minimum[i-1]))
}
if len(data.Normals) != 0 {
temp = append(temp, fmt.Sprintf("%f", data.Normals[i-1]))
}
if len(data.Primary) != 0 {
temp = append(temp, fmt.Sprintf("%f", data.Primary[i-1]))
}
records = append(records, temp)
}
return records
}
func GetDataDownload(request models.CSVRequest) string {
fileId := uuid.New()
......@@ -150,21 +436,10 @@ func GetDataDownload(request models.CSVRequest) string {
w := csv.NewWriter(f)
keys := fillKeys(request)
dates := fillDates()
primary := getPrimary(request, dates)
normals := getNormals(request, dates)
analog := getAnalogYear(request, dates)
records := [][]string{keys}
data := pullData(request)
for i := 1; i < 366; i++ {
records = append(records,
[]string{timeToString(dates[i-1]),
fmt.Sprintf("%f", analog[i-1]),
fmt.Sprintf("%f", primary[i-1]),
fmt.Sprintf("%f", normals[i-1]),
})
}
records := createRecords(keys, data)
for _, record := range records {
if err := w.Write(record); err != nil {
......@@ -176,6 +451,9 @@ func GetDataDownload(request models.CSVRequest) string {
fileText, err := ioutil.ReadFile(fileId.String() + ".csv")
f.Close()
os.Remove(fileId.String() + ".csv")
e := os.Remove(fileId.String() + ".csv")
if e != nil {
log.Fatal(e)
}
return string(fileText)
}
......@@ -31,7 +31,6 @@ func isLeapYear(year int) bool {
func GetFreezingDate(request models.FreezingDateRequest) models.FreezingDateResponse {
// product := enums.GetProductFromString(request.Product)
var freezingDates entities.FreezingDates
freezingDates = persistence.FindFreezingDates(request.BuildLocation())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment