better performances + show team
This commit is contained in:
parent
f3124bcf03
commit
d949fd80c3
117
src/game.rs
117
src/game.rs
@ -12,17 +12,76 @@ static BOARD: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
pub struct GameClient {
|
||||
res_buf: Vec<u8, 4096>,
|
||||
/// State of the board last time it has been sent
|
||||
last_board: u32,
|
||||
team: Team
|
||||
}
|
||||
impl GameClient {
|
||||
pub fn new(team: Team) -> Self {
|
||||
Self {
|
||||
res_buf: Vec::new(),
|
||||
last_board: 0,
|
||||
team
|
||||
}
|
||||
}
|
||||
/// Generate board html
|
||||
pub async fn generate_board_res<'a>(&'a mut self, board: u32, turn: Team, outer_html: bool) -> &'a [u8] {
|
||||
self.res_buf.clear();
|
||||
if outer_html {
|
||||
unwrap(self.res_buf.extend_from_slice(
|
||||
b"<div \
|
||||
id=\"game\" \
|
||||
hx-get=\"/ttt/game\" \
|
||||
hx-swap=\"innerHTML\" \
|
||||
hx-trigger=\"every 100ms\" \
|
||||
hx-target=\"this\"\
|
||||
>"
|
||||
)).await;
|
||||
}
|
||||
unwrap(write!(
|
||||
self.res_buf,
|
||||
"<h3>Team : <span style=\"color:{}\">{}</span></h3>\
|
||||
<div id=\"grid\">",
|
||||
self.team.color(),
|
||||
self.team.name()
|
||||
)).await;
|
||||
for c in 0..=8 {
|
||||
let picked_by = if board & 2_u32.pow(c) != 0 {
|
||||
Some(Team::Zero)
|
||||
} else if board & 2_u32.pow(9 + c) != 0 {
|
||||
Some(Team::One)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match picked_by {
|
||||
Some(t) => {
|
||||
unwrap(write!(
|
||||
self.res_buf,
|
||||
"<div class=\"cell\" style=\"background-color:{}\"></div>",
|
||||
t.color()
|
||||
)).await;
|
||||
}
|
||||
None => if self.team == turn.into() {
|
||||
unwrap(write!(
|
||||
self.res_buf,
|
||||
"<button class=\"cell\" hx-post=\"/ttt/cell{}\" hx-trigger=\"click\" hx-target=\"#game\" hx-swap=\"innerHTML\"></button>",
|
||||
c
|
||||
)).await;
|
||||
} else {
|
||||
unwrap(self.res_buf.extend_from_slice(
|
||||
b"<div class=\"cell\"></div>",
|
||||
)).await;
|
||||
}
|
||||
};
|
||||
}
|
||||
unwrap(self.res_buf.extend_from_slice(b"</div>")).await;
|
||||
if outer_html {
|
||||
unwrap(self.res_buf.extend_from_slice(b"</div>")).await;
|
||||
}
|
||||
&self.res_buf
|
||||
}
|
||||
pub async fn handle_request<'a>(&'a mut self, path: &str) -> (HttpResCode, &'static str, &'a [u8]) {
|
||||
if (path.starts_with("/ttt/cell") && path.len() == 10) || path == "/ttt/board" {
|
||||
if (path.starts_with("/ttt/cell") && path.len() == 10) || path == "/ttt/game" {
|
||||
let mut board = BOARD.load(Ordering::Acquire);
|
||||
let mut turn = TURN.load(Ordering::Acquire);
|
||||
|
||||
@ -46,42 +105,16 @@ impl GameClient {
|
||||
BOARD.store(board, Ordering::Release);
|
||||
TURN.store(turn, Ordering::Release);
|
||||
}
|
||||
|
||||
self.res_buf.clear();
|
||||
for c in 0..=8 {
|
||||
let picked_by = if board & 2_u32.pow(c) != 0 {
|
||||
Some(Team::Zero)
|
||||
} else if board & 2_u32.pow(9 + c) != 0 {
|
||||
Some(Team::One)
|
||||
if self.last_board != board {
|
||||
self.last_board = board;
|
||||
(HttpResCode::Ok, "html", self.generate_board_res(board, turn.into(), false).await)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match picked_by {
|
||||
Some(Team::Zero) => {
|
||||
unwrap(self.res_buf
|
||||
.extend_from_slice(
|
||||
b"<div class=\"cell\" style=\"background-color:blue\"></div>",
|
||||
)).await;
|
||||
(HttpResCode::NoContent, "", &[])
|
||||
}
|
||||
Some(Team::One) => {
|
||||
unwrap(self.res_buf.extend_from_slice(
|
||||
b"<div class=\"cell\" style=\"background-color:red\"></div>",
|
||||
)).await;
|
||||
}
|
||||
None => if self.team == turn.into() {
|
||||
unwrap(write!(
|
||||
self.res_buf,
|
||||
"<button class=\"cell\" hx-post=\"/ttt/cell{}\" hx-trigger=\"click\" hx-target=\"#grid\" hx-swap=\"innerHTML\"></button>",
|
||||
c
|
||||
)).await;
|
||||
} else {
|
||||
unwrap(self.res_buf.extend_from_slice(
|
||||
b"<div class=\"cell\"></div>",
|
||||
)).await;
|
||||
}
|
||||
};
|
||||
}
|
||||
(HttpResCode::Ok, "html", &self.res_buf)
|
||||
} else if path == "/ttt/initial_game" {
|
||||
let board = BOARD.load(Ordering::Acquire);
|
||||
let turn = TURN.load(Ordering::Acquire);
|
||||
(HttpResCode::Ok, "html", self.generate_board_res(board, turn.into(), true).await)
|
||||
} else {
|
||||
(HttpResCode::NotFound, "", &[])
|
||||
}
|
||||
@ -115,6 +148,20 @@ impl Not for Team {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Team {
|
||||
fn color(self) -> &'static str {
|
||||
match self {
|
||||
Team::Zero => "dodgerblue",
|
||||
Team::One => "firebrick"
|
||||
}
|
||||
}
|
||||
fn name(self) -> &'static str {
|
||||
match self {
|
||||
Team::Zero => "blue",
|
||||
Team::One => "red"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Cell {
|
||||
|
@ -105,16 +105,16 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, team: Team, port: u
|
||||
Timer::after_secs(0).await;
|
||||
|
||||
let (code, res_type, res_content): (HttpResCode, &str, &[u8]) = match path {
|
||||
"/" => (HttpResCode::Ok, "html", include_bytes!("../web/index.html")),
|
||||
"/" => (HttpResCode::Ok, "html", include_bytes!("../static/index.html")),
|
||||
"/htmx.min.js" => (
|
||||
HttpResCode::Ok,
|
||||
"javascript",
|
||||
include_bytes!("../web/htmx.min.js"),
|
||||
include_bytes!("../static/htmx.min.js"),
|
||||
),
|
||||
"/htmx.js" => (
|
||||
HttpResCode::Ok,
|
||||
"javascript",
|
||||
include_bytes!("../web/htmx.js"),
|
||||
include_bytes!("../static/htmx.js"),
|
||||
),
|
||||
p => game_client.handle_request(p).await
|
||||
};
|
||||
@ -168,6 +168,7 @@ impl Into<&str> for HttpRequestType {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum HttpResCode {
|
||||
Ok,
|
||||
NoContent,
|
||||
NotFound,
|
||||
Forbidden,
|
||||
}
|
||||
@ -175,6 +176,7 @@ impl Into<&str> for HttpResCode {
|
||||
fn into(self) -> &'static str {
|
||||
match self {
|
||||
HttpResCode::Ok => "HTTP/1.1 200 OK",
|
||||
HttpResCode::NoContent => "HTTP/1.1 204 NO CONTENT",
|
||||
HttpResCode::NotFound => "HTTP/1.1 404 NOT FOUND",
|
||||
HttpResCode::Forbidden => "HTTP/1.1 403 FORBIDDEN",
|
||||
}
|
||||
|
0
web/htmx.min.js → static/htmx.min.js
vendored
0
web/htmx.min.js → static/htmx.min.js
vendored
@ -20,10 +20,11 @@
|
||||
<body>
|
||||
<h1>TicTacToe</h1>
|
||||
<div
|
||||
id="grid"
|
||||
hx-post="/ttt/board"
|
||||
hx-swap="innerHTML"
|
||||
hx-trigger="every 1s"
|
||||
id="game"
|
||||
hx-get="/ttt/initial_game"
|
||||
hx-swap="outerHTML"
|
||||
hx-trigger="load"
|
||||
hx-target="this"
|
||||
></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user