From 6e1018fc7121d22078fd950a35710b15a043a15b Mon Sep 17 00:00:00 2001 From: yedhink Date: Thu, 9 Apr 2020 22:25:37 +0530 Subject: [PATCH] :art:fix #8 : modularly organize the location handler and add comments for each of the separate functions --- internal/server/api_location_handler.go | 93 ++++++++++++------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/internal/server/api_location_handler.go b/internal/server/api_location_handler.go index ab51526..e83f3aa 100644 --- a/internal/server/api_location_handler.go +++ b/internal/server/api_location_handler.go @@ -1,32 +1,42 @@ package server import ( - "time" - "github.com/gin-gonic/gin" + . "github.com/yedhink/covid19-kerala-api/internal/date" . "github.com/yedhink/covid19-kerala-api/internal/storage" ) -type Locations struct { +type Query struct { Loc []string `form:"loc"` Date string `form:"date"` } -func filterByLoc(value map[string]interface{}, key string, d map[string]interface{}, userLoc []string) { +// goes through all the input loc and append matches from value obj to the obj d +// value is server.JsonData.All.Data[timestamp], d is the result and userLoc contains all loc params +func filterByLoc(value map[string]interface{}, d map[string]interface{}, userLoc []string) { for _, loc := range userLoc { - d[key].(map[string]interface{})[loc] = value[loc] + d[loc] = value[loc] } } -func parseDate(k string, s string) (time.Time, time.Time) { - userDate, err := time.Parse("02-01-2006", s) - if err != nil { - userDate, _ = time.Parse("02/01/2006", s) - } - userDate.Format(time.RFC3339) - keyDate, _ := time.Parse(time.RFC3339, k) - return keyDate, userDate -} +// q is the Query struct, d is our final result, st is Storage referenc and apiData is server.JsonData.All.Data +// the function validates the date and filters using loc and date parameters of user +func LocDateFilter(q *Query, d map[string]interface{}, st *Storage, apiData map[string]interface{}, locExist bool) { + // start by checking if the date param value is valid formatted Date + switch IsDate(q.Date) { + case true: + for key, value := range apiData { + if ValidDate(key, q.Date, st) { + // if loc length > 0 then only filterByLoc + if locExist == true { + d[key] = make(map[string]interface{}, len(q.Loc)) + filterByLoc(value.(map[string]interface{}), d[key].(map[string]interface{}), q.Loc) + } else { + // if no loc, then just assign to valid date + d[key] = value + } + } + } // if the date is not correctly formatted case false: d["success"] = false @@ -34,43 +44,32 @@ func parseDate(k string, s string) (time.Time, time.Time) { } } +// handles the /location related parameter and non-parametric queries func (server *Server) Location(st *Storage) gin.HandlerFunc { return func(c *gin.Context) { - var l Locations - c.Bind(&l) - if len(l.Loc) > 0 { - d := make(map[string]interface{}) - d["success"] = true + var q Query + c.Bind(&q) + // initialize the final result 'd' with success=true + d := make(map[string]interface{}) + d["success"] = true + // check if loc param is nil or not + switch length := len(q.Loc); { + //serve the array of locations + case length == 0 && q.Date == "": + d = server.JsonData.Districts.Loc + // validate just the date and append matching obj entries + case length == 0 && q.Date != "": + LocDateFilter(&q, d, st, server.JsonData.All.Data, false) + // just filter by loc parameter + case length > 0 && q.Date == "": for key, value := range server.JsonData.All.Data { - // since we cant assert a value interface of type bool as map[string]interface{} - if key == "success" { - continue - } - if l.Date != "" { - if validateDate(key, l.Date, st) { - d[key] = make(map[string]interface{}, len(l.Loc)) - filterByLoc(value.(map[string]interface{}), key, d, l.Loc) - } - } else { - d[key] = make(map[string]interface{}, len(l.Loc)) - filterByLoc(value.(map[string]interface{}), key, d, l.Loc) - } - } - c.IndentedJSON(200, d) - } else { - if l.Date != "" { - d := make(map[string]interface{}) - d["success"] = true - for key, value := range server.JsonData.All.Data { - if key != "success" && validateDate(key, l.Date, st) { - d[key] = value - } - } - c.IndentedJSON(200, d) - } else { - server.JsonData.Districts.Loc["success"] = true - c.IndentedJSON(200, server.JsonData.Districts.Loc) + d[key] = make(map[string]interface{}, len(q.Loc)) + filterByLoc(value.(map[string]interface{}), d[key].(map[string]interface{}), q.Loc) } + // filter by both loc and date params + case length > 0 && q.Date != "": + LocDateFilter(&q, d, st, server.JsonData.All.Data, true) } + c.IndentedJSON(200, d) } }