support fisher's intuition

This commit is contained in:
insects 2025-02-11 15:45:57 +01:00
parent b966d78be3
commit a99ee46d26
7 changed files with 194 additions and 98 deletions

View file

@ -10,7 +10,7 @@ The data for fish is based on the data used in [Carbuncle Plushy's Fish Tracker]
Current major missing features include: Current major missing features include:
- [ ] Fisher's Intution (catching other fish to spawn a big fish) - [x] Fisher's Intuition (catching other fish to spawn a big fish)
- [ ] Spearfishing - [ ] Spearfishing
- [x] Better condition display, show the weather, etc - [x] Better condition display, show the weather, etc
- [ ] Folklore requirement display - [ ] Folklore requirement display

View file

@ -6,6 +6,13 @@ pub fn changelog_page() -> Markup {
layout(html! { layout(html! {
h1 { "Beacon Changelog" } h1 { "Beacon Changelog" }
section {
h2 { "1.4.0" }
ul {
li { "Implemented support for Fisher's Intuition" }
}
}
section { section {
h2 { "1.3.0, 11.02.2025" } h2 { "1.3.0, 11.02.2025" }
ul { ul {

View file

@ -189,6 +189,7 @@ pub struct CombinedFish<'a> {
pub is_always_up: bool, pub is_always_up: bool,
pub windows: Vec<Window>, pub windows: Vec<Window>,
pub rarity: f32, pub rarity: f32,
pub filtered: bool,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -490,6 +491,7 @@ impl Data {
let mut cfish = CombinedFish { let mut cfish = CombinedFish {
entry: v, entry: v,
meta: m, meta: m,
filtered: false,
is_up: false, // fake default values for now is_up: false, // fake default values for now
is_always_up: false, // dito is_always_up: false, // dito
windows: Vec::new(), // dito windows: Vec::new(), // dito
@ -528,9 +530,10 @@ impl Filters {
&'a self, &'a self,
fish: Vec<&'a CombinedFish>, fish: Vec<&'a CombinedFish>,
caught_fish_ids: &[i32], caught_fish_ids: &[i32],
) -> Vec<&'a CombinedFish> { ) -> Vec<CombinedFish> {
fish.into_iter() fish.into_iter()
.filter(|fish| { .cloned()
.map(|fish| {
let f_caught = if self.include_caught { let f_caught = if self.include_caught {
true true
} else { } else {
@ -549,7 +552,10 @@ impl Filters {
true true
}; };
f_caught && f_patch && f_big CombinedFish {
filtered: !(f_caught && f_patch && f_big),
..fish
}
}) })
.collect() .collect()
} }
@ -566,3 +572,8 @@ pub fn get_weather_icon(data: &Data, id: &u32) -> String {
pub fn get_zone_name(data: &Data, id: u32) -> &str { pub fn get_zone_name(data: &Data, id: u32) -> &str {
&data.db_data.zones.get(&id).unwrap().name_en &data.db_data.zones.get(&id).unwrap().name_en
} }
pub fn display_intuition_length(length: u32) -> String {
let dur = Duration::seconds(length as i64);
format!("{}m{}s", dur.num_minutes(), dur.num_seconds() % 60)
}

View file

@ -85,7 +85,7 @@ async fn main_handler(
// Extract the list of fish we want to render. // Extract the list of fish we want to render.
let meta = state.data.fish_with_meta(); let meta = state.data.fish_with_meta();
let mut values: Vec<&CombinedFish> = filters.filter(meta.values().collect(), &caught_fish); let mut values: Vec<CombinedFish> = filters.filter(meta.values().collect(), &caught_fish);
values.sort_by(|afish, bfish| { values.sort_by(|afish, bfish| {
pinned_fish pinned_fish
.contains(&(bfish.entry.id as i32)) .contains(&(bfish.entry.id as i32))

View file

@ -11,7 +11,7 @@ use crate::{
pub struct ViewData<'a> { pub struct ViewData<'a> {
pub state: State<Arc<AppState>>, pub state: State<Arc<AppState>>,
pub fish: Vec<&'a CombinedFish<'a>>, pub fish: Vec<CombinedFish<'a>>,
pub caught_fish: Vec<i32>, pub caught_fish: Vec<i32>,
pub pinned_fish: Vec<i32>, pub pinned_fish: Vec<i32>,
pub acc_id: String, pub acc_id: String,
@ -75,6 +75,28 @@ pub fn main_page(data: ViewData) -> Markup {
pub fn fish_list(data: &ViewData) -> Markup { pub fn fish_list(data: &ViewData) -> Markup {
html! { html! {
@for fish in data.fish.clone() { @for fish in data.fish.clone() {
@if !fish.filtered {
(fish_display(&fish, data))
@if !fish.entry.predators.is_empty() {
.predators {
div.predators-header { small { "⇖ Requirements" } }
@for predator in &fish.entry.predators {
@if let Some(pred_fish) = data.fish.iter().find(|f| f.entry.id == predator[0]) {
.predators-fish {
.amount { (predator[1]) }
(fish_display(pred_fish, data))
}
}
}
}
}
}
}
}
}
pub fn fish_display(fish: &CombinedFish, data: &ViewData) -> Markup {
html! {
section.fish.up[fish.is_up].alwaysup[fish.is_always_up].pinned[data.pinned_fish.contains(&(fish.entry.id as i32))] { section.fish.up[fish.is_up].alwaysup[fish.is_always_up].pinned[data.pinned_fish.contains(&(fish.entry.id as i32))] {
.title { .title {
div { div {
@ -94,15 +116,23 @@ pub fn fish_list(data: &ViewData) -> Markup {
} }
} }
} }
div { div.name {
h3 { h3 {
(fish.meta.name_en) (fish.meta.name_en)
span class=(format!("patch patch-{}", fish.entry.patch as u32)) { (fish.entry.patch) } span class=(format!("patch patch-{}", fish.entry.patch as u32)) { (fish.entry.patch) }
}
.subtitle { .subtitle {
span { "Rarity: " (format!("{:.2}", fish.rarity * 100.)) "%" } span { "Rarity: " (format!("{:.2}", fish.rarity * 100.)) "%" }
} }
} }
@if let Some(length) = fish.entry.intuition_length {
.intuition {
img src="/static/intuition.png";
div { (data::display_intuition_length(length)) }
}
}
}
} }
.when { .when {
@if let Some(window) = fish.windows.first() { @if let Some(window) = fish.windows.first() {
@ -205,7 +235,6 @@ pub fn fish_list(data: &ViewData) -> Markup {
} }
} }
} }
}
pub fn header(data: &ViewData) -> Markup { pub fn header(data: &ViewData) -> Markup {
html! { html! {

BIN
static/intuition.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 B

View file

@ -46,6 +46,7 @@ select {
.title .subtitle { .title .subtitle {
margin: 0; margin: 0;
font-size: 14px; font-size: 14px;
font-weight: normal;
color: gray; color: gray;
} }
@ -219,3 +220,51 @@ section.pinned {
.pinned *:not(button) { .pinned *:not(button) {
color: white; color: white;
} }
.pinned + .predators {
background: #ffd6cf;
}
.predators-header {
color: gray;
}
.predators-fish {
display: flex;
align-items: center;
gap: 5px;
}
.predators {
margin-left: 30px;
padding: 0 10px;
margin-bottom: 10px;
}
.predators-fish section {
flex-grow: 1;
border: 1px gray dotted;
border-radius: 5px;
}
.predators-fish .amount {
font-size: 30px;
color: gray;
}
.name {
display: flex;
align-items: center;
gap: 10px;
}
.intuition {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.intuition div {
font-size: 12px;
}