github.com/hzck/speedroute@v0.0.0-20201115191102-403b7d0e443f/parser/jsonconverter.go (about) 1 // Package parser manages JSON/XML object and converts them into a graph. 2 package parser 3 4 import ( 5 "encoding/json" 6 "io/ioutil" 7 8 m "github.com/hzck/speedroute/model" 9 ) 10 11 type rewardRef struct { 12 RewardID string `json:"rewardId"` 13 Quantity *int `json:"quantity"` 14 } 15 16 type graph struct { 17 Rewards []reward `json:"rewards"` 18 Nodes []node `json:"nodes"` 19 Edges []edge `json:"edges"` 20 StartID string `json:"startId"` 21 EndID string `json:"endId"` 22 } 23 24 type reward struct { 25 ID string `json:"id"` 26 Unique bool `json:"unique"` 27 IsA string `json:"isA"` 28 } 29 30 type node struct { 31 ID string `json:"id"` 32 Rewards []rewardRef `json:"rewards"` 33 Revisitable bool `json:"revisitable"` 34 } 35 36 type weight struct { 37 Time string `json:"time"` 38 Requirements []rewardRef `json:"requirements"` 39 } 40 41 type edge struct { 42 From string `json:"from"` 43 To string `json:"to"` 44 Weights []weight `json:"weights"` 45 } 46 47 // CreateGraphFromFile takes a path as a parameter and creates rewards, nodes and edges before 48 // returning a pointer to a graph. 49 func CreateGraphFromFile(path string) (*m.Graph, error) { 50 file, err := ioutil.ReadFile(path) 51 if err != nil { 52 return nil, err 53 } 54 55 var g graph 56 err = json.Unmarshal(file, &g) 57 if err != nil { 58 return nil, err 59 } 60 61 rewards := make(map[string]*m.Reward) 62 // ugly loop to make sure to handle different ordered rewards 63 for rewardAdded := true; rewardAdded; { 64 rewardAdded = false 65 for _, r := range g.Rewards { 66 if rewards[r.ID] == nil && (r.IsA == "" || rewards[r.IsA] != nil) { 67 rewards[r.ID] = m.CreateReward(r.ID, r.Unique, rewards[r.IsA]) 68 rewardAdded = true 69 } 70 } 71 } 72 73 nodes := make(map[string]*m.Node) 74 for _, n := range g.Nodes { 75 node := m.CreateNode(n.ID, n.Revisitable) 76 for _, rewardRef := range n.Rewards { 77 // duplicate code 78 node.AddReward(rewards[rewardRef.RewardID], getPointerValueOrOne(rewardRef.Quantity)) 79 } 80 nodes[node.ID()] = node 81 } 82 83 for _, e := range g.Edges { 84 edge := m.CreateEdge(nodes[e.From], nodes[e.To]) 85 for _, w := range e.Weights { 86 time, err := parseTime(w.Time) 87 if err != nil { 88 return nil, err 89 } 90 weight := m.CreateWeight(time) 91 for _, rewardRef := range w.Requirements { 92 // duplicate code 93 weight.AddRequirement(rewards[rewardRef.RewardID], getPointerValueOrOne(rewardRef.Quantity)) 94 } 95 edge.AddWeight(weight) 96 } 97 } 98 return m.CreateGraph(nodes[g.StartID], nodes[g.EndID]), nil 99 } 100 101 func getPointerValueOrOne(ptr *int) int { 102 if ptr != nil { 103 return *ptr 104 } 105 return 1 106 } 107 108 // CreateJSONFromRoutedPath takes an array of edges and creates an array of the included nodes, 109 // and marshals it as json data in a byte array. 110 func CreateJSONFromRoutedPath(path []*m.Edge) ([]byte, error) { 111 if len(path) == 0 { 112 return json.Marshal(path) 113 } 114 result := make([]string, len(path)+1) 115 result[0] = path[0].From().ID() 116 for i := 1; i < len(result); i++ { 117 result[i] = path[i-1].To().ID() 118 } 119 return json.Marshal(result) 120 }