diff --git a/backend/src/routes.rs b/backend/src/routes.rs index 443fe55..159428d 100644 --- a/backend/src/routes.rs +++ b/backend/src/routes.rs @@ -74,7 +74,7 @@ async fn debug_get() -> Result { #[get("/visualizer")] async fn visualizer_get() -> Template { let game_options = get_games().await; - let context = Context::new_with("Visualizer", ContextT::Games(game_options)); + let context = Context::new_with("Visualizer", json!({"games": game_options, "colours": COLOURS})); Template::render("visualizer", &context) } diff --git a/backend/src/util.rs b/backend/src/util.rs index 66b8c40..d954b98 100644 --- a/backend/src/util.rs +++ b/backend/src/util.rs @@ -9,6 +9,10 @@ static NAV: [(&'static str, &'static str); 5] = [ ("/debug", "Debug Station"), ]; +pub static COLOURS: [&'static str; 9] = [ + "gray", "blue", "cyan", "green", "yellow", "orange", "red", "pink", "purple", +]; + #[derive(Serialize)] pub struct Map { name: String, @@ -91,7 +95,9 @@ impl Ord for GameState { } impl From for GameState { - fn from(state: FinishedState) -> Self { + fn from(mut state: FinishedState) -> Self { + state.players.sort_by_key(|x| x.0); + GameState::Finished { map: String::new(), players: state @@ -136,11 +142,11 @@ pub struct Lobby { pub maps: Vec, } -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub enum ContextT { - Games(Vec), -} +// #[derive(Serialize)] +// #[serde(rename_all = "camelCase")] +// pub enum ContextT { +// Games(Vec), +// } #[derive(Serialize)] pub struct Context { @@ -213,11 +219,15 @@ pub async fn get_games() -> Vec { match fs::File::open("games.ini").await { Ok(file) => { let mut file = BufReader::new(file); - file.lines().filter_map(move |maybe| async { - maybe - .ok() - .and_then(|line| serde_json::from_str::(&line).ok()) - }).map(|state| state.into()).collect().await + file.lines() + .filter_map(move |maybe| async { + maybe + .ok() + .and_then(|line| serde_json::from_str::(&line).ok()) + }) + .map(|state| state.into()) + .collect() + .await } Err(_) => Vec::new(), } diff --git a/backend/templates/visualizer.html.tera b/backend/templates/visualizer.html.tera index d559696..2400ca6 100644 --- a/backend/templates/visualizer.html.tera +++ b/backend/templates/visualizer.html.tera @@ -1,6 +1,7 @@ {% extends "base" %} {% block content %} + @@ -24,20 +25,21 @@ +
{% for state in games %} -
-

{{state.name}} ({{ state.map }}) {{state.turns}} turns

-
-
- {% for player in state.players %} -

{{ player[0] }}

- {% endfor %} +
+

{{state.name}} ({{ state.map }}) {{state.turns}} turns

+
+
+ {% for player in state.players %} +

{{ player[0] }}

+ {% endfor %} +
-
{% endfor %}
diff --git a/frontend/www/static/res/style.css b/frontend/www/static/res/style.css index aadf372..636ac30 100644 --- a/frontend/www/static/res/style.css +++ b/frontend/www/static/res/style.css @@ -16,11 +16,12 @@ p { min-height: 100%; width: 100%; height: 100%; + display: flex; } #main { - height: calc(100% - 200px); - width: 100%; + height: 100%; + flex-grow: 1; position: relative; } @@ -40,46 +41,143 @@ p { } .options { - background-color: #444; - overflow-y: hidden; - overflow-x: scroll; - white-space: nowrap; - height: 200px; - min-height: 200px !important; - max-height: 200px !important; + background-color: black; + max-width: 300px; + width: 20%; + min-width: 150px; + height: 100%; + display: flex; + flex-direction: column; + overflow-y: auto; } .option { - display: inline-block; color: white; - text-align: center; - width: 200px; - height: 100%; - vertical-align: top + margin: 0 0 20px 0; + padding: 10px; + background-color: grey; +} + +.option:last-child { + margin: 0; } .option:hover { background-color: #777; } -.loading { - position: relative; +.lds-roller { + display: none; +} + +.loading>.lds-roller { display: inline-block; } -.loading::before { - content: ""; +.lds-roller { position: absolute; - width: 100px; - height: 100px; - background-color: #1c5ba2; - border-radius: 100%; - z-index: 5; left: 50%; top: 50%; transform: translate(-50%, -50%); - -webkit-animation: slide-top 0.5s ease-out infinite alternate; - animation: slide-top 0.5s ease-out infinite alternate; + width: 80px; + height: 80px; +} + +.lds-roller div { + animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; + transform-origin: 40px 40px; +} + +.lds-roller div:after { + content: " "; + display: block; + position: absolute; + width: 7px; + height: 7px; + border-radius: 50%; + background: #fff; + margin: -4px 0 0 -4px; +} + +.lds-roller div:nth-child(1) { + animation-delay: -0.036s; +} + +.lds-roller div:nth-child(1):after { + top: 63px; + left: 63px; +} + +.lds-roller div:nth-child(2) { + animation-delay: -0.072s; +} + +.lds-roller div:nth-child(2):after { + top: 68px; + left: 56px; +} + +.lds-roller div:nth-child(3) { + animation-delay: -0.108s; +} + +.lds-roller div:nth-child(3):after { + top: 71px; + left: 48px; +} + +.lds-roller div:nth-child(4) { + animation-delay: -0.144s; +} + +.lds-roller div:nth-child(4):after { + top: 72px; + left: 40px; +} + +.lds-roller div:nth-child(5) { + animation-delay: -0.18s; +} + +.lds-roller div:nth-child(5):after { + top: 71px; + left: 32px; +} + +.lds-roller div:nth-child(6) { + animation-delay: -0.216s; +} + +.lds-roller div:nth-child(6):after { + top: 68px; + left: 24px; +} + +.lds-roller div:nth-child(7) { + animation-delay: -0.252s; +} + +.lds-roller div:nth-child(7):after { + top: 63px; + left: 17px; +} + +.lds-roller div:nth-child(8) { + animation-delay: -0.288s; +} + +.lds-roller div:nth-child(8):after { + top: 56px; + left: 12px; +} + +@keyframes lds-roller { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } } #speed { @@ -226,4 +324,4 @@ p { border-radius: 10px; background-color: #F90; background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%, transparent 75%, transparent) -} +} \ No newline at end of file