Sort the player's hand by rank then suit
This commit is contained in:
@@ -551,6 +551,21 @@ pub fn card_asset(code: &str) -> String {
|
||||
|
||||
pub const CARD_BACK: &str = "/assets/cards/back.svg";
|
||||
|
||||
/// Display order key for a hand: rank ascending (01..10, i.e. 1..7 then
|
||||
/// Fante, Cavallo, Re), then suit (denari, coppe, spade, bastoni).
|
||||
/// Malformed codes sort last.
|
||||
pub fn hand_sort_key(code: &str) -> (u8, u8) {
|
||||
let rank = code.get(..2).and_then(|r| r.parse().ok()).unwrap_or(u8::MAX);
|
||||
let suit = match code.get(2..3) {
|
||||
Some("D") => 0,
|
||||
Some("C") => 1,
|
||||
Some("S") => 2,
|
||||
Some("B") => 3,
|
||||
_ => u8::MAX,
|
||||
};
|
||||
(rank, suit)
|
||||
}
|
||||
|
||||
/// Human-friendly rank+suit label, e.g. `07D` -> "7 of denari".
|
||||
pub fn card_label(code: &str) -> String {
|
||||
if code.len() != 3 {
|
||||
@@ -600,6 +615,38 @@ mod tests {
|
||||
assert_eq!("7 di denari", card_label("07D"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hand_sort_orders_ranks_ascending() {
|
||||
let mut hand = vec![
|
||||
"10B".to_string(),
|
||||
"01S".to_string(),
|
||||
"07D".to_string(),
|
||||
"08C".to_string(),
|
||||
];
|
||||
hand.sort_by_key(|c| hand_sort_key(c));
|
||||
assert_eq!(vec!["01S", "07D", "08C", "10B"], hand);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hand_sort_breaks_ties_by_suit() {
|
||||
let mut hand = vec![
|
||||
"02B".to_string(),
|
||||
"02S".to_string(),
|
||||
"02C".to_string(),
|
||||
"02D".to_string(),
|
||||
"01S".to_string(),
|
||||
];
|
||||
hand.sort_by_key(|c| hand_sort_key(c));
|
||||
assert_eq!(vec!["01S", "02D", "02C", "02S", "02B"], hand);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hand_sort_puts_malformed_codes_last() {
|
||||
let mut hand = vec!["07D".to_string(), "xx".to_string(), "AB1".to_string()];
|
||||
hand.sort_by_key(|c| hand_sort_key(c));
|
||||
assert_eq!(vec!["07D", "xx", "AB1"], hand);
|
||||
}
|
||||
|
||||
fn scopone_match() -> MatchSummary {
|
||||
serde_json::from_value(json!({
|
||||
"id": "m1",
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::api;
|
||||
use crate::components::card::{card_back, card_img};
|
||||
use crate::components::summary::{hand_summary_modal, summary_rows};
|
||||
use crate::components::toast::toast;
|
||||
use crate::model::{card_label, GameView, MoveView, PlayerView, Scores, ServerMessage};
|
||||
use crate::model::{card_label, hand_sort_key, GameView, MoveView, PlayerView, Scores, ServerMessage};
|
||||
use crate::ws::{self, GameSocket};
|
||||
|
||||
fn send_play(socket: Signal<Option<GameSocket>>, card: String, capture: Option<Vec<String>>) {
|
||||
@@ -593,7 +593,8 @@ fn table_view(
|
||||
let viewer = player_for_seat(&game, viewer_seat);
|
||||
let my_captured = viewer.as_ref().map(|p| p.captured_count).unwrap_or(0);
|
||||
let my_scope = viewer.as_ref().map(|p| p.scope).unwrap_or(0);
|
||||
let hand = viewer.and_then(|p| p.hand).unwrap_or_default();
|
||||
let mut hand = viewer.and_then(|p| p.hand).unwrap_or_default();
|
||||
hand.sort_by_key(|c| hand_sort_key(c));
|
||||
let current_selection = selected.get_clone();
|
||||
let hand_cards = hand
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user