-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPrintStatistics.kt
150 lines (128 loc) · 5.21 KB
/
PrintStatistics.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package tasks.print_statistics
import de.westnordost.osm_opening_hours.parser.toOpeningHoursOrNull
import okio.FileSystem
import okio.Path.Companion.toPath
import java.io.ByteArrayInputStream
import java.util.Locale
import kotlin.time.Duration
import kotlin.time.TimeSource
fun main() {
val file = "./src/jvmTest/resources/opening_hours_counts.tsv"
val lines = FileSystem.SYSTEM.read(file.toPath()) { readUtf8() }
.lineSequence()
.drop(1)
.filterNot { it.isBlank() }
.map { line ->
val t = line.lastIndexOf('\t')
val oh = line.substring(1, t - 1)
val count = line.substring(t + 1).toInt()
oh to count
}
.toList()
.asReversed()
val invalidButUnambiguousOhStrings = mutableListOf<String>()
val invalidOhStrings = mutableListOf<String>()
val timeSource = TimeSource.Monotonic
var total = 0L
var parseTime = Duration.ZERO
var parseStrictTime = Duration.ZERO
var createTime = Duration.ZERO
var parsed = 0L
var valid = 0L
var canonical = 0L
var pooleParseTime = Duration.ZERO
var pooleParseStrictTime = Duration.ZERO
var pooleCreateTime = Duration.ZERO
var pooleParsed = 0L
var pooleValid = 0L
var pooleCanonical = 0L
for ((oh, count) in lines) {
var pooleHoursString: String? = null
var hoursString: String? = null
var mark = timeSource.markNow()
val pooleHours = pooleParse(oh, strict = false)
pooleParseTime += (timeSource.markNow() - mark) * count
if (pooleHours != null) {
pooleParsed += count
mark = timeSource.markNow()
pooleHoursString = pooleCreate(pooleHours)
pooleCreateTime += (timeSource.markNow() - mark) * count
if (pooleHoursString == oh) {
pooleCanonical += count
}
}
mark = timeSource.markNow()
if (pooleParse(oh, strict = true) != null) {
pooleValid += count
}
pooleParseStrictTime += (timeSource.markNow() - mark) * count
mark = timeSource.markNow()
val hours = oh.toOpeningHoursOrNull(lenient = true)
parseTime += (timeSource.markNow() - mark) * count
if (hours != null) {
mark = timeSource.markNow()
hoursString = hours.toString()
createTime += (timeSource.markNow() - mark) * count
parsed += count
if (hoursString == oh) {
canonical += count
}
}
mark = timeSource.markNow()
val strictHours = oh.toOpeningHoursOrNull(lenient = false)
parseStrictTime += (timeSource.markNow() - mark) * count
if (strictHours != null) {
valid += count
}
if (strictHours == null && hours != null) {
invalidButUnambiguousOhStrings.add("$count\t$oh\r\n")
}
if (strictHours == null && hours == null) {
invalidOhStrings.add("$count\t$oh\r\n")
}
total += count
}
FileSystem.SYSTEM.write("./src/jvmTest/resources/invalid_but_unambiguous_opening_hours.tsv".toPath()) {
invalidButUnambiguousOhStrings.asReversed().forEach { writeUtf8(it) }
}
FileSystem.SYSTEM.write("./src/jvmTest/resources/invalid_opening_hours.tsv".toPath()) {
invalidOhStrings.asReversed().forEach { writeUtf8(it) }
}
println("Parsed $total opening hours strings.")
println()
println("ch.poole.openinghoursparser: ")
print("${(100.0 * pooleValid / total).digits(2)}% are valid, ")
print("${(100.0 * pooleParsed / total).digits(2)}% can be parsed, ")
print("${(100.0 * pooleCanonical / total).digits(2)}% are in canonical form ")
println()
print("Average parse times: ")
print("${(1.0 * pooleParseStrictTime.inWholeMicroseconds / total).digits(2)}μs in strict mode, ")
print("${(1.0 * pooleParseTime.inWholeMicroseconds / total).digits(2)}μs in lenient mode.")
println()
print("Average creation time: ")
print("${(1.0 * pooleCreateTime.inWholeMicroseconds / total).digits(2)}μs")
println()
println()
println("de.westnordost.osm_opening_hours: ")
print("${(100.0 * valid / total).digits(2)}% are valid, ")
print("${(100.0 * parsed / total).digits(2)}% can be parsed, ")
print("${(100.0 * canonical / total).digits(2)}% are in canonical form ")
println()
print("Average parse times: ")
print("${(1.0 * parseStrictTime.inWholeMicroseconds / total).digits(2)}μs in strict mode, ")
print("${(1.0 * parseTime.inWholeMicroseconds / total).digits(2)}μs in lenient mode.")
println()
print("Average creation time: ")
print("${(1.0 * createTime.inWholeMicroseconds / total).digits(2)}μs")
println()
println()
}
private fun pooleParse(openingHours: String, strict: Boolean) =
try {
ch.poole.openinghoursparser.OpeningHoursParser(ByteArrayInputStream(openingHours.toByteArray())).rules(strict)
} catch (e: ch.poole.openinghoursparser.ParseException) {
null
}
private fun pooleCreate(rules: List<ch.poole.openinghoursparser.Rule>) =
ch.poole.openinghoursparser.Util.rulesToOpeningHoursString(rules)
private fun Double.digits(d: Int) = "%.${d}f".format(Locale.US, this)