diff --git a/material/rest-api-ui-ktor-quiz-collector/build.gradle.kts b/material/rest-api-ui-ktor-quiz-collector/build.gradle.kts index 9fb8aa95..21a817d3 100644 --- a/material/rest-api-ui-ktor-quiz-collector/build.gradle.kts +++ b/material/rest-api-ui-ktor-quiz-collector/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { implementation(libs.ktor.server.netty) implementation(libs.logback.classic) implementation(libs.ktor.server.config.yaml) + implementation(libs.kandy.lets.plot) testImplementation(libs.ktor.server.test.host) testImplementation(libs.kotlin.test.junit) } diff --git a/material/rest-api-ui-ktor-quiz-collector/gradle/libs.versions.toml b/material/rest-api-ui-ktor-quiz-collector/gradle/libs.versions.toml index 191dc865..1500c9d3 100644 --- a/material/rest-api-ui-ktor-quiz-collector/gradle/libs.versions.toml +++ b/material/rest-api-ui-ktor-quiz-collector/gradle/libs.versions.toml @@ -22,6 +22,7 @@ logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "lo ktor-server-config-yaml = { module = "io.ktor:ktor-server-config-yaml", version.ref = "ktor-version" } ktor-server-test-host = { module = "io.ktor:ktor-server-test-host-jvm", version.ref = "ktor-version" } kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin-version" } +kandy-lets-plot = { module = "org.jetbrains.kotlinx:kandy-lets-plot", version = "0.7.0" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin-version" } diff --git a/material/rest-api-ui-ktor-quiz-collector/result-explorer/demo01.ipynb b/material/rest-api-ui-ktor-quiz-collector/result-explorer/demo01.ipynb index ca9a8e5a..6e2ee463 100644 --- a/material/rest-api-ui-ktor-quiz-collector/result-explorer/demo01.ipynb +++ b/material/rest-api-ui-ktor-quiz-collector/result-explorer/demo01.ipynb @@ -12,8 +12,8 @@ "languageId": "python" }, "ExecuteTime": { - "end_time": "2024-08-24T10:23:18.959803600Z", - "start_time": "2024-08-24T10:23:13.328613100Z" + "end_time": "2024-08-24T11:14:19.583192900Z", + "start_time": "2024-08-24T11:14:12.242893300Z" } }, "source": [ @@ -23,7 +23,7 @@ "%use dataframe" ], "outputs": [], - "execution_count": 90 + "execution_count": 100 }, { "metadata": {}, @@ -33,8 +33,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2024-08-24T10:23:19.179801200Z", - "start_time": "2024-08-24T10:23:18.975805100Z" + "end_time": "2024-08-24T11:14:19.925191Z", + "start_time": "2024-08-24T11:14:19.603194600Z" } }, "cell_type": "code", @@ -46,7 +46,7 @@ { "data": { "text/html": [ - " \n", " \n", " " ], "application/kotlindataframe+json": "{\"$version\":\"2.0.0\",\"metadata\":{\"columns\":[\"What is the primary goal of Kotlin Multiplatform?\",\"How does Kotlin Multiplatform facilitate code sharing between platforms?\",\"Which platforms does Kotlin Multiplatform support?\",\"What is a common use case for Kotlin Multiplatform?\",\"What is a shared code module in Kotlin Multiplatform called?\",\"How does Kotlin Multiplatform handle platform-specific implementations?\",\"What languages can be interoperable with Kotlin Multiplatform?\",\"What tooling supports Kotlin Multiplatform development?\",\"What is the benefit of using Kotlin Multiplatform for mobile development?\",\"How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?\"],\"nrow\":2,\"ncol\":10},\"kotlin_dataframe\":[{\"What is the primary goal of Kotlin Multiplatform?\":\"To share\",\"How does Kotlin Multiplatform facilitate code sharing between platforms?\":\"By sharing business logic and adapting UI\",\"Which platforms does Kotlin Multiplatform support?\":\"Android, iOS, and web\",\"What is a common use case for Kotlin Multiplatform?\":\"Developing a cross-platform app\",\"What is a shared code module in Kotlin Multiplatform called?\":\"Shared module\",\"How does Kotlin Multiplatform handle platform-specific implementations?\":\"actual\",\"What languages can be interoperable with Kotlin Multiplatform?\":\"Java, Swift\",\"What tooling supports Kotlin Multiplatform development?\":\"IntelliJ IDEA\",\"What is the benefit of using Kotlin Multiplatform for mobile development?\":\"and sharing\",\"How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?\":\"None\"},{\"What is the primary goal of Kotlin Multiplatform?\":\"To share code between multiple platforms\",\"How does Kotlin Multiplatform facilitate code sharing between platforms?\":\"By sharing business logic and adapting UI\",\"Which platforms does Kotlin Multiplatform support?\":\"Android, iOS, and web\",\"What is a common use case for Kotlin Multiplatform?\":\"Developing a cross-platform app\",\"What is a shared code module in Kotlin Multiplatform called?\":\"Shared module\",\"How does Kotlin Multiplatform handle platform-specific implementations?\":\"Through expect and actual declarations\",\"What languages can be interoperable with Kotlin Multiplatform?\":\"Java, JavaScript, Swift\",\"What tooling supports Kotlin Multiplatform development?\":\"IntelliJ IDEA, Android Studio\",\"What is the benefit of using Kotlin Multiplatform for mobile development?\":\"Code reuse and sharing\",\"How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?\":\"Kotlin Multiplatform allows sharing code between different platforms using common modules.\"}]}" }, - "execution_count": 91, + "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 91 + "execution_count": 101 }, { "metadata": {}, @@ -714,8 +714,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2024-08-24T10:23:19.446801800Z", - "start_time": "2024-08-24T10:23:19.220805400Z" + "end_time": "2024-08-24T11:14:20.162191700Z", + "start_time": "2024-08-24T11:14:19.946198800Z" } }, "cell_type": "code", @@ -731,18 +731,18 @@ "correct: Int" ] }, - "execution_count": 92, + "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 92 + "execution_count": 102 }, { "metadata": { "ExecuteTime": { - "end_time": "2024-08-24T10:23:20.040806Z", - "start_time": "2024-08-24T10:23:19.652806400Z" + "end_time": "2024-08-24T11:14:20.619193Z", + "start_time": "2024-08-24T11:14:20.287192300Z" } }, "cell_type": "code", @@ -754,7 +754,7 @@ { "data": { "text/html": [ - " \n", " \n", " " ], "application/kotlindataframe+json": "{\"$version\":\"2.0.0\",\"metadata\":{\"columns\":[\"question\",\"correct\",\"tq\"],\"nrow\":10,\"ncol\":3},\"kotlin_dataframe\":[{\"question\":\"What is the primary goal of Kotlin Multiplatform?\",\"correct\":1,\"tq\":\"Wha\\u2026 of Kotlin Multiplatform?\"},{\"question\":\"How does Kotlin Multiplatform facilitate code sharing between platforms?\",\"correct\":2,\"tq\":\"How\\u2026haring between platforms?\"},{\"question\":\"Which platforms does Kotlin Multiplatform support?\",\"correct\":2,\"tq\":\"Whi\\u2026in Multiplatform support?\"},{\"question\":\"What is a common use case for Kotlin Multiplatform?\",\"correct\":2,\"tq\":\"Wha\\u2026for Kotlin Multiplatform?\"},{\"question\":\"What is a shared code module in Kotlin Multiplatform called?\",\"correct\":2,\"tq\":\"Wha\\u2026lin Multiplatform called?\"},{\"question\":\"How does Kotlin Multiplatform handle platform-specific implementations?\",\"correct\":1,\"tq\":\"How\\u2026specific implementations?\"},{\"question\":\"What languages can be interoperable with Kotlin Multiplatform?\",\"correct\":1,\"tq\":\"Wha\\u2026ith Kotlin Multiplatform?\"},{\"question\":\"What tooling supports Kotlin Multiplatform development?\",\"correct\":1,\"tq\":\"Wha\\u2026ultiplatform development?\"},{\"question\":\"What is the benefit of using Kotlin Multiplatform for mobile development?\",\"correct\":1,\"tq\":\"Wha\\u2026m for mobile development?\"},{\"question\":\"How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?\",\"correct\":1,\"tq\":\"How\\u2026lin Native and Kotlin/JS?\"}]}" }, - "execution_count": 93, + "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 93 + "execution_count": 103 }, { "metadata": { "ExecuteTime": { - "end_time": "2024-08-24T10:23:20.291806700Z", - "start_time": "2024-08-24T10:23:20.072802700Z" + "end_time": "2024-08-24T11:14:20.800192Z", + "start_time": "2024-08-24T11:14:20.651193800Z" } }, "cell_type": "code", @@ -1436,7 +1436,7 @@ " <script type="text/javascript" data-lets-plot-script="library" src="https://cdn.jsdelivr.net/gh/JetBrains/lets-plot@v4.3.3/js-package/distr/lets-plot.min.js"></script>\n", " </head>\n", " <body>\n", - " <div id="NosaSt"></div>\n", + " <div id="O5Obtq"></div>\n", " <script type="text/javascript" data-lets-plot-script="plot">\n", " var plotSpec={\n", ""mapping":{\n", @@ -1468,11 +1468,11 @@ "}\n", "}]\n", "};\n", - " var plotContainer = document.getElementById("NosaSt");\n", + " var plotContainer = document.getElementById("O5Obtq");\n", " LetsPlot.buildPlotFromProcessedSpecs(plotSpec, -1, -1, plotContainer);\n", " </script>\n", " </body>\n", - "</html>\"> \n", + "</html>\"> \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1642,7 +1642,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1670,7 +1670,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1813,10 +1813,10 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", "\n", - " " + " " ], "application/plot+json": { "output_type": "lets_plot_spec", @@ -1880,12 +1880,12 @@ "swing_enabled": true } }, - "execution_count": 94, + "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 94 + "execution_count": 104 }, { "cell_type": "code", @@ -1894,8 +1894,8 @@ "languageId": "python" }, "ExecuteTime": { - "end_time": "2024-08-24T10:23:20.788804700Z", - "start_time": "2024-08-24T10:23:20.506803500Z" + "end_time": "2024-08-24T11:14:21.188191800Z", + "start_time": "2024-08-24T11:14:20.934195Z" } }, "source": [ @@ -1906,7 +1906,7 @@ { "data": { "text/html": [ - " \n", " \n", - "
What is the primary goal of Kotlin Multiplatform?How does Kotlin Multiplatform facilitate code sharing between platforms?Which platforms does Kotlin Multiplatform support?What is a common use case for Kotlin Multiplatform?What is a shared code module in Kotlin Multiplatform called?How does Kotlin Multiplatform handle platform-specific implementations?What languages can be interoperable with Kotlin Multiplatform?What tooling supports Kotlin Multiplatform development?What is the benefit of using Kotlin Multiplatform for mobile development?How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?
[To share, To share code between mult...[By sharing business logic and adapti...[Android, iOS, and web, Android, iOS,...[Developing a cross-platform app, Dev...[Shared module, Shared module][actual, Through expect and actual de...[Java, Swift, Java, JavaScript, Swift][IntelliJ IDEA, IntelliJ IDEA, Androi...[and sharing, Code reuse and sharing][None, Kotlin Multiplatform allows sh...
\n", + "
What is the primary goal of Kotlin Multiplatform?How does Kotlin Multiplatform facilitate code sharing between platforms?Which platforms does Kotlin Multiplatform support?What is a common use case for Kotlin Multiplatform?What is a shared code module in Kotlin Multiplatform called?How does Kotlin Multiplatform handle platform-specific implementations?What languages can be interoperable with Kotlin Multiplatform?What tooling supports Kotlin Multiplatform development?What is the benefit of using Kotlin Multiplatform for mobile development?How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?
[To share, To share code between mult...[By sharing business logic and adapti...[Android, iOS, and web, Android, iOS,...[Developing a cross-platform app, Dev...[Shared module, Shared module][actual, Through expect and actual de...[Java, Swift, Java, JavaScript, Swift][IntelliJ IDEA, IntelliJ IDEA, Androi...[and sharing, Code reuse and sharing][None, Kotlin Multiplatform allows sh...
\n", " \n", " \n", " " ], "application/kotlindataframe+json": "{\"$version\":\"2.0.0\",\"metadata\":{\"columns\":[\"What is the primary goal of Kotlin Multiplatform?\",\"How does Kotlin Multiplatform facilitate code sharing between platforms?\",\"Which platforms does Kotlin Multiplatform support?\",\"What is a common use case for Kotlin Multiplatform?\",\"What is a shared code module in Kotlin Multiplatform called?\",\"How does Kotlin Multiplatform handle platform-specific implementations?\",\"What languages can be interoperable with Kotlin Multiplatform?\",\"What tooling supports Kotlin Multiplatform development?\",\"What is the benefit of using Kotlin Multiplatform for mobile development?\",\"How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?\"],\"nrow\":1,\"ncol\":10},\"kotlin_dataframe\":[{\"What is the primary goal of Kotlin Multiplatform?\":[\"To share\",\"To share code between multiple platforms\"],\"How does Kotlin Multiplatform facilitate code sharing between platforms?\":[\"By sharing business logic and adapting UI\",\"By sharing business logic and adapting UI\"],\"Which platforms does Kotlin Multiplatform support?\":[\"Android, iOS, and web\",\"Android, iOS, and web\"],\"What is a common use case for Kotlin Multiplatform?\":[\"Developing a cross-platform app\",\"Developing a cross-platform app\"],\"What is a shared code module in Kotlin Multiplatform called?\":[\"Shared module\",\"Shared module\"],\"How does Kotlin Multiplatform handle platform-specific implementations?\":[\"actual\",\"Through expect and actual declarations\"],\"What languages can be interoperable with Kotlin Multiplatform?\":[\"Java, Swift\",\"Java, JavaScript, Swift\"],\"What tooling supports Kotlin Multiplatform development?\":[\"IntelliJ IDEA\",\"IntelliJ IDEA, Android Studio\"],\"What is the benefit of using Kotlin Multiplatform for mobile development?\":[\"and sharing\",\"Code reuse and sharing\"],\"How does Kotlin Multiplatform differ from Kotlin Native and Kotlin/JS?\":[\"None\",\"Kotlin Multiplatform allows sharing code between different platforms using common modules.\"]}]}" }, - "execution_count": 95, + "execution_count": 105, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 95 + "execution_count": 105 } ], "metadata": { diff --git a/material/rest-api-ui-ktor-quiz-collector/src/main/kotlin/example/com/QuizCollector.kt b/material/rest-api-ui-ktor-quiz-collector/src/main/kotlin/example/com/QuizCollector.kt index bbc21ea9..ab7d9d4e 100644 --- a/material/rest-api-ui-ktor-quiz-collector/src/main/kotlin/example/com/QuizCollector.kt +++ b/material/rest-api-ui-ktor-quiz-collector/src/main/kotlin/example/com/QuizCollector.kt @@ -1,5 +1,6 @@ package example.com +import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.html.* import io.ktor.server.request.* @@ -7,8 +8,20 @@ import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.html.* import kotlinx.serialization.Serializable +import org.jetbrains.kotlinx.dataframe.api.dataFrameOf +import org.jetbrains.kotlinx.kandy.dsl.plot +import org.jetbrains.kotlinx.kandy.letsplot.export.toHTML +import org.jetbrains.kotlinx.kandy.letsplot.export.toSVG +import org.jetbrains.kotlinx.kandy.letsplot.layers.bars + +@Serializable +data class QuestionStats(val question: String, val correct: Int) fun Application.configureQuizCollector() { + fun getCorrectStats() = quizResponses.flatMap { it.responses }.groupBy { it.question } + .mapValues { it.value.count { qr -> correctResponses[qr.question] == qr.answer } } + .map { QuestionStats(it.key, it.value) } + routing { post("/respond") { val quizResponse = call.receive() @@ -26,13 +39,7 @@ fun Application.configureQuizCollector() { } get("/correct-stats") { - @Serializable - data class QuestionStats(val question: String, val correct: Int) - - val result = quizResponses.flatMap { it.responses }.groupBy { it.question } - .mapValues { it.value.count { qr -> correctResponses[qr.question] == qr.answer } } - .map { QuestionStats(it.key, it.value) } - call.respond(result) + call.respond(getCorrectStats()) } get("/table2") { @@ -52,20 +59,32 @@ fun Application.configureQuizCollector() { } body { h1 { +"Quiz Collector" } - if (quizResponses.isEmpty()) { - +"No responses yet." - } else { - +"Responses:" - ul { - quizResponses.forEach { quizResponse -> - li { - +"Score: ${quizResponse.getScore()}" - } + div { + val correctStats = getCorrectStats() + val statsDataFrame = dataFrameOf("question" to correctStats.map { it.question }, + "correct" to correctStats.map { it.correct }) + val content = statsDataFrame.plot { + bars { + y("question") + x("correct") } - } + }.toSVG() + unsafe { +content } } } } } + get("/ui/correct") { + val correctStats = getCorrectStats() + val statsDataFrame = dataFrameOf("question" to correctStats.map { it.question }, + "correct" to correctStats.map { it.correct }) + val html = statsDataFrame.plot { + bars { + y("question") + x("correct") + } + }.toHTML(false) + call.respondText(html, ContentType.Text.Html) + } } } \ No newline at end of file