-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRoute.kt
113 lines (88 loc) · 3.71 KB
/
Route.kt
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package org.gnit.cpsd
import org.neo4j.driver.*
import java.io.FileOutputStream
import java.io.IOException
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.time.*
// cpsd: church planting strategy database
@OptIn(ExperimentalTime::class)
fun main(){
val duration = measureTime {
extractRoutes()
}
print("Finished in ${duration.toDouble(DurationUnit.SECONDS)} s.")
}
fun extractRoutes() {
val driver = getDriver();
val session = driver.session()
val stations = session.run("MATCH (s:Station) RETURN s;").list()
val churches = session.run("MATCH (c:Church) RETURN c;").list()
DuplicateOption.values().forEach { findDuplicates(churches, it) }
val totalRoutes = stations.size * churches.size
var searchCount: Int = 1
var recordCount: Int = 1
val path: Path = Paths.get("src/main/resources/routes.csv")
FileOutputStream(path.toFile(), true).bufferedWriter().use { writer ->
writer.appendLine("stationId,churchId,distance")
}
try {
stations.forEach { s ->
churches.forEach { c ->
val station = s.get("s").asNode()
val church = c.get("c").asNode()
val distance = distance(station, church)
if (distance < 5 * 1000) { // routes from church to station less than 5 km
println(
"recording $recordCount routes, " +
"searched $searchCount routes of total routes: $totalRoutes, " +
"${(searchCount.toDouble() / totalRoutes) * 100} % search done"
)
val stationId = station.get("id").asString()
val churchId = church.get("id").asString()
FileOutputStream(path.toFile(), true).bufferedWriter().use { writer ->
writer.appendLine("$stationId,$churchId,$distance")
}
/*val query = query(station, church, distance)
session.run(query)*/
recordCount++
}
searchCount++
}
}
} catch (ex: IOException) {
ex.printStackTrace()
}
session.close()
driver.close()
}
enum class DuplicateOption { NAME, ADDRESS, LAT_LNG, URL }
private fun findDuplicates(churches: MutableList<Record>, duplicateOption: DuplicateOption) {
churches.groupBy { it.get("c").asNode().get("url") }
println(churches.map {
val church = it.get("c").asNode()
when (duplicateOption) {
DuplicateOption.NAME -> church.get("name").toString()
DuplicateOption.ADDRESS -> church.get("address").toString()
DuplicateOption.LAT_LNG -> church.get("lat").toString() + church.get("lng").toString()
DuplicateOption.URL -> church.get("url").toString()
}
}.groupingBy { it }.eachCount().filter { it.value > 1 })
}
fun query(station: org.neo4j.driver.types.Node, church: org.neo4j.driver.types.Node, distance: Double): String {
val stationId = station.get("id").asString()
val churchId = church.get("id").asString()
return """
MATCH (c:Church), (s:Station)
WHERE s.id = '$stationId' AND c.url = '$churchId'
CREATE (s)-[r:ROUTE {distance: toFloat($distance)} ]->(c)
RETURN type(r)
""".trimIndent()
}
fun distance(station: org.neo4j.driver.types.Node, church: org.neo4j.driver.types.Node): Double {
val lat1 = station.get("lat").asDouble()
val lng1 = station.get("lng").asDouble()
val lat2 = church.get("lat").asDouble()
val lng2 = church.get("lng").asDouble()
return distanceOf(lat1 = lat1, lat2 = lat2, lng1 = lng1, lng2 = lng2, el1 = 1.0, el2 = 1.0)
}