Skip to content

Commit b125edb

Browse files
Competition round 1
1 parent 2449ab6 commit b125edb

File tree

103 files changed

+1020351
-35322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1020351
-35322
lines changed
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import io.vertx.core.json.Json
2+
import io.vertx.core.json.JsonObject
3+
import org.funktionale.collections.tail
4+
import org.jetbrains.research.kotopunter.config.Config
5+
import org.jetbrains.research.kotopunter.database.tables.records.GameRecord
6+
import org.jetbrains.research.kotopunter.dispatch.GameFinished
7+
import org.jetbrains.research.kotopunter.dispatch.Update
8+
import org.jetbrains.research.kotopunter.eventbus.Address
9+
import org.jetbrains.research.kotopunter.util.*
10+
import java.io.File
11+
import java.util.*
12+
import java.util.concurrent.TimeUnit
13+
14+
object Competition {
15+
16+
fun runServer(punters: Int, map: File) = ProcessBuilder(
17+
"lampunt",
18+
"--coordinates",
19+
"--address",
20+
"0.0.0.0",
21+
"--port",
22+
"9000",
23+
"--punters",
24+
"$punters",
25+
"--move-timeout",
26+
"${Config.Game.Timeout}",
27+
"--map",
28+
map.absolutePath
29+
).also { println("Running ${it.command().joinToString(" ")}") }
30+
.let { pb -> pb.redirectErrorStream(true).start()!! }
31+
32+
fun lineToJson(line: String): JsonObject? {
33+
val reLine = line.removePrefix("lampunt: main: ")
34+
if (reLine.startsWith("JSON:")) {
35+
return JsonObject(reLine.substringAfter("JSON:"))
36+
}
37+
return null
38+
}
39+
40+
fun getLog(process: Process): JsonObject {
41+
println("Game created")
42+
43+
val lines = process.inputStream.bufferedReader().lineSequence()
44+
val logArray = jsonArrayOf(JsonObject("start" to JsonObject()))
45+
for (line in lines) {
46+
lineToJson(line)?.let { logArray += it }
47+
}
48+
49+
process.waitFor(5, TimeUnit.SECONDS)
50+
println("Game finished")
51+
process.destroy()
52+
53+
logArray += JsonObject("stop" to JsonObject())
54+
return JsonObject("game" to logArray)
55+
}
56+
57+
fun runClient(dir: File) =
58+
ProcessBuilder("bash", "${dir.absolutePath}/go.sh")
59+
.apply { println("Running ${command()}") }
60+
.redirectErrorStream(true)
61+
.start()
62+
.apply {
63+
Thread {
64+
val reader = this.inputStream.bufferedReader()
65+
while(this.isAlive) {
66+
if(reader.ready()) reader.readLine().let { println("${dir.name}: $it") }
67+
}
68+
}.start()
69+
}
70+
71+
72+
val scoring = mutableMapOf<String, Int>()
73+
val points = mutableMapOf<String, Long>()
74+
75+
fun runRound(map: File, clients: List<File>): JsonObject {
76+
val pb = runServer(clients.size, map)
77+
val clientProcesses = clients.map { Thread.sleep(500); runClient(it) }
78+
val log = getLog(pb)
79+
clientProcesses.forEach {
80+
it.waitFor(1, TimeUnit.SECONDS)
81+
it.destroyForcibly()
82+
}
83+
val roundRes = log
84+
.getJsonArray("game")
85+
.filterIsInstance<JsonObject>()
86+
.find { it.containsKey("scores") }!!
87+
.getJsonArray("scores")
88+
.filterIsInstance<JsonObject>()
89+
.sortedByDescending { it.getInteger("score") }
90+
91+
var score = roundRes.size
92+
for(res in roundRes) {
93+
val team = res.getString("team")
94+
points[team] = points.getOrDefault(team, 0) + res.getLong("score")
95+
scoring[team] = scoring.getOrDefault(team, 0) + score
96+
score--
97+
}
98+
return log
99+
}
100+
101+
lateinit var baseDir: String
102+
lateinit var teamDirs: List<File>
103+
val joe by lazy { File(File(baseDir, "teams"), "\$average_joe") }
104+
val mack by lazy { File(File(baseDir, "teams"), "\$nasty_mack") }
105+
106+
fun sanityCheckRound() {
107+
val scores = mutableMapOf<File, Int>()
108+
teamDirs.forEach { team -> scores[team] = 0 }
109+
110+
teamDirs.forEach { team ->
111+
val res = runRound(File("maps/default.json"), listOf(team))
112+
File("sanity", "${team.name}.json").apply { parentFile.mkdirs() }.writeText(res.encodePrettily())
113+
scores[team] = (scores[team] ?: 0) +
114+
res
115+
.getJsonArray("game")
116+
.filterIsInstance<JsonObject>()
117+
.find { it.containsKey("scores") }!!
118+
.getJsonArray("scores")
119+
.filterIsInstance<JsonObject>()
120+
.first()
121+
.getInteger("score")
122+
}
123+
124+
teamDirs.forEach { team ->
125+
val res = runRound(File("maps/lambda.json"), listOf(team))
126+
File("sanity2", "${team.name}.json").apply { parentFile.mkdirs() }.writeText(res.encodePrettily())
127+
scores[team] = (scores[team] ?: 0) +
128+
res
129+
.getJsonArray("game")
130+
.filterIsInstance<JsonObject>()
131+
.find { it.containsKey("scores") }!!
132+
.getJsonArray("scores")
133+
.filterIsInstance<JsonObject>()
134+
.first()
135+
.getInteger("score")
136+
}
137+
138+
for ((team, score) in scores) if(score == 0) teamDirs -= team
139+
}
140+
141+
fun firstRound() {
142+
val maps = listOf("vancouver", "boston", "triangle", "star")
143+
144+
maps.forEach { map ->
145+
val mapFile = File("maps/$map.json")
146+
teamDirs.forEachIndexed { i, team ->
147+
val res = runRound(mapFile, listOf(team, joe))
148+
File("round1", "$map-$i.json").apply { parentFile.mkdirs() }.writeText(res.encodePrettily())
149+
}
150+
}
151+
152+
}
153+
154+
fun secondRound() {
155+
val firsts = ArrayList(teamDirs)
156+
Collections.shuffle(firsts, ThreadLocalRandom())
157+
val seconds = ArrayList(firsts).also { Collections.rotate(it, 1) }
158+
val thirds = ArrayList(firsts).also { Collections.rotate(it, -1) }
159+
160+
val groups = (firsts zip seconds zip thirds).map { (a, b) -> Triple(a.first, a.second, b) }
161+
162+
val maps = listOf("vancouver", "boston", "triangle", "star", "oxford-10000", "icfp-coauthors-pj")
163+
164+
maps.forEach { map ->
165+
val mapFile = File("maps/$map.json")
166+
groups.forEachIndexed { i, group ->
167+
val res = runRound(mapFile, group.toList())
168+
File("round2", "$map-$i.json").apply { parentFile.mkdirs() }.writeText(res.encodePrettily())
169+
}
170+
}
171+
172+
}
173+
174+
fun thirdRound() {
175+
val maps = listOf("vancouver", "boston", "triangle", "star", "gothenburg")
176+
177+
maps.forEach { map ->
178+
val mapFile = File("maps/$map.json")
179+
teamDirs.forEachIndexed { i, team ->
180+
val res = runRound(mapFile, listOf(team, mack))
181+
File("round3", "$map-$i.json").apply { parentFile.mkdirs() }.writeText(res.encodePrettily())
182+
}
183+
}
184+
}
185+
186+
@JvmStatic
187+
fun main(args: Array<String>) {
188+
189+
baseDir = args.firstOrNull() ?: System.getProperty("user.dir")
190+
teamDirs = File(baseDir, "teams").listFiles().filter { it.isDirectory && !it.name.startsWith("$") }
191+
192+
sanityCheckRound()
193+
println("Current scores: \n${scoring.asIterable().joinToString("\n")}")
194+
firstRound()
195+
println("Current scores: \n${scoring.asIterable().joinToString("\n")}")
196+
secondRound()
197+
println("Current scores: \n${scoring.asIterable().joinToString("\n")}")
198+
thirdRound()
199+
println("Final scores: \n${scoring.asIterable().joinToString("\n")}")
200+
println("Final points: \n${points.asIterable().joinToString("\n")}")
201+
}
202+
203+
}

kotopunter-server/src/main/resources/webroot/orgs/punttv/css/style-selector.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ header h1 {
2727
}
2828

2929
#phrase {
30-
background-image: url('/punttv/img/searchicon.png'); /* Add a search icon to input */
30+
background-image: url('/legacy/punttv/img/searchicon.png'); /* Add a search icon to input */
3131
background-position: 10px 12px; /* Position the search icon */
3232
background-repeat: no-repeat; /* Do not repeat the icon image */
3333
width: 100%; /* Full-width */

kotopunter-server/src/main/resources/webroot/orgs/punttv/css/style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ main > div {
162162
}
163163

164164
.zombie {
165-
background: url('../img/zombie.png') no-repeat center center;
165+
background: url('/legacy/punttv/img/zombie.png') no-repeat center center;
166166
background-size: contain;
167167
}
168168

0 commit comments

Comments
 (0)