Impl use of win/draw check, fixes
Also added unit tests for win/draw checks.
This commit is contained in:
parent
9e9bb0758c
commit
b902b1c7b4
5 changed files with 396 additions and 146 deletions
|
@ -14,8 +14,8 @@ pub fn check_win_draw(board: &BoardType) -> Option<BoardState> {
|
|||
}
|
||||
}
|
||||
|
||||
if has_empty_slot {
|
||||
return None;
|
||||
if !has_empty_slot {
|
||||
return Some(BoardState::Empty);
|
||||
}
|
||||
|
||||
let check_result = |state| -> Option<BoardState> {
|
||||
|
@ -130,3 +130,200 @@ fn has_right_down_diagonal_at_idx(idx: usize, board: &BoardType) -> BoardState {
|
|||
}
|
||||
BoardState::Empty
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::state::{new_empty_board, BoardState};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_horizontal_check() {
|
||||
let board = new_empty_board();
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
assert_eq!(
|
||||
has_right_horizontal_at_idx(x + y * (COLS as usize), &board),
|
||||
BoardState::Empty
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
board[50].replace(BoardState::Cyan);
|
||||
board[51].replace(BoardState::Cyan);
|
||||
board[52].replace(BoardState::Cyan);
|
||||
board[53].replace(BoardState::Cyan);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 50 {
|
||||
assert_eq!(has_right_horizontal_at_idx(idx, &board), BoardState::Cyan);
|
||||
} else {
|
||||
assert_eq!(has_right_horizontal_at_idx(idx, &board), BoardState::Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
board[51].replace(BoardState::Magenta);
|
||||
|
||||
board[43].replace(BoardState::Magenta);
|
||||
board[44].replace(BoardState::Magenta);
|
||||
board[45].replace(BoardState::Magenta);
|
||||
board[46].replace(BoardState::Magenta);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 43 {
|
||||
assert_eq!(
|
||||
has_right_horizontal_at_idx(idx, &board),
|
||||
BoardState::Magenta
|
||||
);
|
||||
} else {
|
||||
assert_eq!(has_right_horizontal_at_idx(idx, &board), BoardState::Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vertical_check() {
|
||||
let board = new_empty_board();
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
assert_eq!(
|
||||
has_down_vertical_at_idx(x + y * (COLS as usize), &board),
|
||||
BoardState::Empty
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
board[30].replace(BoardState::Cyan);
|
||||
board[37].replace(BoardState::Cyan);
|
||||
board[44].replace(BoardState::Cyan);
|
||||
board[51].replace(BoardState::Cyan);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 30 {
|
||||
assert_eq!(has_down_vertical_at_idx(idx, &board), BoardState::Cyan);
|
||||
} else {
|
||||
assert_eq!(has_down_vertical_at_idx(idx, &board), BoardState::Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
board[16].replace(BoardState::Magenta);
|
||||
board[23].replace(BoardState::Magenta);
|
||||
board[30].replace(BoardState::Magenta);
|
||||
board[37].replace(BoardState::Magenta);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 16 {
|
||||
assert_eq!(has_down_vertical_at_idx(idx, &board), BoardState::Magenta);
|
||||
} else {
|
||||
assert_eq!(has_down_vertical_at_idx(idx, &board), BoardState::Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_upper_diagonal_check() {
|
||||
let board = new_empty_board();
|
||||
|
||||
board[44].replace(BoardState::Cyan);
|
||||
board[38].replace(BoardState::Cyan);
|
||||
board[32].replace(BoardState::Cyan);
|
||||
board[26].replace(BoardState::Cyan);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 44 {
|
||||
assert_eq!(has_right_up_diagonal_at_idx(idx, &board), BoardState::Cyan);
|
||||
} else {
|
||||
assert_eq!(has_right_up_diagonal_at_idx(idx, &board), BoardState::Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
board[38].replace(BoardState::Magenta);
|
||||
|
||||
board[28].replace(BoardState::Magenta);
|
||||
board[22].replace(BoardState::Magenta);
|
||||
board[16].replace(BoardState::Magenta);
|
||||
board[10].replace(BoardState::Magenta);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 28 {
|
||||
assert_eq!(
|
||||
has_right_up_diagonal_at_idx(idx, &board),
|
||||
BoardState::Magenta
|
||||
);
|
||||
} else {
|
||||
assert_eq!(has_right_up_diagonal_at_idx(idx, &board), BoardState::Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lower_diagonal_check() {
|
||||
let board = new_empty_board();
|
||||
|
||||
board[17].replace(BoardState::Cyan);
|
||||
board[25].replace(BoardState::Cyan);
|
||||
board[33].replace(BoardState::Cyan);
|
||||
board[41].replace(BoardState::Cyan);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 17 {
|
||||
assert_eq!(
|
||||
has_right_down_diagonal_at_idx(idx, &board),
|
||||
BoardState::Cyan
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
has_right_down_diagonal_at_idx(idx, &board),
|
||||
BoardState::Empty
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
board[25].replace(BoardState::Magenta);
|
||||
|
||||
board[28].replace(BoardState::Magenta);
|
||||
board[36].replace(BoardState::Magenta);
|
||||
board[44].replace(BoardState::Magenta);
|
||||
board[52].replace(BoardState::Magenta);
|
||||
|
||||
for y in 0..(ROWS as usize) {
|
||||
for x in 0..(COLS as usize) {
|
||||
let idx = x + y * (COLS as usize);
|
||||
if idx == 28 {
|
||||
assert_eq!(
|
||||
has_right_down_diagonal_at_idx(idx, &board),
|
||||
BoardState::Magenta
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
has_right_down_diagonal_at_idx(idx, &board),
|
||||
BoardState::Empty
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
54
front_end/src/html_helper.rs
Normal file
54
front_end/src/html_helper.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use web_sys::{window, Document, Window};
|
||||
|
||||
pub fn get_window_document() -> Result<(Window, Document), String> {
|
||||
let window = window().ok_or_else(|| String::from("Failed to get window"))?;
|
||||
let document = window
|
||||
.document()
|
||||
.ok_or_else(|| String::from("Failed to get document"))?;
|
||||
|
||||
Ok((window, document))
|
||||
}
|
||||
|
||||
pub fn append_to_info_text(
|
||||
document: &Document,
|
||||
id: &str,
|
||||
msg: &str,
|
||||
limit: u32,
|
||||
) -> Result<(), String> {
|
||||
let info_text = document
|
||||
.get_element_by_id(id)
|
||||
.ok_or_else(|| format!("Failed to get info_text \"{}\"", id))?;
|
||||
|
||||
let height = info_text.client_height();
|
||||
|
||||
// create the new text to be appended in the text
|
||||
let p = document
|
||||
.create_element("p")
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
p.set_inner_html(msg);
|
||||
|
||||
// check if scrolled to top
|
||||
let at_top: bool = info_text.scroll_top() <= height - info_text.scroll_height();
|
||||
|
||||
// append text to output
|
||||
info_text
|
||||
.append_with_node_1(&p)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
while info_text.child_element_count() > limit {
|
||||
info_text
|
||||
.remove_child(
|
||||
&info_text.first_child().ok_or_else(|| {
|
||||
format!("Failed to get first_child() of info_text \"{}\"", id)
|
||||
})?,
|
||||
)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
}
|
||||
|
||||
if at_top {
|
||||
info_text.set_scroll_top(height - info_text.scroll_height());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
mod ai;
|
||||
mod constants;
|
||||
mod game_logic;
|
||||
mod html_helper;
|
||||
mod random_helper;
|
||||
mod state;
|
||||
mod yew_components;
|
||||
|
|
|
@ -9,7 +9,7 @@ pub enum GameState {
|
|||
SinglePlayer,
|
||||
LocalMultiplayer,
|
||||
NetworkedMultiplayer,
|
||||
PostGameResults(Turn),
|
||||
PostGameResults(BoardState),
|
||||
}
|
||||
|
||||
impl Default for GameState {
|
||||
|
@ -108,6 +108,67 @@ impl Turn {
|
|||
|
||||
pub type BoardType = [Rc<Cell<BoardState>>; 56];
|
||||
|
||||
pub fn new_empty_board() -> BoardType {
|
||||
[
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
]
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SharedState {
|
||||
pub board: BoardType,
|
||||
|
@ -119,64 +180,7 @@ impl Default for SharedState {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
// cannot use [<type>; 56] because Rc does not impl Copy
|
||||
board: [
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
Rc::new(Cell::new(BoardState::default())),
|
||||
],
|
||||
board: new_empty_board(),
|
||||
game_state: Rc::new(Cell::new(GameState::default())),
|
||||
turn: Rc::new(Cell::new(Turn::CyanPlayer)),
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use crate::constants::{COLS, INFO_TEXT_MAX_ITEMS, ROWS};
|
||||
use crate::game_logic::check_win_draw;
|
||||
use crate::html_helper::{append_to_info_text, get_window_document};
|
||||
use crate::state::{BoardState, GameState, SharedState, Turn};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use yew::prelude::*;
|
||||
|
||||
pub struct MainMenu {}
|
||||
|
@ -117,6 +121,13 @@ impl Component for Slot {
|
|||
.context::<SharedState>(Callback::noop())
|
||||
.expect("state to be set");
|
||||
|
||||
match shared.game_state.get() {
|
||||
GameState::MainMenu => return false,
|
||||
GameState::SinglePlayer
|
||||
| GameState::LocalMultiplayer
|
||||
| GameState::NetworkedMultiplayer => (),
|
||||
GameState::PostGameResults(_) => return false,
|
||||
}
|
||||
if shared.game_state.get() == GameState::MainMenu {
|
||||
return false;
|
||||
}
|
||||
|
@ -228,8 +239,8 @@ impl Component for Wrapper {
|
|||
.link()
|
||||
.context::<SharedState>(Callback::noop())
|
||||
.expect("state to be set");
|
||||
let window = web_sys::window().expect("no window exists");
|
||||
let document = window.document().expect("window should have a document");
|
||||
let (window, document) =
|
||||
get_window_document().expect("Should be able to get Window and Document");
|
||||
|
||||
match msg {
|
||||
WrapperMsg::Pressed(idx) => {
|
||||
|
@ -268,99 +279,82 @@ impl Component for Wrapper {
|
|||
placed = true;
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
//log::info!("{} is {:?}", idx, shared.board[idx as usize].get());
|
||||
|
||||
// DEBUG
|
||||
//log::info!("{}", &output_str);
|
||||
|
||||
// info text below the grid
|
||||
if let Some(info_text) = document.get_element_by_id("info_text0") {
|
||||
let height = info_text.client_height();
|
||||
|
||||
// create the new text to be appended in the output
|
||||
let p = document
|
||||
.create_element("p")
|
||||
.expect("document should be able to create <p>");
|
||||
let output_str = match placed {
|
||||
true => format!("{} placed into slot {}", current_player, bottom_idx),
|
||||
false => "Invalid place to insert".into(),
|
||||
};
|
||||
p.set_text_content(Some(&output_str));
|
||||
|
||||
// DEBUG
|
||||
//log::info!(
|
||||
// "pre: scroll top is {}, scroll height is {}",
|
||||
// info_text.scroll_top(),
|
||||
// info_text.scroll_height()
|
||||
//);
|
||||
|
||||
// check if scrolled to top
|
||||
let at_top: bool = info_text.scroll_top() <= height - info_text.scroll_height();
|
||||
|
||||
// append text to output
|
||||
info_text
|
||||
.append_with_node_1(&p)
|
||||
.expect("should be able to append to info_text");
|
||||
while info_text.child_element_count() > INFO_TEXT_MAX_ITEMS {
|
||||
info_text
|
||||
.remove_child(&info_text.first_child().unwrap())
|
||||
.expect("should be able to limit items in info_text");
|
||||
// check for win
|
||||
let check_win_draw_opt = check_win_draw(&shared.board);
|
||||
if let Some(endgame_state) = check_win_draw_opt {
|
||||
if endgame_state == BoardState::Empty {
|
||||
// draw
|
||||
let text_append_result = append_to_info_text(
|
||||
&document,
|
||||
"info_text0",
|
||||
"Game ended in a draw",
|
||||
INFO_TEXT_MAX_ITEMS,
|
||||
);
|
||||
if let Err(e) = text_append_result {
|
||||
log::warn!("ERROR: text append to info_text0 failed: {}", e);
|
||||
}
|
||||
} else {
|
||||
// a player won
|
||||
let turn = Turn::from(endgame_state);
|
||||
let text_string =
|
||||
format!("<b class=\"{}\">{} has won</b>", turn.get_color(), turn);
|
||||
let text_append_result = append_to_info_text(
|
||||
&document,
|
||||
"info_text0",
|
||||
&text_string,
|
||||
INFO_TEXT_MAX_ITEMS,
|
||||
);
|
||||
if let Err(e) = text_append_result {
|
||||
log::warn!("ERROR: text append to info_text0 failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
//log::info!("at_top is {}", if at_top { "true" } else { "false" });
|
||||
|
||||
// scroll to top only if at top
|
||||
if at_top {
|
||||
info_text.set_scroll_top(height - info_text.scroll_height());
|
||||
let text_append_result =
|
||||
append_to_info_text(&document, "info_text1", "<b>Game Over</b>", 1);
|
||||
if let Err(e) = text_append_result {
|
||||
log::warn!("ERROR: text append to info_text1 failed: {}", e);
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
//log::info!(
|
||||
// "post: scroll top is {}, scroll height is {}",
|
||||
// info_text.scroll_top(),
|
||||
// info_text.scroll_height()
|
||||
//);
|
||||
shared
|
||||
.game_state
|
||||
.replace(GameState::PostGameResults(endgame_state));
|
||||
} else {
|
||||
log::warn!("Failed to get bottom \"info_text\"");
|
||||
}
|
||||
// game is still ongoing
|
||||
|
||||
// info text right of the grid
|
||||
if let Some(info_text) = document.get_element_by_id("info_text1") {
|
||||
let height = info_text.client_height();
|
||||
// info text below the grid
|
||||
{
|
||||
let output_str = match placed {
|
||||
true => format!("{} placed into slot {}", current_player, bottom_idx),
|
||||
false => "Invalid place to insert".into(),
|
||||
};
|
||||
|
||||
// create the new text to be appended in the output
|
||||
let p = document
|
||||
.create_element("p")
|
||||
.expect("document should be able to create <p>");
|
||||
let turn = shared.turn.get();
|
||||
p.set_inner_html(&format!(
|
||||
"<b class=\"{}\">It is {}'s turn</b>",
|
||||
turn.get_color(),
|
||||
turn
|
||||
));
|
||||
|
||||
// check if scrolled to top
|
||||
let at_top: bool = info_text.scroll_top() <= height - info_text.scroll_height();
|
||||
|
||||
// append text to output
|
||||
info_text
|
||||
.append_with_node_1(&p)
|
||||
.expect("should be able to append to info_text");
|
||||
while info_text.child_element_count() > 1 {
|
||||
info_text
|
||||
.remove_child(&info_text.first_child().unwrap())
|
||||
.expect("should be able to limit items in info_text");
|
||||
let text_append_result = append_to_info_text(
|
||||
&document,
|
||||
"info_text0",
|
||||
&output_str,
|
||||
INFO_TEXT_MAX_ITEMS,
|
||||
);
|
||||
if let Err(e) = text_append_result {
|
||||
log::warn!("ERROR: text append to info_text0 failed: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// scroll to top only if at top
|
||||
if at_top {
|
||||
info_text.set_scroll_top(height - info_text.scroll_height());
|
||||
// info text right of the grid
|
||||
{
|
||||
let turn = shared.turn.get();
|
||||
let output_str = format!(
|
||||
"<b class=\"{}\">It is {}'s turn</b>",
|
||||
turn.get_color(),
|
||||
turn
|
||||
);
|
||||
|
||||
let text_append_result =
|
||||
append_to_info_text(&document, "info_text1", &output_str, 1);
|
||||
if let Err(e) = text_append_result {
|
||||
log::warn!("ERROR: text append to info_text1 failed: {}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::warn!("Failed to get side \"info_text\"");
|
||||
}
|
||||
} // else: game is still ongoing after logic check
|
||||
} // WrapperMsg::Pressed(idx) =>
|
||||
} // match (msg)
|
||||
|
||||
|
|
Loading…
Reference in a new issue