daytime parity/dead info clarity

This commit is contained in:
emilis 2025-11-20 00:16:13 +00:00
parent c2f33e670c
commit 3388894504
No known key found for this signature in database
4 changed files with 139 additions and 13 deletions

View File

@ -11,11 +11,11 @@ $village_border: color.change($village_color, $alpha: 1.0);
$wolves_border: color.change($wolves_color, $alpha: 1.0); $wolves_border: color.change($wolves_color, $alpha: 1.0);
$intel_color: color.adjust($village_color, $hue: -30deg); $intel_color: color.adjust($village_color, $hue: -30deg);
$intel_border: color.change($intel_color, $alpha: 1.0); $intel_border: color.change($intel_color, $alpha: 1.0);
$defensive_color: color.adjust($intel_color, $hue: -30deg); $defensive_color: color.adjust($village_color, $hue: -60deg);
$defensive_border: color.change($defensive_color, $alpha: 1.0); $defensive_border: color.change($defensive_color, $alpha: 1.0);
$offensive_color: color.adjust($village_color, $hue: 30deg); $offensive_color: color.adjust($village_color, $hue: 30deg);
$offensive_border: color.change($offensive_color, $alpha: 1.0); $offensive_border: color.change($offensive_color, $alpha: 1.0);
$starts_as_villager_color: color.adjust($offensive_color, $hue: 30deg); $starts_as_villager_color: color.adjust($village_color, $hue: 60deg);
$starts_as_villager_border: color.change($starts_as_villager_color, $alpha: 1.0); $starts_as_villager_border: color.change($starts_as_villager_color, $alpha: 1.0);
$traitor_color: color.adjust($village_color, $hue: 45deg); $traitor_color: color.adjust($village_color, $hue: 45deg);
$traitor_border: color.change($traitor_color, $alpha: 1.0); $traitor_border: color.change($traitor_color, $alpha: 1.0);
@ -1433,6 +1433,7 @@ input {
} }
& .title { & .title {
text-shadow: black 3px 2px;
margin-bottom: 10px; margin-bottom: 10px;
} }
@ -1468,6 +1469,8 @@ input {
} }
.role { .role {
text-shadow: black 3px 2px;
width: 100%; width: 100%;
filter: saturate(40%); filter: saturate(40%);
padding-left: 10px; padding-left: 10px;
@ -2414,3 +2417,58 @@ li.choice {
flex-grow: 1; flex-grow: 1;
} }
} }
.top-of-day-info {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
padding: 10px;
gap: 10vw;
.info-tidbit {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
gap: 5px;
label {
font-size: 1.5em;
opacity: 70%;
}
.parity {
font-size: 2em;
}
.parity-pct {
font-size: 1.25em;
}
.last-nights-kills {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 2cm;
.identity {
.number {
color: red;
font-size: 1.5em;
}
text-align: center;
font-size: 1.25em;
}
}
.current-day {
color: red;
font-size: 3em;
flex-grow: 1;
}
}
}

View File

@ -759,8 +759,8 @@ impl Host {
(None, false) (None, false)
} }
}, },
HostEvent::Error(err) => (None, false), HostEvent::Error(_) => (None, false),
HostEvent::SetBigScreenState(state) => (None, true), HostEvent::SetBigScreenState(_) => (None, true),
HostEvent::Continue => (None, false), HostEvent::Continue => (None, false),
} }
} }

View File

@ -49,6 +49,43 @@ pub fn DaytimePlayerList(
) -> Html { ) -> Html {
let on_select = big_screen.not().then(|| on_mark.clone()); let on_select = big_screen.not().then(|| on_mark.clone());
let mut characters = characters.clone(); let mut characters = characters.clone();
let last_nights_kills = {
let kills = characters
.iter()
.filter_map(|c| {
c.died_to
.as_ref()
.and_then(|died_to| match died_to.date_time() {
GameTime::Day { .. } => None,
GameTime::Night { number } => {
if let Some(day) = day.as_ref()
&& number == day.get() - 1
{
Some(c)
} else {
None
}
}
})
})
.map(|killed| {
let ident = killed.identity.clone().into_public();
html! {
<span>
<Identity ident={ident} />
</span>
}
})
.collect::<Box<[_]>>();
kills.is_empty().not().then_some(html! {
<div class="info-tidbit">
<label>{"died last night"}</label>
<div class="last-nights-kills">
{kills.into_iter().collect::<Html>()}
</div>
</div>
})
};
characters.sort_by(|l, r| l.identity.number.cmp(&r.identity.number)); characters.sort_by(|l, r| l.identity.number.cmp(&r.identity.number));
let chars = characters let chars = characters
.iter() .iter()
@ -84,6 +121,29 @@ pub fn DaytimePlayerList(
} else { } else {
"execute" "execute"
}; };
let parity = {
let wolves = characters
.iter()
.filter(|c| c.died_to.is_none() && c.role.wolf())
.count();
let total = characters.iter().filter(|c| c.died_to.is_none()).count();
let pct_parity = (((wolves as f64) * 100.0) / (total as f64)).round();
html! {
<div class="info-tidbit">
<label>{"parity"}</label>
<span class="parity">
<span class="red">{wolves}</span>
{"/"}
<span class="total">{total}</span>
</span>
<span class="parity-pct">
{"("}
{pct_parity}
{"%)"}
</span>
</div>
}
};
let button = big_screen let button = big_screen
.not() .not()
.then_some(()) .then_some(())
@ -97,12 +157,19 @@ pub fn DaytimePlayerList(
}); });
let day = day.as_ref().map(|day| { let day = day.as_ref().map(|day| {
html! { html! {
<h2>{"day "}{day.get()}</h2> <div class="info-tidbit">
<label>{"day"}</label>
<span class="current-day">{day.get()}</span>
</div>
} }
}); });
html! { html! {
<div class="character-picker"> <div class="character-picker">
<div class="top-of-day-info">
{day} {day}
{parity}
{last_nights_kills}
</div>
<div class="player-list"> <div class="player-list">
{chars} {chars}
</div> </div>

View File

@ -131,7 +131,8 @@ pub fn SetupCategory(
.map(|(r, count)| { .map(|(r, count)| {
let as_role = r.into_role(); let as_role = r.into_role();
let wakes = as_role.wakes_night_zero().then_some("wakes"); let wakes = as_role.wakes_night_zero().then_some("wakes");
let count = matches!(mode, CategoryMode::ShowExactRoleCount).then(|| { let count =
(matches!(mode, CategoryMode::ShowExactRoleCount) && count > 0).then(|| {
html! { html! {
<span class="count">{count}</span> <span class="count">{count}</span>
} }
@ -142,9 +143,9 @@ pub fn SetupCategory(
html! { html! {
<div class={classes!("slot")}> <div class={classes!("slot")}>
{count} {count}
<div class={classes!("role", wakes, r.category().class())}> <span class={classes!("role", wakes, r.category().class())}>
{r.to_string().to_case(Case::Title)} {r.to_string().to_case(Case::Title)}
</div> </span>
<div class="attributes"> <div class="attributes">
<div class="alignment"> <div class="alignment">
<Icon source={alignment} icon_type={IconType::Small}/> <Icon source={alignment} icon_type={IconType::Small}/>