challenge: 12
This commit is contained in:
parent
2b614ee8c4
commit
81263f7803
@ -13,6 +13,7 @@ tokio = "1.28.2"
|
||||
cargo-manifest = { version = "0.17.0", optional = true }
|
||||
serde_yml = { version = "0.0.12", optional = true }
|
||||
toml = { version = "0.8.19", optional = true }
|
||||
rand = { version = "0.8.5", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
axum-test = "16.4.0"
|
||||
@ -20,7 +21,7 @@ axum-test = "16.4.0"
|
||||
[features]
|
||||
default = []
|
||||
task1-9 = ["cargo-manifest", "serde_yml", "toml"]
|
||||
task12 = []
|
||||
task12 = ["rand"]
|
||||
task16 = []
|
||||
task19 = []
|
||||
task23 = []
|
||||
|
22
src/lib.rs
22
src/lib.rs
@ -1,17 +1,20 @@
|
||||
mod routes;
|
||||
|
||||
// use axum::routing::{get, post};
|
||||
#[cfg(feature = "task12")]
|
||||
use routes::{board, place, random_board, reset, Board};
|
||||
#[cfg(feature = "task1-9")]
|
||||
use routes::{
|
||||
hello_bird, hello_world, ipv4_dest, ipv4_key, ipv6_dest, ipv6_key, manifest, milk, minus_one,
|
||||
refill, MilkFactory,
|
||||
};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub fn router() -> axum::Router {
|
||||
#[cfg(feature = "task1-9")]
|
||||
use axum::routing::get;
|
||||
#[cfg(feature = "task1-9")]
|
||||
use axum::routing::post;
|
||||
use axum::Router;
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
|
||||
#[cfg(feature = "task1-9")]
|
||||
let milk_factory = MilkFactory::new();
|
||||
@ -30,6 +33,13 @@ pub fn router() -> axum::Router {
|
||||
.with_state(milk_factory)
|
||||
.route("/", get(hello_bird));
|
||||
|
||||
// #[cfg(feature="task12")]
|
||||
#[cfg(feature = "task12")]
|
||||
Router::new()
|
||||
.route("/12/board", get(board))
|
||||
.route("/12/reset", post(reset))
|
||||
.route("/12/place/:team/:column", post(place))
|
||||
.route("/12/random-board", get(random_board))
|
||||
.with_state(Board::new());
|
||||
|
||||
Router::new()
|
||||
}
|
||||
|
@ -1,18 +1,38 @@
|
||||
#![cfg(feature = "task1-9")]
|
||||
#[cfg(feature = "task12")]
|
||||
mod task_twelve;
|
||||
#[cfg(feature = "task12")]
|
||||
pub use task_twelve::{board, game::Board, place, random_board, reset};
|
||||
|
||||
#[cfg(feature = "task1-9")]
|
||||
mod hello_bird;
|
||||
|
||||
#[cfg(feature = "task1-9")]
|
||||
mod hello_world;
|
||||
#[cfg(feature = "task1-9")]
|
||||
mod minus_one;
|
||||
#[cfg(feature = "task1-9")]
|
||||
mod task_five;
|
||||
#[cfg(feature = "task1-9")]
|
||||
mod task_nine;
|
||||
#[cfg(feature = "task1-9")]
|
||||
mod task_two;
|
||||
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use hello_bird::hello_bird;
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use hello_world::hello_world;
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use minus_one::minus_one;
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use task_five::manifest;
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use task_two::ipv4_dest;
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use task_two::ipv4_key;
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use task_two::ipv6_dest;
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use task_two::ipv6_key;
|
||||
|
||||
#[cfg(feature = "task1-9")]
|
||||
pub use task_nine::{milk, refill, MilkFactory};
|
||||
|
38
src/routes/task_twelve/error.rs
Normal file
38
src/routes/task_twelve/error.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use axum::response::IntoResponse;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum GameError {
|
||||
ColumnFull,
|
||||
GameOver,
|
||||
InvalidColumn,
|
||||
InvalidTeam,
|
||||
}
|
||||
|
||||
impl Display for GameError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ColumnFull => write!(f, "Column is full"),
|
||||
Self::InvalidColumn => write!(f, "Invalid column"),
|
||||
Self::GameOver => write!(f, "Game is over"),
|
||||
Self::InvalidTeam => write!(f, "Invalid team"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for GameError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
match self {
|
||||
Self::ColumnFull | Self::GameOver | Self::InvalidColumn => (
|
||||
axum::http::StatusCode::SERVICE_UNAVAILABLE,
|
||||
self.to_string(),
|
||||
)
|
||||
.into_response(),
|
||||
Self::InvalidTeam => {
|
||||
(axum::http::StatusCode::BAD_REQUEST, self.to_string()).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
196
src/routes/task_twelve/game/board.rs
Normal file
196
src/routes/task_twelve/game/board.rs
Normal file
@ -0,0 +1,196 @@
|
||||
use std::{
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
pub const DEFAULT_SEED: u64 = 2024;
|
||||
|
||||
use axum::response::IntoResponse;
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
|
||||
use super::{super::error::GameError, column::Column, Slot, EMPTY, WALL};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Board {
|
||||
columns: Arc<Mutex<[[Option<Slot>; 4]; 4]>>,
|
||||
seed: Arc<Mutex<StdRng>>,
|
||||
}
|
||||
|
||||
impl Board {
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
columns: Arc::new(Mutex::new([[None; 4]; 4])),
|
||||
seed: Arc::new(Mutex::new(StdRng::seed_from_u64(DEFAULT_SEED))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display(&self) -> String {
|
||||
format!(
|
||||
"{}\n",
|
||||
self.to_string()
|
||||
.split_terminator('\n')
|
||||
.take(5)
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_seed(&self) -> Arc<Mutex<StdRng>> {
|
||||
self.seed.clone()
|
||||
}
|
||||
|
||||
pub fn random(&self, random: &mut StdRng) {
|
||||
let mut columns: [[Option<Slot>; 4]; 4] = [[None; 4]; 4];
|
||||
// let mut seed = self.seed.lock().unwrap();
|
||||
for i in (0..4).rev() {
|
||||
(0..4).for_each(|j| {
|
||||
let random = random.gen::<bool>();
|
||||
let slot = if random {
|
||||
Some(Slot::Cookie)
|
||||
} else {
|
||||
Some(Slot::Milk)
|
||||
};
|
||||
columns[j][i] = slot;
|
||||
});
|
||||
}
|
||||
// for column in &mut columns.iter_mut() {
|
||||
// for slot in column.iter_mut() {
|
||||
// let random = random.gen::<bool>();
|
||||
// if random {
|
||||
// *slot = Some(Slot::Cookie);
|
||||
// } else {
|
||||
// *slot = Some(Slot::Milk);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// drop(seed);
|
||||
|
||||
{
|
||||
let mut cols = self.columns.lock().unwrap();
|
||||
*cols = columns;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_full(&self) -> bool {
|
||||
let columns = self.columns.lock().unwrap();
|
||||
columns
|
||||
.iter()
|
||||
.all(|column| column.iter().all(std::option::Option::is_some))
|
||||
}
|
||||
|
||||
pub fn check(&self) -> Option<Slot> {
|
||||
let columns = self.columns.lock().unwrap();
|
||||
|
||||
// Check rows and columns
|
||||
for i in 0..4 {
|
||||
if columns[i][0].is_some()
|
||||
&& columns[i][0] == columns[i][1]
|
||||
&& columns[i][0] == columns[i][2]
|
||||
&& columns[i][0] == columns[i][3]
|
||||
{
|
||||
return columns[i][0];
|
||||
}
|
||||
if columns[0][i].is_some()
|
||||
&& columns[0][i] == columns[1][i]
|
||||
&& columns[0][i] == columns[2][i]
|
||||
&& columns[0][i] == columns[3][i]
|
||||
{
|
||||
return columns[0][i];
|
||||
}
|
||||
}
|
||||
|
||||
// Check diagonals
|
||||
if columns[0][0].is_some()
|
||||
&& columns[0][0] == columns[1][1]
|
||||
&& columns[0][0] == columns[2][2]
|
||||
&& columns[0][0] == columns[3][3]
|
||||
{
|
||||
return columns[0][0];
|
||||
}
|
||||
if columns[0][3].is_some()
|
||||
&& columns[0][3] == columns[1][2]
|
||||
&& columns[0][3] == columns[2][1]
|
||||
&& columns[0][3] == columns[3][0]
|
||||
{
|
||||
return columns[0][3];
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn reset(&self) {
|
||||
{
|
||||
let mut columns = self.columns.lock().unwrap();
|
||||
for i in 0..4 {
|
||||
for j in 0..4 {
|
||||
columns[i][j] = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
let mut seed = self.seed.lock().unwrap();
|
||||
*seed = StdRng::seed_from_u64(DEFAULT_SEED);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn insert(&self, column: Column, slot: Slot) -> Result<(), GameError> {
|
||||
if self.check().is_some() {
|
||||
return Err(GameError::GameOver);
|
||||
}
|
||||
{
|
||||
let column: usize = column.into();
|
||||
let column = column - 1;
|
||||
let mut columns = self.columns.lock().unwrap();
|
||||
|
||||
if column > columns.len() - 1 {
|
||||
return Err(GameError::InvalidColumn);
|
||||
}
|
||||
for i in 0..4 {
|
||||
if columns[column][i].is_none() {
|
||||
columns[column][i] = Some(slot);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
drop(columns);
|
||||
}
|
||||
Err(GameError::ColumnFull)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Board {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
{
|
||||
let columns = self.columns.lock().unwrap();
|
||||
for j in (0..4).rev() {
|
||||
write!(f, "{WALL}")?;
|
||||
for i in 0..4 {
|
||||
match columns[i][j] {
|
||||
Some(slot) => write!(f, "{slot}")?,
|
||||
None => write!(f, "{EMPTY}")?,
|
||||
}
|
||||
}
|
||||
writeln!(f, "{WALL}")?;
|
||||
}
|
||||
}
|
||||
for _ in 0..6 {
|
||||
write!(f, "{WALL}")?;
|
||||
}
|
||||
|
||||
writeln!(f)?;
|
||||
if let Some(winner) = self.check() {
|
||||
writeln!(f, "{winner} wins!")?;
|
||||
} else if self.is_full() {
|
||||
writeln!(f, "No winner.")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for Board {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
(axum::http::StatusCode::OK, self.to_string()).into_response()
|
||||
}
|
||||
}
|
47
src/routes/task_twelve/game/column.rs
Normal file
47
src/routes/task_twelve/game/column.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use serde::de::{self, Deserializer, Visitor};
|
||||
use serde::Deserialize;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Column(usize);
|
||||
|
||||
impl Display for Column {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Column> for usize {
|
||||
fn from(column: Column) -> Self {
|
||||
column.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Column {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ColumnVisitor;
|
||||
|
||||
impl Visitor<'_> for ColumnVisitor {
|
||||
type Value = Column;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("an integer between 1 and 4")
|
||||
}
|
||||
|
||||
fn visit_u8<E>(self, value: u8) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match value {
|
||||
1..=4 => Ok(Column(value as usize)),
|
||||
_ => Err(de::Error::custom("value must be between 1 and 4")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_u8(ColumnVisitor)
|
||||
}
|
||||
}
|
28
src/routes/task_twelve/game/mod.rs
Normal file
28
src/routes/task_twelve/game/mod.rs
Normal file
@ -0,0 +1,28 @@
|
||||
pub mod board;
|
||||
pub mod column;
|
||||
pub mod slot;
|
||||
|
||||
pub use board::Board;
|
||||
pub use slot::Slot;
|
||||
|
||||
const EMPTY: &str = "⬛";
|
||||
const COOKIE: &str = "🍪";
|
||||
const MILK: &str = "🥛";
|
||||
const WALL: &str = "⬜";
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
|
||||
// #[test]
|
||||
// fn test_board() {
|
||||
// let board = Board::new();
|
||||
// println!("{board}");
|
||||
|
||||
// for _ in 0..4 {
|
||||
// assert!(board.insert(0, Slot::Milk).is_ok());
|
||||
// }
|
||||
|
||||
// println!("{board}");
|
||||
// }
|
||||
// }
|
34
src/routes/task_twelve/game/slot.rs
Normal file
34
src/routes/task_twelve/game/slot.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::{super::error::GameError, COOKIE, MILK};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Slot {
|
||||
Milk,
|
||||
Cookie,
|
||||
}
|
||||
|
||||
impl Display for Slot {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Milk => write!(f, "{MILK}"),
|
||||
Self::Cookie => write!(f, "{COOKIE}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Slot {
|
||||
type Error = GameError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
"milk" => Ok(Self::Milk),
|
||||
"cookie" => Ok(Self::Cookie),
|
||||
_ => Err(GameError::InvalidTeam),
|
||||
}
|
||||
}
|
||||
}
|
44
src/routes/task_twelve/mod.rs
Normal file
44
src/routes/task_twelve/mod.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use game::{column::Column, Board, Slot};
|
||||
|
||||
pub mod error;
|
||||
pub mod game;
|
||||
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn board(State(board): State<Board>) -> impl IntoResponse {
|
||||
board.into_response()
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn reset(State(board): State<Board>) -> impl IntoResponse {
|
||||
board.reset();
|
||||
board.into_response()
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn place(
|
||||
State(board): State<Board>,
|
||||
Path((team, column)): Path<(Slot, Column)>,
|
||||
) -> impl IntoResponse {
|
||||
board.insert(column, team).map_err(|err| match err {
|
||||
error::GameError::ColumnFull | error::GameError::GameOver => (
|
||||
axum::http::StatusCode::SERVICE_UNAVAILABLE,
|
||||
board.to_string(),
|
||||
)
|
||||
.into_response(),
|
||||
e => e.into_response(),
|
||||
})?;
|
||||
Ok::<_, axum::response::Response>(board.into_response())
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn random_board(State(board): State<Board>) -> impl IntoResponse {
|
||||
// let mut random = rand::rngs::StdRng::seed_from_u64(2024);
|
||||
let seed = board.get_seed();
|
||||
let mut random = seed.lock().unwrap();
|
||||
board.random(&mut random);
|
||||
board.display().into_response()
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#[cfg(feature = "task12")]
|
||||
#![cfg(feature = "task12")]
|
||||
#[cfg(test)]
|
||||
mod task_twelve {
|
||||
use axum_test::TestServer;
|
||||
use itsscb_shuttlings_cch24::router;
|
||||
@ -6,4 +7,214 @@ mod task_twelve {
|
||||
fn test_server() -> TestServer {
|
||||
TestServer::new(router()).unwrap()
|
||||
}
|
||||
const EMPTY_BOARD: &str = "⬜⬛⬛⬛⬛⬜
|
||||
⬜⬛⬛⬛⬛⬜
|
||||
⬜⬛⬛⬛⬛⬜
|
||||
⬜⬛⬛⬛⬛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_task_1() {
|
||||
let server = test_server();
|
||||
|
||||
let response = server.get("/12/board").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(EMPTY_BOARD);
|
||||
|
||||
let response = server.post("/12/reset").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(EMPTY_BOARD);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_task_2() {
|
||||
let server = test_server();
|
||||
let response = server.post("/12/reset").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(EMPTY_BOARD);
|
||||
|
||||
let want = "\
|
||||
⬜⬛⬛⬛⬛⬜
|
||||
⬜⬛⬛⬛⬛⬜
|
||||
⬜⬛⬛⬛⬛⬜
|
||||
⬜🍪⬛⬛⬛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
|
||||
let response = server.post("/12/place/cookie/1").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
|
||||
let want = "\
|
||||
⬜🍪⬛⬛⬛⬜
|
||||
⬜🍪⬛⬛⬛⬜
|
||||
⬜🍪⬛⬛⬛⬜
|
||||
⬜🍪⬛⬛⬛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
🍪 wins!
|
||||
";
|
||||
|
||||
let response = server.post("/12/place/cookie/1").await;
|
||||
response.assert_status_ok();
|
||||
|
||||
let response = server.post("/12/place/cookie/1").await;
|
||||
response.assert_status_ok();
|
||||
let response = server.post("/12/place/cookie/1").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
|
||||
let response = server.post("/12/place/milk/2").await;
|
||||
response.assert_status_service_unavailable();
|
||||
response.assert_text(want);
|
||||
|
||||
let mut response = server.post("/12/reset").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(EMPTY_BOARD);
|
||||
|
||||
let want = "⬜🥛🍪🥛🍪⬜
|
||||
⬜🍪🥛🍪🥛⬜
|
||||
⬜🍪🥛🍪🥛⬜
|
||||
⬜🍪🥛🍪🥛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
No winner.
|
||||
";
|
||||
|
||||
for i in 1..5 {
|
||||
for _ in 0..3 {
|
||||
let slot = if i % 2 == 0 { "milk" } else { "cookie" };
|
||||
response = server.post(&format!("/12/place/{slot}/{i}")).await;
|
||||
response.assert_status_ok();
|
||||
}
|
||||
}
|
||||
for i in 1..5 {
|
||||
let slot = if i % 2 == 0 { "cookie" } else { "milk" };
|
||||
|
||||
response = server.post(&format!("/12/place/{slot}/{i}")).await;
|
||||
response.assert_status_ok();
|
||||
}
|
||||
response.assert_text(want);
|
||||
|
||||
let response = server.post("/12/place/milk/1").await;
|
||||
response.assert_status_service_unavailable();
|
||||
response.assert_text(want);
|
||||
|
||||
let response = server.post("/12/reset").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(EMPTY_BOARD);
|
||||
|
||||
let want = "⬜⬛⬛⬛🍪⬜
|
||||
⬜⬛⬛🍪🥛⬜
|
||||
⬜⬛🍪🥛🥛⬜
|
||||
⬜🍪🥛🥛🥛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
🍪 wins!
|
||||
";
|
||||
|
||||
let response = server.post("/12/place/cookie/1").await;
|
||||
response.assert_status_ok();
|
||||
|
||||
for i in 2..5 {
|
||||
let response = server.post(&format!("/12/place/milk/{i}")).await;
|
||||
response.assert_status_ok();
|
||||
}
|
||||
let response = server.post("/12/place/cookie/2").await;
|
||||
response.assert_status_ok();
|
||||
|
||||
for i in 3..5 {
|
||||
let response = server.post(&format!("/12/place/milk/{i}")).await;
|
||||
response.assert_status_ok();
|
||||
}
|
||||
let response = server.post("/12/place/cookie/3").await;
|
||||
response.assert_status_ok();
|
||||
|
||||
// for i in 4..5 {
|
||||
let response = server.post("/12/place/milk/4").await;
|
||||
response.assert_status_ok();
|
||||
// }
|
||||
let response = server.post("/12/place/cookie/4").await;
|
||||
response.assert_status_ok();
|
||||
|
||||
response.assert_text(want);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_task_3() {
|
||||
let server = test_server();
|
||||
|
||||
let response = server.post("/12/reset").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(EMPTY_BOARD);
|
||||
|
||||
let want = "\
|
||||
⬜🍪🍪🍪🍪⬜
|
||||
⬜🥛🍪🍪🥛⬜
|
||||
⬜🥛🥛🥛🥛⬜
|
||||
⬜🍪🥛🍪🥛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
let response = server.get("/12/random-board").await;
|
||||
// dbg!(response.text());
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
|
||||
let want = "\
|
||||
⬜🍪🥛🍪🍪⬜
|
||||
⬜🥛🍪🥛🍪⬜
|
||||
⬜🥛🍪🍪🍪⬜
|
||||
⬜🍪🥛🥛🥛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
let response = server.get("/12/random-board").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
|
||||
let want = "\
|
||||
⬜🍪🍪🥛🍪⬜
|
||||
⬜🍪🥛🍪🍪⬜
|
||||
⬜🥛🍪🍪🥛⬜
|
||||
⬜🍪🥛🍪🍪⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
let response = server.get("/12/random-board").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
|
||||
let want = "\
|
||||
⬜🥛🍪🍪🥛⬜
|
||||
⬜🥛🍪🍪🍪⬜
|
||||
⬜🍪🥛🥛🥛⬜
|
||||
⬜🍪🥛🍪🥛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
let response = server.get("/12/random-board").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
|
||||
let want = "\
|
||||
⬜🥛🥛🥛🍪⬜
|
||||
⬜🍪🍪🍪🥛⬜
|
||||
⬜🥛🍪🍪🥛⬜
|
||||
⬜🍪🥛🥛🍪⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
let response = server.get("/12/random-board").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
|
||||
let response = server.post("/12/reset").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(EMPTY_BOARD);
|
||||
|
||||
let want = "\
|
||||
⬜🍪🍪🍪🍪⬜
|
||||
⬜🥛🍪🍪🥛⬜
|
||||
⬜🥛🥛🥛🥛⬜
|
||||
⬜🍪🥛🍪🥛⬜
|
||||
⬜⬜⬜⬜⬜⬜
|
||||
";
|
||||
let response = server.get("/12/random-board").await;
|
||||
response.assert_status_ok();
|
||||
response.assert_text(want);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user