Skip to content

Commit

Permalink
🎨fix #8 : modularly organize the location handler and add comments fo…
Browse files Browse the repository at this point in the history
…r each of the separate functions
  • Loading branch information
yedhink committed Apr 9, 2020
1 parent c2a3b01 commit 6e1018f
Showing 1 changed file with 46 additions and 47 deletions.
93 changes: 46 additions & 47 deletions internal/server/api_location_handler.go
Original file line number Diff line number Diff line change
@@ -1,76 +1,75 @@
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
d["message"] = "Invalid Date Format as Parameter"
}
}

// 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)
}
}

0 comments on commit 6e1018f

Please sign in to comment.