only show top 10 participants + total amount
This commit is contained in:
@@ -29,6 +29,7 @@ location_linz: "Wo: überall in Linz"
|
||||
game_title: "Wer findet die meisten Kameras?"
|
||||
game_explanation_todo: "Willkommen zu unserem Überwachungsbewusstseinsspiel! Als Teil unserer Digital Shadows Ausstellung beim Ars Electronica Festival haben wir QR-Codes bei Überwachungskameras in ganz Linz platziert. Deine Mission: Entdecke die Kameras, scanne unsere Codes und finde heraus, wie allgegenwärtig öffentliche Überwachung wirklich ist. Wir sind aber nur Menschen – wir haben nur einen kleinen Teil aller Kameras erfasst, die unsere Stadt beobachten. Wer beobachtet wen in unseren öffentlichen Räumen? Die Jagd beginnt jetzt! 🕵️"
|
||||
save_button: "Speichern"
|
||||
amount_participants: "In total there are %{amount} participants so far."
|
||||
cameras_found: "Du hast %{found}/%{total} Kameras gefunden:"
|
||||
highscore_title: "Bestenliste"
|
||||
not_found_title: "ups"
|
||||
|
@@ -29,6 +29,7 @@ location_linz: "Where: all over Linz"
|
||||
game_title: "Who finds the most cameras?"
|
||||
game_explanation_todo: "Welcome to our public surveillance awareness game! As part of our Digital Shadows exhibition at Ars Electronica Festival, we've placed QR codes near surveillance cameras throughout Linz. Your mission: spot the cameras, scan our codes, and discover how pervasive public monitoring really is. We're only human though – we've mapped just a small subset of all the cameras watching our city. Who's watching whom in our public spaces? The hunt begins now! 🕵️"
|
||||
save_button: "Save"
|
||||
amount_participants: "Aktuell gibt es insgesamt %{amount} Teilnehmer."
|
||||
cameras_found: "You have found %{found}/%{total} cameras:"
|
||||
highscore_title: "Highscore"
|
||||
not_found_title: "uups"
|
||||
|
17
src/game.rs
17
src/game.rs
@@ -1,17 +1,17 @@
|
||||
use crate::{
|
||||
AppState, Backend, NameUpdateError,
|
||||
language::language,
|
||||
page::{MyMessage, Page},
|
||||
AppState, Backend, NameUpdateError,
|
||||
};
|
||||
use axum::{
|
||||
Form, Router,
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
response::{IntoResponse, Response},
|
||||
routing::{get, post},
|
||||
Form, Router,
|
||||
};
|
||||
use axum_extra::extract::{CookieJar, PrivateCookieJar};
|
||||
use maud::{Markup, PreEscaped, html};
|
||||
use maud::{html, Markup, PreEscaped};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
@@ -38,7 +38,8 @@ async fn retu(
|
||||
|
||||
let sightings = backend.sightings_for_client(&client).await;
|
||||
let amount_total_cameras = backend.amount_total_cameras().await;
|
||||
let highscore = backend.highscore().await;
|
||||
let highscore = backend.highscore(&client).await;
|
||||
let amount_participants = backend.amount_participants().await;
|
||||
|
||||
let mut page = Page::new(req.lang);
|
||||
if let Some(message) = message {
|
||||
@@ -85,6 +86,13 @@ async fn retu(
|
||||
h2 { (t!("highscore_title")) }
|
||||
ul.iterated {
|
||||
@for rank in highscore {
|
||||
@if rank.show_dots_above {
|
||||
li.card {
|
||||
span {
|
||||
"⋮"
|
||||
}
|
||||
}
|
||||
}
|
||||
li.card {
|
||||
span {
|
||||
span.font-headline.rank.text-muted { (rank.rank) "." }
|
||||
@@ -100,6 +108,7 @@ async fn retu(
|
||||
}
|
||||
}
|
||||
}
|
||||
(t!("amount_participants", amount = amount_participants))
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -1,17 +1,32 @@
|
||||
use crate::{Backend, model::client::Client};
|
||||
use crate::{model::client::Client, Backend};
|
||||
|
||||
pub(crate) struct Rank {
|
||||
pub(crate) rank: i64,
|
||||
pub(crate) client: Client,
|
||||
pub(crate) amount: i64,
|
||||
pub(crate) show_dots_above: bool,
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
pub(crate) async fn highscore(&self) -> Vec<Rank> {
|
||||
pub(crate) async fn amount_participants(&self) -> i64 {
|
||||
match self {
|
||||
Backend::Sqlite(db) => {
|
||||
let row = sqlx::query!("SELECT COUNT(*) as count FROM client")
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
row.count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn highscore(&self, client: &Client) -> Vec<Rank> {
|
||||
match self {
|
||||
Backend::Sqlite(db) => {
|
||||
let rows = sqlx::query!(
|
||||
"SELECT
|
||||
"WITH ranked_clients AS (
|
||||
SELECT
|
||||
DENSE_RANK() OVER (ORDER BY COUNT(s.client_uuid) DESC) as rank,
|
||||
c.name,
|
||||
c.uuid,
|
||||
@@ -19,22 +34,69 @@ impl Backend {
|
||||
FROM client c
|
||||
LEFT JOIN sightings s ON c.uuid = s.client_uuid
|
||||
GROUP BY c.uuid, c.name
|
||||
ORDER BY amount DESC"
|
||||
)
|
||||
SELECT rank, name, uuid, amount
|
||||
FROM ranked_clients
|
||||
WHERE rank <= (
|
||||
SELECT rank
|
||||
FROM ranked_clients
|
||||
ORDER BY rank
|
||||
LIMIT 1 OFFSET 9
|
||||
)
|
||||
ORDER BY rank, name"
|
||||
)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
rows.into_iter()
|
||||
let mut ret: Vec<Rank> = rows
|
||||
.into_iter()
|
||||
.map(|row| Rank {
|
||||
rank: row.rank.unwrap(),
|
||||
client: Client {
|
||||
uuid: row.uuid.unwrap(),
|
||||
name: row.name,
|
||||
},
|
||||
amount: row.amount.unwrap(),
|
||||
show_dots_above: false,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let user_is_in_top = ret.iter().find(|x| &x.client == client).is_some();
|
||||
if !user_is_in_top {
|
||||
let row = sqlx::query!(
|
||||
"WITH ranked_clients AS (
|
||||
SELECT
|
||||
DENSE_RANK() OVER (ORDER BY COUNT(s.client_uuid) DESC) as rank,
|
||||
c.name,
|
||||
c.uuid,
|
||||
COUNT(s.client_uuid) as amount
|
||||
FROM client c
|
||||
LEFT JOIN sightings s ON c.uuid = s.client_uuid
|
||||
GROUP BY c.uuid, c.name
|
||||
)
|
||||
SELECT rank, name, uuid, amount
|
||||
FROM ranked_clients
|
||||
WHERE uuid = ?
|
||||
ORDER BY rank, name",
|
||||
client.uuid
|
||||
)
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ret.push(Rank {
|
||||
rank: row.rank,
|
||||
client: Client {
|
||||
uuid: row.uuid,
|
||||
name: row.name,
|
||||
},
|
||||
amount: row.amount,
|
||||
show_dots_above: true,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user