basic weather-based "uptime"

This commit is contained in:
insects 2025-02-04 16:53:04 +01:00
parent 3584ecce96
commit f427c0fbae
7 changed files with 267 additions and 10 deletions

22
src/clock.rs Normal file
View file

@ -0,0 +1,22 @@
// Mostly nicked from https://github.com/icykoneko/ff14-fish-tracker-app/blob/master/js/app/time.js. Thanks!
use chrono::{DateTime, Utc};
const EARTH_TO_EORZEA: f64 = 3600. / 175.;
const EORZEA_TO_EARTH: f64 = 1. / EARTH_TO_EORZEA;
pub fn to_eorzea_time(earth_time: DateTime<Utc>) -> DateTime<Utc> {
let et_ts = earth_time.timestamp();
let new_ts = et_ts.abs() as f64 * EARTH_TO_EORZEA;
DateTime::from_timestamp(new_ts.floor() as i64, 0).unwrap()
}
pub fn get_current_eorzea_date() -> DateTime<Utc> {
to_eorzea_time(Utc::now())
}
pub fn to_earth_time(ez_time: DateTime<Utc>) -> DateTime<Utc> {
let ez_ts = ez_time.timestamp();
let new_ts = (ez_ts.abs() as f64 * EORZEA_TO_EARTH).ceil();
DateTime::from_timestamp(new_ts as i64, 0).unwrap()
}

View file

@ -1,7 +1,10 @@
use std::collections::HashMap;
use chrono::Timelike;
use serde::{Deserialize, Serialize};
use crate::clock;
const DATA: &'static str = include_str!("../data.json");
#[derive(Serialize, Deserialize, Debug)]
@ -24,6 +27,14 @@ pub struct FishEntry {
pub start_hour: Option<f32>,
pub end_hour: Option<f32>,
pub location: Option<u32>,
pub best_catch_path: Vec<u32>,
pub predators: Vec<Vec<u32>>,
pub intuition_length: Option<u32>,
pub patch: f32,
pub folklore: Option<u32>,
pub fish_eyes: bool,
pub big_fish: bool,
pub weather_set: Vec<u32>,
}
#[derive(Serialize, Deserialize, Debug)]
@ -39,9 +50,44 @@ pub struct FishMeta {
pub name_en: String,
}
impl Data {
pub fn new() -> Self {
let json = serde_json::from_str(DATA).unwrap();
json
pub struct CombinedFish<'a> {
pub entry: &'a FishEntry,
pub meta: &'a FishMeta,
}
impl<'a> CombinedFish<'a> {
pub fn is_in_time_range(&self) -> bool {
if self.entry.start_hour.is_none() || self.entry.end_hour.is_none() {
return false;
}
let et = clock::get_current_eorzea_date();
let start_hour = self.entry.start_hour.unwrap();
let end_hour = self.entry.end_hour.unwrap();
let spans_midnight = start_hour > end_hour;
let cur_hour = et.hour() as f32 + et.minute() as f32 / 60.;
if spans_midnight {
return cur_hour > start_hour || cur_hour < end_hour;
} else {
return start_hour < cur_hour && cur_hour < end_hour;
}
}
}
impl Data {
pub fn new() -> Self {
let json = &mut serde_json::Deserializer::from_str(DATA);
let json = serde_path_to_error::deserialize(json).unwrap();
json
}
pub fn fish_with_meta(&self) -> HashMap<u32, CombinedFish> {
self.db_data
.fish
.iter()
.filter_map(|(k, v)| {
let corresponding_meta = self.fish_entries.iter().find(|m| &m.id == k);
corresponding_meta.map(|m| (k.clone(), CombinedFish { entry: v, meta: m }))
})
.collect()
}
}

View file

@ -4,6 +4,7 @@ use axum::{extract::State, http::StatusCode, response::IntoResponse, routing::ge
use data::Data;
use maud::{html, Markup};
pub mod clock;
pub mod data;
pub struct AppState {
@ -33,12 +34,24 @@ where
#[axum::debug_handler]
async fn main_handler(state: State<Arc<AppState>>) -> Result<Markup, AppError> {
println!("{:?}", state.data.db_data.fish);
let values = state.data.db_data.fish.values();
let meta = state.data.fish_with_meta();
let values = meta.values();
Ok(html! {
h1 { "Hello!" }
h1 { "Hello! Current ET " (clock::get_current_eorzea_date().format("%H:%M")) }
@for fish in values {
li { (fish.id) }
li {
@if fish.is_in_time_range() {
"Up! "
}
(fish.meta.name_en)
br;
@if fish.entry.start_hour.is_some() && fish.entry.end_hour.is_some() {
"From " (fish.entry.start_hour.unwrap()) "h to " (fish.entry.end_hour.unwrap()) "h"
}
@if fish.entry.weather_set.len() > 0 {
" Weather(s) " (fish.entry.weather_set.iter().map(|i| i.to_string()).collect::<Vec<_>>().join(", "))
}
}
}
})
}