Improve life calendar and add it to header

This commit is contained in:
2021-05-31 23:19:41 +02:00
parent 6f984ed6fb
commit 653853b4f6
5 changed files with 91 additions and 52 deletions

View File

@ -9,8 +9,10 @@ use crate::auth::MasterPassword;
use crate::database::migrations::migrate;
use crate::database::unversioned::global::schema_version;
use crate::database::SCHEMA_VERSION;
use crate::routes::pages::weeks::BirthDate;
use crate::util::EventNotifier;
use bincode::{deserialize, serialize};
use chrono::NaiveDate;
use dotenv::dotenv;
use rocket_contrib::serve::StaticFiles;
use rocket_contrib::templates::Template;
@ -29,6 +31,10 @@ async fn main() -> io::Result<()> {
})
.into();
let birth_date: BirthDate = env::var("BIRTH_DATE")
.map(|s| BirthDate(s.parse().expect("failed to parse BIRTH_DATE")))
.unwrap_or_else(|_| BirthDate(NaiveDate::from_ymd(2000, 1, 1)));
let mut sled = sled::open(db_path)?;
match sled.insert(
serialize(schema_version::K).unwrap(),
@ -56,6 +62,7 @@ async fn main() -> io::Result<()> {
}))
.manage(sled)
.manage(master_pass)
.manage(birth_date)
.manage(EventNotifier::new())
.mount("/static", StaticFiles::from("static"))
.mount(

View File

@ -1,30 +1,49 @@
use crate::auth::Authorized;
use crate::status_json::StatusJson;
use chrono::{Duration, Local, NaiveDate};
use rocket::get;
use itertools::Itertools;
use rocket::{get, State};
use rocket_contrib::templates::Template;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::iter::{once, repeat};
pub struct BirthDate(pub NaiveDate);
#[get("/weeks")]
pub fn weeks(_auth: Authorized) -> Result<Template, StatusJson> {
pub fn weeks(_auth: Authorized, birth_date: State<BirthDate>) -> 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>>,
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
struct Style<'a> {
border: Color<'a>,
fill: Option<Color<'a>>,
}
impl<'a, T> From<T> for WeekCtx<'a>
#[derive(Debug, Clone, Serialize, Deserialize)]
struct PeriodCtx<'a> {
style: Style<'a>,
weeks: Vec<()>,
}
impl<'a> Style<'a> {
fn border<C>(border: C) -> Self
where
T: Into<Cow<'a, str>>,
C: Into<Cow<'a, str>>,
{
fn from(color: T) -> Self {
WeekCtx {
border_color: color.into(),
fill_color: None,
Style {
border: border.into(),
fill: None,
}
}
fn fill<C>(border: C, fill: C) -> Self
where
C: Into<Cow<'a, str>>,
{
Style {
border: border.into(),
fill: Some(fill.into()),
}
}
}
@ -32,13 +51,11 @@ pub fn weeks(_auth: Authorized) -> Result<Template, StatusJson> {
#[derive(Debug, Serialize, Deserialize)]
struct Ctx<'a> {
weeks_left: i64,
weeks: Vec<WeekCtx<'a>>,
periods: Vec<PeriodCtx<'a>>,
}
let now = Local::now().date();
// TODO: change this
let birth_date = NaiveDate::from_ymd(1999, 01, 01);
let birth_date = birth_date.0;
let lived: Duration = now.naive_local() - birth_date;
let one_year = Duration::days(365);
@ -51,39 +68,40 @@ pub fn weeks(_auth: Authorized) -> Result<Template, StatusJson> {
let color_birth = "green";
let color_child = "#ff0";
let color_teen = "#f0f";
let color_adult = "#f33";
let color_teen = "#f33";
let color_adult = "#f0f";
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()),
})
periods: once(Style::fill(color_birth, color_birth))
// childhood
.chain((1..childhood_end).map(|_| color_child.into()))
.chain((1..childhood_end).map(|_| Style::border(color_child)))
// teens
.chain((childhood_end..teenage_end).map(|_| color_teen.into()))
.chain((childhood_end..teenage_end).map(|_| Style::border(color_teen)))
// adulthood
.chain((teenage_end..).map(|_| color_adult.into()))
.chain((teenage_end..).map(|_| Style::border(color_adult)))
// 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()),
}))
.chain(once(Style::fill(color_today, color_today)))
// fill remaining weeks until death
.chain(repeat(color_future.into()))
.chain(repeat(Style::border(color_future)))
.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()
Style::border(format!("#eeeeee{:02x}", alpha))
}))
// group weeks by color to save space
.group_by(|style| style.clone())
.into_iter()
.map(|(style, weeks)| PeriodCtx {
style,
weeks: vec![(); weeks.count()],
})
.collect(),
};

View File

@ -241,20 +241,26 @@ ul.striped_list > li:nth-child(odd) ul li:nth-child(odd) { background-color:#30
margin: auto;
}
.life_calendar > p {
.life_calendar > span {
display: contents;
}
.life_calendar > span > p {
height: 0.5em;
width: 0.5em;
margin: 0.1em;
border: solid 0.05em;
border-radius: 0.5em;
background-color: inherit;
}
.life_calendar_ticker {
position: relative;
top: -20rem;
top: -16rem;
width: 100%;
text-align: center;
font-size: 10rem;
font-family: "Ubuntu Mono";
}
.life_calendar_ticker > h1 {

View File

@ -1,7 +1,11 @@
<h1 class="title">
<a href="/stats">🗠</a>
<a title="Life Calendar" href="/weeks">🕱</a>
-
<a title="Session Stats" href="/stats">🗠</a>
-
<a href="/">stl</a>
-
<a href="/history">🕮</a>
<a title="Session List" href="/history">🕮</a>
-
<a title="Source Code" href="https://git.nubo.sh/hulthe/stl">🖹</a>
</h1>

View File

@ -5,7 +5,11 @@
{{> 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}}
{{#each periods}}
<span style="color: {{this.style.border}}{{#if this.style.fill}}; background-color: {{this.style.fill}}{{/if}}">
{{#each weeks}}<p></p>{{/each}}
</span>
{{/each}}
</div>
<div class="life_calendar_ticker">
<h2>circa</h2>