-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathGraphUtil.scala
More file actions
74 lines (69 loc) · 2.14 KB
/
GraphUtil.scala
File metadata and controls
74 lines (69 loc) · 2.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package utils
import play.api.libs.json._
/**
* A custom graph theory utility based on the simplicity
*
* Philosophies
* - Given a JSON, return a pure value
* - Given an value and a JSON, result a JSON
* - Given a JSON, return a JSON
* - Strictly follows the Graph Theory
* - JSON data is based on ScalaJson
*/
class GraphUtil {
def getNodesByKeyVal(graph: JsValue, key: String, value: String): List[JsValue] = {
(graph \ "nodes").get.as[List[JsValue]].filter(x => (x \ key).as[String] == value)
}
/**
* Retreives a simple list of direct successors' IDs from a node
*
* @example
* // .. [{ from: "t1", to: "t2" }, { from: "t2", to: "t3" }, { from: "t3", to: "t4" }]
* getDirectSuccessors(graph, "t2")
* // Result: [ "t3" ]
*
* @param json
* @param node
* @return
*/
def getDirectSuccessors(graph: JsValue, node: String): List[String] = {
val edges = (graph \ "edges").get
val sources = edges.as[List[JsValue]].filter(x => (x \ "from").as[String] == node)
sources.map(x => (x \ "to").as[String])
}
/**
* Get all paths until there are no more direct successors left
*
* @example
* // .. [{ from: "t1", to: "t2" }, { from: "t2", to: "t3" }, { from: "t3", to: "t4" }]
* getAllPaths(graph, "t1")
* // Result: [ ["t1", "t2", "t3", "t4"] ]
*
* @param graph
* @param startingNode
* @return
*/
def getAllPaths(graph: JsValue, startingNode: String): List[Any] = {
def traverse(node: String, paths: List[String]): List[Any] = {
val directs = getDirectSuccessors(graph, node)
if (directs.length == 0) {
// Dead end
paths
} else if (directs.length == 1) {
// Node with single direction, simply returns itself
if (paths.length == 0) {
// instead of appending successor, append itself
traverse(directs(0), paths :+ startingNode :+ directs(0))
} else {
traverse(directs(0), paths :+ directs(0))
}
} else {
directs.map(d => {
traverse(d, paths :+ d)
})
}
}
val accum = List[String]()
traverse(startingNode, accum)
}
}