Add WIP life calendar
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
.env
|
.env
|
||||||
target
|
target
|
||||||
database*
|
/server/database*
|
||||||
|
|||||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2180,7 +2180,6 @@ dependencies = [
|
|||||||
"rocket_contrib",
|
"rocket_contrib",
|
||||||
"semver 0.11.0",
|
"semver 0.11.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sled",
|
"sled",
|
||||||
"stl_lib",
|
"stl_lib",
|
||||||
|
|||||||
@ -8,9 +8,8 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dotenv = "0.13.0"
|
dotenv = "0.13.0"
|
||||||
serde = "1"
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_derive = "1"
|
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#![allow(dead_code)] // old schema, not used anymore
|
#![allow(dead_code)] // old schema, not used anymore
|
||||||
|
|
||||||
pub(self) use chrono::NaiveDateTime;
|
pub(self) use chrono::NaiveDateTime;
|
||||||
pub(self) use serde_derive::{Deserialize, Serialize};
|
pub(self) use serde::{Deserialize, Serialize};
|
||||||
pub(self) use uuid::Uuid;
|
pub(self) use uuid::Uuid;
|
||||||
|
|
||||||
/// Stuff in the default namespace
|
/// Stuff in the default namespace
|
||||||
|
|||||||
@ -69,6 +69,7 @@ async fn main() -> io::Result<()> {
|
|||||||
routes::pages::bump_session,
|
routes::pages::bump_session,
|
||||||
routes::pages::stats::single_stats,
|
routes::pages::stats::single_stats,
|
||||||
routes::pages::stats::all_stats,
|
routes::pages::stats::all_stats,
|
||||||
|
routes::pages::weeks::weeks,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.mount(
|
.mount(
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
pub mod stats;
|
pub mod stats;
|
||||||
|
pub mod weeks;
|
||||||
|
|
||||||
use crate::auth::Authorized;
|
use crate::auth::Authorized;
|
||||||
use crate::database::latest::trees::{category, session};
|
use crate::database::latest::trees::{category, session};
|
||||||
@ -10,7 +11,7 @@ use rocket::response::Redirect;
|
|||||||
use rocket::{get, post, uri, State};
|
use rocket::{get, post, uri, State};
|
||||||
use rocket_contrib::templates::Template;
|
use rocket_contrib::templates::Template;
|
||||||
use rocket_contrib::uuid::Uuid;
|
use rocket_contrib::uuid::Uuid;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use rocket::http::Status;
|
|||||||
use rocket::{get, State};
|
use rocket::{get, State};
|
||||||
use rocket_contrib::templates::Template;
|
use rocket_contrib::templates::Template;
|
||||||
use rocket_contrib::uuid::Uuid;
|
use rocket_contrib::uuid::Uuid;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[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 {
|
||||||
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