Add WIP life calendar
This commit is contained in:
@ -8,9 +8,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
dotenv = "0.13.0"
|
||||
serde = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_derive = "1"
|
||||
log = "0.4.8"
|
||||
futures = "0.3"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#![allow(dead_code)] // old schema, not used anymore
|
||||
|
||||
pub(self) use chrono::NaiveDateTime;
|
||||
pub(self) use serde_derive::{Deserialize, Serialize};
|
||||
pub(self) use serde::{Deserialize, Serialize};
|
||||
pub(self) use uuid::Uuid;
|
||||
|
||||
/// Stuff in the default namespace
|
||||
|
||||
@ -69,6 +69,7 @@ async fn main() -> io::Result<()> {
|
||||
routes::pages::bump_session,
|
||||
routes::pages::stats::single_stats,
|
||||
routes::pages::stats::all_stats,
|
||||
routes::pages::weeks::weeks,
|
||||
],
|
||||
)
|
||||
.mount(
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
pub mod stats;
|
||||
pub mod weeks;
|
||||
|
||||
use crate::auth::Authorized;
|
||||
use crate::database::latest::trees::{category, session};
|
||||
@ -10,7 +11,7 @@ use rocket::response::Redirect;
|
||||
use rocket::{get, post, uri, State};
|
||||
use rocket_contrib::templates::Template;
|
||||
use rocket_contrib::uuid::Uuid;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::time::Duration;
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ use rocket::http::Status;
|
||||
use rocket::{get, State};
|
||||
use rocket_contrib::templates::Template;
|
||||
use rocket_contrib::uuid::Uuid;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
||||
91
server/src/routes/pages/weeks.rs
Normal file
91
server/src/routes/pages/weeks.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use crate::auth::Authorized;
|
||||
use crate::status_json::StatusJson;
|
||||
use chrono::{Duration, Local, NaiveDate};
|
||||
use rocket::get;
|
||||
use rocket_contrib::templates::Template;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
use std::iter::{once, repeat};
|
||||
|
||||
#[get("/weeks")]
|
||||
pub fn weeks(_auth: Authorized) -> Result<Template, StatusJson> {
|
||||
type Color<'a> = Cow<'a, str>;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct WeekCtx<'a> {
|
||||
border_color: Color<'a>,
|
||||
fill_color: Option<Color<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, T> From<T> for WeekCtx<'a>
|
||||
where
|
||||
T: Into<Cow<'a, str>>,
|
||||
{
|
||||
fn from(color: T) -> Self {
|
||||
WeekCtx {
|
||||
border_color: color.into(),
|
||||
fill_color: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Ctx<'a> {
|
||||
weeks_left: i64,
|
||||
weeks: Vec<WeekCtx<'a>>,
|
||||
}
|
||||
|
||||
let now = Local::now().date();
|
||||
|
||||
// TODO: change this
|
||||
let birth_date = NaiveDate::from_ymd(1999, 01, 01);
|
||||
|
||||
let lived: Duration = now.naive_local() - birth_date;
|
||||
let one_year = Duration::days(365);
|
||||
|
||||
let life_expectancy = (one_year * 81).num_weeks();
|
||||
let uncertainty = (one_year * 20).num_weeks();
|
||||
|
||||
let childhood_end = (one_year * 12).num_weeks();
|
||||
let teenage_end = (one_year * 20).num_weeks();
|
||||
|
||||
let color_birth = "green";
|
||||
let color_child = "#ff0";
|
||||
let color_teen = "#f0f";
|
||||
let color_adult = "#f33";
|
||||
let color_today = "wheat";
|
||||
let color_future = "#eee";
|
||||
|
||||
let context = Ctx {
|
||||
weeks_left: life_expectancy - lived.num_weeks(),
|
||||
weeks: once(WeekCtx {
|
||||
border_color: color_birth.into(),
|
||||
fill_color: Some(color_birth.into()),
|
||||
})
|
||||
// childhood
|
||||
.chain((1..childhood_end).map(|_| color_child.into()))
|
||||
// teens
|
||||
.chain((childhood_end..teenage_end).map(|_| color_teen.into()))
|
||||
// adulthood
|
||||
.chain((teenage_end..).map(|_| color_adult.into()))
|
||||
// take from above for lived number of weeks
|
||||
.take(lived.num_weeks() as usize - 1)
|
||||
// add a week for this week
|
||||
.chain(once(WeekCtx {
|
||||
border_color: color_today.into(),
|
||||
fill_color: Some(color_today.into()),
|
||||
}))
|
||||
// fill remaining weeks until death
|
||||
.chain(repeat(color_future.into()))
|
||||
.take((life_expectancy - uncertainty * 2) as usize)
|
||||
// add some fading around expected life span
|
||||
.chain((0..uncertainty).rev().map(|i| {
|
||||
let m = u8::MAX as i64;
|
||||
let alpha = ((m * i) / (uncertainty)) as u8;
|
||||
format!("#eeeeee{:02x}", alpha).into()
|
||||
}))
|
||||
.collect(),
|
||||
};
|
||||
|
||||
Ok(Template::render("weeks", &context))
|
||||
}
|
||||
@ -232,3 +232,37 @@ ul.striped_list > li:nth-child(odd) ul li:nth-child(odd) { background-color:#30
|
||||
.display_none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.life_calendar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: 30rem;
|
||||
flex-wrap: wrap;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.life_calendar > p {
|
||||
height: 0.5em;
|
||||
width: 0.5em;
|
||||
margin: 0.1em;
|
||||
border: solid 0.05em;
|
||||
border-radius: 0.5em;
|
||||
}
|
||||
|
||||
.life_calendar_ticker {
|
||||
position: relative;
|
||||
top: -20rem;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 10rem;
|
||||
}
|
||||
|
||||
.life_calendar_ticker > h1 {
|
||||
font-size: 8rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.life_calendar_ticker > h2 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
16
server/templates/weeks.hbs
Normal file
16
server/templates/weeks.hbs
Normal file
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{{> head}}
|
||||
<body>
|
||||
{{> header}}
|
||||
|
||||
<div class="life_calendar">
|
||||
{{#each weeks}}<p style="color: {{this.border_color}}{{#if this.fill_color}}; background-color: {{this.fill_color}}{{/if}}"></p>{{/each}}
|
||||
</div>
|
||||
<div class="life_calendar_ticker">
|
||||
<h2>circa</h2>
|
||||
<h1>{{weeks_left}}</h1>
|
||||
<h2>veckor kvar</h2>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user